xref: /xnu-10002.41.9/libkern/c++/OSKext.cpp (revision 699cd48037512bf4380799317ca44ca453c82f57)
1 /*
2  * Copyright (c) 2008-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #define IOKIT_ENABLE_SHARED_PTR
30 
31 extern "C" {
32 #include <string.h>
33 #include <kern/clock.h>
34 #include <kern/host.h>
35 #include <kern/kext_alloc.h>
36 #include <firehose/tracepoint_private.h>
37 #include <firehose/chunk_private.h>
38 #include <os/firehose_buffer_private.h>
39 #include <vm/vm_map.h>
40 #include <kextd/kextd_mach.h>
41 #include <libkern/kernel_mach_header.h>
42 #include <libkern/kext_panic_report.h>
43 #include <libkern/kext_request_keys.h>
44 #include <libkern/mkext.h>
45 #include <libkern/prelink.h>
46 #include <libkern/version.h>
47 #include <libkern/zlib.h>
48 #include <mach/host_special_ports.h>
49 #include <mach/mach_vm.h>
50 #include <mach/mach_time.h>
51 #include <uuid/uuid.h>
52 #include <sys/random.h>
53 #include <pexpert/pexpert.h>
54 
55 #include <sys/pgo.h>
56 
57 #if CONFIG_CSR
58 #include <sys/csr.h>
59 #include <sys/stat.h>
60 #include <sys/vnode.h>
61 #endif /* CONFIG_CSR */
62 };
63 
64 #if CONFIG_MACF
65 #include <sys/kauth.h>
66 #include <security/mac_framework.h>
67 #endif
68 
69 #include <vm/vm_kern.h>
70 #include <sys/sysctl.h>
71 #include <kern/task.h>
72 #include <os/cpp_util.h>
73 
74 #include <libkern/OSKextLibPrivate.h>
75 #include <libkern/c++/OSKext.h>
76 #include <libkern/c++/OSLib.h>
77 
78 #include <IOKit/IOLib.h>
79 #include <IOKit/IOCatalogue.h>
80 #include <IOKit/IORegistryEntry.h>
81 #include <IOKit/IOService.h>
82 #include <IOKit/IOUserServer.h>
83 
84 #include <IOKit/IOStatisticsPrivate.h>
85 #include <IOKit/IOBSD.h>
86 #include <IOKit/IOPlatformExpert.h>
87 
88 #include <san/kasan.h>
89 
90 
91 #if PRAGMA_MARK
92 #pragma mark External & Internal Function Protos
93 #endif
94 /*********************************************************************
95 *********************************************************************/
96 extern "C" {
97 extern int  IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
98 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
99 
100 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
101 extern int dtrace_keep_kernel_symbols(void);
102 
103 #if defined(__x86_64__) || defined(__i386__)
104 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide);
105 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers);
106 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size);
107 static void *allocate_kcfileset_map_entry_list(void);
108 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size);
109 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable);
110 int vnode_put(struct vnode *vp);
111 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size,
112     void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot);
113 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size);
114 void * ubc_getobject(struct vnode *vp, __unused int flags);
115 #endif //(__x86_64__) || defined(__i386__)
116 }
117 
118 extern unsigned long gVirtBase;
119 extern unsigned long gPhysBase;
120 extern vm_map_t g_kext_map;
121 
122 bool pageableKCloaded = false;
123 bool auxKCloaded = false;
124 bool resetAuxKCSegmentOnUnload = false;
125 
126 extern boolean_t pageablekc_uuid_valid;
127 extern uuid_t pageablekc_uuid;
128 extern uuid_string_t pageablekc_uuid_string;
129 
130 extern boolean_t auxkc_uuid_valid;
131 extern uuid_t auxkc_uuid;
132 extern uuid_string_t auxkc_uuid_string;
133 
134 static OSReturn _OSKextCreateRequest(
135 	const char    * predicate,
136 	OSSharedPtr<OSDictionary> & requestP);
137 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
138 static OSObject * _OSKextGetRequestArgument(
139 	OSDictionary * requestDict,
140 	const char   * argName);
141 static bool _OSKextSetRequestArgument(
142 	OSDictionary    * requestDict,
143 	const char      * argName,
144 	OSMetaClassBase * value);
145 template <typename T>
146 static T * _OSKextExtractPointer(OSValueObject<T *> * wrapper);
147 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper);
148 static OSReturn _OSDictionarySetCStringValue(
149 	OSDictionary * dict,
150 	const char   * key,
151 	const char   * value);
152 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
153 #if CONFIG_KXLD
154 static bool _OSKextInPrelinkRebuildWindow(void);
155 #endif
156 
157 // We really should add containsObject() & containsCString to OSCollection & subclasses.
158 // So few pad slots, though....
159 static bool _OSArrayContainsCString(OSArray * array, const char * cString);
160 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code);
161 
162 static const char *getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size);
163 
164 /* Prelinked arm kexts do not have VM entries because the method we use to
165  * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
166  * not work on ARM.  To get around that, we must free prelinked kext
167  * executables with ml_static_mfree() instead of kext_free().
168  */
169 #if __i386__ || __x86_64__
170 #define VM_MAPPED_KEXTS 1
171 #define KASLR_KEXT_DEBUG 0
172 #define KASLR_IOREG_DEBUG 0
173 #elif __arm__ || __arm64__
174 #define VM_MAPPED_KEXTS 0
175 #define KASLR_KEXT_DEBUG 0
176 #else
177 #error Unsupported architecture
178 #endif
179 
180 #if PRAGMA_MARK
181 #pragma mark Constants & Macros
182 #endif
183 /*********************************************************************
184 * Constants & Macros
185 *********************************************************************/
186 
187 /* Use this number to create containers.
188  */
189 #define kOSKextTypicalLoadCount      (150)
190 #define kOSKextTypicalUpgradeCount     (5)
191 
192 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
193  * A loaded kext will no dependents or external retains will have 2 retains.
194  */
195 #define kOSKextMinRetainCount        (1)
196 #define kOSKextMinLoadedRetainCount  (2)
197 
198 #define kOSKextMaxDextLaunchedCount  (~((uint32_t)0))
199 #define KOSBundleDextUniqueIdentifierMaxStringLength (KOSBundleDextUniqueIdentifierMaxLength * 2 +1)
200 
201 /**********
202  * Strings and substrings used in dependency resolution.
203  */
204 #define APPLE_KEXT_PREFIX            "com.apple."
205 #define KERNEL_LIB                   "com.apple.kernel"
206 
207 #define PRIVATE_KPI                  "com.apple.kpi.private"
208 
209 /* Version for compatbility pseudokexts (com.apple.kernel.*),
210  * compatible back to v6.0.
211  */
212 #define KERNEL6_LIB                  "com.apple.kernel.6.0"
213 #define KERNEL6_VERSION              "7.9.9"
214 
215 #define KERNEL_LIB_PREFIX            "com.apple.kernel."
216 #define KPI_LIB_PREFIX               "com.apple.kpi."
217 
218 #define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0)
219 
220 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
221 #define MINIMUM_WAKEUP_SECONDS (30)
222 
223 /*********************************************************************
224 * infoDict keys for internally-stored data. Saves on ivar slots for
225 * objects we don't keep around past boot time or during active load.
226 *********************************************************************/
227 
228 /* A usable, uncompressed file is stored under this key.
229  */
230 #define _kOSKextExecutableKey                "_OSKextExecutable"
231 
232 /* An indirect reference to the executable file from an mkext
233  * is stored under this key.
234  */
235 #define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference"
236 
237 /* If the file is contained in a larger buffer laid down by the booter or
238  * sent from user space, the OSKext stores that OSData under this key so that
239  * references are properly tracked. This is always an mkext, right now.
240  */
241 #define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData"
242 
243 #define OS_LOG_HDR_VERSION  1
244 #define NUM_OS_LOG_SECTIONS 3
245 
246 #define OS_LOG_SECT_IDX         0
247 #define CSTRING_SECT_IDX        1
248 #define ASAN_CSTRING_SECT_IDX   2
249 
250 #if PRAGMA_MARK
251 #pragma mark Typedefs
252 #endif
253 /*********************************************************************
254 * Typedefs
255 *********************************************************************/
256 
257 /*********************************************************************
258 * osLogDataHeaderRef describes the header information of an OSData
259 * object that is returned when querying for kOSBundleLogStringsKey.
260 * We currently return information regarding 2 sections - os_log and
261 * cstring. In the case that the os_log section doesn't exist, we just
262 * return an offset and length of 0 for that section.
263 *********************************************************************/
264 typedef struct osLogDataHeader {
265 	uint32_t version;
266 	uint32_t sect_count;
267 	struct {
268 		uint32_t sect_offset;
269 		uint32_t sect_size;
270 	} sections[0];
271 } osLogDataHeaderRef;
272 
273 /*********************************************************************
274 * MkextEntryRef describes the contents of an OSData object
275 * referencing a file entry from an mkext so that we can uncompress
276 * (if necessary) and extract it on demand.
277 *
278 * It contains the mkextVersion in case we ever wind up supporting
279 * multiple mkext formats. Mkext format 1 is officially retired as of
280 * Snow Leopard.
281 *********************************************************************/
282 typedef struct MkextEntryRef {
283 	mkext_basic_header * mkext; // beginning of whole mkext file
284 	void               * fileinfo;// mkext2_file_entry or equiv; see mkext.h
285 } MkextEntryRef;
286 
287 #if PRAGMA_MARK
288 #pragma mark Global and static Module Variables
289 #endif
290 /*********************************************************************
291 * Global & static variables, used to keep track of kexts.
292 *********************************************************************/
293 
294 static  bool                sPrelinkBoot               = false;
295 static  bool                sSafeBoot                  = false;
296 static  bool                sKeepSymbols               = false;
297 static  bool                sPanicOnKCMismatch         = false;
298 static  bool                sOSKextWasResetAfterUserspaceReboot = false;
299 
300 /*********************************************************************
301  * sKextLock is the principal lock for OSKext, and guards all static
302  * and global variables not owned by other locks (declared further
303  * below). It must be taken by any entry-point method or function,
304  * including internal functions called on scheduled threads.
305  *
306  * sKextLock and sKextInnerLock are recursive due to multiple functions
307  * that are called both externally and internally. The other locks are
308  * nonrecursive.
309  *
310  * Which locks are taken depends on what they protect, but if more than
311  * one must be taken, they must always be locked in this order
312  * (and unlocked in reverse order) to prevent deadlocks:
313  *
314  *    1. sKextLock
315  *    2. sKextInnerLock
316  *    3. sKextSummariesLock
317  *    4. sKextLoggingLock
318  */
319 static IORecursiveLock    * sKextLock                  = NULL;
320 
321 static OSSharedPtr<OSDictionary>   sKextsByID;
322 static OSSharedPtr<OSDictionary>   sExcludeListByID;
323 static OSKextVersion               sExcludeListVersion        = 0;
324 static OSSharedPtr<OSArray>        sLoadedKexts;
325 static OSSharedPtr<OSDictionary>   sNonLoadableKextsByID;
326 static OSSharedPtr<OSArray>        sUnloadedPrelinkedKexts;
327 static OSSharedPtr<OSArray>        sLoadedDriverKitKexts;
328 static OSSharedPtr<OSDictionary>   sDriverKitToUpgradeByID;
329 
330 // Requests to the IOKit daemon waiting to be picked up.
331 static OSSharedPtr<OSArray>        sKernelRequests;
332 // Identifier of kext load requests in sKernelRequests
333 static OSSharedPtr<OSSet>          sPostedKextLoadIdentifiers;
334 static OSSharedPtr<OSArray>        sRequestCallbackRecords;
335 
336 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
337 static OSSharedPtr<OSSet>          sAllKextLoadIdentifiers;
338 #if CONFIG_KXLD
339 static KXLDContext        * sKxldContext               = NULL;
340 #endif
341 static uint32_t             sNextLoadTag               = 0;
342 static uint32_t             sNextRequestTag            = 0;
343 
344 static bool                 sUserLoadsActive           = false;
345 static bool                 sIOKitDaemonActive         = false;
346 static bool                 sDeferredLoadSucceeded     = false;
347 static bool                 sConsiderUnloadsExecuted   = false;
348 
349 #if NO_KEXTD
350 static bool                 sKernelRequestsEnabled     = false;
351 #else
352 static bool                 sKernelRequestsEnabled     = true;
353 #endif
354 static bool                 sLoadEnabled               = true;
355 static bool                 sUnloadEnabled             = true;
356 
357 /*********************************************************************
358  * Stuff for the OSKext representing the kernel itself.
359  **********/
360 static OSKext          * sKernelKext             = NULL;
361 
362 /* Load Tag IDs used by statically loaded binaries (e.g, the kernel itself). */
363 enum : uint32_t {
364 	kOSKextKernelLoadTag = 0,
365 	kOSKextLoadTagCount
366 };
367 
368 /* Set up a fake kmod_info struct for the kernel.
369  * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
370  * before OSKext is initialized; that call only needs the name
371  * and address to be set correctly.
372  *
373  * We don't do much else with the kerne's kmod_info; we never
374  * put it into the kmod list, never adjust the reference count,
375  * and never have kernel components reference it.
376  * For that matter, we don't do much with kmod_info structs
377  * at all anymore! We just keep them filled in for gdb and
378  * binary compability.
379  */
380 kmod_info_t g_kernel_kmod_info = {
381 	.next =            NULL,
382 	.info_version =    KMOD_INFO_VERSION,
383 	.id =              kOSKextKernelLoadTag,   // loadTag: kernel is always 0
384 	.name =            kOSKextKernelIdentifier,// bundle identifier
385 	.version =         "0",           // filled in in OSKext::initialize()
386 	.reference_count = -1,            // never adjusted; kernel never unloads
387 	.reference_list =  NULL,
388 	.address =         0,
389 	.size =            0,             // filled in in OSKext::initialize()
390 	.hdr_size =        0,
391 	.start =           NULL,
392 	.stop =            NULL
393 };
394 
395 
396 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
397 
398 kmod_info_t invalid_kmod_info = {
399 	.next =            NULL,
400 	.info_version =    KMOD_INFO_VERSION,
401 	.id =              UINT32_MAX,
402 	.name =            "invalid",
403 	.version =         "0",
404 	.reference_count = -1,
405 	.reference_list =  NULL,
406 	.address =         0,
407 	.size =            0,
408 	.hdr_size =        0,
409 	.start =           NULL,
410 	.stop =            NULL
411 };
412 
413 extern "C" {
414 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
415 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
416 // misc_protos.h, db_low_trace.c, kgmacros
417 // 'kmod' is a holdover from the old kmod system, we can't rename it.
418 kmod_info_t * kmod = NULL;
419 
420 #define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE)
421 
422 
423 static char     * loaded_kext_paniclist         = NULL;
424 static uint32_t   loaded_kext_paniclist_size    = 0;
425 
426 AbsoluteTime      last_loaded_timestamp;
427 static char       last_loaded_str_buf[2 * KMOD_MAX_NAME];
428 static u_long     last_loaded_strlen            = 0;
429 static void     * last_loaded_address           = NULL;
430 static u_long     last_loaded_size              = 0;
431 
432 AbsoluteTime      last_unloaded_timestamp;
433 static char       last_unloaded_str_buf[2 * KMOD_MAX_NAME];
434 static u_long     last_unloaded_strlen          = 0;
435 static void     * last_unloaded_address         = NULL;
436 static u_long     last_unloaded_size            = 0;
437 
438 // Statically linked kmods described by several mach-o sections:
439 //
440 // kPrelinkInfoSegment:kBuiltinInfoSection
441 // Array of pointers to kmod_info_t structs.
442 //
443 // kPrelinkInfoSegment:kBuiltinInfoSection
444 // Array of pointers to an embedded mach-o header.
445 //
446 // __DATA:kBuiltinInitSection, kBuiltinTermSection
447 // Structors for all kmods. Has to be filtered by proc address.
448 //
449 
450 static uint32_t gBuiltinKmodsCount;
451 static kernel_section_t * gBuiltinKmodsSectionInfo;
452 static kernel_section_t * gBuiltinKmodsSectionStart;
453 
454 const OSSymbol              * gIOSurfaceIdentifier;
455 vm_tag_t                      gIOSurfaceTag;
456 
457 /*********************************************************************
458  * sKextInnerLock protects against cross-calls with IOService and
459  * IOCatalogue, and owns the variables declared immediately below.
460  *
461  * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
462  *
463  * When both sKextLock and sKextInnerLock need to be taken,
464  * always lock sKextLock first and unlock it second. Never take both
465  * locks in an entry point to OSKext; if you need to do so, you must
466  * spawn an independent thread to avoid potential deadlocks for threads
467  * calling into OSKext.
468  **********/
469 static IORecursiveLock *    sKextInnerLock             = NULL;
470 
471 #if XNU_TARGET_OS_OSX
472 static bool                 sAutounloadEnabled         = true;
473 #endif
474 static bool                 sConsiderUnloadsCalled     = false;
475 static bool                 sConsiderUnloadsPending    = false;
476 
477 static unsigned int         sConsiderUnloadDelay       = 60;     // seconds
478 static thread_call_t        sUnloadCallout             = NULL;
479 #if CONFIG_KXLD
480 static thread_call_t        sDestroyLinkContextThread  = NULL;   // one-shot, one-at-a-time thread
481 #endif // CONFIG_KXLD
482 static bool                 sSystemSleep               = false;  // true when system going to sleep
483 static AbsoluteTime         sLastWakeTime;                       // last time we woke up
484 
485 /*********************************************************************
486  * Backtraces can be printed at various times so we need a tight lock
487  * on data used for that. sKextSummariesLock protects the variables
488  * declared immediately below.
489  *
490  * gLoadedKextSummaries is accessed by other modules, but only during
491  * a panic so the lock isn't needed then.
492  *
493  * gLoadedKextSummaries has the "used" attribute in order to ensure
494  * that it remains visible even when we are performing extremely
495  * aggressive optimizations, as it is needed to allow the debugger
496  * to automatically parse the list of loaded kexts.
497  **********/
498 static IOLock                 * sKextSummariesLock                = NULL;
499 extern "C" lck_ticket_t         vm_allocation_sites_lock;
500 extern "C" lck_grp_t            vm_page_lck_grp_bucket;
501 static lck_ticket_t           * sKextAccountsLock = &vm_allocation_sites_lock;
502 static lck_grp_t              * sKextAccountsLockGrp = &vm_page_lck_grp_bucket;
503 
504 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
505 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
506 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
507 static size_t sLoadedKextSummariesAllocSize = 0;
508 
509 static OSKextActiveAccount    * sKextAccounts;
510 static uint32_t                 sKextAccountsCount;
511 };
512 
513 /*********************************************************************
514  * sKextLoggingLock protects the logging variables declared immediately below.
515  **********/
516 static IOLock                 * sKextLoggingLock           = NULL;
517 
518 static  const OSKextLogSpec     kDefaultKernelLogFilter    = kOSKextLogBasicLevel |
519     kOSKextLogVerboseFlagsMask;
520 static  OSKextLogSpec           sKernelLogFilter           = kDefaultKernelLogFilter;
521 static  bool                    sBootArgLogFilterFound     = false;
522 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
523     0, "kernel kext logging");
524 
525 static  OSKextLogSpec           sUserSpaceKextLogFilter    = kOSKextLogSilentFilter;
526 static  OSSharedPtr<OSArray>    sUserSpaceLogSpecArray;
527 static  OSSharedPtr<OSArray>    sUserSpaceLogMessageArray;
528 
529 /*********
530  * End scope for sKextInnerLock-protected variables.
531  *********************************************************************/
532 
533 /*********************************************************************
534  * OSValueObject concrete type instantiations
535  **********/
536 OSDefineValueObjectForDependentType(void*)
537 OSDefineValueObjectForDependentType(OSKextRequestResourceCallback)
538 
539 
540 /**********************************************************************/
541 
542 TUNABLE(uint32_t, kMaxDextCrashesInOneDay, "daily_max_dext_crashes", kMaxDextCrashesInOneDayDefault);
543 
544 /*********************************************************************
545  *  helper function used for collecting PGO data upon unload of a kext
546  */
547 
548 static int OSKextGrabPgoDataLocked(OSKext *kext,
549     bool metadata,
550     uuid_t instance_uuid,
551     uint64_t *pSize,
552     char *pBuffer,
553     uint64_t bufferSize);
554 
555 /**********************************************************************/
556 
557 
558 
559 #if PRAGMA_MARK
560 #pragma mark OSData callbacks (need to move to OSData)
561 #endif
562 /*********************************************************************
563 * C functions used for callbacks.
564 *********************************************************************/
565 extern "C" {
566 void
osdata_kmem_free(void * ptr,unsigned int length)567 osdata_kmem_free(void * ptr, unsigned int length)
568 {
569 	kmem_free(kernel_map, (vm_address_t)ptr, length);
570 	return;
571 }
572 
573 void
osdata_phys_free(void * ptr,unsigned int length)574 osdata_phys_free(void * ptr, unsigned int length)
575 {
576 	ml_static_mfree((vm_offset_t)ptr, length);
577 	return;
578 }
579 
580 void
osdata_vm_deallocate(void * ptr,unsigned int length)581 osdata_vm_deallocate(void * ptr, unsigned int length)
582 {
583 	(void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
584 	return;
585 }
586 
587 void
osdata_kext_free(void * ptr,unsigned int length)588 osdata_kext_free(void * ptr, unsigned int length)
589 {
590 	(void)kext_free((vm_offset_t)ptr, length);
591 }
592 };
593 
594 #if PRAGMA_MARK
595 #pragma mark KXLD Allocation Callback
596 #endif
597 #if CONFIG_KXLD
598 /*********************************************************************
599 * KXLD Allocation Callback
600 *********************************************************************/
601 kxld_addr_t
kern_allocate(u_long size,KXLDAllocateFlags * flags,void * user_data)602 kern_allocate(
603 	u_long              size,
604 	KXLDAllocateFlags * flags,
605 	void              * user_data)
606 {
607 	vm_address_t  result       = 0; // returned
608 	kern_return_t mach_result  = KERN_FAILURE;
609 	bool          success      = false;
610 	OSKext      * theKext      = (OSKext *)user_data;
611 	unsigned int  roundSize    = 0;
612 	OSSharedPtr<OSData>      linkBuffer;
613 
614 	if (round_page(size) > UINT_MAX) {
615 		OSKextLog(theKext,
616 		    kOSKextLogErrorLevel |
617 		    kOSKextLogGeneralFlag,
618 		    "%s: Requested memory size is greater than UINT_MAX.",
619 		    theKext->getIdentifierCString());
620 		goto finish;
621 	}
622 
623 	roundSize = (unsigned int)round_page(size);
624 
625 	mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
626 	if (mach_result != KERN_SUCCESS) {
627 		OSKextLog(theKext,
628 		    kOSKextLogErrorLevel |
629 		    kOSKextLogGeneralFlag,
630 		    "Can't allocate kernel memory to link %s.",
631 		    theKext->getIdentifierCString());
632 		goto finish;
633 	}
634 
635 	/* Create an OSData wrapper for the allocated buffer.
636 	 */
637 	linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
638 	if (!linkBuffer) {
639 		OSKextLog(theKext,
640 		    kOSKextLogErrorLevel |
641 		    kOSKextLogGeneralFlag,
642 		    "Can't allocate linked executable wrapper for %s.",
643 		    theKext->getIdentifierCString());
644 		goto finish;
645 	}
646 	linkBuffer->setDeallocFunction(osdata_kext_free);
647 	OSKextLog(theKext,
648 	    kOSKextLogProgressLevel |
649 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
650 	    "Allocated link buffer for kext %s at %p (%lu bytes).",
651 	    theKext->getIdentifierCString(),
652 	    (void *)result, (unsigned long)roundSize);
653 
654 	theKext->setLinkedExecutable(linkBuffer.get());
655 
656 	*flags = kKxldAllocateWritable;
657 	success = true;
658 
659 finish:
660 	if (!success && result) {
661 		kext_free(result, roundSize);
662 		result = 0;
663 	}
664 
665 	return (kxld_addr_t)result;
666 }
667 
668 /*********************************************************************
669 *********************************************************************/
670 void
kxld_log_callback(KXLDLogSubsystem subsystem,KXLDLogLevel level,const char * format,va_list argList,void * user_data)671 kxld_log_callback(
672 	KXLDLogSubsystem    subsystem,
673 	KXLDLogLevel        level,
674 	const char        * format,
675 	va_list             argList,
676 	void              * user_data)
677 {
678 	OSKext *theKext = (OSKext *) user_data;
679 	OSKextLogSpec logSpec = 0;
680 
681 	switch (subsystem) {
682 	case kKxldLogLinking:
683 		logSpec |= kOSKextLogLinkFlag;
684 		break;
685 	case kKxldLogPatching:
686 		logSpec |= kOSKextLogPatchFlag;
687 		break;
688 	}
689 
690 	switch (level) {
691 	case kKxldLogExplicit:
692 		logSpec |= kOSKextLogExplicitLevel;
693 		break;
694 	case kKxldLogErr:
695 		logSpec |= kOSKextLogErrorLevel;
696 		break;
697 	case kKxldLogWarn:
698 		logSpec |= kOSKextLogWarningLevel;
699 		break;
700 	case kKxldLogBasic:
701 		logSpec |= kOSKextLogProgressLevel;
702 		break;
703 	case kKxldLogDetail:
704 		logSpec |= kOSKextLogDetailLevel;
705 		break;
706 	case kKxldLogDebug:
707 		logSpec |= kOSKextLogDebugLevel;
708 		break;
709 	}
710 
711 	OSKextVLog(theKext, logSpec, format, argList);
712 }
713 #endif // CONFIG_KXLD
714 
715 #if PRAGMA_MARK
716 #pragma mark IOStatistics defines
717 #endif
718 
719 #if IOKITSTATS
720 
721 #define notifyKextLoadObservers(kext, kmod_info) \
722 do { \
723     IOStatistics::onKextLoad(kext, kmod_info); \
724 } while (0)
725 
726 #define notifyKextUnloadObservers(kext) \
727 do { \
728     IOStatistics::onKextUnload(kext); \
729 } while (0)
730 
731 #define notifyAddClassObservers(kext, addedClass, flags) \
732 do { \
733     IOStatistics::onClassAdded(kext, addedClass); \
734 } while (0)
735 
736 #define notifyRemoveClassObservers(kext, removedClass, flags) \
737 do { \
738     IOStatistics::onClassRemoved(kext, removedClass); \
739 } while (0)
740 
741 #else
742 
743 #define notifyKextLoadObservers(kext, kmod_info)
744 #define notifyKextUnloadObservers(kext)
745 #define notifyAddClassObservers(kext, addedClass, flags)
746 #define notifyRemoveClassObservers(kext, removedClass, flags)
747 
748 #endif /* IOKITSTATS */
749 
750 #if PRAGMA_MARK
751 #pragma mark Module Config (Startup & Shutdown)
752 #endif
753 /*********************************************************************
754 * Module Config (Class Definition & Class Methods)
755 *********************************************************************/
756 #define super OSObject
757 OSDefineMetaClassAndStructors(OSKext, OSObject)
758 
759 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject);
760 
761 OSDefineMetaClassAndStructors(OSDextStatistics, OSObject);
762 
763 /*********************************************************************
764 *********************************************************************/
765 /**
766  * Allocate and intialize a fake/representative OSKext object for a statically
767  * loaded (by iBoot) binary (e.g., the XNU kernel itself).
768  *
769  * @param kmod_info Pointer to the kmod_info structure for the binary being
770  *                  setup. At least the "name" and "id" fields needs to already
771  *                  be set correctly.
772  *
773  * @return The allocated and initialized OSKext object.
774  */
775 /* static */
776 OSKext *
allocAndInitFakeKext(kmod_info_t * kmod_info)777 OSKext::allocAndInitFakeKext(kmod_info_t *kmod_info)
778 {
779 	vm_offset_t load_address = 0;
780 	const char *bundle_name = NULL;
781 	bool macho_is_unslid = false;
782 	bool set_custom_path = false;
783 	const char *executable_fallback_name = NULL;
784 
785 	if (kmod_info->id == kOSKextKernelLoadTag) {
786 		load_address = (vm_offset_t)&_mh_execute_header;
787 		bundle_name = "mach_kernel";
788 
789 		/* The kernel Mach-O header is fixed up to slide all of its addresses. */
790 		macho_is_unslid = false;
791 
792 		/**
793 		 * No path to the binary is set for the kernel in its OSKext object. The
794 		 * kernel binary is located in fixed directories depending on the OS.
795 		 */
796 		set_custom_path = false;
797 		executable_fallback_name = NULL;
798 	} else {
799 		panic("%s: Unsupported kmod_info->id (%d)", __func__, kmod_info->id);
800 	}
801 
802 	/* Set up an OSKext instance to represent the statically loaded binary. */
803 	OSKext *fakeKext = new OSKext;
804 	assert(fakeKext);
805 	assert(load_address != 0);
806 
807 	/*
808 	 * The start address is always a slid address whereas the last VA returned
809 	 * by getlastaddr() might be unslid depending on the Mach-O. If the address
810 	 * coming from the Mach-O is unslid, then unslide the start address before
811 	 * computing the length of the executable.
812 	 */
813 	size_t binaryLength = getlastaddr((kernel_mach_header_t*)load_address);
814 	binaryLength -= (macho_is_unslid) ? ml_static_unslide(load_address) : load_address;
815 	assert(binaryLength <= UINT_MAX);
816 
817 	/**
818 	 * The load address is always slid. That value will be unslid before being
819 	 * exposed to userspace.
820 	 */
821 	OSSharedPtr<OSData> executable = OSData::withBytesNoCopy(
822 		(void*)load_address, (unsigned int)binaryLength);
823 	assert(executable);
824 
825 	fakeKext->loadTag = sNextLoadTag++;
826 	fakeKext->bundleID = OSSymbol::withCString(kmod_info->name);
827 
828 	fakeKext->version = OSKextParseVersionString(osrelease);
829 	fakeKext->compatibleVersion = fakeKext->version;
830 	fakeKext->linkedExecutable = os::move(executable);
831 	fakeKext->interfaceUUID = fakeKext->copyUUID();
832 
833 	fakeKext->flags.hasAllDependencies = 1;
834 	fakeKext->flags.kernelComponent = 1;
835 	fakeKext->flags.prelinked = 0;
836 	fakeKext->flags.loaded = 1;
837 	fakeKext->flags.started = 1;
838 	fakeKext->flags.CPPInitialized = 0;
839 	fakeKext->flags.jettisonLinkeditSeg = 0;
840 	fakeKext->flags.unslidMachO = macho_is_unslid;
841 
842 
843 	fakeKext->kmod_info = kmod_info;
844 	strlcpy(kmod_info->version, osrelease,
845 	    sizeof(kmod_info->version));
846 	kmod_info->size = binaryLength;
847 	assert(kmod_info->id == fakeKext->loadTag);
848 
849 	/*
850 	 * Con up an info dict, so we don't have to have special-case checking all
851 	 * over.
852 	 */
853 	fakeKext->infoDict = OSDictionary::withCapacity(5);
854 	assert(fakeKext->infoDict);
855 	bool setResult = fakeKext->infoDict->setObject(kCFBundleIdentifierKey,
856 	    fakeKext->bundleID.get());
857 	assert(setResult);
858 	setResult = fakeKext->infoDict->setObject(kOSKernelResourceKey,
859 	    kOSBooleanTrue);
860 	assert(setResult);
861 
862 	{
863 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease));
864 		assert(scratchString);
865 		setResult = fakeKext->infoDict->setObject(kCFBundleVersionKey,
866 		    scratchString.get());
867 		assert(setResult);
868 	}
869 
870 	{
871 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(bundle_name));
872 		assert(scratchString);
873 		setResult = fakeKext->infoDict->setObject(kCFBundleNameKey,
874 		    scratchString.get());
875 		assert(setResult);
876 	}
877 
878 	return fakeKext;
879 }
880 
881 /* static */
882 void
initialize(void)883 OSKext::initialize(void)
884 {
885 	OSSharedPtr<OSData>     kernelExecutable   = NULL;// do not release
886 	IORegistryEntry * registryRoot       = NULL;// do not release
887 	OSSharedPtr<OSNumber> kernelCPUType;
888 	OSSharedPtr<OSNumber> kernelCPUSubtype;
889 	OSKextLogSpec     bootLogFilter      = kOSKextLogSilentFilter;
890 	bool              setResult          = false;
891 	uint64_t        * timestamp          = NULL;
892 	__unused char     bootArgBuffer[16];// for PE_parse_boot_argn w/strings
893 
894 	/* This must be the first thing allocated. Everything else grabs this lock.
895 	 */
896 	sKextLock = IORecursiveLockAlloc();
897 	sKextInnerLock = IORecursiveLockAlloc();
898 	sKextSummariesLock = IOLockAlloc();
899 	sKextLoggingLock = IOLockAlloc();
900 	assert(sKextLock);
901 	assert(sKextInnerLock);
902 	assert(sKextSummariesLock);
903 	assert(sKextLoggingLock);
904 
905 	sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
906 	sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
907 	sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
908 	sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
909 	sKernelRequests = OSArray::withCapacity(0);
910 	sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
911 	sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
912 	sRequestCallbackRecords = OSArray::withCapacity(0);
913 	sDriverKitToUpgradeByID = OSDictionary::withCapacity(kOSKextTypicalUpgradeCount);
914 
915 	assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests &&
916 	    sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
917 	    sRequestCallbackRecords && sUnloadedPrelinkedKexts && sDriverKitToUpgradeByID);
918 
919 	/* Read the log flag boot-args and set the log flags.
920 	 */
921 	if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
922 		sBootArgLogFilterFound = true;
923 		sKernelLogFilter = bootLogFilter;
924 		// log this if any flags are set
925 		OSKextLog(/* kext */ NULL,
926 		    kOSKextLogBasicLevel |
927 		    kOSKextLogFlagsMask,
928 		    "Kernel kext log filter 0x%x per kextlog boot arg.",
929 		    (unsigned)sKernelLogFilter);
930 	}
931 
932 #if !defined(__arm__) && !defined(__arm64__)
933 	/*
934 	 * On our ARM targets, the kernelcache/boot kernel collection contains
935 	 * the set of kexts required to boot, as specified by KCB.  Safeboot is
936 	 * either unsupported, or is supported by the bootloader only loading
937 	 * the boot kernel collection; as a result OSKext has no role to play
938 	 * in safeboot policy on ARM.
939 	 */
940 	sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
941 	    sizeof(bootArgBuffer)) ? true : false;
942 #endif /* defined(__arm__) && defined(__arm64__) */
943 
944 	if (sSafeBoot) {
945 		OSKextLog(/* kext */ NULL,
946 		    kOSKextLogWarningLevel |
947 		    kOSKextLogGeneralFlag,
948 		    "SAFE BOOT DETECTED - "
949 		    "only valid OSBundleRequired kexts will be loaded.");
950 	}
951 
952 	PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
953 #if CONFIG_DTRACE
954 	if (dtrace_keep_kernel_symbols()) {
955 		sKeepSymbols = true;
956 	}
957 #endif /* CONFIG_DTRACE */
958 #if KASAN_DYNAMIC_BLACKLIST
959 	/* needed for function lookup */
960 	sKeepSymbols = true;
961 #endif
962 
963 	/*
964 	 * Should we panic when the SystemKC is not linked against the
965 	 * BootKC that was loaded by the booter? By default: yes, if the
966 	 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic
967 	 * on mis-match and instead just print an error and continue.
968 	 */
969 	sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer,
970 	    sizeof(bootArgBuffer)) ? false : true;
971 
972 	/* Set up an OSKext instance to represent the kernel itself. */
973 	sKernelKext = allocAndInitFakeKext(&g_kernel_kmod_info);
974 	assert(sKernelKext);
975 
976 
977 	/* Add the kernel kext to the bookkeeping dictionaries. Note that
978 	 * the kernel kext doesn't have a kmod_info struct. copyInfo()
979 	 * gathers info from other places anyhow.
980 	 */
981 	setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext);
982 	assert(setResult);
983 	setResult = sLoadedKexts->setObject(sKernelKext);
984 	assert(setResult);
985 
986 
987 	// XXX: better way with OSSharedPtr?
988 	// sKernelKext remains a valid pointer even after the decref
989 	sKernelKext->release();
990 
991 	registryRoot = IORegistryEntry::getRegistryRoot();
992 	kernelCPUType = OSNumber::withNumber(
993 		(long long unsigned int)_mh_execute_header.cputype,
994 		8 * sizeof(_mh_execute_header.cputype));
995 	kernelCPUSubtype = OSNumber::withNumber(
996 		(long long unsigned int)_mh_execute_header.cpusubtype,
997 		8 * sizeof(_mh_execute_header.cpusubtype));
998 	assert(registryRoot && kernelCPUSubtype && kernelCPUType);
999 
1000 	registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get());
1001 	registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get());
1002 
1003 	gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
1004 	if (gBuiltinKmodsSectionInfo) {
1005 		uint32_t count;
1006 
1007 		assert(gBuiltinKmodsSectionInfo->addr);
1008 		assert(gBuiltinKmodsSectionInfo->size);
1009 		assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX);
1010 		gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
1011 
1012 		gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
1013 		assert(gBuiltinKmodsSectionStart);
1014 		assert(gBuiltinKmodsSectionStart->addr);
1015 		assert(gBuiltinKmodsSectionStart->size);
1016 		assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX);
1017 		count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
1018 		// one extra pointer for the end of last kmod
1019 		assert(count == (gBuiltinKmodsCount + 1));
1020 
1021 		vm_kernel_builtinkmod_text     = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
1022 		vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
1023 	}
1024 
1025 	// Don't track this object -- it's never released
1026 	gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach();
1027 
1028 	timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
1029 	*timestamp = 0;
1030 	timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
1031 	*timestamp = 0;
1032 	timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
1033 	*timestamp = 0;
1034 
1035 	OSKextLog(/* kext */ NULL,
1036 	    kOSKextLogProgressLevel |
1037 	    kOSKextLogGeneralFlag,
1038 	    "Kext system initialized.");
1039 
1040 	notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
1041 
1042 	return;
1043 }
1044 
1045 /*********************************************************************
1046 * This is expected to be called exactly once, from exactly one thread
1047 * context, during kernel bootstrap.
1048 *********************************************************************/
1049 /* static */
1050 OSReturn
removeKextBootstrap(void)1051 OSKext::removeKextBootstrap(void)
1052 {
1053 	OSReturn                   result                = kOSReturnError;
1054 
1055 	const char               * dt_kernel_header_name = "Kernel-__HEADER";
1056 	const char               * dt_kernel_symtab_name = "Kernel-__SYMTAB";
1057 	kernel_mach_header_t     * dt_mach_header        = NULL;
1058 	int                        dt_mach_header_size   = 0;
1059 	struct symtab_command    * dt_symtab             = NULL;
1060 	int                        dt_symtab_size        = 0;
1061 	int                        dt_result             = 0;
1062 
1063 	kernel_segment_command_t * seg_kld               = NULL;
1064 	kernel_segment_command_t * seg_klddata           = NULL;
1065 	kernel_segment_command_t * seg_linkedit          = NULL;
1066 
1067 	const char __unused      * dt_segment_name       = NULL;
1068 	void       __unused      * segment_paddress      = NULL;
1069 	int        __unused        segment_size          = 0;
1070 
1071 	OSKextLog(/* kext */ NULL,
1072 	    kOSKextLogProgressLevel |
1073 	    kOSKextLogGeneralFlag,
1074 	    "Jettisoning kext bootstrap segments.");
1075 
1076 	/*
1077 	 * keep the linkedit segment around when booted from a new MH_FILESET
1078 	 * KC because all the kexts shared a linkedit segment.
1079 	 */
1080 	kc_format_t kc_format;
1081 	if (!PE_get_primary_kc_format(&kc_format)) {
1082 		OSKextLog(/* kext */ NULL,
1083 		    kOSKextLogErrorLevel |
1084 		    kOSKextLogGeneralFlag,
1085 		    "Unable to determine primary KC format");
1086 	}
1087 
1088 	/*****
1089 	 * Dispose of unnecessary stuff that the booter didn't need to load.
1090 	 */
1091 	dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
1092 	    (void **)&dt_mach_header, &dt_mach_header_size);
1093 	if (dt_result == 0 && dt_mach_header) {
1094 		IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
1095 		    round_page_32(dt_mach_header_size));
1096 	}
1097 	dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
1098 	    (void **)&dt_symtab, &dt_symtab_size);
1099 	if (dt_result == 0 && dt_symtab) {
1100 		IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
1101 		    round_page_32(dt_symtab_size));
1102 	}
1103 
1104 	/*****
1105 	 * KLD & KLDDATA bootstrap segments.
1106 	 */
1107 	// xxx - should rename KLD segment
1108 	seg_kld = getsegbyname("__KLD");
1109 	seg_klddata = getsegbyname("__KLDDATA");
1110 	if (seg_klddata) {
1111 		// __mod_term_func is part of __KLDDATA
1112 		OSRuntimeUnloadCPPForSegment(seg_klddata);
1113 	}
1114 
1115 #if __arm__ || __arm64__
1116 	/* Free the memory that was set up by iBoot.
1117 	 */
1118 #if !defined(KERNEL_INTEGRITY_KTRR) && !defined(KERNEL_INTEGRITY_CTRR)
1119 	/* We cannot free the KLD segment with CTRR enabled as it contains text and
1120 	 * is covered by the contiguous rorgn.
1121 	 */
1122 	dt_segment_name = "Kernel-__KLD";
1123 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1124 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1125 		    (int)segment_size); // calls ml_static_mfree
1126 	} else if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1127 		/* With fileset KCs, the Kernel KLD segment is not recorded in the DT. */
1128 		ml_static_mfree(ml_static_ptovirt(seg_kld->vmaddr - gVirtBase + gPhysBase),
1129 		    seg_kld->vmsize);
1130 	}
1131 #endif
1132 	dt_segment_name = "Kernel-__KLDDATA";
1133 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1134 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1135 		    (int)segment_size);  // calls ml_static_mfree
1136 	} else if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1137 		/* With fileset KCs, the Kernel KLDDATA segment is not recorded in the DT. */
1138 		ml_static_mfree(ml_static_ptovirt(seg_klddata->vmaddr - gVirtBase + gPhysBase),
1139 		    seg_klddata->vmsize);
1140 	}
1141 #elif __i386__ || __x86_64__
1142 	/* On x86, use the mapping data from the segment load command to
1143 	 * unload KLD & KLDDATA directly.
1144 	 * This may invalidate any assumptions about  "avail_start"
1145 	 * defining the lower bound for valid physical addresses.
1146 	 */
1147 	if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1148 		bzero((void *)seg_kld->vmaddr, seg_kld->vmsize);
1149 		ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize);
1150 	}
1151 	if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1152 		bzero((void *)seg_klddata->vmaddr, seg_klddata->vmsize);
1153 		ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize);
1154 	}
1155 #else
1156 #error arch
1157 #endif
1158 
1159 	/*****
1160 	 * Prelinked kernel's symtab (if there is one).
1161 	 */
1162 	if (kc_format != KCFormatFileset) {
1163 		kernel_section_t * sect;
1164 		sect = getsectbyname("__PRELINK", "__symtab");
1165 		if (sect && sect->addr && sect->size) {
1166 			ml_static_mfree(sect->addr, sect->size);
1167 		}
1168 	}
1169 
1170 	seg_linkedit = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
1171 
1172 	/* kxld always needs the kernel's __LINKEDIT segment, but we can make it
1173 	 * pageable, unless keepsyms is set.  To do that, we have to copy it from
1174 	 * its booter-allocated memory, free the booter memory, reallocate proper
1175 	 * managed memory, then copy the segment back in.
1176 	 *
1177 	 * NOTE: This optimization is not valid for fileset KCs because each
1178 	 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment
1179 	 * that points to one fileset-global LINKEDIT segment. This
1180 	 * optimization is also only valid for platforms that support vm
1181 	 * mapped kexts or mapped kext collections (pageable KCs)
1182 	 */
1183 #if VM_MAPPED_KEXTS
1184 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1185 		kern_return_t mem_result;
1186 		void *seg_copy = NULL;
1187 		void *seg_data = NULL;
1188 		vm_map_offset_t seg_offset = 0;
1189 		vm_map_offset_t seg_copy_offset = 0;
1190 		vm_map_size_t seg_length = 0;
1191 
1192 		seg_data = (void *) seg_linkedit->vmaddr;
1193 		seg_offset = (vm_map_offset_t) seg_linkedit->vmaddr;
1194 		seg_length = (vm_map_size_t) seg_linkedit->vmsize;
1195 
1196 		/* Allocate space for the LINKEDIT copy.
1197 		 */
1198 		mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
1199 		    seg_length, KMA_ZERO, VM_KERN_MEMORY_KEXT);
1200 		if (mem_result != KERN_SUCCESS) {
1201 			OSKextLog(/* kext */ NULL,
1202 			    kOSKextLogErrorLevel |
1203 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1204 			    "Can't copy __LINKEDIT segment for VM reassign.");
1205 			return result;
1206 		}
1207 		seg_copy_offset = (vm_map_offset_t) seg_copy;
1208 
1209 		/* Copy it out.
1210 		 */
1211 		memcpy(seg_copy, seg_data, seg_length);
1212 
1213 		/* Dump the booter memory.
1214 		 */
1215 		ml_static_mfree(seg_offset, seg_length);
1216 
1217 		/* Set up the VM region.
1218 		 */
1219 		mem_result = vm_map_enter_mem_object(
1220 			kernel_map,
1221 			&seg_offset,
1222 			seg_length, /* mask */ 0,
1223 			VM_MAP_KERNEL_FLAGS_FIXED(.vmf_overwrite = true),
1224 			(ipc_port_t)NULL,
1225 			(vm_object_offset_t) 0,
1226 			/* copy */ FALSE,
1227 			/* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
1228 			/* max_protection */ VM_PROT_ALL,
1229 			/* inheritance */ VM_INHERIT_DEFAULT);
1230 		if ((mem_result != KERN_SUCCESS) ||
1231 		    (seg_offset != (vm_map_offset_t) seg_data)) {
1232 			OSKextLog(/* kext */ NULL,
1233 			    kOSKextLogErrorLevel |
1234 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1235 			    "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1236 			    seg_data, seg_length, mem_result);
1237 			return result;
1238 		}
1239 
1240 		/* And copy it back.
1241 		 */
1242 		memcpy(seg_data, seg_copy, seg_length);
1243 
1244 		/* Free the copy.
1245 		 */
1246 		kmem_free(kernel_map, seg_copy_offset, seg_length);
1247 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1248 		/* Remove the linkedit segment of the Boot KC */
1249 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1250 		OSKext::jettisonFileSetLinkeditSegment(mh);
1251 	}
1252 #else // !VM_MAPPED_KEXTS
1253 	/*****
1254 	 * Dump the LINKEDIT segment, unless keepsyms is set.
1255 	 */
1256 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1257 		dt_segment_name = "Kernel-__LINKEDIT";
1258 		if (0 == IODTGetLoaderInfo(dt_segment_name,
1259 		    &segment_paddress, &segment_size)) {
1260 #ifdef SECURE_KERNEL
1261 			vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
1262 			bzero((void*)vmaddr, segment_size);
1263 #endif
1264 			IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1265 			    (int)segment_size);
1266 		}
1267 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1268 		/* Remove the linkedit segment of the Boot KC */
1269 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1270 		OSKext::jettisonFileSetLinkeditSegment(mh);
1271 	} else {
1272 		OSKextLog(/* kext */ NULL,
1273 		    kOSKextLogBasicLevel |
1274 		    kOSKextLogGeneralFlag,
1275 		    "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1276 	}
1277 #endif // VM_MAPPED_KEXTS
1278 
1279 	result = kOSReturnSuccess;
1280 
1281 	return result;
1282 }
1283 
1284 #if CONFIG_KXLD
1285 /*********************************************************************
1286 *********************************************************************/
1287 void
flushNonloadedKexts(Boolean flushPrelinkedKexts)1288 OSKext::flushNonloadedKexts(
1289 	Boolean flushPrelinkedKexts)
1290 {
1291 	OSSharedPtr<OSSet>                keepKexts;
1292 
1293 	/* TODO: make this more efficient with MH_FILESET kexts */
1294 
1295 	// Do not unload prelinked kexts on arm because the kernelcache is not
1296 	// structured in a way that allows them to be unmapped
1297 #if !defined(__x86_64__)
1298 	flushPrelinkedKexts = false;
1299 #endif /* defined(__x86_64__) */
1300 
1301 	IORecursiveLockLock(sKextLock);
1302 
1303 	OSKextLog(/* kext */ NULL,
1304 	    kOSKextLogProgressLevel |
1305 	    kOSKextLogKextBookkeepingFlag,
1306 	    "Flushing nonloaded kexts and other unused data.");
1307 
1308 	OSKext::considerDestroyingLinkContext();
1309 
1310 	/* If we aren't flushing unused prelinked kexts, we have to put them
1311 	 * aside while we flush everything else so make a container for them.
1312 	 */
1313 	keepKexts = OSSet::withCapacity(16);
1314 	if (!keepKexts) {
1315 		goto finish;
1316 	}
1317 
1318 	/* Set aside prelinked kexts (in-use or not) and break
1319 	 * any lingering inter-kext references for nonloaded kexts
1320 	 * so they have min. retain counts.
1321 	 */
1322 	{
1323 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1324 			OSKext * thisKext = OSDynamicCast(OSKext, obj);
1325 			if (!thisKext) {
1326 			        return false;
1327 			}
1328 			if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
1329 			        keepKexts->setObject(thisKext);
1330 			} else if (!thisKext->declaresExecutable()) {
1331 			        /*
1332 			         * Don't unload codeless kexts, because they never appear in the loadedKexts array.
1333 			         * Requesting one from the IOKit daemon will load it and then immediately remove it by calling
1334 			         * flushNonloadedKexts().
1335 			         * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
1336 			         */
1337 			        keepKexts->setObject(thisKext);
1338 			} else if (thisKext->isInFileset()) {
1339 			        /* keep all kexts in the new MH_FILESET KC */
1340 			        keepKexts->setObject(thisKext);
1341 			}
1342 
1343 			thisKext->flushDependencies(/* forceIfLoaded */ false);
1344 			return false;
1345 		});
1346 	}
1347 	/* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1348 	 */
1349 	sKextsByID->flushCollection();
1350 
1351 	/* Now put the loaded kexts back into the ID dictionary.
1352 	 */
1353 	sLoadedKexts->iterateObjects(^bool (OSObject * obj) {
1354 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1355 		if (!thisKext) {
1356 		        return false;
1357 		}
1358 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1359 		return false;
1360 	});
1361 
1362 	/* Finally, put back the kept kexts if we saved any.
1363 	 */
1364 	keepKexts->iterateObjects(^bool (OSObject * obj) {
1365 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1366 		if (!thisKext) {
1367 		        return false;
1368 		}
1369 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1370 		return false;
1371 	});
1372 
1373 finish:
1374 	IORecursiveLockUnlock(sKextLock);
1375 	return;
1376 }
1377 #else /* !CONFIG_KXLD */
1378 
1379 void
flushNonloadedKexts(Boolean flushPrelinkedKexts __unused)1380 OSKext::flushNonloadedKexts(
1381 	Boolean flushPrelinkedKexts __unused)
1382 {
1383 	IORecursiveLockLock(sKextLock);
1384 
1385 	OSKextLog(/* kext */ NULL,
1386 	    kOSKextLogProgressLevel |
1387 	    kOSKextLogKextBookkeepingFlag,
1388 	    "Flushing dependency info for non-loaded kexts.");
1389 
1390 	/*
1391 	 * In a world where we don't dynamically link kexts, they all come
1392 	 * from a kext collection that's either in wired memory, or
1393 	 * wire-on-demand. We don't need to mess around with moving kexts in
1394 	 * and out of the sKextsByID array - they can all just stay there.
1395 	 * Here we just flush the dependency list for kexts that are not
1396 	 * loaded.
1397 	 */
1398 	sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1399 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1400 		if (!thisKext) {
1401 		        return false;
1402 		}
1403 		thisKext->flushDependencies(/* forceIfLoaded */ false);
1404 		return false;
1405 	});
1406 
1407 	IORecursiveLockUnlock(sKextLock);
1408 	return;
1409 }
1410 
1411 #endif /* CONFIG_KXLD */
1412 
1413 /*********************************************************************
1414 *********************************************************************/
1415 /* static */
1416 void
setIOKitDaemonActive(bool active)1417 OSKext::setIOKitDaemonActive(bool active)
1418 {
1419 	IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
1420 	IORecursiveLockLock(sKextLock);
1421 	sIOKitDaemonActive = active;
1422 	if (sKernelRequests->getCount()) {
1423 		OSKext::pingIOKitDaemon();
1424 	}
1425 	IORecursiveLockUnlock(sKextLock);
1426 
1427 	return;
1428 }
1429 
1430 /*********************************************************************
1431 * OSKextLib.cpp might need access to this someday but for now it's
1432 * private.
1433 *********************************************************************/
1434 extern "C" {
1435 extern void ipc_port_release_send(ipc_port_t);
1436 };
1437 
1438 /* static */
1439 OSReturn
pingIOKitDaemon(void)1440 OSKext::pingIOKitDaemon(void)
1441 {
1442 	OSReturn    result     = kOSReturnError;
1443 #if !NO_KEXTD
1444 	mach_port_t kextd_port = IPC_PORT_NULL;
1445 
1446 	if (!sIOKitDaemonActive) {
1447 		result = kOSKextReturnDisabled; // basically unavailable
1448 		goto finish;
1449 	}
1450 
1451 	result = host_get_kextd_port(host_priv_self(), &kextd_port);
1452 	if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1453 		OSKextLog(/* kext */ NULL,
1454 		    kOSKextLogErrorLevel |
1455 		    kOSKextLogIPCFlag,
1456 		    "Can't get " kIOKitDaemonName " port.");
1457 		goto finish;
1458 	}
1459 
1460 	result = kextd_ping(kextd_port);
1461 	if (result != KERN_SUCCESS) {
1462 		OSKextLog(/* kext */ NULL,
1463 		    kOSKextLogErrorLevel |
1464 		    kOSKextLogIPCFlag,
1465 		    kIOKitDaemonName " ping failed (0x%x).", (int)result);
1466 		goto finish;
1467 	}
1468 
1469 finish:
1470 	if (IPC_PORT_VALID(kextd_port)) {
1471 		ipc_port_release_send(kextd_port);
1472 	}
1473 #endif
1474 
1475 	return result;
1476 }
1477 
1478 /*********************************************************************
1479 *********************************************************************/
1480 /* static */
1481 bool
iokitDaemonAvailable(void)1482 OSKext::iokitDaemonAvailable(void)
1483 {
1484 	int notused;
1485 	if (PE_parse_boot_argn("-restore", &notused, sizeof(notused))) {
1486 		return false;
1487 	}
1488 	return true;
1489 }
1490 
1491 /*********************************************************************
1492 *********************************************************************/
1493 /* static */
1494 void
setDeferredLoadSucceeded(Boolean succeeded)1495 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1496 {
1497 	IORecursiveLockLock(sKextLock);
1498 	sDeferredLoadSucceeded = succeeded;
1499 	IORecursiveLockUnlock(sKextLock);
1500 
1501 	return;
1502 }
1503 
1504 /*********************************************************************
1505 * Called from IOSystemShutdownNotification.
1506 *********************************************************************/
1507 /* static */
1508 void
willShutdown(void)1509 OSKext::willShutdown(void)
1510 {
1511 #if !NO_KEXTD
1512 	OSReturn       checkResult = kOSReturnError;
1513 #endif
1514 	OSSharedPtr<OSDictionary> exitRequest;
1515 
1516 	IORecursiveLockLock(sKextLock);
1517 
1518 	OSKext::setLoadEnabled(false);
1519 	OSKext::setUnloadEnabled(false);
1520 	OSKext::setAutounloadsEnabled(false);
1521 	OSKext::setKernelRequestsEnabled(false);
1522 
1523 #if defined(__x86_64__) || defined(__i386__)
1524 	if (IOPMRootDomainGetWillShutdown()) {
1525 		OSKext::freeKCFileSetcontrol();
1526 	}
1527 #endif // (__x86_64__) || defined(__i386__)
1528 
1529 #if !NO_KEXTD
1530 	OSKextLog(/* kext */ NULL,
1531 	    kOSKextLogProgressLevel |
1532 	    kOSKextLogGeneralFlag,
1533 	    "System shutdown; requesting immediate " kIOKitDaemonName " exit.");
1534 
1535 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit,
1536 	    exitRequest);
1537 	if (checkResult != kOSReturnSuccess) {
1538 		goto finish;
1539 	}
1540 	if (!sKernelRequests->setObject(exitRequest.get())) {
1541 		goto finish;
1542 	}
1543 
1544 	OSKext::pingIOKitDaemon();
1545 
1546 finish:
1547 #endif
1548 
1549 	IORecursiveLockUnlock(sKextLock);
1550 	return;
1551 }
1552 
1553 void
willUserspaceReboot(void)1554 OSKext::willUserspaceReboot(void)
1555 {
1556 	OSKext::willShutdown();
1557 	IOService::userSpaceWillReboot();
1558 	gIOCatalogue->terminateDriversForUserspaceReboot();
1559 }
1560 
1561 void
resetAfterUserspaceReboot(void)1562 OSKext::resetAfterUserspaceReboot(void)
1563 {
1564 	OSSharedPtr<OSArray> arr = OSArray::withCapacity(1);
1565 	IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */);
1566 
1567 	IORecursiveLockLock(sKextLock);
1568 	gIOCatalogue->resetAfterUserspaceReboot();
1569 	IOService::userSpaceDidReboot();
1570 	OSKext::removeDaemonExitRequests();
1571 	OSKext::setLoadEnabled(true);
1572 	OSKext::setUnloadEnabled(true);
1573 	OSKext::setAutounloadsEnabled(true);
1574 	OSKext::setKernelRequestsEnabled(true);
1575 	sOSKextWasResetAfterUserspaceReboot = true;
1576 	IORecursiveLockUnlock(sKextLock);
1577 }
1578 
1579 extern "C" void
OSKextResetAfterUserspaceReboot(void)1580 OSKextResetAfterUserspaceReboot(void)
1581 {
1582 	OSKext::resetAfterUserspaceReboot();
1583 }
1584 
1585 /*
1586  * Remove daemon exit requests from sKernelRequests
1587  *
1588  * If we sent a daemon exit request during a userspace reboot and launchd
1589  * killed the IOKit daemon before it was able to dequeue the exit request, the
1590  * next time the daemon starts up it will immediately exit as it gets the old exit request.
1591  *
1592  * This removes exit requests so that this does not happen.
1593  */
1594 void
removeDaemonExitRequests(void)1595 OSKext::removeDaemonExitRequests(void)
1596 {
1597 	OSDictionary * current = NULL;
1598 	OSString     * predicate = NULL;
1599 	size_t         index     = 0;
1600 	OSSharedPtr<const OSSymbol> predicateKey = OSSymbol::withCString(kKextRequestPredicateKey);
1601 
1602 	while (index < sKernelRequests->getCount()) {
1603 		current = OSDynamicCast(OSDictionary, sKernelRequests->getObject(index));
1604 		if (current) {
1605 			predicate = OSDynamicCast(OSString, current->getObject(predicateKey.get()));
1606 			if (predicate && predicate->isEqualTo(kKextRequestPredicateRequestDaemonExit)) {
1607 				sKernelRequests->removeObject(index);
1608 				continue;
1609 			}
1610 		}
1611 		index++;
1612 	}
1613 }
1614 
1615 /*********************************************************************
1616 *********************************************************************/
1617 /* static */
1618 bool
getLoadEnabled(void)1619 OSKext::getLoadEnabled(void)
1620 {
1621 	bool result;
1622 
1623 	IORecursiveLockLock(sKextLock);
1624 	result = sLoadEnabled;
1625 	IORecursiveLockUnlock(sKextLock);
1626 	return result;
1627 }
1628 
1629 /*********************************************************************
1630 *********************************************************************/
1631 /* static */
1632 bool
setLoadEnabled(bool flag)1633 OSKext::setLoadEnabled(bool flag)
1634 {
1635 	bool result;
1636 
1637 	IORecursiveLockLock(sKextLock);
1638 	result = sLoadEnabled;
1639 	sLoadEnabled = (flag ? true : false);
1640 
1641 	if (sLoadEnabled != result) {
1642 		OSKextLog(/* kext */ NULL,
1643 		    kOSKextLogBasicLevel |
1644 		    kOSKextLogLoadFlag,
1645 		    "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1646 	}
1647 
1648 	IORecursiveLockUnlock(sKextLock);
1649 
1650 	return result;
1651 }
1652 
1653 /*********************************************************************
1654 *********************************************************************/
1655 /* static */
1656 bool
getUnloadEnabled(void)1657 OSKext::getUnloadEnabled(void)
1658 {
1659 	bool result;
1660 
1661 	IORecursiveLockLock(sKextLock);
1662 	result = sUnloadEnabled;
1663 	IORecursiveLockUnlock(sKextLock);
1664 	return result;
1665 }
1666 
1667 /*********************************************************************
1668 *********************************************************************/
1669 /* static */
1670 bool
setUnloadEnabled(bool flag)1671 OSKext::setUnloadEnabled(bool flag)
1672 {
1673 	bool result;
1674 
1675 	IORecursiveLockLock(sKextLock);
1676 	result = sUnloadEnabled;
1677 	sUnloadEnabled = (flag ? true : false);
1678 	IORecursiveLockUnlock(sKextLock);
1679 
1680 	if (sUnloadEnabled != result) {
1681 		OSKextLog(/* kext */ NULL,
1682 		    kOSKextLogBasicLevel |
1683 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1684 		    "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1685 	}
1686 
1687 	return result;
1688 }
1689 
1690 /*********************************************************************
1691 * Do not call any function that takes sKextLock here!
1692 *********************************************************************/
1693 /* static */
1694 bool
getAutounloadEnabled(void)1695 OSKext::getAutounloadEnabled(void)
1696 {
1697 #if XNU_TARGET_OS_OSX
1698 	bool result;
1699 
1700 	IORecursiveLockLock(sKextInnerLock);
1701 	result = sAutounloadEnabled ? true : false;
1702 	IORecursiveLockUnlock(sKextInnerLock);
1703 	return result;
1704 #else
1705 	return false;
1706 #endif /* XNU_TARGET_OS_OSX */
1707 }
1708 
1709 /*********************************************************************
1710 * Do not call any function that takes sKextLock here!
1711 *********************************************************************/
1712 /* static */
1713 bool
setAutounloadsEnabled(bool flag)1714 OSKext::setAutounloadsEnabled(bool flag)
1715 {
1716 #if XNU_TARGET_OS_OSX
1717 	bool result;
1718 
1719 	IORecursiveLockLock(sKextInnerLock);
1720 
1721 	result = sAutounloadEnabled;
1722 	sAutounloadEnabled = (flag ? true : false);
1723 	if (!sAutounloadEnabled && sUnloadCallout) {
1724 		thread_call_cancel(sUnloadCallout);
1725 	}
1726 
1727 	if (sAutounloadEnabled != result) {
1728 		OSKextLog(/* kext */ NULL,
1729 		    kOSKextLogBasicLevel |
1730 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1731 		    "Kext autounloading now %sabled.",
1732 		    sAutounloadEnabled ? "en" : "dis");
1733 	}
1734 
1735 	IORecursiveLockUnlock(sKextInnerLock);
1736 
1737 	return result;
1738 #else
1739 	(void)flag;
1740 	return false;
1741 #endif /* XNU_TARGET_OS_OSX */
1742 }
1743 
1744 /*********************************************************************
1745 *********************************************************************/
1746 /* instance method operating on OSKext field */
1747 bool
setAutounloadEnabled(bool flag)1748 OSKext::setAutounloadEnabled(bool flag)
1749 {
1750 	bool result = flags.autounloadEnabled ? true : false;
1751 	flags.autounloadEnabled = flag ? (0 == flags.unloadUnsupported) : 0;
1752 
1753 	if (result != (flag ? true : false)) {
1754 		OSKextLog(this,
1755 		    kOSKextLogProgressLevel |
1756 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1757 		    "Autounloading for kext %s now %sabled.",
1758 		    getIdentifierCString(),
1759 		    flags.autounloadEnabled ? "en" : "dis");
1760 	}
1761 	return result;
1762 }
1763 
1764 /*********************************************************************
1765 *********************************************************************/
1766 /* static */
1767 bool
setKernelRequestsEnabled(bool flag)1768 OSKext::setKernelRequestsEnabled(bool flag)
1769 {
1770 	bool result;
1771 
1772 	IORecursiveLockLock(sKextLock);
1773 	result = sKernelRequestsEnabled;
1774 	sKernelRequestsEnabled = flag ? true : false;
1775 
1776 	if (sKernelRequestsEnabled != result) {
1777 		OSKextLog(/* kext */ NULL,
1778 		    kOSKextLogBasicLevel |
1779 		    kOSKextLogGeneralFlag,
1780 		    "Kernel requests now %sabled.",
1781 		    sKernelRequestsEnabled ? "en" : "dis");
1782 	}
1783 	IORecursiveLockUnlock(sKextLock);
1784 	return result;
1785 }
1786 
1787 /*********************************************************************
1788 *********************************************************************/
1789 /* static */
1790 bool
getKernelRequestsEnabled(void)1791 OSKext::getKernelRequestsEnabled(void)
1792 {
1793 	bool result;
1794 
1795 	IORecursiveLockLock(sKextLock);
1796 	result = sKernelRequestsEnabled;
1797 	IORecursiveLockUnlock(sKextLock);
1798 	return result;
1799 }
1800 
1801 static bool
segmentIsMutable(kernel_segment_command_t * seg)1802 segmentIsMutable(kernel_segment_command_t *seg)
1803 {
1804 	/* Mutable segments have to have VM_PROT_WRITE */
1805 	if ((seg->maxprot & VM_PROT_WRITE) == 0) {
1806 		return false;
1807 	}
1808 	/* Exclude the __DATA_CONST segment */
1809 	if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) {
1810 		return false;
1811 	}
1812 	/* Exclude __LINKEDIT */
1813 	if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) {
1814 		return false;
1815 	}
1816 	return true;
1817 }
1818 
1819 #if PRAGMA_MARK
1820 #pragma mark Kext Life Cycle
1821 #endif
1822 /*********************************************************************
1823 *********************************************************************/
1824 OSSharedPtr<OSKext>
withPrelinkedInfoDict(OSDictionary * anInfoDict,bool doCoalescedSlides,kc_kind_t type)1825 OSKext::withPrelinkedInfoDict(
1826 	OSDictionary * anInfoDict,
1827 	bool doCoalescedSlides,
1828 	kc_kind_t type)
1829 {
1830 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
1831 
1832 	if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) {
1833 		return NULL;
1834 	}
1835 
1836 	return newKext;
1837 }
1838 
1839 OSData *
parseDextUniqueID(OSDictionary * anInfoDict,const char * dextIDCS)1840 OSKext::parseDextUniqueID(
1841 	OSDictionary * anInfoDict,
1842 	const char *dextIDCS)
1843 {
1844 	OSData *ret = NULL;
1845 	OSData *data_duid = OSDynamicCast(OSData, anInfoDict->getObject(kOSBundleDextUniqueIdentifierKey));
1846 	if (data_duid != NULL) {
1847 		if (data_duid->getLength() > KOSBundleDextUniqueIdentifierMaxLength) {
1848 			OSKextLog(NULL,
1849 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
1850 			    "Dext %s DextUniqueIdentifier too long.",
1851 			    dextIDCS);
1852 		} else {
1853 			/*
1854 			 * If the DextUniqueID exists it should be
1855 			 * present also into the personalities.
1856 			 */
1857 			setDextUniqueIDInPersonalities(anInfoDict, data_duid);
1858 			ret = data_duid;
1859 		}
1860 	} else {
1861 		OSKextLog(NULL,
1862 		    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
1863 		    "Dext %s does not have a DextUniqueIdentifier",
1864 		    dextIDCS);
1865 	}
1866 	return ret;
1867 }
1868 
1869 void
setDextUniqueIDInPersonalities(OSDictionary * anInfoDict,OSData * dextUniqueID)1870 OSKext::setDextUniqueIDInPersonalities(
1871 	OSDictionary * anInfoDict,
1872 	OSData * dextUniqueID)
1873 {
1874 	OSDictionary * dextPersonalities = NULL;
1875 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
1876 	OSString * personalityName = NULL;
1877 
1878 	dextPersonalities = OSDynamicCast(OSDictionary,
1879 	    anInfoDict->getObject(kIOKitPersonalitiesKey));
1880 	if (!dextPersonalities || !dextPersonalities->getCount()) {
1881 		return;
1882 	}
1883 
1884 	personalitiesIterator =
1885 	    OSCollectionIterator::withCollection(dextPersonalities);
1886 	if (!personalitiesIterator) {
1887 		return;
1888 	}
1889 	while ((personalityName = OSDynamicCast(OSString,
1890 	    personalitiesIterator->getNextObject()))) {
1891 		OSDictionary * personality = OSDynamicCast(OSDictionary,
1892 		    dextPersonalities->getObject(personalityName));
1893 		if (personality) {
1894 			OSObject *duid = personality->getObject(kOSBundleDextUniqueIdentifierKey);
1895 			if (duid == NULL) {
1896 				personality->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID);
1897 			}
1898 		}
1899 	}
1900 }
1901 /*********************************************************************
1902 *********************************************************************/
1903 bool
initWithPrelinkedInfoDict(OSDictionary * anInfoDict,bool doCoalescedSlides,kc_kind_t type)1904 OSKext::initWithPrelinkedInfoDict(
1905 	OSDictionary * anInfoDict,
1906 	bool doCoalescedSlides,
1907 	kc_kind_t type)
1908 {
1909 	bool            result              = false;
1910 	OSString      * kextPath            = NULL;                // do not release
1911 	OSNumber      * addressNum          = NULL;                // reused; do not release
1912 	OSNumber      * lengthNum           = NULL;                // reused; do not release
1913 	OSBoolean     * scratchBool         = NULL;                // do not release
1914 	void          * data                = NULL;                // do not free
1915 	void          * srcData             = NULL;                // do not free
1916 	OSSharedPtr<OSData>        prelinkedExecutable;
1917 	uint32_t        length              = 0;                // reused
1918 	uintptr_t       kext_slide          = PE_get_kc_slide(type);
1919 	bool            shouldSaveSegments  = false;
1920 	kc_format     format                = KCFormatUnknown;
1921 
1922 	if (!super::init()) {
1923 		goto finish;
1924 	}
1925 
1926 	/* Get the path. Don't look for an arch-specific path property.
1927 	 */
1928 	kextPath = OSDynamicCast(OSString,
1929 	    anInfoDict->getObject(kPrelinkBundlePathKey));
1930 
1931 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
1932 		goto finish;
1933 	}
1934 
1935 #if KASLR_KEXT_DEBUG
1936 	IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString());
1937 #endif
1938 
1939 	/* Also get the executable's bundle-relative path if present.
1940 	 * Don't look for an arch-specific path property.
1941 	 */
1942 	executableRelPath.reset(OSDynamicCast(OSString,
1943 	    anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain);
1944 	userExecutableRelPath.reset(OSDynamicCast(OSString,
1945 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
1946 
1947 	/* Don't need the paths to be in the info dictionary any more.
1948 	 */
1949 	anInfoDict->removeObject(kPrelinkBundlePathKey);
1950 	anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
1951 
1952 	scratchBool = OSDynamicCast(OSBoolean,
1953 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
1954 	if (scratchBool == kOSBooleanTrue) {
1955 		flags.requireExplicitLoad = 1;
1956 	}
1957 
1958 	/* Create an OSData wrapper around the linked executable.
1959 	 */
1960 	addressNum = OSDynamicCast(OSNumber,
1961 	    anInfoDict->getObject(kPrelinkExecutableLoadKey));
1962 	if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) {
1963 		lengthNum = OSDynamicCast(OSNumber,
1964 		    anInfoDict->getObject(kPrelinkExecutableSizeKey));
1965 		if (!lengthNum) {
1966 			OSKextLog(this,
1967 			    kOSKextLogErrorLevel |
1968 			    kOSKextLogArchiveFlag,
1969 			    "Kext %s can't find prelinked kext executable size.",
1970 			    getIdentifierCString());
1971 			return result;
1972 		}
1973 
1974 		data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1975 		length = (uint32_t) (lengthNum->unsigned32BitValue());
1976 
1977 #if KASLR_KEXT_DEBUG
1978 		IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1979 		    (unsigned long)ml_static_unslide((vm_offset_t)data),
1980 		    (unsigned long)data,
1981 		    length);
1982 #endif
1983 
1984 		anInfoDict->removeObject(kPrelinkExecutableLoadKey);
1985 		anInfoDict->removeObject(kPrelinkExecutableSizeKey);
1986 
1987 		/* If the kext's load address differs from its source address, allocate
1988 		 * space in the kext map at the load address and copy the kext over.
1989 		 */
1990 		addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
1991 		if (addressNum) {
1992 			srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1993 
1994 #if KASLR_KEXT_DEBUG
1995 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1996 			    (unsigned long)ml_static_unslide((vm_offset_t)srcData),
1997 			    (unsigned long)srcData);
1998 #endif
1999 
2000 			if (data != srcData) {
2001 #if __LP64__
2002 				kern_return_t alloc_result;
2003 
2004 				alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
2005 				if (alloc_result != KERN_SUCCESS) {
2006 					OSKextLog(this,
2007 					    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2008 					    "Failed to allocate space for prelinked kext %s.",
2009 					    getIdentifierCString());
2010 					goto finish;
2011 				}
2012 				memcpy(data, srcData, length);
2013 #else
2014 				OSKextLog(this,
2015 				    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2016 				    "Error: prelinked kext %s - source and load addresses "
2017 				    "differ on ILP32 architecture.",
2018 				    getIdentifierCString());
2019 				goto finish;
2020 #endif /* __LP64__ */
2021 			}
2022 
2023 			anInfoDict->removeObject(kPrelinkExecutableSourceKey);
2024 		}
2025 
2026 		prelinkedExecutable = OSData::withBytesNoCopy(data, length);
2027 		if (!prelinkedExecutable) {
2028 			OSKextLog(this,
2029 			    kOSKextLogErrorLevel |
2030 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
2031 			    "Kext %s failed to create executable wrapper.",
2032 			    getIdentifierCString());
2033 			goto finish;
2034 		}
2035 
2036 		/*
2037 		 * Fileset KCs are mapped as a whole by iBoot.
2038 		 * Individual kext executables should not be unmapped
2039 		 * by xnu.
2040 		 * Doing so may result in panics like rdar://85419651
2041 		 */
2042 		if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
2043 			prelinkedExecutable->setDeallocFunction(NULL);
2044 		} else { // Not from a Fileset KC
2045 #if VM_MAPPED_KEXTS
2046 			prelinkedExecutable->setDeallocFunction(osdata_kext_free);
2047 #else
2048 			prelinkedExecutable->setDeallocFunction(osdata_phys_free);
2049 #endif
2050 		}
2051 		setLinkedExecutable(prelinkedExecutable.get());
2052 		addressNum = OSDynamicCast(OSNumber,
2053 		    anInfoDict->getObject(kPrelinkKmodInfoKey));
2054 		if (!addressNum) {
2055 			OSKextLog(this,
2056 			    kOSKextLogErrorLevel |
2057 			    kOSKextLogArchiveFlag,
2058 			    "Kext %s can't find prelinked kext kmod_info address.",
2059 			    getIdentifierCString());
2060 			goto finish;
2061 		}
2062 
2063 		if (addressNum->unsigned64BitValue() != 0) {
2064 			kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
2065 			if (kmod_info->address) {
2066 				kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide);
2067 			} else {
2068 				kmod_info->address = (uintptr_t)data;
2069 				kmod_info->size = length;
2070 			}
2071 #if KASLR_KEXT_DEBUG
2072 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
2073 			    (unsigned long)((vm_offset_t)kmod_info) - kext_slide,
2074 			    (unsigned long)kmod_info);
2075 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
2076 			    (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide,
2077 			    (unsigned long)kmod_info->address);
2078  #endif
2079 		}
2080 
2081 		anInfoDict->removeObject(kPrelinkKmodInfoKey);
2082 	}
2083 
2084 	if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) {
2085 		uintptr_t builtinTextStart;
2086 		uintptr_t builtinTextEnd;
2087 
2088 		flags.builtin = true;
2089 		builtinKmodIdx = addressNum->unsigned32BitValue();
2090 		assert(builtinKmodIdx < gBuiltinKmodsCount);
2091 
2092 		builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx];
2093 		builtinTextEnd   = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1];
2094 
2095 		kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx];
2096 		kmod_info->address = builtinTextStart;
2097 		kmod_info->size    = builtinTextEnd - builtinTextStart;
2098 	}
2099 
2100 	/* If the plist has a UUID for an interface, save that off.
2101 	 */
2102 	if (isInterface()) {
2103 		interfaceUUID.reset(OSDynamicCast(OSData,
2104 		    anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain);
2105 		if (interfaceUUID) {
2106 			anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
2107 		}
2108 	}
2109 
2110 	result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides));
2111 	if (!result) {
2112 		goto finish;
2113 	}
2114 
2115 	kc_type = type;
2116 	/* Exclude builtin and codeless kexts */
2117 	if (prelinkedExecutable && kmod_info) {
2118 		switch (kc_type) {
2119 		case KCKindPrimary:
2120 			shouldSaveSegments = (
2121 				getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue ||
2122 				getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue);
2123 			if (shouldSaveSegments) {
2124 				flags.resetSegmentsFromImmutableCopy = 1;
2125 			} else {
2126 				flags.unloadUnsupported = 1;
2127 			}
2128 			break;
2129 		case KCKindPageable:
2130 			flags.resetSegmentsFromVnode = 1;
2131 			break;
2132 		case KCKindAuxiliary:
2133 			if (!pageableKCloaded) {
2134 				flags.resetSegmentsFromImmutableCopy = 1;
2135 			} else if (resetAuxKCSegmentOnUnload) {
2136 				flags.resetSegmentsFromVnode = 1;
2137 			} else {
2138 				flags.unloadUnsupported = 1;
2139 			}
2140 			break;
2141 		default:
2142 			break;
2143 		}
2144 	}
2145 
2146 	if (flags.resetSegmentsFromImmutableCopy) {
2147 		/* Save a pristine copy of the mutable segments */
2148 		kernel_segment_command_t *seg = NULL;
2149 		kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
2150 
2151 		savedMutableSegments = OSArray::withCapacity(0);
2152 
2153 		for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) {
2154 			if (!segmentIsMutable(seg)) {
2155 				continue;
2156 			}
2157 			uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
2158 			uint64_t vmsize = seg->vmsize;
2159 			OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2160 			    "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2161 			OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg);
2162 			if (!savedSegment) {
2163 				OSKextLog(this,
2164 				    kOSKextLogErrorLevel |
2165 				    kOSKextLogGeneralFlag,
2166 				    "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2167 				result = false;
2168 				goto finish;
2169 			}
2170 			savedMutableSegments->setObject(savedSegment);
2171 		}
2172 	}
2173 
2174 	if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) {
2175 		/*
2176 		 * set VM protections now, wire pages for the old style Aux KC now,
2177 		 * wire pages for the rest of the KC types at load time.
2178 		 */
2179 		result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false));
2180 		if (!result) {
2181 			goto finish;
2182 		}
2183 	}
2184 
2185 	flags.prelinked = true;
2186 
2187 	if (isDriverKit()) {
2188 		dextStatistics = OSDextStatistics::create();
2189 		dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
2190 		dextLaunchedCount = 0;
2191 	}
2192 
2193 	/* If we created a kext from prelink info,
2194 	 * we must be booting from a prelinked kernel.
2195 	 */
2196 	sPrelinkBoot = true;
2197 
2198 	result = (registerIdentifier() == kOSKextInitialized);
2199 finish:
2200 	return result;
2201 }
2202 
2203 /*********************************************************************
2204 *********************************************************************/
2205 /* static */
2206 OSSharedPtr<OSKext>
withCodelessInfo(OSDictionary * anInfoDict,OSKextInitResult * result)2207 OSKext::withCodelessInfo(OSDictionary * anInfoDict, OSKextInitResult *result)
2208 {
2209 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
2210 	if (!newKext) {
2211 		return NULL;
2212 	}
2213 
2214 	OSKextInitResult ret = newKext->initWithCodelessInfo(anInfoDict);
2215 	if (result != NULL) {
2216 		*result = ret;
2217 	}
2218 	if (ret != kOSKextInitialized) {
2219 		return NULL;
2220 	}
2221 
2222 	return newKext;
2223 }
2224 
2225 /*********************************************************************
2226 *********************************************************************/
2227 OSKextInitResult
initWithCodelessInfo(OSDictionary * anInfoDict)2228 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict)
2229 {
2230 	OSKextInitResult result          = kOSKextInitFailure;
2231 	OSString  * kextPath             = NULL;        // do not release
2232 	OSBoolean * scratchBool          = NULL;        // do not release
2233 
2234 	if (anInfoDict == NULL || !super::init()) {
2235 		goto finish;
2236 	}
2237 
2238 	/*
2239 	 * Get the path. Don't look for an arch-specific path property.
2240 	 */
2241 	kextPath = OSDynamicCast(OSString,
2242 	    anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey));
2243 	if (!kextPath) {
2244 		OSKextLog(NULL,
2245 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2246 		    "Requested codeless kext dictionary does not contain the '%s' key",
2247 		    kKextRequestArgumentCodelessInfoBundlePathKey);
2248 		goto finish;
2249 	}
2250 
2251 	uniquePersonalityProperties(anInfoDict);
2252 
2253 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2254 		goto finish;
2255 	}
2256 
2257 	/*
2258 	 * This path is meant to initialize codeless kexts only. Refuse
2259 	 * anything that looks like it has an executable and/or declares
2260 	 * itself as a kernel component.
2261 	 */
2262 	if (declaresExecutable() || isKernelComponent()) {
2263 		OSKextLog(NULL,
2264 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2265 		    "Refusing to register codeless kext that declares an executable/kernel component: %s",
2266 		    getIdentifierCString());
2267 		goto finish;
2268 	}
2269 
2270 	if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
2271 		boolean_t updated = updateExcludeList(infoDict.get());
2272 		if (updated) {
2273 			OSKextLog(this,
2274 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2275 			    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
2276 		}
2277 	}
2278 
2279 	kc_type = KCKindNone;
2280 
2281 	scratchBool = OSDynamicCast(OSBoolean,
2282 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
2283 	if (scratchBool == kOSBooleanTrue) {
2284 		flags.requireExplicitLoad = 1;
2285 	}
2286 
2287 	/* Also get the executable's bundle-relative path if present.
2288 	 * Don't look for an arch-specific path property.
2289 	 */
2290 	userExecutableRelPath.reset(OSDynamicCast(OSString,
2291 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
2292 
2293 	/* remove unnecessary paths from the info dict */
2294 	anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey);
2295 
2296 	if (isDriverKit()) {
2297 		dextStatistics = OSDextStatistics::create();
2298 		dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
2299 		dextLaunchedCount = 0;
2300 	}
2301 
2302 	result = registerIdentifier();
2303 
2304 finish:
2305 	return result;
2306 }
2307 
2308 /*********************************************************************
2309 *********************************************************************/
2310 /* static */
2311 void
setAllVMAttributes(void)2312 OSKext::setAllVMAttributes(void)
2313 {
2314 	OSSharedPtr<OSCollectionIterator> kextIterator;
2315 	const OSSymbol * thisID                 = NULL;        // do not release
2316 
2317 	IORecursiveLockLock(sKextLock);
2318 
2319 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
2320 	if (!kextIterator) {
2321 		goto finish;
2322 	}
2323 
2324 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
2325 		OSKext *    thisKext;        // do not release
2326 
2327 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
2328 		if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
2329 			continue;
2330 		}
2331 
2332 		if (!thisKext->flags.resetSegmentsFromVnode) {
2333 			/*
2334 			 * set VM protections now, wire pages for the old style Aux KC now,
2335 			 * wire pages for the rest of the KC types at load time.
2336 			 */
2337 			thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false);
2338 		}
2339 	}
2340 
2341 finish:
2342 	IORecursiveLockUnlock(sKextLock);
2343 
2344 	return;
2345 }
2346 
2347 /*********************************************************************
2348 *********************************************************************/
2349 OSSharedPtr<OSKext>
withBooterData(OSString * deviceTreeName,OSData * booterData)2350 OSKext::withBooterData(
2351 	OSString * deviceTreeName,
2352 	OSData   * booterData)
2353 {
2354 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
2355 
2356 	if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
2357 		return NULL;
2358 	}
2359 
2360 	return newKext;
2361 }
2362 
2363 /*********************************************************************
2364 *********************************************************************/
2365 typedef struct _BooterKextFileInfo {
2366 	uint32_t  infoDictPhysAddr;
2367 	uint32_t  infoDictLength;
2368 	uint32_t  executablePhysAddr;
2369 	uint32_t  executableLength;
2370 	uint32_t  bundlePathPhysAddr;
2371 	uint32_t  bundlePathLength;
2372 } _BooterKextFileInfo;
2373 
2374 bool
initWithBooterData(OSString * deviceTreeName,OSData * booterData)2375 OSKext::initWithBooterData(
2376 	OSString * deviceTreeName,
2377 	OSData   * booterData)
2378 {
2379 	bool                  result         = false;
2380 	_BooterKextFileInfo * kextFileInfo   = NULL;        // do not free
2381 	char                * infoDictAddr   = NULL;        // do not free
2382 	void                * executableAddr = NULL;        // do not free
2383 	char                * bundlePathAddr = NULL;        // do not free
2384 
2385 	OSDictionary        * theInfoDict    = NULL;        // do not release
2386 	OSSharedPtr<OSObject> parsedXML;
2387 	OSSharedPtr<OSString> kextPath;
2388 
2389 	OSSharedPtr<OSString> errorString;
2390 	OSSharedPtr<OSData>   executable;
2391 
2392 	if (!super::init()) {
2393 		goto finish;
2394 	}
2395 
2396 	kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
2397 	if (!kextFileInfo) {
2398 		OSKextLog(this,
2399 		    kOSKextLogErrorLevel |
2400 		    kOSKextLogGeneralFlag,
2401 		    "No booter-provided data for kext device tree entry %s.",
2402 		    deviceTreeName->getCStringNoCopy());
2403 		goto finish;
2404 	}
2405 
2406 	/* The info plist must exist or we can't read the kext.
2407 	 */
2408 	if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
2409 		OSKextLog(this,
2410 		    kOSKextLogErrorLevel |
2411 		    kOSKextLogGeneralFlag,
2412 		    "No kext info dictionary for booter device tree entry %s.",
2413 		    deviceTreeName->getCStringNoCopy());
2414 		goto finish;
2415 	}
2416 
2417 	infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
2418 	if (!infoDictAddr) {
2419 		OSKextLog(this,
2420 		    kOSKextLogErrorLevel |
2421 		    kOSKextLogGeneralFlag,
2422 		    "Can't translate physical address 0x%x of kext info dictionary "
2423 		    "for device tree entry %s.",
2424 		    (int)kextFileInfo->infoDictPhysAddr,
2425 		    deviceTreeName->getCStringNoCopy());
2426 		goto finish;
2427 	}
2428 
2429 	parsedXML = OSUnserializeXML(infoDictAddr, errorString);
2430 	if (parsedXML) {
2431 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
2432 	}
2433 	if (!theInfoDict) {
2434 		const char * errorCString = "(unknown error)";
2435 
2436 		if (errorString && errorString->getCStringNoCopy()) {
2437 			errorCString = errorString->getCStringNoCopy();
2438 		} else if (parsedXML) {
2439 			errorCString = "not a dictionary";
2440 		}
2441 		OSKextLog(this,
2442 		    kOSKextLogErrorLevel |
2443 		    kOSKextLogGeneralFlag,
2444 		    "Error unserializing info dictionary for device tree entry %s: %s.",
2445 		    deviceTreeName->getCStringNoCopy(), errorCString);
2446 		goto finish;
2447 	}
2448 
2449 	/* A bundle path is not mandatory.
2450 	 */
2451 	if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
2452 		bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
2453 		if (!bundlePathAddr) {
2454 			OSKextLog(this,
2455 			    kOSKextLogErrorLevel |
2456 			    kOSKextLogGeneralFlag,
2457 			    "Can't translate physical address 0x%x of kext bundle path "
2458 			    "for device tree entry %s.",
2459 			    (int)kextFileInfo->bundlePathPhysAddr,
2460 			    deviceTreeName->getCStringNoCopy());
2461 			goto finish;
2462 		}
2463 		bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0';         // just in case!
2464 
2465 		kextPath = OSString::withCString(bundlePathAddr);
2466 		if (!kextPath) {
2467 			OSKextLog(this,
2468 			    kOSKextLogErrorLevel |
2469 			    kOSKextLogGeneralFlag,
2470 			    "Failed to create wrapper for device tree entry %s kext path %s.",
2471 			    deviceTreeName->getCStringNoCopy(), bundlePathAddr);
2472 			goto finish;
2473 		}
2474 	}
2475 
2476 	if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) {
2477 		goto finish;
2478 	}
2479 
2480 	/* An executable is not mandatory.
2481 	 */
2482 	if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
2483 		executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
2484 		if (!executableAddr) {
2485 			OSKextLog(this,
2486 			    kOSKextLogErrorLevel |
2487 			    kOSKextLogGeneralFlag,
2488 			    "Can't translate physical address 0x%x of kext executable "
2489 			    "for device tree entry %s.",
2490 			    (int)kextFileInfo->executablePhysAddr,
2491 			    deviceTreeName->getCStringNoCopy());
2492 			goto finish;
2493 		}
2494 
2495 		executable = OSData::withBytesNoCopy(executableAddr,
2496 		    kextFileInfo->executableLength);
2497 		if (!executable) {
2498 			OSKextLog(this,
2499 			    kOSKextLogErrorLevel |
2500 			    kOSKextLogGeneralFlag,
2501 			    "Failed to create executable wrapper for device tree entry %s.",
2502 			    deviceTreeName->getCStringNoCopy());
2503 			goto finish;
2504 		}
2505 
2506 		/* A kext with an executable needs to retain the whole booterData
2507 		 * object to keep the executable in memory.
2508 		 */
2509 		if (!setExecutable(executable.get(), booterData)) {
2510 			OSKextLog(this,
2511 			    kOSKextLogErrorLevel |
2512 			    kOSKextLogGeneralFlag,
2513 			    "Failed to set kext executable for device tree entry %s.",
2514 			    deviceTreeName->getCStringNoCopy());
2515 			goto finish;
2516 		}
2517 	}
2518 
2519 	if (isDriverKit()) {
2520 		dextStatistics = OSDextStatistics::create();
2521 		dextUniqueID.reset(parseDextUniqueID(theInfoDict, getIdentifierCString()), OSRetain);
2522 		dextLaunchedCount = 0;
2523 	}
2524 
2525 	result = (registerIdentifier() == kOSKextInitialized);
2526 
2527 finish:
2528 	return result;
2529 }
2530 
2531 /*********************************************************************
2532 *********************************************************************/
2533 OSKextInitResult
registerIdentifier(void)2534 OSKext::registerIdentifier(void)
2535 {
2536 	OSKextInitResult  result                  = kOSKextInitFailure;
2537 	OSKext        * existingKext              = NULL;        // do not release
2538 	bool            existingIsLoaded          = false;
2539 	bool            existingIsPrelinked       = false;
2540 	bool            existingIsCodeless        = false;
2541 	bool            existingIsDext            = false;
2542 	OSKextVersion   newVersion                = -1;
2543 	OSKextVersion   existingVersion           = -1;
2544 	char            newVersionCString[kOSKextVersionMaxLength];
2545 	char            existingVersionCString[kOSKextVersionMaxLength];
2546 	OSSharedPtr<OSData> newUUID;
2547 	OSSharedPtr<OSData> existingUUID;
2548 	const char *newDextUniqueIDCString = NULL;
2549 	const char *existingDextUniqueIDCString = NULL;
2550 	unsigned int newDextUniqueIDCStringSize = 0;
2551 	unsigned int existingDextUniqueIDCStringSize = 0;
2552 
2553 	IORecursiveLockLock(sKextLock);
2554 
2555 	/* Get the new kext's version for checks & log messages.
2556 	 */
2557 	newVersion = getVersion();
2558 	OSKextVersionGetString(newVersion, newVersionCString,
2559 	    kOSKextVersionMaxLength);
2560 
2561 	/* If we don't have an existing kext with this identifier,
2562 	 * just record the new kext and we're done!
2563 	 */
2564 	existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get()));
2565 	if (!existingKext) {
2566 		sKextsByID->setObject(bundleID.get(), this);
2567 		result = kOSKextInitialized;
2568 		goto finish;
2569 	}
2570 
2571 	/* Get the existing kext's version for checks & log messages.
2572 	 */
2573 	existingVersion = existingKext->getVersion();
2574 	OSKextVersionGetString(existingVersion,
2575 	    existingVersionCString, kOSKextVersionMaxLength);
2576 
2577 	existingIsLoaded = existingKext->isLoaded();
2578 	existingIsPrelinked = existingKext->isPrelinked();
2579 	existingIsDext = existingKext->isDriverKit();
2580 	existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext;
2581 
2582 	/*
2583 	 * Check if we are trying to upgrade a dext
2584 	 * with another dext.
2585 	 */
2586 	if (isDriverKit() && existingIsDext) {
2587 		OSData *newDextUID = getDextUniqueID();
2588 		if (!newDextUID) {
2589 			OSKextLog(this,
2590 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2591 			    "New dext %s, v%s requested does not have a unique dext identifier\n",
2592 			    getIdentifierCString(), newVersionCString);
2593 			goto finish;
2594 		}
2595 		newDextUniqueIDCString = getDextUniqueIDCString(newDextUID, &newDextUniqueIDCStringSize);
2596 		assert(newDextUniqueIDCString != NULL);
2597 
2598 		OSData *existingDextUID = existingKext->getDextUniqueID();
2599 		if (!existingDextUID) {
2600 			OSKextLog(this,
2601 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2602 			    "Found a dext %s, v%s: with no unique dext identifier\n",
2603 			    existingKext->getIdentifierCString(), existingVersionCString);
2604 			goto finish;
2605 		}
2606 		existingDextUniqueIDCString = getDextUniqueIDCString(existingDextUID, &existingDextUniqueIDCStringSize);
2607 		assert(existingDextUniqueIDCString != NULL);
2608 
2609 		/*
2610 		 * We might get multiple requests to save the same dext.
2611 		 * Check if we already have saved it or if this is an upgrade
2612 		 * for a dext with the same BundleID.
2613 		 * Dexts are uniquely identified by DextUniqueID, if a new DextUniqueID
2614 		 * is requested for a BundleID we are going to upgrade to the newest
2615 		 * received irrespective from the dext version.
2616 		 */
2617 		if (newDextUID->isEqualTo(existingDextUID) && existingKext->flags.dextToReplace == 0) {
2618 			OSKextLog(this,
2619 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2620 			    "Refusing new dext %s, v%s:"
2621 			    "a dext v %s with the same unique dext identifier (%s) already exists\n",
2622 			    getIdentifierCString(), newVersionCString,
2623 			    existingVersionCString, newDextUniqueIDCString);
2624 			result = kOSKextAlreadyExist;
2625 			goto finish;
2626 		}
2627 
2628 		bool upgraded = upgradeDext(existingKext, this);
2629 		if (upgraded) {
2630 			/* If the dext was upgraded existingKext might have been deallocated */
2631 			existingKext = NULL;
2632 			OSKextLog(this,
2633 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2634 			    "Dext %s, v%s , unique dext identifier %s "
2635 			    "Upgraded to v%s, unique dext identifier %s \n",
2636 			    getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
2637 			    newVersionCString, newDextUniqueIDCString);
2638 			result = kOSKextInitialized;
2639 		} else {
2640 			OSKextLog(this,
2641 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2642 			    "Upgrade delayed for %s v%s, unique dext identifier %s "
2643 			    "with v%s, unique dext identifier %s.\n",
2644 			    getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
2645 			    newVersionCString, newDextUniqueIDCString);
2646 			result = kOSKextAlreadyExist;
2647 		}
2648 
2649 		goto finish;
2650 	}
2651 
2652 	/* If we have a non-codeless kext with this identifier that's already
2653 	 * loaded/prelinked, we can't use the new one, but let's be really
2654 	 * thorough and check how the two are related for a precise diagnostic
2655 	 * log message.
2656 	 *
2657 	 * This check is valid for kexts that declare an executable and for
2658 	 * dexts, but not for codeless kexts - we can just replace those.
2659 	 */
2660 	if ((!existingIsCodeless || existingIsDext) &&
2661 	    (existingIsLoaded || existingIsPrelinked)) {
2662 		bool sameVersion = (newVersion == existingVersion);
2663 		bool sameExecutable = true;         // assume true unless we have UUIDs
2664 
2665 		/* Only get the UUID if the existing kext is loaded. Doing so
2666 		 * might have to uncompress an mkext executable and we shouldn't
2667 		 * take that hit when neither kext is loaded.
2668 		 *
2669 		 * Note: there is no decompression that happens when all kexts
2670 		 * are loaded from kext collecitons.
2671 		 */
2672 		newUUID = copyUUID();
2673 		existingUUID = existingKext->copyUUID();
2674 
2675 		if (existingIsDext && !isDriverKit()) {
2676 			OSKextLog(this,
2677 			    kOSKextLogWarningLevel |
2678 			    kOSKextLogKextBookkeepingFlag,
2679 			    "Notice - new kext %s, v%s matches a %s dext"
2680 			    "with the same bundle ID, v%s.",
2681 			    getIdentifierCString(), newVersionCString,
2682 			    (existingIsLoaded ? "loaded" : "prelinked"),
2683 			    existingVersionCString);
2684 			goto finish;
2685 		}
2686 
2687 		/* I'm entirely too paranoid about checking equivalence of executables,
2688 		 * but I remember nasty problems with it in the past.
2689 		 *
2690 		 * - If we have UUIDs for both kexts, compare them.
2691 		 * - If only one kext has a UUID, they're definitely different.
2692 		 */
2693 		if (newUUID && existingUUID) {
2694 			sameExecutable = newUUID->isEqualTo(existingUUID.get());
2695 		} else if (newUUID || existingUUID) {
2696 			sameExecutable = false;
2697 		}
2698 
2699 		if (!newUUID && !existingUUID) {
2700 			/* If there are no UUIDs, we can't really tell that the executables
2701 			 * are *different* without a lot of work; the loaded kext's
2702 			 * unrelocated executable is no longer around (and we never had it
2703 			 * in-kernel for a prelinked kext). We certainly don't want to do
2704 			 * a whole fake link for the new kext just to compare, either.
2705 			 */
2706 			OSKextLog(this,
2707 			    kOSKextLogWarningLevel |
2708 			    kOSKextLogKextBookkeepingFlag,
2709 			    "Notice - new kext %s, v%s matches %s kext "
2710 			    "but can't determine if executables are the same (no UUIDs).",
2711 			    getIdentifierCString(),
2712 			    newVersionCString,
2713 			    (existingIsLoaded ? "loaded" : "prelinked"));
2714 		}
2715 
2716 		if (sameVersion && sameExecutable) {
2717 			OSKextLog(this,
2718 			    (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
2719 			    kOSKextLogKextBookkeepingFlag,
2720 			    "Refusing new kext %s, v%s: a %s copy is already present "
2721 			    "(same version and executable).",
2722 			    getIdentifierCString(), newVersionCString,
2723 			    (existingIsLoaded ? "loaded" : "prelinked"));
2724 		} else {
2725 			if (!sameVersion) {
2726 				/* This condition is significant so log it under warnings.
2727 				 */
2728 				OSKextLog(this,
2729 				    kOSKextLogWarningLevel |
2730 				    kOSKextLogKextBookkeepingFlag,
2731 				    "Refusing new kext %s, v%s: already have %s v%s.",
2732 				    getIdentifierCString(),
2733 				    newVersionCString,
2734 				    (existingIsLoaded ? "loaded" : "prelinked"),
2735 				    existingVersionCString);
2736 			} else {
2737 				/* This condition is significant so log it under warnings.
2738 				 */
2739 				OSKextLog(this,
2740 				    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2741 				    "Refusing new kext %s, v%s: a %s copy with a different "
2742 				    "executable UUID is already present.",
2743 				    getIdentifierCString(), newVersionCString,
2744 				    (existingIsLoaded ? "loaded" : "prelinked"));
2745 			}
2746 		}
2747 		goto finish;
2748 	} /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */
2749 
2750 	/* Refuse to allow an existing loaded codeless kext be replaced by a
2751 	 * normal kext with the same bundle ID.
2752 	 */
2753 	if (existingIsCodeless && declaresExecutable()) {
2754 		OSKextLog(this,
2755 		    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2756 		    "Refusing new kext %s, v%s: a codeless copy is already %s",
2757 		    getIdentifierCString(), newVersionCString,
2758 		    (existingIsLoaded ? "loaded" : "prelinked"));
2759 		goto finish;
2760 	}
2761 
2762 	/* Dexts packaged in the BootKC will be protected against replacement
2763 	 * by non-dexts by the logic above which checks if they are prelinked.
2764 	 * Dexts which are prelinked into the System KC will be registered
2765 	 * before any other kexts in the AuxKC are registered, and we never
2766 	 * put dexts in the AuxKC. Therefore, there is no need to check if an
2767 	 * existing object is a dext and is being replaced by a non-dext.
2768 	 * The scenario cannot happen by construction.
2769 	 *
2770 	 * See: OSKext::loadFileSetKexts()
2771 	 */
2772 
2773 
2774 	/* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2775 	 * user loads are happening or if we're still in early boot. User agents are
2776 	 * supposed to resolve dependencies topside and include only the exact
2777 	 * kexts needed; so we always accept the new kext (in fact we should never
2778 	 * see an older unloaded copy hanging around).
2779 	 */
2780 	if (sUserLoadsActive) {
2781 		sKextsByID->setObject(bundleID.get(), this);
2782 		result = kOSKextInitialized;
2783 
2784 		OSKextLog(this,
2785 		    kOSKextLogStepLevel |
2786 		    kOSKextLogKextBookkeepingFlag,
2787 		    "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2788 		    getIdentifierCString(),
2789 		    existingVersionCString,
2790 		    newVersionCString);
2791 
2792 		goto finish;
2793 	}
2794 
2795 	/* During early boot, the kext with the highest version always wins out.
2796 	 * Prelinked kernels will never hit this, but mkexts and booter-read
2797 	 * kexts might have duplicates.
2798 	 */
2799 	if (newVersion > existingVersion) {
2800 		sKextsByID->setObject(bundleID.get(), this);
2801 		result = kOSKextInitialized;
2802 
2803 		OSKextLog(this,
2804 		    kOSKextLogStepLevel |
2805 		    kOSKextLogKextBookkeepingFlag,
2806 		    "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2807 		    existingVersionCString,
2808 		    getIdentifierCString(),
2809 		    newVersionCString);
2810 	} else {
2811 		OSKextLog(this,
2812 		    kOSKextLogStepLevel |
2813 		    kOSKextLogKextBookkeepingFlag,
2814 		    "Kext %s is already registered with a higher/same version (v%s); "
2815 		    "dropping newly-added (v%s).",
2816 		    getIdentifierCString(),
2817 		    existingVersionCString,
2818 		    newVersionCString);
2819 	}
2820 
2821 	/* result has been set appropriately by now. */
2822 
2823 finish:
2824 
2825 	IORecursiveLockUnlock(sKextLock);
2826 
2827 	if (newDextUniqueIDCString != NULL) {
2828 		kfree_data(newDextUniqueIDCString, newDextUniqueIDCStringSize);
2829 	}
2830 	if (existingDextUniqueIDCString != NULL) {
2831 		kfree_data(existingDextUniqueIDCString, existingDextUniqueIDCStringSize);
2832 	}
2833 
2834 	if (result == kOSKextInitialized) {
2835 		OSKextLog(this,
2836 		    kOSKextLogStepLevel |
2837 		    kOSKextLogKextBookkeepingFlag,
2838 		    "Kext %s, v%s registered and available for loading.",
2839 		    getIdentifierCString(), newVersionCString);
2840 	}
2841 
2842 	return result;
2843 }
2844 
2845 /*********************************************************************
2846  * Does the bare minimum validation to look up a kext.
2847  * All other validation is done on the spot as needed.
2848  **********************************************************************/
2849 bool
setInfoDictionaryAndPath(OSDictionary * aDictionary,OSString * aPath)2850 OSKext::setInfoDictionaryAndPath(
2851 	OSDictionary * aDictionary,
2852 	OSString     * aPath)
2853 {
2854 	bool           result                   = false;
2855 	OSString     * bundleIDString           = NULL;        // do not release
2856 	OSString     * versionString            = NULL;        // do not release
2857 	OSString     * compatibleVersionString  = NULL;        // do not release
2858 	const char   * versionCString           = NULL;        // do not free
2859 	const char   * compatibleVersionCString = NULL;        // do not free
2860 	OSBoolean    * scratchBool              = NULL;        // do not release
2861 	OSDictionary * scratchDict              = NULL;        // do not release
2862 
2863 	if (infoDict) {
2864 		panic("Attempt to set info dictionary on a kext "
2865 		    "that already has one (%s).",
2866 		    getIdentifierCString());
2867 	}
2868 
2869 	if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
2870 		goto finish;
2871 	}
2872 
2873 	infoDict.reset(aDictionary, OSRetain);
2874 
2875 	/* Check right away if the info dictionary has any log flags.
2876 	 */
2877 	scratchBool = OSDynamicCast(OSBoolean,
2878 	    getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
2879 	if (scratchBool == kOSBooleanTrue) {
2880 		flags.loggingEnabled = 1;
2881 	}
2882 
2883 	/* The very next thing to get is the bundle identifier. Unlike
2884 	 * in user space, a kext with no bundle identifier gets axed
2885 	 * immediately.
2886 	 */
2887 	bundleIDString = OSDynamicCast(OSString,
2888 	    getPropertyForHostArch(kCFBundleIdentifierKey));
2889 	if (!bundleIDString) {
2890 		OSKextLog(this,
2891 		    kOSKextLogErrorLevel |
2892 		    kOSKextLogValidationFlag,
2893 		    "CFBundleIdentifier missing/invalid type in kext %s.",
2894 		    aPath ? aPath->getCStringNoCopy() : "(unknown)");
2895 		goto finish;
2896 	}
2897 	bundleID = OSSymbol::withString(bundleIDString);
2898 	if (!bundleID) {
2899 		OSKextLog(this,
2900 		    kOSKextLogErrorLevel |
2901 		    kOSKextLogValidationFlag,
2902 		    "Can't copy bundle identifier as symbol for kext %s.",
2903 		    bundleIDString->getCStringNoCopy());
2904 		goto finish;
2905 	}
2906 
2907 	/* Save the path if we got one (it should always be available but it's
2908 	 * just something nice to have for bookkeeping).
2909 	 */
2910 	if (aPath) {
2911 		path.reset(aPath, OSRetain);
2912 	}
2913 
2914 	/*****
2915 	 * Minimal validation to initialize. We'll do other validation on the spot.
2916 	 */
2917 	if (bundleID->getLength() >= KMOD_MAX_NAME) {
2918 		OSKextLog(this,
2919 		    kOSKextLogErrorLevel |
2920 		    kOSKextLogValidationFlag,
2921 		    "Kext %s error - CFBundleIdentifier over max length %d.",
2922 		    getIdentifierCString(), KMOD_MAX_NAME - 1);
2923 		goto finish;
2924 	}
2925 
2926 	version = compatibleVersion = -1;
2927 
2928 	versionString = OSDynamicCast(OSString,
2929 	    getPropertyForHostArch(kCFBundleVersionKey));
2930 	if (!versionString) {
2931 		OSKextLog(this,
2932 		    kOSKextLogErrorLevel |
2933 		    kOSKextLogValidationFlag,
2934 		    "Kext %s error - CFBundleVersion missing/invalid type.",
2935 		    getIdentifierCString());
2936 		goto finish;
2937 	}
2938 	versionCString = versionString->getCStringNoCopy();
2939 	version = OSKextParseVersionString(versionCString);
2940 	if (version < 0) {
2941 		OSKextLog(this,
2942 		    kOSKextLogErrorLevel |
2943 		    kOSKextLogValidationFlag,
2944 		    "Kext %s error - CFBundleVersion bad value '%s'.",
2945 		    getIdentifierCString(), versionCString);
2946 		goto finish;
2947 	}
2948 
2949 	compatibleVersion = -1;         // set to illegal value for kexts that don't have
2950 
2951 	compatibleVersionString = OSDynamicCast(OSString,
2952 	    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
2953 	if (compatibleVersionString) {
2954 		compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
2955 		compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
2956 		if (compatibleVersion < 0) {
2957 			OSKextLog(this,
2958 			    kOSKextLogErrorLevel |
2959 			    kOSKextLogValidationFlag,
2960 			    "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2961 			    getIdentifierCString(), compatibleVersionCString);
2962 			goto finish;
2963 		}
2964 
2965 		if (compatibleVersion > version) {
2966 			OSKextLog(this,
2967 			    kOSKextLogErrorLevel |
2968 			    kOSKextLogValidationFlag,
2969 			    "Kext %s error - %s %s > %s %s (must be <=).",
2970 			    getIdentifierCString(),
2971 			    kOSBundleCompatibleVersionKey, compatibleVersionCString,
2972 			    kCFBundleVersionKey, versionCString);
2973 			goto finish;
2974 		}
2975 	}
2976 
2977 	/* Check to see if this kext is in exclude list */
2978 	if (isInExcludeList()) {
2979 		OSKextLog(this,
2980 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2981 		    "Kext %s is in exclude list, not loadable",
2982 		    getIdentifierCString());
2983 		goto finish;
2984 	}
2985 
2986 	/* Set flags for later use if the infoDict gets flushed. We only
2987 	 * check for true values, not false ones(!)
2988 	 */
2989 	scratchBool = OSDynamicCast(OSBoolean,
2990 	    getPropertyForHostArch(kOSBundleIsInterfaceKey));
2991 	if (scratchBool == kOSBooleanTrue) {
2992 		flags.interface = 1;
2993 	}
2994 
2995 	scratchBool = OSDynamicCast(OSBoolean,
2996 	    getPropertyForHostArch(kOSKernelResourceKey));
2997 	if (scratchBool == kOSBooleanTrue) {
2998 		flags.kernelComponent = 1;
2999 		flags.interface = 1;         // xxx - hm. the kernel itself isn't an interface...
3000 		flags.started = 1;
3001 
3002 		/* A kernel component has one implicit dependency on the kernel.
3003 		 */
3004 		flags.hasAllDependencies = 1;
3005 	}
3006 
3007 	/* Make sure common string values in personalities are uniqued to OSSymbols.
3008 	 */
3009 	scratchDict = OSDynamicCast(OSDictionary,
3010 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
3011 	if (scratchDict) {
3012 		uniquePersonalityProperties(scratchDict);
3013 	}
3014 
3015 	result = true;
3016 
3017 finish:
3018 
3019 	return result;
3020 }
3021 
3022 /*********************************************************************
3023 * Not used for prelinked kernel boot as there is no unrelocated
3024 * executable.
3025 *********************************************************************/
3026 bool
setExecutable(OSData * anExecutable,OSData * externalData,bool externalDataIsMkext)3027 OSKext::setExecutable(
3028 	OSData * anExecutable,
3029 	OSData * externalData,
3030 	bool     externalDataIsMkext)
3031 {
3032 	bool         result        = false;
3033 	const char * executableKey = NULL;         // do not free
3034 
3035 	if (!anExecutable) {
3036 		infoDict->removeObject(_kOSKextExecutableKey);
3037 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
3038 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
3039 		result = true;
3040 		goto finish;
3041 	}
3042 
3043 	if (infoDict->getObject(_kOSKextExecutableKey) ||
3044 	    infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
3045 		panic("Attempt to set an executable on a kext "
3046 		    "that already has one (%s).",
3047 		    getIdentifierCString());
3048 		goto finish;
3049 	}
3050 
3051 	if (externalDataIsMkext) {
3052 		executableKey = _kOSKextMkextExecutableReferenceKey;
3053 	} else {
3054 		executableKey = _kOSKextExecutableKey;
3055 	}
3056 
3057 	if (anExecutable) {
3058 		infoDict->setObject(executableKey, anExecutable);
3059 		if (externalData) {
3060 			infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
3061 		}
3062 	}
3063 
3064 	result = true;
3065 
3066 finish:
3067 	return result;
3068 }
3069 
3070 /*********************************************************************
3071 *********************************************************************/
3072 static void
uniqueStringPlistProperty(OSDictionary * dict,const char * key)3073 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
3074 {
3075 	OSObject       * value       = NULL;        // do not release
3076 	OSString       * stringValue = NULL;        // do not release
3077 	OSSharedPtr<const OSSymbol> symbolValue;
3078 
3079 	value = dict->getObject(key);
3080 	if (!value) {
3081 		goto finish;
3082 	}
3083 	if (OSDynamicCast(OSSymbol, value)) {
3084 		/* this is already an OSSymbol: we're good */
3085 		goto finish;
3086 	}
3087 
3088 	stringValue = OSDynamicCast(OSString, value);
3089 	if (!stringValue) {
3090 		goto finish;
3091 	}
3092 
3093 	symbolValue = OSSymbol::withString(stringValue);
3094 	if (!symbolValue) {
3095 		goto finish;
3096 	}
3097 
3098 	dict->setObject(key, symbolValue.get());
3099 
3100 finish:
3101 	return;
3102 }
3103 
3104 /*********************************************************************
3105 *********************************************************************/
3106 static void
uniqueStringPlistProperty(OSDictionary * dict,const OSString * key)3107 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
3108 {
3109 	OSObject       * value       = NULL;        // do not release
3110 	OSString       * stringValue = NULL;        // do not release
3111 	OSSharedPtr<const OSSymbol> symbolValue;
3112 
3113 	value = dict->getObject(key);
3114 	if (!value) {
3115 		goto finish;
3116 	}
3117 	if (OSDynamicCast(OSSymbol, value)) {
3118 		/* this is already an OSSymbol: we're good */
3119 		goto finish;
3120 	}
3121 
3122 	stringValue = OSDynamicCast(OSString, value);
3123 	if (!stringValue) {
3124 		goto finish;
3125 	}
3126 
3127 	symbolValue = OSSymbol::withString(stringValue);
3128 	if (!symbolValue) {
3129 		goto finish;
3130 	}
3131 
3132 	dict->setObject(key, symbolValue.get());
3133 
3134 finish:
3135 	return;
3136 }
3137 
3138 void
uniquePersonalityProperties(OSDictionary * personalityDict)3139 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
3140 {
3141 	OSKext::uniquePersonalityProperties(personalityDict, true);
3142 }
3143 
3144 /*********************************************************************
3145 * Replace common personality property values with uniqued instances
3146 * to save on wired memory.
3147 *********************************************************************/
3148 /* static */
3149 void
uniquePersonalityProperties(OSDictionary * personalityDict,bool defaultAddKernelBundleIdentifier)3150 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier)
3151 {
3152 	/* Properties every personality has.
3153 	 */
3154 	uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
3155 	uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
3156 	uniqueStringPlistProperty(personalityDict, gIOClassKey.get());
3157 	if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) {
3158 		uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey);
3159 	} else if (defaultAddKernelBundleIdentifier) {
3160 		personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey));
3161 	}
3162 
3163 	/* Other commonly used properties.
3164 	 */
3165 	uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
3166 	uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
3167 	uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
3168 
3169 	uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
3170 	uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
3171 	uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
3172 	uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
3173 	uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
3174 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
3175 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
3176 	uniqueStringPlistProperty(personalityDict, "Vendor");
3177 	uniqueStringPlistProperty(personalityDict, "Vendor Identification");
3178 	uniqueStringPlistProperty(personalityDict, "Vendor Name");
3179 	uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
3180 	uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
3181 	uniqueStringPlistProperty(personalityDict, "idProduct");
3182 
3183 	return;
3184 }
3185 
3186 /*********************************************************************
3187 *********************************************************************/
3188 void
free(void)3189 OSKext::free(void)
3190 {
3191 	if (isLoaded()) {
3192 		panic("Attempt to free loaded kext %s.", getIdentifierCString());
3193 	}
3194 
3195 	if (isDriverKit()) {
3196 		if (dextLaunchedCount > 0) {
3197 			panic("Freeing dext %s but dextLaunchedCount is %d\n", getIdentifierCString(), dextLaunchedCount);
3198 		}
3199 	}
3200 
3201 	infoDict.reset();
3202 	bundleID.reset();
3203 	path.reset();
3204 	executableRelPath.reset();
3205 	userExecutableRelPath.reset();
3206 	dependencies.reset();
3207 	linkedExecutable.reset();
3208 	metaClasses.reset();
3209 	interfaceUUID.reset();
3210 	driverKitUUID.reset();
3211 	dextStatistics.reset();
3212 	dextUniqueID.reset();
3213 
3214 	if (isInterface() && kmod_info) {
3215 		kfree_type(kmod_info_t, kmod_info);
3216 	}
3217 
3218 	super::free();
3219 	return;
3220 }
3221 
3222 #if PRAGMA_MARK
3223 #pragma mark Mkext files
3224 #endif
3225 
3226 #if CONFIG_KXLD
3227 /*
3228  * mkext archives are really only relevant on kxld-enabled kernels.
3229  * Without a dynamic kernel linker, we don't need to support any mkexts.
3230  */
3231 
3232 /*********************************************************************
3233 *********************************************************************/
3234 OSReturn
readMkextArchive(OSData * mkextData,uint32_t * checksumPtr)3235 OSKext::readMkextArchive(OSData * mkextData,
3236     uint32_t * checksumPtr)
3237 {
3238 	OSReturn       result       = kOSKextReturnBadData;
3239 	uint32_t       mkextLength  = 0;
3240 	mkext_header * mkextHeader  = NULL;        // do not free
3241 	uint32_t       mkextVersion = 0;
3242 
3243 	/* Note default return of kOSKextReturnBadData above.
3244 	 */
3245 	mkextLength = mkextData->getLength();
3246 	if (mkextLength < sizeof(mkext_basic_header)) {
3247 		OSKextLog(/* kext */ NULL,
3248 		    kOSKextLogErrorLevel |
3249 		    kOSKextLogArchiveFlag,
3250 		    "Mkext archive too small to be valid.");
3251 		goto finish;
3252 	}
3253 
3254 	mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
3255 
3256 	if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
3257 	    MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
3258 		OSKextLog(/* kext */ NULL,
3259 		    kOSKextLogErrorLevel |
3260 		    kOSKextLogArchiveFlag,
3261 		    "Mkext archive has invalid magic or signature.");
3262 		goto finish;
3263 	}
3264 
3265 	if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
3266 		OSKextLog(/* kext */ NULL,
3267 		    kOSKextLogErrorLevel |
3268 		    kOSKextLogArchiveFlag,
3269 		    "Mkext archive recorded length doesn't match actual file length.");
3270 		goto finish;
3271 	}
3272 
3273 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3274 
3275 	if (mkextVersion == MKEXT_VERS_2) {
3276 		result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
3277 	} else {
3278 		OSKextLog(/* kext */ NULL,
3279 		    kOSKextLogErrorLevel |
3280 		    kOSKextLogArchiveFlag,
3281 		    "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
3282 		result = kOSKextReturnUnsupported;
3283 	}
3284 
3285 finish:
3286 	return result;
3287 }
3288 
3289 /*********************************************************************
3290 * Assumes magic, signature, version, length have been checked.
3291 * xxx - need to add further bounds checking for each file entry
3292 *
3293 * Should keep track of all kexts created so far, and if we hit a
3294 * fatal error halfway through, remove those kexts. If we've dropped
3295 * an older version that had already been read, whoops! Might want to
3296 * add a level of buffering?
3297 *********************************************************************/
3298 /* static */
3299 OSReturn
readMkext2Archive(OSData * mkextData,OSDictionary ** mkextPlistOut,uint32_t * checksumPtr)3300 OSKext::readMkext2Archive(
3301 	OSData        * mkextData,
3302 	OSDictionary ** mkextPlistOut,
3303 	uint32_t      * checksumPtr)
3304 {
3305 	OSReturn        result                     = kOSReturnError;
3306 	uint32_t        mkextLength;
3307 	mkext2_header * mkextHeader                = NULL;        // do not free
3308 	void          * mkextEnd                   = NULL;        // do not free
3309 	uint32_t        mkextVersion;
3310 	uint8_t       * crc_address                = NULL;
3311 	size_t          crc_buffer_size            = 0;
3312 	uint32_t        checksum;
3313 	uint32_t        mkextPlistOffset;
3314 	uint32_t        mkextPlistCompressedSize;
3315 	char          * mkextPlistEnd              = NULL;        // do not free
3316 	uint32_t        mkextPlistFullSize;
3317 	OSSharedPtr<OSString>     errorString;
3318 	OSSharedPtr<OSData>       mkextPlistUncompressedData;
3319 	const char    * mkextPlistDataBuffer       = NULL;        // do not free
3320 	OSSharedPtr<OSObject>      parsedXML;
3321 	OSDictionary  * mkextPlist                 = NULL;        // do not release
3322 	OSArray       * mkextInfoDictArray         = NULL;        // do not release
3323 	uint32_t        count, i;
3324 	kc_format_t kc_format;
3325 
3326 	if (!PE_get_primary_kc_format(&kc_format)) {
3327 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3328 		    "Unable to determine primary KC format");
3329 		goto finish;
3330 	}
3331 
3332 	mkextLength = mkextData->getLength();
3333 	mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
3334 	mkextEnd = (char *)mkextHeader + mkextLength;
3335 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3336 
3337 	crc_address = (u_int8_t *)&mkextHeader->version;
3338 	crc_buffer_size = (uintptr_t)mkextHeader +
3339 	    MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address;
3340 	if (crc_buffer_size > INT32_MAX) {
3341 		OSKextLog(/* kext */ NULL,
3342 		    kOSKextLogErrorLevel |
3343 		    kOSKextLogArchiveFlag,
3344 		    "Mkext archive size is too large (%lu > INT32_MAX).",
3345 		    crc_buffer_size);
3346 		result = kOSKextReturnBadData;
3347 		goto finish;
3348 	}
3349 	checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size);
3350 
3351 	if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
3352 		OSKextLog(/* kext */ NULL,
3353 		    kOSKextLogErrorLevel |
3354 		    kOSKextLogArchiveFlag,
3355 		    "Mkext archive has bad checksum.");
3356 		result = kOSKextReturnBadData;
3357 		goto finish;
3358 	}
3359 
3360 	if (checksumPtr) {
3361 		*checksumPtr = checksum;
3362 	}
3363 
3364 	/* Check that the CPU type & subtype match that of the running kernel. */
3365 	if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
3366 		OSKextLog(/* kext */ NULL,
3367 		    kOSKextLogErrorLevel |
3368 		    kOSKextLogArchiveFlag,
3369 		    "Mkext archive must have a specific CPU type.");
3370 		result = kOSKextReturnBadData;
3371 		goto finish;
3372 	} else {
3373 		if ((UInt32)_mh_execute_header.cputype !=
3374 		    MKEXT_GET_CPUTYPE(mkextHeader)) {
3375 			OSKextLog(/* kext */ NULL,
3376 			    kOSKextLogErrorLevel |
3377 			    kOSKextLogArchiveFlag,
3378 			    "Mkext archive does not match the running kernel's CPU type.");
3379 			result = kOSKextReturnArchNotFound;
3380 			goto finish;
3381 		}
3382 	}
3383 
3384 	mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
3385 	mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
3386 	mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
3387 	    mkextPlistCompressedSize;
3388 	if (mkextPlistEnd > mkextEnd) {
3389 		OSKextLog(/* kext */ NULL,
3390 		    kOSKextLogErrorLevel |
3391 		    kOSKextLogArchiveFlag,
3392 		    "Mkext archive file overrun.");
3393 		result = kOSKextReturnBadData;
3394 	}
3395 
3396 	mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
3397 	if (mkextPlistCompressedSize) {
3398 		mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
3399 			(UInt8 *)mkextHeader + mkextPlistOffset,
3400 			"plist",
3401 			mkextPlistCompressedSize, mkextPlistFullSize);
3402 		if (!mkextPlistUncompressedData) {
3403 			goto finish;
3404 		}
3405 		mkextPlistDataBuffer = (const char *)
3406 		    mkextPlistUncompressedData->getBytesNoCopy();
3407 	} else {
3408 		mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
3409 	}
3410 
3411 	/* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
3412 	 */
3413 	parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString);
3414 	if (parsedXML) {
3415 		mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get());
3416 	}
3417 	if (!mkextPlist) {
3418 		const char * errorCString = "(unknown error)";
3419 
3420 		if (errorString && errorString->getCStringNoCopy()) {
3421 			errorCString = errorString->getCStringNoCopy();
3422 		} else if (parsedXML) {
3423 			errorCString = "not a dictionary";
3424 		}
3425 		OSKextLog(/* kext */ NULL,
3426 		    kOSKextLogErrorLevel |
3427 		    kOSKextLogArchiveFlag,
3428 		    "Error unserializing mkext plist: %s.", errorCString);
3429 		goto finish;
3430 	}
3431 
3432 	mkextInfoDictArray = OSDynamicCast(OSArray,
3433 	    mkextPlist->getObject(kMKEXTInfoDictionariesKey));
3434 	if (!mkextInfoDictArray) {
3435 		OSKextLog(/* kext */ NULL,
3436 		    kOSKextLogErrorLevel |
3437 		    kOSKextLogArchiveFlag,
3438 		    "Mkext archive contains no kext info dictionaries.");
3439 		goto finish;
3440 	}
3441 
3442 	count = mkextInfoDictArray->getCount();
3443 	for (i = 0; i < count; i++) {
3444 		OSDictionary * infoDict;
3445 
3446 
3447 		infoDict = OSDynamicCast(OSDictionary,
3448 		    mkextInfoDictArray->getObject(i));
3449 
3450 		/* Create the kext for the entry, then release it, because the
3451 		 * kext system keeps them around until explicitly removed.
3452 		 * Any creation/registration failures are already logged for us.
3453 		 */
3454 		if (infoDict) {
3455 			OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData);
3456 
3457 			/* Fail dynamic loading of a kext when booted from MH_FILESET */
3458 			if (kc_format == KCFormatFileset &&
3459 			    newKext &&
3460 			    !(newKext->isPrelinked()) &&
3461 			    newKext->declaresExecutable()) {
3462 				result = kOSReturnError;
3463 				printf("Kext LOG: Dynamic loading of kext denied for kext %s\n",
3464 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3465 
3466 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
3467 				    "Dynamic loading of kext denied for kext %s\n",
3468 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3469 				goto finish;
3470 			}
3471 		}
3472 	}
3473 
3474 	/* If the caller needs the plist, hand them back our copy
3475 	 */
3476 	if (mkextPlistOut) {
3477 		*mkextPlistOut = mkextPlist;
3478 		parsedXML.detach();
3479 	}
3480 
3481 	/* Even if we didn't keep any kexts from the mkext, we may have a load
3482 	 * request to process, so we are successful (no errors occurred).
3483 	 */
3484 	result = kOSReturnSuccess;
3485 
3486 finish:
3487 	return result;
3488 }
3489 
3490 /* static */
3491 OSReturn
readMkext2Archive(OSData * mkextData,OSSharedPtr<OSDictionary> & mkextPlistOut,uint32_t * checksumPtr)3492 OSKext::readMkext2Archive(
3493 	OSData        * mkextData,
3494 	OSSharedPtr<OSDictionary> &mkextPlistOut,
3495 	uint32_t      * checksumPtr)
3496 {
3497 	OSDictionary * mkextPlist = NULL;
3498 	OSReturn ret;
3499 
3500 	if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData,
3501 	    &mkextPlist,
3502 	    checksumPtr))) {
3503 		mkextPlistOut.reset(mkextPlist, OSNoRetain);
3504 	}
3505 	return ret;
3506 }
3507 
3508 /*********************************************************************
3509 *********************************************************************/
3510 /* static */
3511 OSSharedPtr<OSKext>
withMkext2Info(OSDictionary * anInfoDict,OSData * mkextData)3512 OSKext::withMkext2Info(
3513 	OSDictionary * anInfoDict,
3514 	OSData       * mkextData)
3515 {
3516 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
3517 
3518 	if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
3519 		return NULL;
3520 	}
3521 
3522 	return newKext;
3523 }
3524 
3525 /*********************************************************************
3526 *********************************************************************/
3527 bool
initWithMkext2Info(OSDictionary * anInfoDict,OSData * mkextData)3528 OSKext::initWithMkext2Info(
3529 	OSDictionary * anInfoDict,
3530 	OSData       * mkextData)
3531 {
3532 	bool                   result              = false;
3533 	OSString             * kextPath            = NULL;        // do not release
3534 	OSNumber             * executableOffsetNum = NULL;        // do not release
3535 	OSSharedPtr<OSData>               executable;
3536 
3537 	if (anInfoDict == NULL || !super::init()) {
3538 		goto finish;
3539 	}
3540 
3541 	/* Get the path. Don't look for an arch-specific path property.
3542 	 */
3543 	kextPath = OSDynamicCast(OSString,
3544 	    anInfoDict->getObject(kMKEXTBundlePathKey));
3545 
3546 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
3547 		goto finish;
3548 	}
3549 
3550 	/* If we have a path to the executable, save it.
3551 	 */
3552 	executableRelPath.reset(OSDynamicCast(OSString,
3553 	    anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain);
3554 
3555 	/* Don't need the paths to be in the info dictionary any more.
3556 	 */
3557 	anInfoDict->removeObject(kMKEXTBundlePathKey);
3558 	anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
3559 
3560 	executableOffsetNum = OSDynamicCast(OSNumber,
3561 	    infoDict->getObject(kMKEXTExecutableKey));
3562 	if (executableOffsetNum) {
3563 		executable = createMkext2FileEntry(mkextData,
3564 		    executableOffsetNum, "executable");
3565 		infoDict->removeObject(kMKEXTExecutableKey);
3566 		if (!executable) {
3567 			goto finish;
3568 		}
3569 		if (!setExecutable(executable.get(), mkextData, true)) {
3570 			goto finish;
3571 		}
3572 	}
3573 
3574 	result = (registerIdentifier() == kOSKextInitialized);
3575 finish:
3576 	return result;
3577 }
3578 
3579 /*********************************************************************
3580 *********************************************************************/
3581 OSSharedPtr<OSData>
createMkext2FileEntry(OSData * mkextData,OSNumber * offsetNum,const char * name)3582 OSKext::createMkext2FileEntry(
3583 	OSData     * mkextData,
3584 	OSNumber   * offsetNum,
3585 	const char * name)
3586 {
3587 	OSSharedPtr<OSData> result;
3588 	MkextEntryRef   entryRef;
3589 	uint8_t       * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
3590 	uint32_t        entryOffset = offsetNum->unsigned32BitValue();
3591 
3592 	result = OSData::withCapacity(sizeof(entryRef));
3593 	if (!result) {
3594 		goto finish;
3595 	}
3596 
3597 	entryRef.mkext = (mkext_basic_header *)mkextBuffer;
3598 	entryRef.fileinfo = mkextBuffer + entryOffset;
3599 	if (!result->appendValue(entryRef)) {
3600 		result.reset();
3601 		goto finish;
3602 	}
3603 
3604 finish:
3605 	if (!result) {
3606 		OSKextLog(this,
3607 		    kOSKextLogErrorLevel |
3608 		    kOSKextLogArchiveFlag,
3609 		    "Can't create wrapper for mkext file entry '%s' of kext %s.",
3610 		    name, getIdentifierCString());
3611 	}
3612 	return result;
3613 }
3614 
3615 /*********************************************************************
3616 *********************************************************************/
3617 extern "C" {
3618 static void * z_alloc(void *, u_int items, u_int size);
3619 static void   z_free(void *, void *ptr);
3620 
3621 typedef struct z_mem {
3622 	uint32_t alloc_size;
3623 	uint8_t  data[0];
3624 } z_mem;
3625 
3626 /*
3627  * Space allocation and freeing routines for use by zlib routines.
3628  */
3629 void *
z_alloc(void * notused __unused,u_int num_items,u_int size)3630 z_alloc(void * notused __unused, u_int num_items, u_int size)
3631 {
3632 	void     * result = NULL;
3633 	z_mem    * zmem = NULL;
3634 
3635 	uint64_t   total = ((uint64_t)num_items) * ((uint64_t)size);
3636 	//Check for overflow due to multiplication
3637 	if (total > UINT32_MAX) {
3638 		panic("z_alloc(%p, %x, %x): overflow caused by %x * %x",
3639 		    notused, num_items, size, num_items, size);
3640 	}
3641 
3642 	uint64_t   allocSize64 =  total + ((uint64_t)sizeof(zmem));
3643 	//Check for overflow due to addition
3644 	if (allocSize64 > UINT32_MAX) {
3645 		panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx",
3646 		    notused, num_items, size, (uint32_t)total, sizeof(zmem));
3647 	}
3648 	uint32_t allocSize = (uint32_t)allocSize64;
3649 
3650 	zmem = (z_mem *)kalloc_data_tag(allocSize, Z_WAITOK,
3651 	    VM_KERN_MEMORY_OSKEXT);
3652 	if (!zmem) {
3653 		goto finish;
3654 	}
3655 	zmem->alloc_size = allocSize;
3656 	result = (void *)&(zmem->data);
3657 finish:
3658 	return result;
3659 }
3660 
3661 void
z_free(void * notused __unused,void * ptr)3662 z_free(void * notused __unused, void * ptr)
3663 {
3664 	uint32_t * skipper = (uint32_t *)ptr - 1;
3665 	z_mem    * zmem = (z_mem *)skipper;
3666 	kfree_data(zmem, zmem->alloc_size);
3667 }
3668 };
3669 
3670 OSSharedPtr<OSData>
extractMkext2FileData(UInt8 * data,const char * name,uint32_t compressedSize,uint32_t fullSize)3671 OSKext::extractMkext2FileData(
3672 	UInt8      * data,
3673 	const char * name,
3674 	uint32_t     compressedSize,
3675 	uint32_t     fullSize)
3676 {
3677 	OSSharedPtr<OSData>      result;
3678 	OSSharedPtr<OSData>      uncompressedData;        // release on error
3679 
3680 	uint8_t     * uncompressedDataBuffer = NULL;        // do not free
3681 	unsigned long uncompressedSize;
3682 	z_stream      zstream;
3683 	bool          zstream_inited = false;
3684 	int           zlib_result;
3685 
3686 	/* If the file isn't compressed, we want to make a copy
3687 	 * so that we don't have the tie to the larger mkext file buffer any more.
3688 	 */
3689 	if (!compressedSize) {
3690 		uncompressedData = OSData::withBytes(data, fullSize);
3691 		// xxx - no check for failure?
3692 		result = uncompressedData;
3693 		goto finish;
3694 	}
3695 
3696 	if (KERN_SUCCESS != kmem_alloc(kernel_map,
3697 	    (vm_offset_t*)&uncompressedDataBuffer, fullSize,
3698 	    KMA_DATA, VM_KERN_MEMORY_OSKEXT)) {
3699 		/* How's this for cheesy? The kernel is only asked to extract
3700 		 * kext plists so we tailor the log messages.
3701 		 */
3702 		if (isKernel()) {
3703 			OSKextLog(this,
3704 			    kOSKextLogErrorLevel |
3705 			    kOSKextLogArchiveFlag,
3706 			    "Allocation failure extracting %s from mkext.", name);
3707 		} else {
3708 			OSKextLog(this,
3709 			    kOSKextLogErrorLevel |
3710 			    kOSKextLogArchiveFlag,
3711 			    "Allocation failure extracting %s from mkext for kext %s.",
3712 			    name, getIdentifierCString());
3713 		}
3714 
3715 		goto finish;
3716 	}
3717 	uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
3718 	if (!uncompressedData) {
3719 		if (isKernel()) {
3720 			OSKextLog(this,
3721 			    kOSKextLogErrorLevel |
3722 			    kOSKextLogArchiveFlag,
3723 			    "Allocation failure extracting %s from mkext.", name);
3724 		} else {
3725 			OSKextLog(this,
3726 			    kOSKextLogErrorLevel |
3727 			    kOSKextLogArchiveFlag,
3728 			    "Allocation failure extracting %s from mkext for kext %s.",
3729 			    name, getIdentifierCString());
3730 		}
3731 		goto finish;
3732 	}
3733 	uncompressedData->setDeallocFunction(&osdata_kmem_free);
3734 
3735 	if (isKernel()) {
3736 		OSKextLog(this,
3737 		    kOSKextLogDetailLevel |
3738 		    kOSKextLogArchiveFlag,
3739 		    "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3740 		    name, compressedSize, fullSize);
3741 	} else {
3742 		OSKextLog(this,
3743 		    kOSKextLogDetailLevel |
3744 		    kOSKextLogArchiveFlag,
3745 		    "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3746 		    getIdentifierCString(), name, compressedSize, fullSize);
3747 	}
3748 
3749 	bzero(&zstream, sizeof(zstream));
3750 	zstream.next_in   = (UInt8 *)data;
3751 	zstream.avail_in  = compressedSize;
3752 
3753 	zstream.next_out  = uncompressedDataBuffer;
3754 	zstream.avail_out = fullSize;
3755 
3756 	zstream.zalloc    = z_alloc;
3757 	zstream.zfree     = z_free;
3758 
3759 	zlib_result = inflateInit(&zstream);
3760 	if (Z_OK != zlib_result) {
3761 		if (isKernel()) {
3762 			OSKextLog(this,
3763 			    kOSKextLogErrorLevel |
3764 			    kOSKextLogArchiveFlag,
3765 			    "Mkext error; zlib inflateInit failed (%d) for %s.",
3766 			    zlib_result, name);
3767 		} else {
3768 			OSKextLog(this,
3769 			    kOSKextLogErrorLevel |
3770 			    kOSKextLogArchiveFlag,
3771 			    "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3772 			    getIdentifierCString(), zlib_result, name);
3773 		}
3774 		goto finish;
3775 	} else {
3776 		zstream_inited = true;
3777 	}
3778 
3779 	zlib_result = inflate(&zstream, Z_FINISH);
3780 
3781 	if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
3782 		uncompressedSize = zstream.total_out;
3783 	} else {
3784 		if (isKernel()) {
3785 			OSKextLog(this,
3786 			    kOSKextLogErrorLevel |
3787 			    kOSKextLogArchiveFlag,
3788 			    "Mkext error; zlib inflate failed (%d) for %s.",
3789 			    zlib_result, name);
3790 		} else {
3791 			OSKextLog(this,
3792 			    kOSKextLogErrorLevel |
3793 			    kOSKextLogArchiveFlag,
3794 			    "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3795 			    getIdentifierCString(), zlib_result, name);
3796 		}
3797 		if (zstream.msg) {
3798 			OSKextLog(this,
3799 			    kOSKextLogErrorLevel |
3800 			    kOSKextLogArchiveFlag,
3801 			    "zlib error: %s.", zstream.msg);
3802 		}
3803 		goto finish;
3804 	}
3805 
3806 	if (uncompressedSize != fullSize) {
3807 		if (isKernel()) {
3808 			OSKextLog(this,
3809 			    kOSKextLogErrorLevel |
3810 			    kOSKextLogArchiveFlag,
3811 			    "Mkext error; zlib inflate discrepancy for %s, "
3812 			    "uncompressed size != original size.", name);
3813 		} else {
3814 			OSKextLog(this,
3815 			    kOSKextLogErrorLevel |
3816 			    kOSKextLogArchiveFlag,
3817 			    "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3818 			    "uncompressed size != original size.",
3819 			    getIdentifierCString(), name);
3820 		}
3821 		goto finish;
3822 	}
3823 
3824 	result = os::move(uncompressedData);
3825 
3826 finish:
3827 	/* Don't bother checking return, nothing we can do on fail.
3828 	 */
3829 	if (zstream_inited) {
3830 		inflateEnd(&zstream);
3831 	}
3832 
3833 	return result;
3834 }
3835 
3836 /*********************************************************************
3837 *********************************************************************/
3838 /* static */
3839 OSReturn
loadFromMkext(OSKextLogSpec clientLogFilter,char * mkextBuffer,uint32_t mkextBufferLength,char ** logInfoOut,uint32_t * logInfoLengthOut)3840 OSKext::loadFromMkext(
3841 	OSKextLogSpec   clientLogFilter,
3842 	char          * mkextBuffer,
3843 	uint32_t        mkextBufferLength,
3844 	char         ** logInfoOut,
3845 	uint32_t      * logInfoLengthOut)
3846 {
3847 	OSReturn         result                      = kOSReturnError;
3848 	OSReturn         tempResult                  = kOSReturnError;
3849 
3850 	OSSharedPtr<OSData>        mkextData;
3851 	OSSharedPtr<OSDictionary>  mkextPlist;
3852 
3853 	OSSharedPtr<OSArray>       logInfoArray;
3854 	OSSharedPtr<OSSerialize>   serializer;
3855 
3856 	OSString       * predicate                   = NULL;        // do not release
3857 	OSDictionary   * requestArgs                 = NULL;        // do not release
3858 
3859 	OSString       * kextIdentifier              = NULL;        // do not release
3860 	OSNumber       * startKextExcludeNum         = NULL;        // do not release
3861 	OSNumber       * startMatchingExcludeNum     = NULL;        // do not release
3862 	OSBoolean      * delayAutounloadBool         = NULL;        // do not release
3863 	OSArray        * personalityNames            = NULL;        // do not release
3864 
3865 	/* Default values for these two options: regular autounload behavior,
3866 	 * load all kexts, send no personalities.
3867 	 */
3868 	Boolean            delayAutounload           = false;
3869 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
3870 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3871 
3872 	IORecursiveLockLock(sKextLock);
3873 
3874 	if (logInfoOut) {
3875 		*logInfoOut = NULL;
3876 		*logInfoLengthOut = 0;
3877 	}
3878 
3879 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3880 
3881 	OSKextLog(/* kext */ NULL,
3882 	    kOSKextLogDebugLevel |
3883 	    kOSKextLogIPCFlag,
3884 	    "Received kext load request from user space.");
3885 
3886 	/* Regardless of processing, the fact that we have gotten here means some
3887 	 * user-space program is up and talking to us, so we'll switch our kext
3888 	 * registration to reflect that.
3889 	 */
3890 	if (!sUserLoadsActive) {
3891 		OSKextLog(/* kext */ NULL,
3892 		    kOSKextLogProgressLevel |
3893 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3894 		    "Switching to late startup (user-space) kext loading policy.");
3895 
3896 		sUserLoadsActive = true;
3897 	}
3898 
3899 	if (!sLoadEnabled) {
3900 		OSKextLog(/* kext */ NULL,
3901 		    kOSKextLogErrorLevel |
3902 		    kOSKextLogLoadFlag,
3903 		    "Kext loading is disabled.");
3904 		result = kOSKextReturnDisabled;
3905 		goto finish;
3906 	}
3907 
3908 	/* Note that we do not set a dealloc function on this OSData
3909 	 * object! No references to it can remain after the loadFromMkext()
3910 	 * call since we are in a MIG function, and will vm_deallocate()
3911 	 * the buffer.
3912 	 */
3913 	mkextData = OSData::withBytesNoCopy(mkextBuffer,
3914 	    mkextBufferLength);
3915 	if (!mkextData) {
3916 		OSKextLog(/* kext */ NULL,
3917 		    kOSKextLogErrorLevel |
3918 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3919 		    "Failed to create wrapper for kext load request.");
3920 		result = kOSKextReturnNoMemory;
3921 		goto finish;
3922 	}
3923 
3924 	result = readMkext2Archive(mkextData.get(), mkextPlist, NULL);
3925 	if (result != kOSReturnSuccess) {
3926 		OSKextLog(/* kext */ NULL,
3927 		    kOSKextLogErrorLevel |
3928 		    kOSKextLogLoadFlag,
3929 		    "Failed to read kext load request.");
3930 		goto finish;
3931 	}
3932 
3933 	predicate = _OSKextGetRequestPredicate(mkextPlist.get());
3934 	if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3935 		OSKextLog(/* kext */ NULL,
3936 		    kOSKextLogErrorLevel |
3937 		    kOSKextLogLoadFlag,
3938 		    "Received kext load request with no predicate; skipping.");
3939 		result = kOSKextReturnInvalidArgument;
3940 		goto finish;
3941 	}
3942 
3943 	requestArgs = OSDynamicCast(OSDictionary,
3944 	    mkextPlist->getObject(kKextRequestArgumentsKey));
3945 	if (!requestArgs || !requestArgs->getCount()) {
3946 		OSKextLog(/* kext */ NULL,
3947 		    kOSKextLogErrorLevel |
3948 		    kOSKextLogLoadFlag,
3949 		    "Received kext load request with no arguments.");
3950 		result = kOSKextReturnInvalidArgument;
3951 		goto finish;
3952 	}
3953 
3954 	kextIdentifier = OSDynamicCast(OSString,
3955 	    requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3956 
3957 	if (!kextIdentifier) {
3958 		OSKextLog(/* kext */ NULL,
3959 		    kOSKextLogErrorLevel |
3960 		    kOSKextLogLoadFlag,
3961 		    "Received kext load request with no kext identifier.");
3962 		result = kOSKextReturnInvalidArgument;
3963 		goto finish;
3964 	}
3965 
3966 	startKextExcludeNum = OSDynamicCast(OSNumber,
3967 	    requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3968 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
3969 	    requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3970 	delayAutounloadBool = OSDynamicCast(OSBoolean,
3971 	    requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3972 	personalityNames = OSDynamicCast(OSArray,
3973 	    requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3974 
3975 	if (delayAutounloadBool) {
3976 		delayAutounload = delayAutounloadBool->getValue();
3977 	}
3978 	if (startKextExcludeNum) {
3979 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3980 	}
3981 	if (startMatchingExcludeNum) {
3982 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3983 	}
3984 
3985 	OSKextLog(/* kext */ NULL,
3986 	    kOSKextLogProgressLevel |
3987 	    kOSKextLogIPCFlag,
3988 	    "Received request from user space to load kext %s.",
3989 	    kextIdentifier->getCStringNoCopy());
3990 
3991 	/* Load the kext, with no deferral, since this is a load from outside
3992 	 * the kernel.
3993 	 * xxx - Would like a better way to handle the default values for the
3994 	 * xxx - start/match opt args.
3995 	 */
3996 	result = OSKext::loadKextWithIdentifier(
3997 		kextIdentifier,
3998 		/* kextRef */ NULL,
3999 		/* allowDefer */ false,
4000 		delayAutounload,
4001 		startKextExcludeLevel,
4002 		startMatchingExcludeLevel,
4003 		personalityNames);
4004 	if (result != kOSReturnSuccess) {
4005 		goto finish;
4006 	}
4007 	/* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue
4008 	 * for matching via a separate IOKit calldown.
4009 	 */
4010 
4011 finish:
4012 
4013 	/* Gather up the collected log messages for user space. Any
4014 	 * error messages past this call will not make it up as log messages
4015 	 * but will be in the system log.
4016 	 */
4017 	logInfoArray = OSKext::clearUserSpaceLogFilter();
4018 
4019 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
4020 		tempResult = OSKext::serializeLogInfo(logInfoArray.get(),
4021 		    logInfoOut, logInfoLengthOut);
4022 		if (tempResult != kOSReturnSuccess) {
4023 			result = tempResult;
4024 		}
4025 	}
4026 
4027 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
4028 
4029 	IORecursiveLockUnlock(sKextLock);
4030 
4031 	/* Note: mkextDataObject will have been retained by every kext w/an
4032 	 * executable in it. That should all have been flushed out at the
4033 	 * and of the load operation, but you never know....
4034 	 */
4035 	if (mkextData && mkextData->getRetainCount() > 1) {
4036 		OSKextLog(/* kext */ NULL,
4037 		    kOSKextLogErrorLevel |
4038 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
4039 		    "Kext load request buffer from user space still retained by a kext; "
4040 		    "probable memory leak.");
4041 	}
4042 
4043 	return result;
4044 }
4045 
4046 #endif // CONFIG_KXLD
4047 
4048 /*********************************************************************
4049 *********************************************************************/
4050 /* static */
4051 OSReturn
serializeLogInfo(OSArray * logInfoArray,char ** logInfoOut,uint32_t * logInfoLengthOut)4052 OSKext::serializeLogInfo(
4053 	OSArray   * logInfoArray,
4054 	char     ** logInfoOut,
4055 	uint32_t  * logInfoLengthOut)
4056 {
4057 	OSReturn        result      = kOSReturnError;
4058 	char          * buffer      = NULL;
4059 	kern_return_t   kmem_result = KERN_FAILURE;
4060 	OSSharedPtr<OSSerialize>  serializer;
4061 	char         * logInfo            = NULL;        // returned by reference
4062 	uint32_t       logInfoLength      = 0;
4063 
4064 	if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
4065 		OSKextLog(/* kext */ NULL,
4066 		    kOSKextLogErrorLevel |
4067 		    kOSKextLogIPCFlag,
4068 		    "Internal error; invalid arguments to OSKext::serializeLogInfo().");
4069 		/* Bad programmer. */
4070 		result = kOSKextReturnInvalidArgument;
4071 		goto finish;
4072 	}
4073 
4074 	serializer = OSSerialize::withCapacity(0);
4075 	if (!serializer) {
4076 		OSKextLog(/* kext */ NULL,
4077 		    kOSKextLogErrorLevel |
4078 		    kOSKextLogIPCFlag,
4079 		    "Failed to create serializer on log info for request from user space.");
4080 		/* Incidental error; we're going to (try to) allow the request
4081 		 * itself to succeed. */
4082 	} else {
4083 		if (!logInfoArray->serialize(serializer.get())) {
4084 			OSKextLog(/* kext */ NULL,
4085 			    kOSKextLogErrorLevel |
4086 			    kOSKextLogIPCFlag,
4087 			    "Failed to serialize log info for request from user space.");
4088 			/* Incidental error; we're going to (try to) allow the request
4089 			 * itself to succeed. */
4090 		} else {
4091 			logInfo = serializer->text();
4092 			logInfoLength = serializer->getLength();
4093 
4094 			kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength),
4095 			    KMA_DATA, VM_KERN_MEMORY_OSKEXT);
4096 			if (kmem_result != KERN_SUCCESS) {
4097 				OSKextLog(/* kext */ NULL,
4098 				    kOSKextLogErrorLevel |
4099 				    kOSKextLogIPCFlag,
4100 				    "Failed to copy log info for request from user space.");
4101 				/* Incidental error; we're going to (try to) allow the request
4102 				 * to succeed. */
4103 			} else {
4104 				/* 11981737 - clear uninitialized data in last page */
4105 				bzero((void *)(buffer + logInfoLength),
4106 				    (round_page(logInfoLength) - logInfoLength));
4107 				memcpy(buffer, logInfo, logInfoLength);
4108 				*logInfoOut = buffer;
4109 				*logInfoLengthOut = logInfoLength;
4110 			}
4111 		}
4112 	}
4113 
4114 	result = kOSReturnSuccess;
4115 finish:
4116 	return result;
4117 }
4118 
4119 #if PRAGMA_MARK
4120 #pragma mark Instance Management Methods
4121 #endif
4122 /*********************************************************************
4123 *********************************************************************/
4124 OSSharedPtr<OSKext>
lookupKextWithIdentifier(const char * kextIdentifier)4125 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
4126 {
4127 	OSSharedPtr<OSKext> foundKext;
4128 
4129 	IORecursiveLockLock(sKextLock);
4130 	foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain);
4131 	IORecursiveLockUnlock(sKextLock);
4132 
4133 	return foundKext;
4134 }
4135 
4136 /*********************************************************************
4137 *********************************************************************/
4138 OSSharedPtr<OSKext>
lookupKextWithIdentifier(OSString * kextIdentifier)4139 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
4140 {
4141 	return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
4142 }
4143 
4144 /*********************************************************************
4145 *********************************************************************/
4146 OSSharedPtr<OSKext>
lookupDextWithIdentifier(OSString * dextIdentifier,OSData * dextUniqueIdentifier)4147 OSKext::lookupDextWithIdentifier(OSString * dextIdentifier, OSData *dextUniqueIdentifier)
4148 {
4149 	OSSharedPtr<OSKext> foundDext;
4150 	foundDext.reset();
4151 
4152 	IORecursiveLockLock(sKextLock);
4153 	OSKext *dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIdentifier->getCStringNoCopy()));
4154 	if (dext != NULL && dext->isDriverKit()) {
4155 		if (dext->dextUniqueID == NULL || dext->dextUniqueID->isEqualTo(dextUniqueIdentifier)) {
4156 			foundDext.reset(dext, OSRetain);
4157 		}
4158 	}
4159 	IORecursiveLockUnlock(sKextLock);
4160 
4161 	return foundDext;
4162 }
4163 
4164 /*********************************************************************
4165 *********************************************************************/
4166 OSSharedPtr<OSKext>
lookupKextWithLoadTag(uint32_t aTag)4167 OSKext::lookupKextWithLoadTag(uint32_t aTag)
4168 {
4169 	OSSharedPtr<OSKext> foundKext;             // returned
4170 	uint32_t i, j;
4171 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4172 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4173 
4174 	IORecursiveLockLock(sKextLock);
4175 
4176 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4177 		for (i = 0; i < count[j]; i++) {
4178 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4179 			if (thisKext->getLoadTag() == aTag) {
4180 				foundKext.reset(thisKext, OSRetain);
4181 				goto finish;
4182 			}
4183 		}
4184 	}
4185 
4186 finish:
4187 	IORecursiveLockUnlock(sKextLock);
4188 
4189 	return foundKext;
4190 }
4191 
4192 /*********************************************************************
4193 *********************************************************************/
4194 OSSharedPtr<OSKext>
lookupKextWithAddress(vm_address_t address)4195 OSKext::lookupKextWithAddress(vm_address_t address)
4196 {
4197 	OSSharedPtr<OSKext> foundKext;             // returned
4198 	uint32_t count, i;
4199 	kmod_info_t *kmod_info;
4200 	vm_address_t originalAddress;
4201 #if defined(__arm64__)
4202 	uint64_t   textExecBase;
4203 	size_t     textExecSize;
4204 #endif /* defined(__arm64__) */
4205 
4206 	originalAddress = address;
4207 #if  __has_feature(ptrauth_calls)
4208 	address = (vm_address_t)VM_KERNEL_STRIP_PTR(address);
4209 #endif /*  __has_feature(ptrauth_calls) */
4210 
4211 	IORecursiveLockLock(sKextLock);
4212 
4213 	count = sLoadedKexts->getCount();
4214 	for (i = 0; i < count; i++) {
4215 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
4216 		if (thisKext == sKernelKext) {
4217 			continue;
4218 		}
4219 		if (thisKext->kmod_info && thisKext->kmod_info->address) {
4220 			kmod_info = thisKext->kmod_info;
4221 			vm_address_t kext_start = kmod_info->address;
4222 			vm_address_t kext_end = kext_start + kmod_info->size;
4223 			if ((kext_start <= address) && (address < kext_end)) {
4224 				foundKext.reset(thisKext, OSRetain);
4225 				goto finish;
4226 			}
4227 #if defined(__arm64__)
4228 			textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize);
4229 
4230 			/**
4231 			 * If the addresses within the Mach-O are unslid, then manually
4232 			 * slide any addresses coming from the Mach-O before usage.
4233 			 */
4234 			if (thisKext->flags.unslidMachO) {
4235 				textExecBase = (uintptr_t) ml_static_slide((vm_offset_t) textExecBase);
4236 			}
4237 
4238 			if ((textExecBase <= address) && (address < textExecBase + textExecSize)) {
4239 				foundKext.reset(thisKext, OSRetain);
4240 				goto finish;
4241 			}
4242 #endif /* defined (__arm64__) */
4243 		}
4244 	}
4245 	if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) {
4246 		foundKext.reset(sKernelKext, OSRetain);
4247 		goto finish;
4248 	}
4249 	/*
4250 	 * DriverKit userspace executables do not have a kernel linkedExecutable,
4251 	 * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address
4252 	 * here, so use the original address passed to this method.
4253 	 *
4254 	 * This is supposed to be used for logging reasons only. When logd
4255 	 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
4256 	 * remove it here before checking it against the LoadTag.
4257 	 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
4258 	 */
4259 
4260 	address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
4261 	count = sLoadedDriverKitKexts->getCount();
4262 	for (i = 0; i < count; i++) {
4263 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
4264 		if (thisKext->getLoadTag() == address) {
4265 			foundKext.reset(thisKext, OSRetain);
4266 		}
4267 	}
4268 
4269 finish:
4270 	IORecursiveLockUnlock(sKextLock);
4271 
4272 	return foundKext;
4273 }
4274 
4275 OSSharedPtr<OSData>
copyKextUUIDForAddress(OSNumber * address)4276 OSKext::copyKextUUIDForAddress(OSNumber *address)
4277 {
4278 	OSSharedPtr<OSData>   uuid;
4279 	OSSharedPtr<OSKext>   kext;
4280 
4281 	if (!address) {
4282 		return NULL;
4283 	}
4284 
4285 #if CONFIG_MACF
4286 	/* Is the calling process allowed to query kext info? */
4287 	if (current_task() != kernel_task) {
4288 		int macCheckResult = 0;
4289 		kauth_cred_t cred = NULL;
4290 
4291 		cred = kauth_cred_get_with_ref();
4292 		macCheckResult = mac_kext_check_query(cred);
4293 		kauth_cred_unref(&cred);
4294 
4295 		if (macCheckResult != 0) {
4296 			OSKextLog(/* kext */ NULL,
4297 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
4298 			    "Failed to query kext UUID (MAC policy error 0x%x).",
4299 			    macCheckResult);
4300 			return NULL;
4301 		}
4302 	}
4303 #endif
4304 
4305 	uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue());
4306 	if (slidAddress != 0) {
4307 		kext = lookupKextWithAddress(slidAddress);
4308 		if (kext) {
4309 			uuid = kext->copyTextUUID();
4310 		}
4311 	}
4312 
4313 	if (!uuid) {
4314 		/*
4315 		 * If we still don't have a UUID, then we failed to match the slid + stripped address with
4316 		 * a kext. This might have happened because the log message came from a dext.
4317 		 *
4318 		 * Try again with the original address.
4319 		 */
4320 		kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue());
4321 		if (kext && kext->isDriverKit()) {
4322 			uuid = kext->copyTextUUID();
4323 		}
4324 	}
4325 
4326 	return uuid;
4327 }
4328 
4329 /*********************************************************************
4330 *********************************************************************/
4331 OSSharedPtr<OSKext>
lookupKextWithUUID(uuid_t wanted)4332 OSKext::lookupKextWithUUID(uuid_t wanted)
4333 {
4334 	OSSharedPtr<OSKext> foundKext;             // returned
4335 	uint32_t j, i;
4336 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4337 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4338 
4339 
4340 	IORecursiveLockLock(sKextLock);
4341 
4342 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4343 		for (i = 0; i < count[j]; i++) {
4344 			OSKext   * thisKext     = NULL;
4345 
4346 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4347 			if (!thisKext) {
4348 				continue;
4349 			}
4350 
4351 			OSSharedPtr<OSData> uuid_data = thisKext->copyUUID();
4352 			if (!uuid_data) {
4353 				continue;
4354 			}
4355 
4356 			uuid_t uuid;
4357 			memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
4358 
4359 			if (0 == uuid_compare(wanted, uuid)) {
4360 				foundKext.reset(thisKext, OSRetain);
4361 				goto finish;
4362 			}
4363 		}
4364 	}
4365 finish:
4366 	IORecursiveLockUnlock(sKextLock);
4367 
4368 	return foundKext;
4369 }
4370 
4371 
4372 
4373 
4374 /*********************************************************************
4375 *********************************************************************/
4376 /* static */
4377 bool
isKextWithIdentifierLoaded(const char * kextIdentifier)4378 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
4379 {
4380 	bool result = false;
4381 	OSKext * foundKext = NULL;             // returned
4382 
4383 	IORecursiveLockLock(sKextLock);
4384 
4385 	foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4386 	if (foundKext && foundKext->isLoaded()) {
4387 		result = true;
4388 	}
4389 
4390 	IORecursiveLockUnlock(sKextLock);
4391 
4392 	return result;
4393 }
4394 
4395 /*********************************************************************
4396 * xxx - should spawn a separate thread so a kext can safely have
4397 * xxx - itself unloaded.
4398 *********************************************************************/
4399 /* static */
4400 OSReturn
removeKext(OSKext * aKext,__unused bool terminateServicesAndRemovePersonalitiesFlag)4401 OSKext::removeKext(
4402 	OSKext * aKext,
4403 #if CONFIG_EMBEDDED
4404 	__unused
4405 #endif
4406 	bool     terminateServicesAndRemovePersonalitiesFlag)
4407 {
4408 #if CONFIG_EMBEDDED
4409 	if (!aKext->isDriverKit()) {
4410 		OSKextLog(aKext,
4411 		    kOSKextLogErrorLevel |
4412 		    kOSKextLogKextBookkeepingFlag,
4413 		    "removeKext() called for %s, only supported on embedded for DriverKit dexts",
4414 		    aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
4415 
4416 		return kOSReturnSuccess;
4417 	}
4418 #endif /* CONFIG_EMBEDDED */
4419 	OSReturn result    = kOSKextReturnInUse;
4420 	OSKext * checkKext = NULL;         // do not release
4421 #if CONFIG_MACF
4422 	int macCheckResult = 0;
4423 	kauth_cred_t cred  = NULL;
4424 #endif
4425 
4426 	IORecursiveLockLock(sKextLock);
4427 
4428 	/* If the kext has no identifier, it failed to init
4429 	 * so isn't in sKextsByID and it isn't loaded.
4430 	 */
4431 	if (!aKext->getIdentifier()) {
4432 		result = kOSReturnSuccess;
4433 		goto finish;
4434 	}
4435 
4436 	checkKext = OSDynamicCast(OSKext,
4437 	    sKextsByID->getObject(aKext->getIdentifier()));
4438 	if (checkKext != aKext) {
4439 		result = kOSKextReturnNotFound;
4440 		goto finish;
4441 	}
4442 
4443 	if (aKext->isLoaded() || aKext->isDriverKit()) {
4444 #if CONFIG_MACF
4445 		if (current_task() != kernel_task) {
4446 			cred = kauth_cred_get_with_ref();
4447 			macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
4448 			kauth_cred_unref(&cred);
4449 		}
4450 
4451 		if (macCheckResult != 0) {
4452 			result = kOSReturnError;
4453 			OSKextLog(aKext,
4454 			    kOSKextLogErrorLevel |
4455 			    kOSKextLogKextBookkeepingFlag,
4456 			    "Failed to remove kext %s (MAC policy error 0x%x).",
4457 			    aKext->getIdentifierCString(), macCheckResult);
4458 			goto finish;
4459 		}
4460 #endif
4461 
4462 		/* make sure there are no resource requests in flight - 17187548 */
4463 		if (aKext->declaresExecutable() && aKext->countRequestCallbacks()) {
4464 			goto finish;
4465 		}
4466 		if (aKext->flags.unloadUnsupported) {
4467 			result = kOSKextReturnInUse;
4468 			OSKextLog(aKext,
4469 			    kOSKextLogErrorLevel |
4470 			    kOSKextLogKextBookkeepingFlag,
4471 			    "Can't remove kext %s; unsupported by cache.",
4472 			    aKext->getIdentifierCString());
4473 			goto finish;
4474 		}
4475 
4476 		/* If we are terminating, send the request to the IOCatalogue
4477 		 * (which will actually call us right back but that's ok we have
4478 		 * a recursive lock don't you know) but do not ask the IOCatalogue
4479 		 * to call back with an unload, we'll do that right here.
4480 		 */
4481 		if (terminateServicesAndRemovePersonalitiesFlag) {
4482 			result = gIOCatalogue->terminateDriversForModule(
4483 				aKext->getIdentifierCString(), /* unload */ false);
4484 			if (result != kOSReturnSuccess) {
4485 				OSKextLog(aKext,
4486 				    kOSKextLogErrorLevel |
4487 				    kOSKextLogKextBookkeepingFlag,
4488 				    "Can't remove kext %s; services failed to terminate - 0x%x.",
4489 				    aKext->getIdentifierCString(), result);
4490 				goto finish;
4491 			}
4492 		}
4493 
4494 		result = aKext->unload();
4495 		if (result != kOSReturnSuccess) {
4496 			OSKextLog(aKext,
4497 			    kOSKextLogErrorLevel |
4498 			    kOSKextLogKextBookkeepingFlag,
4499 			    "Can't remove kext %s; kext failed to unload - 0x%x.",
4500 			    aKext->getIdentifierCString(), result);
4501 			goto finish;
4502 		}
4503 	}
4504 
4505 	/* Remove personalities as requested. This is a bit redundant for a loaded
4506 	 * kext as IOCatalogue::terminateDriversForModule() removes driver
4507 	 * personalities, but it doesn't restart matching, which we always want
4508 	 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
4509 	 * that happens.
4510 	 */
4511 	if (terminateServicesAndRemovePersonalitiesFlag) {
4512 		aKext->removePersonalitiesFromCatalog();
4513 	}
4514 
4515 	if (aKext->isInFileset()) {
4516 		OSKextLog(aKext,
4517 		    kOSKextLogProgressLevel |
4518 		    kOSKextLogKextBookkeepingFlag,
4519 		    "Fileset kext %s unloaded.",
4520 		    aKext->getIdentifierCString());
4521 	} else {
4522 		OSKextLog(aKext,
4523 		    kOSKextLogProgressLevel |
4524 		    kOSKextLogKextBookkeepingFlag,
4525 		    "Removing kext %s.",
4526 		    aKext->getIdentifierCString());
4527 
4528 		sKextsByID->removeObject(aKext->getIdentifier());
4529 	}
4530 	result = kOSReturnSuccess;
4531 
4532 finish:
4533 	IORecursiveLockUnlock(sKextLock);
4534 	return result;
4535 }
4536 
4537 /*********************************************************************
4538 *********************************************************************/
4539 /* static */
4540 OSReturn
removeKextWithIdentifier(const char * kextIdentifier,bool terminateServicesAndRemovePersonalitiesFlag)4541 OSKext::removeKextWithIdentifier(
4542 	const char * kextIdentifier,
4543 	bool         terminateServicesAndRemovePersonalitiesFlag)
4544 {
4545 	OSReturn result = kOSReturnError;
4546 
4547 	IORecursiveLockLock(sKextLock);
4548 
4549 	OSKext * aKext = OSDynamicCast(OSKext,
4550 	    sKextsByID->getObject(kextIdentifier));
4551 	if (!aKext) {
4552 		result = kOSKextReturnNotFound;
4553 		OSKextLog(/* kext */ NULL,
4554 		    kOSKextLogErrorLevel |
4555 		    kOSKextLogKextBookkeepingFlag,
4556 		    "Can't remove kext %s - not found.",
4557 		    kextIdentifier);
4558 		goto finish;
4559 	}
4560 
4561 	result = OSKext::removeKext(aKext,
4562 	    terminateServicesAndRemovePersonalitiesFlag);
4563 
4564 finish:
4565 	IORecursiveLockUnlock(sKextLock);
4566 
4567 	return result;
4568 }
4569 
4570 /*********************************************************************
4571 *********************************************************************/
4572 /* static */
4573 OSReturn
removeKextWithLoadTag(OSKextLoadTag loadTag,bool terminateServicesAndRemovePersonalitiesFlag)4574 OSKext::removeKextWithLoadTag(
4575 	OSKextLoadTag loadTag,
4576 	bool          terminateServicesAndRemovePersonalitiesFlag)
4577 {
4578 	OSReturn result    = kOSReturnError;
4579 	OSKext * foundKext = NULL;
4580 	uint32_t i, j;
4581 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4582 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4583 
4584 
4585 	IORecursiveLockLock(sKextLock);
4586 
4587 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4588 		for (i = 0; i < count[j]; i++) {
4589 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4590 			if (thisKext->loadTag == loadTag) {
4591 				foundKext = thisKext;
4592 				break;
4593 			}
4594 		}
4595 	}
4596 
4597 	if (!foundKext) {
4598 		result = kOSKextReturnNotFound;
4599 		OSKextLog(/* kext */ NULL,
4600 		    kOSKextLogErrorLevel |
4601 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4602 		    "Can't remove kext with load tag %d - not found.",
4603 		    loadTag);
4604 		goto finish;
4605 	}
4606 
4607 	result = OSKext::removeKext(foundKext,
4608 	    terminateServicesAndRemovePersonalitiesFlag);
4609 
4610 finish:
4611 	IORecursiveLockUnlock(sKextLock);
4612 
4613 	return result;
4614 }
4615 
4616 /*********************************************************************
4617 *********************************************************************/
4618 OSSharedPtr<OSDictionary>
copyKexts(void)4619 OSKext::copyKexts(void)
4620 {
4621 	OSSharedPtr<OSDictionary> result;
4622 
4623 	IORecursiveLockLock(sKextLock);
4624 	result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection());
4625 	IORecursiveLockUnlock(sKextLock);
4626 
4627 	return result;
4628 }
4629 
4630 /*********************************************************************
4631 *********************************************************************/
4632 #define BOOTER_KEXT_PREFIX   "Driver-"
4633 
4634 typedef struct _DeviceTreeBuffer {
4635 	uint32_t paddr;
4636 	uint32_t length;
4637 } _DeviceTreeBuffer;
4638 
4639 /*********************************************************************
4640 * Create a dictionary of excluded kexts from the given booter data.
4641 *********************************************************************/
4642 /* static */
4643 void
createExcludeListFromBooterData(OSDictionary * theDictionary,OSCollectionIterator * theIterator)4644 OSKext::createExcludeListFromBooterData(
4645 	OSDictionary *          theDictionary,
4646 	OSCollectionIterator *  theIterator )
4647 {
4648 	OSString                  * deviceTreeName      = NULL;        // do not release
4649 	const _DeviceTreeBuffer   * deviceTreeBuffer    = NULL;        // do not release
4650 	char                      * booterDataPtr       = NULL;        // do not release
4651 	_BooterKextFileInfo       * kextFileInfo        = NULL;        // do not release
4652 	char                      * infoDictAddr        = NULL;        // do not release
4653 	OSSharedPtr<OSObject>       parsedXML;
4654 	OSDictionary              * theInfoDict         = NULL;        // do not release
4655 
4656 	theIterator->reset();
4657 
4658 	/* look for AppleKextExcludeList.kext */
4659 	while ((deviceTreeName =
4660 	    OSDynamicCast(OSString, theIterator->getNextObject()))) {
4661 		const char *    devTreeNameCString;
4662 		OSData *        deviceTreeEntry;        // do not release
4663 		OSString *      myBundleID;        // do not release
4664 
4665 		deviceTreeEntry =
4666 		    OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
4667 		if (!deviceTreeEntry) {
4668 			continue;
4669 		}
4670 
4671 		/* Make sure it is a kext */
4672 		devTreeNameCString = deviceTreeName->getCStringNoCopy();
4673 		if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
4674 		    (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
4675 			OSKextLog(NULL,
4676 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4677 			    "\"%s\" not a kext",
4678 			    devTreeNameCString);
4679 			continue;
4680 		}
4681 
4682 		deviceTreeBuffer = (const _DeviceTreeBuffer *)
4683 		    deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
4684 		if (!deviceTreeBuffer) {
4685 			continue;
4686 		}
4687 
4688 		booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
4689 		if (!booterDataPtr) {
4690 			continue;
4691 		}
4692 
4693 		kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
4694 		if (!kextFileInfo->infoDictPhysAddr ||
4695 		    !kextFileInfo->infoDictLength) {
4696 			continue;
4697 		}
4698 
4699 		infoDictAddr = (char *)
4700 		    ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
4701 		if (!infoDictAddr) {
4702 			continue;
4703 		}
4704 
4705 		parsedXML = OSUnserializeXML(infoDictAddr);
4706 		if (!parsedXML) {
4707 			continue;
4708 		}
4709 
4710 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
4711 		if (!theInfoDict) {
4712 			continue;
4713 		}
4714 
4715 		myBundleID =
4716 		    OSDynamicCast(OSString,
4717 		    theInfoDict->getObject(kCFBundleIdentifierKey));
4718 		if (myBundleID &&
4719 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4720 			boolean_t updated = updateExcludeList(theInfoDict);
4721 			if (!updated) {
4722 				/* 25322874 */
4723 				panic("Missing OSKextExcludeList dictionary");
4724 			}
4725 			break;
4726 		}
4727 	}         // while ( (deviceTreeName = ...) )
4728 
4729 	return;
4730 }
4731 
4732 /*********************************************************************
4733 * Create a dictionary of excluded kexts from the given prelink
4734 * info (kernelcache).
4735 *********************************************************************/
4736 /* static */
4737 void
createExcludeListFromPrelinkInfo(OSArray * theInfoArray)4738 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
4739 {
4740 	OSDictionary *  myInfoDict = NULL;        // do not release
4741 	OSString *      myBundleID;        // do not release
4742 	u_int           i;
4743 
4744 	/* Find the Apple Kext Exclude List. */
4745 	for (i = 0; i < theInfoArray->getCount(); i++) {
4746 		myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
4747 		if (!myInfoDict) {
4748 			continue;
4749 		}
4750 		myBundleID =
4751 		    OSDynamicCast(OSString,
4752 		    myInfoDict->getObject(kCFBundleIdentifierKey));
4753 		if (myBundleID &&
4754 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4755 			boolean_t updated = updateExcludeList(myInfoDict);
4756 			if (!updated) {
4757 				/* 25322874 */
4758 				panic("Missing OSKextExcludeList dictionary");
4759 			}
4760 			break;
4761 		}
4762 	}         // for (i = 0; i < theInfoArray->getCount()...
4763 
4764 	return;
4765 }
4766 
4767 /* static */
4768 boolean_t
updateExcludeList(OSDictionary * infoDict)4769 OSKext::updateExcludeList(OSDictionary *infoDict)
4770 {
4771 	OSDictionary *myTempDict = NULL;         // do not free
4772 	OSString     *myTempString = NULL;        // do not free
4773 	OSKextVersion newVersion = 0;
4774 	boolean_t updated = false;
4775 
4776 	if (!infoDict) {
4777 		return false;
4778 	}
4779 
4780 	myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
4781 	if (!myTempDict) {
4782 		return false;
4783 	}
4784 
4785 	myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
4786 	if (!myTempString) {
4787 		return false;
4788 	}
4789 
4790 	newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
4791 	if (newVersion == 0) {
4792 		return false;
4793 	}
4794 
4795 	IORecursiveLockLock(sKextLock);
4796 
4797 	if (newVersion > sExcludeListVersion) {
4798 		sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
4799 		sExcludeListVersion = newVersion;
4800 		updated = true;
4801 	}
4802 
4803 	IORecursiveLockUnlock(sKextLock);
4804 	return updated;
4805 }
4806 
4807 #if PRAGMA_MARK
4808 #pragma mark Accessors
4809 #endif
4810 
4811 /*********************************************************************
4812 *********************************************************************/
4813 const OSObject *
getBundleExecutable(void)4814 OSKext::getBundleExecutable(void)
4815 {
4816 	return infoDict->getObject(kCFBundleExecutableKey);
4817 }
4818 
4819 /*********************************************************************
4820 *********************************************************************/
4821 const OSSymbol *
getIdentifier(void)4822 OSKext::getIdentifier(void)
4823 {
4824 	return bundleID.get();
4825 }
4826 
4827 /*********************************************************************
4828 * A kext must have a bundle identifier to even survive initialization;
4829 * this is guaranteed to exist past then.
4830 *********************************************************************/
4831 const char *
getIdentifierCString(void)4832 OSKext::getIdentifierCString(void)
4833 {
4834 	return bundleID->getCStringNoCopy();
4835 }
4836 
4837 /*********************************************************************
4838 *********************************************************************/
4839 OSKextVersion
getVersion(void)4840 OSKext::getVersion(void)
4841 {
4842 	return version;
4843 }
4844 
4845 /*********************************************************************
4846 *********************************************************************/
4847 OSKextVersion
getCompatibleVersion(void)4848 OSKext::getCompatibleVersion(void)
4849 {
4850 	return compatibleVersion;
4851 }
4852 
4853 /*********************************************************************
4854 *********************************************************************/
4855 bool
isLibrary(void)4856 OSKext::isLibrary(void)
4857 {
4858 	return getCompatibleVersion() > 0;
4859 }
4860 
4861 /*********************************************************************
4862 *********************************************************************/
4863 bool
isCompatibleWithVersion(OSKextVersion aVersion)4864 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
4865 {
4866 	if ((compatibleVersion > -1 && version > -1) &&
4867 	    (compatibleVersion <= version && aVersion <= version)) {
4868 		return true;
4869 	}
4870 	return false;
4871 }
4872 
4873 /*********************************************************************
4874 *********************************************************************/
4875 bool
declaresExecutable(void)4876 OSKext::declaresExecutable(void)
4877 {
4878 	if (isDriverKit()) {
4879 		return false;
4880 	}
4881 	return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
4882 }
4883 
4884 /*********************************************************************
4885 *********************************************************************/
4886 OSData *
getExecutable(void)4887 OSKext::getExecutable(void)
4888 {
4889 	OSData * result              = NULL;
4890 	OSSharedPtr<OSData> extractedExecutable;
4891 
4892 	if (flags.builtin) {
4893 		return sKernelKext->linkedExecutable.get();
4894 	}
4895 
4896 	result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
4897 	if (result) {
4898 		return result;
4899 	}
4900 
4901 #if CONFIG_KXLD
4902 	OSData * mkextExecutableRef  = NULL;        // do not release
4903 	mkextExecutableRef = OSDynamicCast(OSData,
4904 	    getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
4905 
4906 	if (mkextExecutableRef) {
4907 		MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
4908 		    mkextExecutableRef->getBytesNoCopy();
4909 		uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
4910 		if (mkextVersion == MKEXT_VERS_2) {
4911 			mkext2_file_entry * fileinfo =
4912 			    (mkext2_file_entry *)mkextEntryRef->fileinfo;
4913 			uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
4914 			uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
4915 			extractedExecutable = extractMkext2FileData(
4916 				MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
4917 				compressedSize, fullSize);
4918 		} else {
4919 			OSKextLog(this, kOSKextLogErrorLevel |
4920 			    kOSKextLogArchiveFlag,
4921 			    "Kext %s - unknown mkext version 0x%x for executable.",
4922 			    getIdentifierCString(), mkextVersion);
4923 		}
4924 
4925 		/* Regardless of success, remove the mkext executable,
4926 		 * and drop one reference on the mkext.  (setExecutable() does not
4927 		 * replace, it removes, or panics if asked to replace.)
4928 		 */
4929 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4930 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4931 
4932 		if (extractedExecutable && extractedExecutable->getLength()) {
4933 			if (!setExecutable(extractedExecutable.get())) {
4934 				goto finish;
4935 			}
4936 			result = extractedExecutable.get();
4937 		} else {
4938 			goto finish;
4939 		}
4940 	}
4941 
4942 finish:
4943 #endif // CONFIG_KXLD
4944 	return result;
4945 }
4946 
4947 /*********************************************************************
4948 *********************************************************************/
4949 bool
isInterface(void)4950 OSKext::isInterface(void)
4951 {
4952 	return flags.interface;
4953 }
4954 
4955 /*********************************************************************
4956 *********************************************************************/
4957 bool
isKernel(void)4958 OSKext::isKernel(void)
4959 {
4960 	return this == sKernelKext;
4961 }
4962 
4963 /*********************************************************************
4964 *********************************************************************/
4965 bool
isKernelComponent(void)4966 OSKext::isKernelComponent(void)
4967 {
4968 	return flags.kernelComponent ? true : false;
4969 }
4970 
4971 /*********************************************************************
4972 *********************************************************************/
4973 bool
isExecutable(void)4974 OSKext::isExecutable(void)
4975 {
4976 	return !isKernel() && !isInterface() && declaresExecutable();
4977 }
4978 
4979 /*********************************************************************
4980 *********************************************************************/
4981 bool
isSpecialKernelBinary(void)4982 OSKext::isSpecialKernelBinary(void)
4983 {
4984 	return false;
4985 }
4986 
4987 /*********************************************************************
4988 * We might want to check this recursively for all dependencies,
4989 * since a subtree of dependencies could get loaded before we hit
4990 * a dependency that isn't safe-boot-loadable.
4991 *
4992 * xxx - Might want to return false if OSBundleEnableKextLogging or
4993 * OSBundleDebugLevel
4994 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4995 * the point except it's usually development drivers, which might
4996 * cause panics on startup, that have those properties). Heh; could
4997 * use a "kx" boot-arg!
4998 *********************************************************************/
4999 bool
isLoadableInSafeBoot(void)5000 OSKext::isLoadableInSafeBoot(void)
5001 {
5002 	bool       result   = false;
5003 	OSString * required = NULL;         // do not release
5004 
5005 	if (isKernel()) {
5006 		result = true;
5007 		goto finish;
5008 	}
5009 
5010 	if (isDriverKit()) {
5011 		result = true;
5012 		goto finish;
5013 	}
5014 
5015 	required = OSDynamicCast(OSString,
5016 	    getPropertyForHostArch(kOSBundleRequiredKey));
5017 	if (!required) {
5018 		goto finish;
5019 	}
5020 	if (required->isEqualTo(kOSBundleRequiredRoot) ||
5021 	    required->isEqualTo(kOSBundleRequiredLocalRoot) ||
5022 	    required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
5023 	    required->isEqualTo(kOSBundleRequiredSafeBoot) ||
5024 	    required->isEqualTo(kOSBundleRequiredConsole)) {
5025 		result = true;
5026 	}
5027 
5028 finish:
5029 	return result;
5030 }
5031 
5032 /*********************************************************************
5033 *********************************************************************/
5034 bool
isPrelinked(void)5035 OSKext::isPrelinked(void)
5036 {
5037 	return flags.prelinked ? true : false;
5038 }
5039 
5040 /*********************************************************************
5041 *********************************************************************/
5042 bool
isLoaded(void)5043 OSKext::isLoaded(void)
5044 {
5045 	return flags.loaded ? true : false;
5046 }
5047 
5048 /*********************************************************************
5049 *********************************************************************/
5050 bool
isStarted(void)5051 OSKext::isStarted(void)
5052 {
5053 	return flags.started ? true : false;
5054 }
5055 
5056 /*********************************************************************
5057 *********************************************************************/
5058 bool
isCPPInitialized(void)5059 OSKext::isCPPInitialized(void)
5060 {
5061 	return flags.CPPInitialized;
5062 }
5063 
5064 /*********************************************************************
5065 *********************************************************************/
5066 void
setCPPInitialized(bool initialized)5067 OSKext::setCPPInitialized(bool initialized)
5068 {
5069 	flags.CPPInitialized = initialized;
5070 }
5071 
5072 /*********************************************************************
5073 *********************************************************************/
5074 uint32_t
getLoadTag(void)5075 OSKext::getLoadTag(void)
5076 {
5077 	return loadTag;
5078 }
5079 
5080 /*********************************************************************
5081 *********************************************************************/
5082 void
getSizeInfo(uint32_t * loadSize,uint32_t * wiredSize)5083 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
5084 {
5085 	if (linkedExecutable) {
5086 		*loadSize = linkedExecutable->getLength();
5087 
5088 		/* If we have a kmod_info struct, calculated the wired size
5089 		 * from that. Otherwise it's the full load size.
5090 		 */
5091 		if (kmod_info) {
5092 			*wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size;
5093 		} else {
5094 			*wiredSize = *loadSize;
5095 		}
5096 	} else {
5097 		*wiredSize = 0;
5098 		*loadSize = 0;
5099 	}
5100 }
5101 
5102 /*********************************************************************
5103 *********************************************************************/
5104 OSSharedPtr<OSData>
copyUUID(void)5105 OSKext::copyUUID(void)
5106 {
5107 	OSSharedPtr<OSData>          result;
5108 	OSData                     * theExecutable = NULL;        // do not release
5109 	const kernel_mach_header_t * header;
5110 
5111 	/* An interface kext doesn't have a linked executable with an LC_UUID,
5112 	 * we create one when it's linked.
5113 	 */
5114 	if (interfaceUUID) {
5115 		result = interfaceUUID;
5116 		goto finish;
5117 	}
5118 
5119 	if (flags.builtin || isInterface()) {
5120 		return sKernelKext->copyUUID();
5121 	}
5122 
5123 	if (isDriverKit() && infoDict) {
5124 		return driverKitUUID;
5125 	}
5126 
5127 	/* For real kexts, try to get the UUID from the linked executable,
5128 	 * or if is hasn't been linked yet, the unrelocated executable.
5129 	 */
5130 	theExecutable = linkedExecutable.get();
5131 	if (!theExecutable) {
5132 		theExecutable = getExecutable();
5133 	}
5134 
5135 	if (!theExecutable) {
5136 		goto finish;
5137 	}
5138 
5139 	header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
5140 	result = copyMachoUUID(header);
5141 
5142 finish:
5143 	return result;
5144 }
5145 
5146 /*********************************************************************
5147 *********************************************************************/
5148 OSSharedPtr<OSData>
copyTextUUID(void)5149 OSKext::copyTextUUID(void)
5150 {
5151 	if (flags.builtin) {
5152 		return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
5153 	}
5154 	return copyUUID();
5155 }
5156 
5157 /*********************************************************************
5158 *********************************************************************/
5159 OSSharedPtr<OSData>
copyMachoUUID(const kernel_mach_header_t * header)5160 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
5161 {
5162 	OSSharedPtr<OSData>                     result;
5163 	const struct load_command  * load_cmd      = NULL;
5164 	const struct uuid_command  * uuid_cmd      = NULL;
5165 	uint32_t                     i;
5166 
5167 	load_cmd = (const struct load_command *)&header[1];
5168 
5169 	if (header->magic != MH_MAGIC_KERNEL) {
5170 		OSKextLog(NULL,
5171 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
5172 		    "%s: bad header %p",
5173 		    __func__,
5174 		    header);
5175 		goto finish;
5176 	}
5177 
5178 	for (i = 0; i < header->ncmds; i++) {
5179 		if (load_cmd->cmd == LC_UUID) {
5180 			uuid_cmd = (struct uuid_command *)load_cmd;
5181 			result = OSData::withValue(uuid_cmd->uuid);
5182 			goto finish;
5183 		}
5184 		load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
5185 	}
5186 
5187 finish:
5188 	return result;
5189 }
5190 
5191 void
setDriverKitUUID(OSData * uuid)5192 OSKext::setDriverKitUUID(OSData *uuid)
5193 {
5194 	if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
5195 		OSSafeReleaseNULL(uuid);
5196 	}
5197 }
5198 
5199 OSData *
getDextUniqueID(void)5200 OSKext::getDextUniqueID(void)
5201 {
5202 	if (isDriverKit() && dextUniqueID != NULL) {
5203 		return dextUniqueID.get();
5204 	}
5205 
5206 	return NULL;
5207 }
5208 
5209 /*
5210  * In case a DextUniqueID exists this function returns
5211  * an allocated char* with the hexadecimal represantition of
5212  * DextUniqueID.
5213  * The returned pinter needs to be freed with kfree_data, the
5214  * size of the allocated buffer is returned in size.
5215  */
5216 static const char *
getDextUniqueIDCString(OSData * dextUniqueID,unsigned int * size)5217 getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size)
5218 {
5219 	if (dextUniqueID != NULL) {
5220 		char *s_buffer = NULL;
5221 		unsigned int d_length = dextUniqueID->getLength();
5222 		/*
5223 		 * We are converting in hex, so for every byte we will have
5224 		 * 2 hex chars and one last \0.
5225 		 */
5226 		unsigned int s_length = d_length * 2 + 1;
5227 		s_buffer = (char *) kalloc_data(s_length, Z_WAITOK_ZERO);
5228 
5229 		char *uid = (char*) dextUniqueID->getBytesNoCopy();
5230 		int cpos = 0;
5231 		for (unsigned int i = 0; i < d_length && cpos < (s_length - 1); i++) {
5232 			int ret = snprintf(s_buffer + cpos, s_length - cpos - 1, "%02X", uid[i]);
5233 			if (ret <= 0) {
5234 				break;
5235 			}
5236 			cpos += ret;
5237 		}
5238 		*size = s_length;
5239 
5240 		return s_buffer;
5241 	}
5242 
5243 	return NULL;
5244 }
5245 
5246 /*
5247  * Atomically swaps the olddext with newdext.
5248  * olddext will be unloaded, so it might be freed
5249  * after this call unless it was previously retained.
5250  *
5251  * If newdext is NULL, this unloads olddext and does not perform an upgrade
5252  */
5253 void
replaceDextInternal(OSKext * olddext,OSKext * newdext)5254 OSKext::replaceDextInternal(OSKext *olddext, OSKext *newdext)
5255 {
5256 	OSReturn result;
5257 	const OSSymbol * dextID = olddext->getIdentifier();
5258 	OSData * oldDextUniqueIdentifier = olddext->getDextUniqueID();
5259 	OSSharedPtr<OSArray> new_personalities;
5260 	OSSharedPtr<OSString> kextIdentifier;
5261 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5262 	assert(lock_held);
5263 
5264 	// The old dext will be unloaded and release dextID, so we need to retain dextID here
5265 	dextID->retain();
5266 
5267 	if (newdext != NULL) {
5268 		__assert_only bool eq = dextID->isEqualTo(newdext->getIdentifier());
5269 		assert(eq);
5270 	}
5271 
5272 	if (newdext != NULL) {
5273 		/*
5274 		 * Swap the catalog personalities.
5275 		 */
5276 		new_personalities = newdext->copyPersonalitiesArray();
5277 		olddext->updatePersonalitiesInCatalog(new_personalities.get());
5278 	}
5279 
5280 	if (NULL != oldDextUniqueIdentifier) {
5281 		oldDextUniqueIdentifier->retain();
5282 	}
5283 
5284 	/*
5285 	 * Unload the dext.
5286 	 */
5287 	result = olddext->unload();
5288 	if (result != kOSReturnSuccess) {
5289 		OSKextLog(NULL,
5290 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5291 		    "Cannot unload dext for upgrade %s: %d\n",
5292 		    dextID->getCStringNoCopy(), result);
5293 	}
5294 
5295 	if (newdext != NULL) {
5296 		/*
5297 		 * Swap the dexts on the OSKext dictionary.
5298 		 * This might free the dext.
5299 		 */
5300 		sKextsByID->setObject(dextID, newdext);
5301 	} else {
5302 		/*
5303 		 * Remove the old dext
5304 		 */
5305 		removeKext(olddext, true);
5306 	}
5307 
5308 	/*
5309 	 * Inform userspace.
5310 	 */
5311 	if (newdext != NULL) {
5312 		result = notifyDextUpgrade(OSDynamicCast(OSString, dextID), newdext->getDextUniqueID());
5313 		if (result != kOSReturnSuccess) {
5314 			OSKextLog(NULL,
5315 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5316 			    "Cannot send upgrade notification for %s\n",
5317 			    dextID->getCStringNoCopy());
5318 		}
5319 	} else {
5320 		// notify dext removal
5321 		queueKextNotification(kKextRequestPredicateUnloadNotification,
5322 		    OSDynamicCast(OSString, dextID), oldDextUniqueIdentifier);
5323 	}
5324 
5325 	OSSafeReleaseNULL(dextID);
5326 	OSSafeReleaseNULL(oldDextUniqueIdentifier);
5327 }
5328 
5329 /*
5330  * To be called with sKextLock held.
5331  * NOTE: this could unload the olddext.
5332  */
5333 bool
upgradeDext(OSKext * olddext,OSKext * newdext)5334 OSKext::upgradeDext(OSKext *olddext, OSKext *newdext)
5335 {
5336 	const char * dextIDCS = newdext->getIdentifierCString();
5337 	__assert_only bool old_isDext = olddext->isDriverKit();
5338 	__assert_only bool new_isDext = newdext->isDriverKit();
5339 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5340 
5341 	assert(old_isDext && new_isDext);
5342 	assert(lock_held);
5343 
5344 	/*
5345 	 * New dext and old dext have the same ID.
5346 	 * We use this ID as key on the OSKext
5347 	 * dictionarys/arrays.
5348 	 */
5349 	const OSSymbol * dextID = newdext->getIdentifier();
5350 	__assert_only bool eq = dextID->isEqualTo(olddext->getIdentifier());
5351 	assert(eq);
5352 
5353 	/*
5354 	 * Set this OSKect as to update.
5355 	 * Note that this flags will never be removed once set.
5356 	 * When a OSKext is marked, it will be substitued by a new
5357 	 * OSKext, and every subsystem having a reference on this
5358 	 * OSKext need to know they have check if they can use
5359 	 * this OSKext or look for a new one.
5360 	 */
5361 	olddext->flags.dextToReplace = 1;
5362 
5363 	/*
5364 	 * Check if the current OSKext has any
5365 	 * userspace processes launched.
5366 	 * In this case we cannot upgrade and we have to
5367 	 * delay the upgrade until all processes
5368 	 * are done.
5369 	 */
5370 	if (olddext->dextLaunchedCount == 0) {
5371 		/*
5372 		 * Be sure that if there are no launched dexts, no
5373 		 * pending upgrades exist.
5374 		 * This is an error if it happens, as the decrement
5375 		 * should have removed the dext from sDriverKitToUpgradeByID
5376 		 * in case it reached 0.
5377 		 */
5378 		OSObject *pending_upgdare = sDriverKitToUpgradeByID->getObject(dextID);
5379 		if (pending_upgdare != NULL) {
5380 			OSKextLog(NULL,
5381 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5382 			    "Pending upgrade found for %s but dextLaunchedCount is 0!\n",
5383 			    dextIDCS);
5384 			goto out;
5385 		}
5386 
5387 		replaceDextInternal(olddext, newdext);
5388 		return true;
5389 	}
5390 
5391 out:
5392 
5393 	/*
5394 	 * Delay the upgrade.
5395 	 * Make the new dext available in sDriverKitToUpgradeByID.
5396 	 * In case there was already a pending upgrade, this will
5397 	 * overwrite it.
5398 	 */
5399 	sDriverKitToUpgradeByID->setObject(dextID, newdext);
5400 	return false;
5401 }
5402 
5403 /*
5404  * To be called with sKextLock held.
5405  * NOTE: this could unload the dext.
5406  */
5407 bool
removeDext(OSKext * dext)5408 OSKext::removeDext(OSKext *dext)
5409 {
5410 	__assert_only bool dext_isDext = dext->isDriverKit();
5411 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5412 	IOReturn result;
5413 
5414 	assert(dext_isDext);
5415 	assert(lock_held);
5416 
5417 	/*
5418 	 * Set this OSKext to be unloaded when all running instances exit.
5419 	 */
5420 	dext->flags.dextToReplace = 1;
5421 
5422 	result = gIOCatalogue->terminateDriversForModule(
5423 		dext->getIdentifierCString(), /* unload */ false, /* asynchronous */ true);
5424 	if (result != kOSReturnSuccess) {
5425 		OSKextLog(dext,
5426 		    kOSKextLogErrorLevel |
5427 		    kOSKextLogKextBookkeepingFlag,
5428 		    "%s services failed to terminate - 0x%x.",
5429 		    dext->getIdentifierCString(), result);
5430 	}
5431 
5432 	dext->removePersonalitiesFromCatalog();
5433 	sDriverKitToUpgradeByID->removeObject(dext->getIdentifier());
5434 
5435 	/*
5436 	 * Check if the current OSKext has any
5437 	 * userspace processes launched.
5438 	 * In this case we cannot unload and we have to
5439 	 * delay the unload until all processes
5440 	 * are done.
5441 	 */
5442 	if (dext->dextLaunchedCount == 0) {
5443 		replaceDextInternal(dext, NULL);
5444 		return true;
5445 	}
5446 
5447 	return false;
5448 }
5449 
5450 bool
incrementDextLaunchCount(OSKext * dext,OSData * dextUniqueIDToMatch)5451 OSKext::incrementDextLaunchCount(OSKext *dext, OSData *dextUniqueIDToMatch)
5452 {
5453 	bool ret = false;
5454 	__assert_only bool isDext = dext->isDriverKit();
5455 	assert(isDext);
5456 
5457 	const char * dextIDCS = dext->getIdentifierCString();
5458 	OSData *myDextUniqueID = dext->getDextUniqueID();
5459 
5460 	if (!myDextUniqueID || !dextUniqueIDToMatch) {
5461 		OSKextLog(dext,
5462 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5463 		    "Cannot find dext UniqueID for %s, cannot increment dext launches\n",
5464 		    dextIDCS);
5465 		return ret;
5466 	}
5467 
5468 	unsigned int dextUniqueIDCStringSize = 0, dextUniqueIDToMatchCStringSize = 0;
5469 	const char *dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
5470 	const char *dextUniqueIDToMatchCString = getDextUniqueIDCString(dextUniqueIDToMatch, &dextUniqueIDToMatchCStringSize);
5471 	assert(dextUniqueIDCString != NULL);
5472 	assert(dextUniqueIDToMatchCString != NULL);
5473 
5474 	IORecursiveLockLock(sKextLock);
5475 
5476 	/*
5477 	 * Check that the dext we are referencing is the same
5478 	 * looked for the match.
5479 	 */
5480 	if (myDextUniqueID->isEqualTo(dextUniqueIDToMatch)) {
5481 		if (dext->flags.dextToReplace == 0 || dext->dextLaunchedCount > 0) {
5482 			if (dext->dextLaunchedCount == kOSKextMaxDextLaunchedCount) {
5483 				OSKextLog(dext,
5484 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5485 				    "Too many dexts launched for %s UniqueID %s\n",
5486 				    dextIDCS, dextUniqueIDCString);
5487 			} else {
5488 				dext->dextLaunchedCount++;
5489 				ret = true;
5490 
5491 				OSKextLog(dext,
5492 				    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5493 				    "New dext launched for  %s UniqueID %s",
5494 				    dextIDCS, dextUniqueIDCString);
5495 			}
5496 		} else {
5497 			OSKextLog(dext,
5498 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5499 			    "Dext %s UniqueID %s requires update, cannot launch a new dext\n",
5500 			    dextIDCS, dextUniqueIDCString);
5501 		}
5502 	} else {
5503 		OSKextLog(dext,
5504 		    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5505 		    "Dext %s: UniqueID %s does not match UniqueID looked for %s, cannot launch a new dext\n",
5506 		    dextIDCS, dextUniqueIDCString, dextUniqueIDToMatchCString);
5507 	}
5508 
5509 	IORecursiveLockUnlock(sKextLock);
5510 
5511 	if (dextUniqueIDCString != NULL) {
5512 		kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
5513 	}
5514 	if (dextUniqueIDToMatchCString != NULL) {
5515 		kfree_data(dextUniqueIDToMatchCString, dextUniqueIDToMatchCStringSize);
5516 	}
5517 	return ret;
5518 }
5519 
5520 bool
decrementDextLaunchCount(OSString * bundleID)5521 OSKext::decrementDextLaunchCount(OSString *bundleID)
5522 {
5523 	bool ret = false;
5524 	const char * dextIDCS;
5525 	OSData *myDextUniqueID;
5526 	unsigned int dextUniqueIDCStringSize = 0;
5527 	const char * dextUniqueIDCString = NULL;
5528 	OSKext* dext = NULL;
5529 
5530 	if (!bundleID) {
5531 		return ret;
5532 	}
5533 	dextIDCS = bundleID->getCStringNoCopy();
5534 
5535 	IORecursiveLockLock(sKextLock);
5536 
5537 	/*
5538 	 * Look for the dext with the bundle it. This
5539 	 * call is triggered only if a previous increment was
5540 	 * performed. It means that the dext could have not
5541 	 * been upgraded as its dextLaunchedCount was at least 1.
5542 	 * Because of this it still needs to be available
5543 	 * in sKextsByID.
5544 	 */
5545 	dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIDCS));
5546 	if (!dext || !dext->isDriverKit()) {
5547 		OSKextLog(NULL,
5548 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5549 		    "Cannot find dext for %s, cannot decrement dext launches\n",
5550 		    dextIDCS);
5551 
5552 		goto out_locked;
5553 	}
5554 
5555 	myDextUniqueID = dext->getDextUniqueID();
5556 	if (!myDextUniqueID) {
5557 		OSKextLog(dext,
5558 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5559 		    "Cannot find dext UniqueID for %s, cannot decrement dext launches\n",
5560 		    dextIDCS);
5561 
5562 		goto out_locked;
5563 	}
5564 	dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
5565 	assert(dextUniqueIDCString != NULL);
5566 
5567 	if (dext->dextLaunchedCount == 0) {
5568 		OSKextLog(dext,
5569 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5570 		    "Over decrementing dext launch for %s UniqueID %s\n",
5571 		    dextIDCS, dextUniqueIDCString);
5572 
5573 		goto out_locked;
5574 	}
5575 
5576 	dext->dextLaunchedCount--;
5577 
5578 	OSKextLog(dext,
5579 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5580 	    "Dext terminated for %s UniqueID %s",
5581 	    dextIDCS, dextUniqueIDCString);
5582 
5583 	if (dext->dextLaunchedCount == 0 && dext->flags.dextToReplace == 1) {
5584 		/*
5585 		 * Find the upgraded dext.
5586 		 */
5587 		OSKext *newdext = OSDynamicCast(OSKext, sDriverKitToUpgradeByID->getObject(dextIDCS));
5588 		if (newdext) {
5589 			OSKextLog(dext,
5590 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5591 			    "Dext upgrade for %s UniqueID %s",
5592 			    dextIDCS, dextUniqueIDCString);
5593 			replaceDextInternal(dext, newdext);
5594 			/* NOTE dext could have been freed past this point */
5595 
5596 			sDriverKitToUpgradeByID->removeObject(dextIDCS);
5597 		} else {
5598 			OSKextLog(dext,
5599 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5600 			    "Dext unload for %s UniqueID %s",
5601 			    dextIDCS, dextUniqueIDCString);
5602 			replaceDextInternal(dext, NULL);
5603 		}
5604 
5605 		ret = true;
5606 	}
5607 out_locked:
5608 	IORecursiveLockUnlock(sKextLock);
5609 
5610 	if (dextUniqueIDCString != NULL) {
5611 		kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
5612 	}
5613 
5614 	return ret;
5615 }
5616 
5617 /*********************************************************************
5618 *********************************************************************/
5619 #if defined (__arm__)
5620 #include <arm/arch.h>
5621 #endif
5622 
5623 #if   defined (__x86_64__)
5624 #define ARCHNAME "x86_64"
5625 #elif defined (__arm64__)
5626 #define ARCHNAME "arm64"
5627 #elif defined (__arm__)
5628 
5629 #if defined (__ARM_ARCH_7S__)
5630 #define ARCHNAME "armv7s"
5631 #elif defined (__ARM_ARCH_7F__)
5632 #define ARCHNAME "armv7f"
5633 #elif defined (__ARM_ARCH_7K__)
5634 #define ARCHNAME "armv7k"
5635 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
5636 #define ARCHNAME "armv7"
5637 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
5638 #define ARCHNAME "armv6"
5639 #endif
5640 
5641 #elif defined (__arm64__)
5642 #define ARCHNAME "arm64"
5643 #else
5644 #error architecture not supported
5645 #endif
5646 
5647 #define ARCH_SEPARATOR_CHAR  '_'
5648 
5649 static char *
makeHostArchKey(const char * key,size_t * keySizeOut)5650 makeHostArchKey(const char * key, size_t * keySizeOut)
5651 {
5652 	char     * result = NULL;
5653 	size_t     keyLength = strlen(key);
5654 	size_t     keySize;
5655 
5656 	/* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
5657 	 */
5658 	keySize = 1 + 1 + keyLength + strlen(ARCHNAME);
5659 	result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
5660 
5661 	if (!result) {
5662 		goto finish;
5663 	}
5664 	strlcpy(result, key, keySize);
5665 	result[keyLength++] = ARCH_SEPARATOR_CHAR;
5666 	result[keyLength] = '\0';
5667 	strlcat(result, ARCHNAME, keySize);
5668 	*keySizeOut = keySize;
5669 
5670 finish:
5671 	return result;
5672 }
5673 
5674 /*********************************************************************
5675 *********************************************************************/
5676 OSObject *
getPropertyForHostArch(const char * key)5677 OSKext::getPropertyForHostArch(const char * key)
5678 {
5679 	OSObject * result           = NULL;// do not release
5680 	size_t     hostArchKeySize  = 0;
5681 	char     * hostArchKey      = NULL;// must kfree
5682 
5683 	if (!key || !infoDict) {
5684 		goto finish;
5685 	}
5686 
5687 	/* Some properties are not allowed to be arch-variant:
5688 	 * - Any CFBundle... property.
5689 	 * - OSBundleIsInterface.
5690 	 * - OSKernelResource.
5691 	 */
5692 	if (STRING_HAS_PREFIX(key, "OS") ||
5693 	    STRING_HAS_PREFIX(key, "IO")) {
5694 		hostArchKey = makeHostArchKey(key, &hostArchKeySize);
5695 		if (!hostArchKey) {
5696 			OSKextLog(/* kext (this isn't about a kext) */ NULL,
5697 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
5698 			    "Allocation failure.");
5699 			goto finish;
5700 		}
5701 		result = infoDict->getObject(hostArchKey);
5702 	}
5703 
5704 	if (!result) {
5705 		result = infoDict->getObject(key);
5706 	}
5707 
5708 finish:
5709 	if (hostArchKey) {
5710 		kfree_data(hostArchKey, hostArchKeySize);
5711 	}
5712 	return result;
5713 }
5714 
5715 #if PRAGMA_MARK
5716 #pragma mark Load/Start/Stop/Unload
5717 #endif
5718 
5719 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
5720 
5721 /*********************************************************************
5722 * sExcludeListByID is a dictionary with keys / values of:
5723 *  key = bundleID string of kext we will not allow to load
5724 *  value = version string(s) of the kext that is to be denied loading.
5725 *      The version strings can be comma delimited.  For example if kext
5726 *      com.foocompany.fookext has two versions that we want to deny
5727 *      loading then the version strings might look like:
5728 *      1.0.0, 1.0.1
5729 *      If the current fookext has a version of 1.0.0 OR 1.0.1 we will
5730 *      not load the kext.
5731 *
5732 *      Value may also be in the form of "LE 2.0.0" (version numbers
5733 *      less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
5734 *      number less than 2.0.0 will not load)
5735 *
5736 *      NOTE - we cannot use the characters "<=" or "<" because we have code
5737 *      that serializes plists and treats '<' as a special character.
5738 *********************************************************************/
5739 bool
isInExcludeList(void)5740 OSKext::isInExcludeList(void)
5741 {
5742 	OSString *      versionString           = NULL;        // do not release
5743 	char *          versionCString          = NULL;        // do not free
5744 	size_t          i;
5745 	boolean_t       wantLessThan = false;
5746 	boolean_t       wantLessThanEqualTo = false;
5747 	boolean_t       isInExcludeList = true;
5748 	char            myBuffer[32];
5749 
5750 	IORecursiveLockLock(sKextLock);
5751 
5752 	if (!sExcludeListByID) {
5753 		isInExcludeList = false;
5754 	} else {
5755 		/* look up by bundleID in our exclude list and if found get version
5756 		 * string (or strings) that we will not allow to load
5757 		 */
5758 		versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get()));
5759 		if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
5760 			isInExcludeList = false;
5761 		}
5762 	}
5763 
5764 	IORecursiveLockUnlock(sKextLock);
5765 
5766 	if (!isInExcludeList) {
5767 		return false;
5768 	}
5769 
5770 	/* parse version strings */
5771 	versionCString = (char *) versionString->getCStringNoCopy();
5772 
5773 	/* look for "LT" or "LE" form of version string, must be in first two
5774 	 * positions.
5775 	 */
5776 	if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
5777 		wantLessThan = true;
5778 		versionCString += 2;
5779 	} else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
5780 		wantLessThanEqualTo = true;
5781 		versionCString += 2;
5782 	}
5783 
5784 	for (i = 0; *versionCString != 0x00; versionCString++) {
5785 		/* skip whitespace */
5786 		if (isWhiteSpace(*versionCString)) {
5787 			continue;
5788 		}
5789 
5790 		/* peek ahead for version string separator or null terminator */
5791 		if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
5792 			/* OK, we have a version string */
5793 			myBuffer[i++] = *versionCString;
5794 			myBuffer[i] = 0x00;
5795 
5796 			OSKextVersion excludeVers;
5797 			excludeVers = OSKextParseVersionString(myBuffer);
5798 
5799 			if (wantLessThanEqualTo) {
5800 				if (version <= excludeVers) {
5801 					return true;
5802 				}
5803 			} else if (wantLessThan) {
5804 				if (version < excludeVers) {
5805 					return true;
5806 				}
5807 			} else if (version == excludeVers) {
5808 				return true;
5809 			}
5810 
5811 			/* reset for the next (if any) version string */
5812 			i = 0;
5813 			wantLessThan = false;
5814 			wantLessThanEqualTo = false;
5815 		} else {
5816 			/* save valid version character */
5817 			myBuffer[i++] = *versionCString;
5818 
5819 			/* make sure bogus version string doesn't overrun local buffer */
5820 			if (i >= sizeof(myBuffer)) {
5821 				break;
5822 			}
5823 		}
5824 	}
5825 
5826 	return false;
5827 }
5828 
5829 /*********************************************************************
5830 * sNonLoadableKextsByID is a dictionary with keys / values of:
5831 *  key = bundleID string of kext we will not allow to load
5832 *  value = boolean (true == loadable, false == not loadable)
5833 *
5834 *  Only kexts which are in the AuxKC will be marked as "not loadble,"
5835 *  i.e., the value for the kext's bundleID will be false. All kexts in
5836 *  the primary and system KCs will always be marked as "loadable."
5837 *
5838 *  This list ultimately comes from kexts which have been uninstalled
5839 *  in user space by deleting the kext from disk, but which have not
5840 *  yet been removed from the AuxKC. Because the user could choose to
5841 *  re-install the exact same version of the kext, we need to keep
5842 *  a dictionary of boolean values so that user space only needs to
5843 *  keep a simple list of "uninstalled" or "missing" bundles. When
5844 *  a bundle is re-installed, the iokit daemon can use the
5845 *  AucKCBundleAvailable  predicate to set the individual kext's
5846 *  availability to true.
5847 *********************************************************************/
5848 bool
isLoadable(void)5849 OSKext::isLoadable(void)
5850 {
5851 	bool isLoadable = true;
5852 
5853 	if (kc_type != KCKindAuxiliary) {
5854 		/* this filtering only applies to kexts in the auxkc */
5855 		return true;
5856 	}
5857 
5858 	IORecursiveLockLock(sKextLock);
5859 
5860 	if (sNonLoadableKextsByID) {
5861 		/* look up by bundleID in our exclude list and if found get version
5862 		 * string (or strings) that we will not allow to load
5863 		 */
5864 		OSBoolean *loadableVal;
5865 		loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get()));
5866 		if (loadableVal && !loadableVal->getValue()) {
5867 			isLoadable = false;
5868 		}
5869 	}
5870 	IORecursiveLockUnlock(sKextLock);
5871 
5872 	return isLoadable;
5873 }
5874 
5875 /*********************************************************************
5876 *********************************************************************/
5877 /* static */
5878 OSReturn
loadKextWithIdentifier(const char * kextIdentifierCString,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5879 OSKext::loadKextWithIdentifier(
5880 	const char       * kextIdentifierCString,
5881 	Boolean            allowDeferFlag,
5882 	Boolean            delayAutounloadFlag,
5883 	OSKextExcludeLevel startOpt,
5884 	OSKextExcludeLevel startMatchingOpt,
5885 	OSArray          * personalityNames)
5886 {
5887 	OSReturn   result         = kOSReturnError;
5888 	OSSharedPtr<OSString> kextIdentifier;
5889 
5890 	kextIdentifier = OSString::withCString(kextIdentifierCString);
5891 	if (!kextIdentifier) {
5892 		result = kOSKextReturnNoMemory;
5893 		goto finish;
5894 	}
5895 	result = OSKext::loadKextWithIdentifier(kextIdentifier.get(),
5896 	    NULL /* kextRef */,
5897 	    allowDeferFlag, delayAutounloadFlag,
5898 	    startOpt, startMatchingOpt, personalityNames);
5899 
5900 finish:
5901 	return result;
5902 }
5903 
5904 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSSharedPtr<OSObject> & kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5905 OSKext::loadKextWithIdentifier(
5906 	OSString          * kextIdentifier,
5907 	OSSharedPtr<OSObject>         &kextRef,
5908 	Boolean             allowDeferFlag,
5909 	Boolean             delayAutounloadFlag,
5910 	OSKextExcludeLevel  startOpt,
5911 	OSKextExcludeLevel  startMatchingOpt,
5912 	OSArray           * personalityNames)
5913 {
5914 	OSObject * kextRefRaw = NULL;
5915 	OSReturn result;
5916 
5917 	result = loadKextWithIdentifier(kextIdentifier,
5918 	    &kextRefRaw,
5919 	    allowDeferFlag,
5920 	    delayAutounloadFlag,
5921 	    startOpt,
5922 	    startMatchingOpt,
5923 	    personalityNames);
5924 	if ((kOSReturnSuccess == result) && kextRefRaw) {
5925 		kextRef.reset(kextRefRaw, OSNoRetain);
5926 	}
5927 	return result;
5928 }
5929 
5930 /*********************************************************************
5931 *********************************************************************/
5932 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSObject ** kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5933 OSKext::loadKextWithIdentifier(
5934 	OSString          * kextIdentifier,
5935 	OSObject         ** kextRef,
5936 	Boolean             allowDeferFlag,
5937 	Boolean             delayAutounloadFlag,
5938 	OSKextExcludeLevel  startOpt,
5939 	OSKextExcludeLevel  startMatchingOpt,
5940 	OSArray           * personalityNames)
5941 {
5942 	OSReturn          result               = kOSReturnError;
5943 	OSReturn          pingResult           = kOSReturnError;
5944 	OSKext          * theKext              = NULL;        // do not release
5945 	OSSharedPtr<OSDictionary>   loadRequest;
5946 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
5947 
5948 	if (kextRef) {
5949 		*kextRef = NULL;
5950 	}
5951 
5952 	IORecursiveLockLock(sKextLock);
5953 
5954 	if (!kextIdentifier) {
5955 		result = kOSKextReturnInvalidArgument;
5956 		goto finish;
5957 	}
5958 
5959 	OSKext::recordIdentifierRequest(kextIdentifier);
5960 
5961 	theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
5962 	if (!theKext) {
5963 		if (!allowDeferFlag) {
5964 			OSKextLog(/* kext */ NULL,
5965 			    kOSKextLogErrorLevel |
5966 			    kOSKextLogLoadFlag,
5967 			    "Can't load kext %s - not found.",
5968 			    kextIdentifier->getCStringNoCopy());
5969 			goto finish;
5970 		}
5971 
5972 		if (!sKernelRequestsEnabled) {
5973 			OSKextLog(theKext,
5974 			    kOSKextLogErrorLevel |
5975 			    kOSKextLogLoadFlag,
5976 			    "Can't load kext %s - requests to user space are disabled.",
5977 			    kextIdentifier->getCStringNoCopy());
5978 			result = kOSKextReturnDisabled;
5979 			goto finish;
5980 		}
5981 
5982 		/* Create a new request unless one is already sitting
5983 		 * in sKernelRequests for this bundle identifier
5984 		 */
5985 		kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
5986 		if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
5987 			result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
5988 			    loadRequest);
5989 			if (result != kOSReturnSuccess) {
5990 				goto finish;
5991 			}
5992 			if (!_OSKextSetRequestArgument(loadRequest.get(),
5993 			    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
5994 				result = kOSKextReturnNoMemory;
5995 				goto finish;
5996 			}
5997 			if (!sKernelRequests->setObject(loadRequest.get())) {
5998 				result = kOSKextReturnNoMemory;
5999 				goto finish;
6000 			}
6001 
6002 			if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
6003 				result = kOSKextReturnNoMemory;
6004 				goto finish;
6005 			}
6006 
6007 			OSKextLog(theKext,
6008 			    kOSKextLogDebugLevel |
6009 			    kOSKextLogLoadFlag,
6010 			    "Kext %s not found; queued load request to user space.",
6011 			    kextIdentifier->getCStringNoCopy());
6012 		}
6013 
6014 		pingResult = OSKext::pingIOKitDaemon();
6015 		if (pingResult == kOSKextReturnDisabled) {
6016 			OSKextLog(/* kext */ NULL,
6017 			    ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
6018 			    kOSKextLogLoadFlag,
6019 			    "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.",
6020 			    kextIdentifier->getCStringNoCopy());
6021 		}
6022 
6023 		result = kOSKextReturnDeferred;
6024 		goto finish;
6025 	}
6026 
6027 	result = theKext->load(startOpt, startMatchingOpt, personalityNames);
6028 
6029 	if (result != kOSReturnSuccess) {
6030 		OSKextLog(theKext,
6031 		    kOSKextLogErrorLevel |
6032 		    kOSKextLogLoadFlag,
6033 		    "Failed to load kext %s (error 0x%x).",
6034 		    kextIdentifier->getCStringNoCopy(), (int)result);
6035 
6036 		if (theKext->kc_type == KCKindUnknown) {
6037 			OSKext::removeKext(theKext,
6038 			    /* terminateService/removePersonalities */ true);
6039 		}
6040 		goto finish;
6041 	}
6042 
6043 	if (delayAutounloadFlag) {
6044 		OSKextLog(theKext,
6045 		    kOSKextLogProgressLevel |
6046 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6047 		    "Setting delayed autounload for %s.",
6048 		    kextIdentifier->getCStringNoCopy());
6049 		theKext->flags.delayAutounload = 1;
6050 	}
6051 
6052 finish:
6053 	if ((kOSReturnSuccess == result) && kextRef) {
6054 		*kextRef = theKext;
6055 		theKext->matchingRefCount++;
6056 		theKext->retain();
6057 	}
6058 
6059 	IORecursiveLockUnlock(sKextLock);
6060 
6061 	return result;
6062 }
6063 
6064 /*********************************************************************
6065 *********************************************************************/
6066 /* static */
6067 OSReturn
loadKextFromKC(OSKext * theKext,OSDictionary * requestDict)6068 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict)
6069 {
6070 	OSReturn  result = kOSReturnError;
6071 
6072 	OSBoolean *delayAutounloadBool     = NULL; // do not release
6073 	OSNumber  *startKextExcludeNum     = NULL; // do not release
6074 	OSNumber  *startMatchingExcludeNum = NULL; // do not release
6075 	OSArray   *personalityNames        = NULL; // do not release
6076 
6077 	/*
6078 	 * Default values for these options:
6079 	 *      regular autounload behavior
6080 	 *      start the kext
6081 	 *      send all personalities to the catalog
6082 	 */
6083 	Boolean            delayAutounload           = false;
6084 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
6085 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone;
6086 
6087 	IORecursiveLockLock(sKextLock);
6088 
6089 	OSKextLog(/* kext */ NULL,
6090 	    kOSKextLogDebugLevel |
6091 	    kOSKextLogIPCFlag,
6092 	    "Received kext KC load request from user space.");
6093 
6094 	/* Regardless of processing, the fact that we have gotten here means some
6095 	 * user-space program is up and talking to us, so we'll switch our kext
6096 	 * registration to reflect that.
6097 	 */
6098 	if (!sUserLoadsActive) {
6099 		OSKextLog(/* kext */ NULL,
6100 		    kOSKextLogProgressLevel |
6101 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6102 		    "Switching to late startup (user-space) kext loading policy.");
6103 		sUserLoadsActive = true;
6104 	}
6105 
6106 	delayAutounloadBool = OSDynamicCast(OSBoolean,
6107 	    _OSKextGetRequestArgument(requestDict,
6108 	    kKextRequestArgumentDelayAutounloadKey));
6109 	startKextExcludeNum = OSDynamicCast(OSNumber,
6110 	    _OSKextGetRequestArgument(requestDict,
6111 	    kKextRequestArgumentStartExcludeKey));
6112 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
6113 	    _OSKextGetRequestArgument(requestDict,
6114 	    kKextRequestArgumentStartMatchingExcludeKey));
6115 	personalityNames = OSDynamicCast(OSArray,
6116 	    _OSKextGetRequestArgument(requestDict,
6117 	    kKextRequestArgumentPersonalityNamesKey));
6118 
6119 	if (delayAutounloadBool) {
6120 		delayAutounload = delayAutounloadBool->getValue();
6121 	}
6122 	if (startKextExcludeNum) {
6123 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
6124 	}
6125 	if (startMatchingExcludeNum) {
6126 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
6127 	}
6128 
6129 	OSKextLog(/* kext */ NULL,
6130 	    kOSKextLogProgressLevel |
6131 	    kOSKextLogIPCFlag,
6132 	    "Received request from user space to load KC kext %s.",
6133 	    theKext->getIdentifierCString());
6134 
6135 	/* this could be in the Auxiliary KC, so record the load request */
6136 	OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier()));
6137 
6138 	/*
6139 	 * Load the kext
6140 	 */
6141 	result = theKext->load(startKextExcludeLevel,
6142 	    startMatchingExcludeLevel, personalityNames);
6143 
6144 	if (result != kOSReturnSuccess) {
6145 		OSKextLog(theKext,
6146 		    kOSKextLogErrorLevel |
6147 		    kOSKextLogLoadFlag,
6148 		    "Failed to load kext %s (error 0x%x).",
6149 		    theKext->getIdentifierCString(), (int)result);
6150 
6151 		OSKext::removeKext(theKext,
6152 		    /* terminateService/removePersonalities */ true);
6153 		goto finish;
6154 	} else {
6155 		OSKextLog(theKext,
6156 		    kOSKextLogProgressLevel |
6157 		    kOSKextLogLoadFlag,
6158 		    "Kext %s Loaded successfully from %s KC",
6159 		    theKext->getIdentifierCString(), theKext->getKCTypeString());
6160 	}
6161 
6162 	if (delayAutounload) {
6163 		OSKextLog(theKext,
6164 		    kOSKextLogProgressLevel |
6165 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6166 		    "Setting delayed autounload for %s.",
6167 		    theKext->getIdentifierCString());
6168 		theKext->flags.delayAutounload = 1;
6169 	}
6170 
6171 finish:
6172 	IORecursiveLockUnlock(sKextLock);
6173 
6174 	return result;
6175 }
6176 
6177 /*********************************************************************
6178 *********************************************************************/
6179 /* static */
6180 OSReturn
loadCodelessKext(OSString * kextIdentifier,OSDictionary * requestDict)6181 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict)
6182 {
6183 	OSReturn  result = kOSReturnError;
6184 	OSDictionary *anInfoDict = NULL; // do not release
6185 
6186 	anInfoDict = OSDynamicCast(OSDictionary,
6187 	    _OSKextGetRequestArgument(requestDict,
6188 	    kKextRequestArgumentCodelessInfoKey));
6189 	if (anInfoDict == NULL) {
6190 		OSKextLog(/* kext */ NULL,
6191 		    kOSKextLogErrorLevel |
6192 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6193 		    "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.",
6194 		    kextIdentifier->getCStringNoCopy());
6195 		return kOSKextReturnInvalidArgument;
6196 	}
6197 
6198 	IORecursiveLockLock(sKextLock);
6199 
6200 	OSKextLog(/* kext */ NULL,
6201 	    kOSKextLogProgressLevel |
6202 	    kOSKextLogIPCFlag,
6203 	    "Received request from user space to load codeless kext %s.",
6204 	    kextIdentifier->getCStringNoCopy());
6205 
6206 	{
6207 		// instantiate a new kext, and don't hold a reference
6208 		// (the kext subsystem will hold one implicitly)
6209 		OSKextInitResult ret;
6210 		OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict, &ret);
6211 		if (!newKext) {
6212 			/*
6213 			 * We might have failed to create a new OSKext
6214 			 * because the old one should still be used.
6215 			 * Check if that is the case.
6216 			 */
6217 			if (ret != kOSKextInitFailure) {
6218 				result = kOSReturnSuccess;
6219 				goto finish;
6220 			}
6221 			OSKextLog(/* kext */ NULL,
6222 			    kOSKextLogErrorLevel |
6223 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6224 			    "Could not instantiate codeless kext.");
6225 			result = kOSKextReturnNotLoadable;
6226 			goto finish;
6227 		}
6228 		if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) {
6229 			OSKextLog(/* kext */ NULL,
6230 			    kOSKextLogErrorLevel |
6231 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6232 			    "Codeless kext identifiers don't match '%s' != '%s'",
6233 			    kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString());
6234 
6235 			OSKext::removeKext(newKext.get(), false);
6236 			result = kOSKextReturnInvalidArgument;
6237 			goto finish;
6238 		}
6239 
6240 		/* Record the request for the codeless kext */
6241 		OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier()));
6242 
6243 		result = kOSReturnSuccess;
6244 		/* Send the kext's personalities to the IOCatalog. This is an explicit load. */
6245 		result = newKext->sendPersonalitiesToCatalog(true, NULL);
6246 	}
6247 
6248 finish:
6249 	IORecursiveLockUnlock(sKextLock);
6250 
6251 	return result;
6252 }
6253 
6254 /*********************************************************************
6255 *********************************************************************/
6256 /* static */
6257 void
dropMatchingReferences(OSSet * kexts)6258 OSKext::dropMatchingReferences(
6259 	OSSet * kexts)
6260 {
6261 	IORecursiveLockLock(sKextLock);
6262 	kexts->iterateObjects(^bool (OSObject * obj) {
6263 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
6264 		if (!thisKext) {
6265 		        return false;
6266 		}
6267 		thisKext->matchingRefCount--;
6268 		return false;
6269 	});
6270 	IORecursiveLockUnlock(sKextLock);
6271 }
6272 
6273 /*********************************************************************
6274 *********************************************************************/
6275 /* static */
6276 void
recordIdentifierRequest(OSString * kextIdentifier)6277 OSKext::recordIdentifierRequest(
6278 	OSString * kextIdentifier)
6279 {
6280 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
6281 	bool             fail                 = false;
6282 
6283 	if (!sAllKextLoadIdentifiers || !kextIdentifier) {
6284 		goto finish;
6285 	}
6286 
6287 	kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
6288 	if (!kextIdentifierSymbol) {
6289 		// xxx - this is really a basic alloc failure
6290 		fail = true;
6291 		goto finish;
6292 	}
6293 
6294 	IORecursiveLockLock(sKextLock);
6295 	if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
6296 		if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
6297 			fail = true;
6298 		} else {
6299 			// xxx - need to find a way to associate this whole func w/the kext
6300 			OSKextLog(/* kext */ NULL,
6301 			    // xxx - check level
6302 			    kOSKextLogStepLevel |
6303 			    kOSKextLogArchiveFlag,
6304 			    "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
6305 			    kextIdentifier->getCStringNoCopy());
6306 		}
6307 	}
6308 	IORecursiveLockUnlock(sKextLock);
6309 
6310 finish:
6311 
6312 	if (fail) {
6313 		OSKextLog(/* kext */ NULL,
6314 		    kOSKextLogErrorLevel |
6315 		    kOSKextLogArchiveFlag,
6316 		    "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
6317 		    kextIdentifier->getCStringNoCopy());
6318 	}
6319 	return;
6320 }
6321 
6322 /*********************************************************************
6323 *********************************************************************/
6324 OSReturn
load(OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)6325 OSKext::load(
6326 	OSKextExcludeLevel   startOpt,
6327 	OSKextExcludeLevel   startMatchingOpt,
6328 	OSArray            * personalityNames)
6329 {
6330 	OSReturn             result                       = kOSReturnError;
6331 	OSKextExcludeLevel   dependenciesStartOpt         = startOpt;
6332 	OSKextExcludeLevel   dependenciesStartMatchingOpt = startMatchingOpt;
6333 	unsigned int         i, count;
6334 	Boolean              alreadyLoaded                = false;
6335 	OSKext             * lastLoadedKext               = NULL;        // do not release
6336 
6337 	if (isInExcludeList()) {
6338 		OSKextLog(this,
6339 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
6340 		    kOSKextLogLoadFlag,
6341 		    "Kext %s is in exclude list, not loadable",
6342 		    getIdentifierCString());
6343 
6344 		result = kOSKextReturnNotLoadable;
6345 		goto finish;
6346 	}
6347 	if (!isLoadable()) {
6348 		OSKextLog(this,
6349 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
6350 		    kOSKextLogLoadFlag,
6351 		    "Kext %s is not loadable",
6352 		    getIdentifierCString());
6353 
6354 		result = kOSKextReturnNotLoadable;
6355 		goto finish;
6356 	}
6357 
6358 	if (isLoaded()) {
6359 		alreadyLoaded = true;
6360 		result = kOSReturnSuccess;
6361 
6362 		OSKextLog(this,
6363 		    kOSKextLogDebugLevel |
6364 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6365 		    "Kext %s is already loaded.",
6366 		    getIdentifierCString());
6367 		goto loaded;
6368 	}
6369 
6370 #if CONFIG_MACF
6371 	/*
6372 	 * On kxld and on embedded, only call into the MAC hook when on a
6373 	 * user thread, for access control over userspace kextloads.
6374 	 *
6375 	 * On non-kxld systems, additionally check the MAC hook for kexts in
6376 	 * the Pageable and Aux KCs, regardless of whether we are on a user
6377 	 * thread or not. This means on Apple silicon devices that the MAC
6378 	 * hook will only be useful to block 3rd party kexts loaded via
6379 	 * matching, and any kexts loaded from userspace kextloads.
6380 	 *
6381 	 * Note that this should _not_ be called on kexts loaded from the
6382 	 * kernel bootstrap thread as the kernel proc's cred struct is not
6383 	 * yet initialized! This won't happen on macOS because all the kexts
6384 	 * in the BootKC are self-contained and their kc_type = KCKindPrimary.
6385 	 */
6386 	if (current_task() != kernel_task
6387 #if XNU_TARGET_OS_OSX && !CONFIG_KXLD
6388 	    || (kc_type != KCKindPrimary && kc_type != KCKindUnknown)
6389 #endif
6390 	    ) {
6391 		int                 macCheckResult      = 0;
6392 		kauth_cred_t        cred                = NULL;
6393 
6394 		cred = kauth_cred_get_with_ref();
6395 		macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
6396 		kauth_cred_unref(&cred);
6397 
6398 		if (macCheckResult != 0) {
6399 			result = kOSReturnError;
6400 			OSKextLog(this,
6401 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6402 			    "Failed to load kext %s (MAC policy error 0x%x).",
6403 			    getIdentifierCString(), macCheckResult);
6404 			goto finish;
6405 		}
6406 	}
6407 #endif /* CONFIG_MACF */
6408 
6409 	if (!sLoadEnabled) {
6410 		OSKextLog(this,
6411 		    kOSKextLogErrorLevel |
6412 		    kOSKextLogLoadFlag,
6413 		    "Kext loading is disabled (attempt to load kext %s).",
6414 		    getIdentifierCString());
6415 		result = kOSKextReturnDisabled;
6416 		goto finish;
6417 	}
6418 
6419 	/* If we've pushed the next available load tag to the invalid value,
6420 	 * we can't load any more kexts.
6421 	 */
6422 	if (sNextLoadTag == kOSKextInvalidLoadTag) {
6423 		OSKextLog(this,
6424 		    kOSKextLogErrorLevel |
6425 		    kOSKextLogLoadFlag,
6426 		    "Can't load kext %s - no more load tags to assign.",
6427 		    getIdentifierCString());
6428 		result = kOSKextReturnNoResources;
6429 		goto finish;
6430 	}
6431 
6432 	/* This is a bit of a hack, because we shouldn't be handling
6433 	 * personalities within the load function.
6434 	 */
6435 	if (!declaresExecutable()) {
6436 		/* There is a special case where a non-executable kext can be loaded: the
6437 		 * AppleKextExcludeList.  Detect that special kext by bundle identifier and
6438 		 * load its metadata into the global data structures, if appropriate
6439 		 */
6440 		if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
6441 			boolean_t updated = updateExcludeList(infoDict.get());
6442 			if (updated) {
6443 				OSKextLog(this,
6444 				    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
6445 				    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
6446 			}
6447 		}
6448 
6449 		if (isDriverKit()) {
6450 			if (loadTag == 0) {
6451 				sLoadedDriverKitKexts->setObject(this);
6452 				loadTag = sNextLoadTag++;
6453 			}
6454 		}
6455 		result = kOSReturnSuccess;
6456 		goto loaded;
6457 	}
6458 
6459 	/* Are we in safe boot?
6460 	 */
6461 	if (sSafeBoot && !isLoadableInSafeBoot()) {
6462 		OSKextLog(this,
6463 		    kOSKextLogErrorLevel |
6464 		    kOSKextLogLoadFlag,
6465 		    "Can't load kext %s - not loadable during safe boot.",
6466 		    getIdentifierCString());
6467 		result = kOSKextReturnBootLevel;
6468 		goto finish;
6469 	}
6470 
6471 	OSKextLog(this,
6472 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
6473 	    "Loading kext %s.",
6474 	    getIdentifierCString());
6475 
6476 #if !VM_MAPPED_KEXTS
6477 	if (isPrelinked() == false) {
6478 		OSKextLog(this,
6479 		    kOSKextLogErrorLevel |
6480 		    kOSKextLogLoadFlag,
6481 		    "Can't load kext %s - not in a kext collection.",
6482 		    getIdentifierCString());
6483 		result = kOSKextReturnDisabled;
6484 		goto finish;
6485 	}
6486 #endif /* defined(__x86_64__) */
6487 
6488 #if CONFIG_KXLD
6489 	if (!sKxldContext) {
6490 		kern_return_t kxldResult;
6491 		kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
6492 		    &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
6493 		    /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
6494 		if (kxldResult) {
6495 			OSKextLog(this,
6496 			    kOSKextLogErrorLevel |
6497 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6498 			    "Can't load kext %s - failed to create link context.",
6499 			    getIdentifierCString());
6500 			result = kOSKextReturnNoMemory;
6501 			goto finish;
6502 		}
6503 	}
6504 #endif // CONFIG_KXLD
6505 
6506 	/* We only need to resolve dependencies once for the whole graph, but
6507 	 * resolveDependencies will just return if there's no work to do, so it's
6508 	 * safe to call it more than once.
6509 	 */
6510 	if (!resolveDependencies()) {
6511 		// xxx - check resolveDependencies() for log msg
6512 		OSKextLog(this,
6513 		    kOSKextLogErrorLevel |
6514 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6515 		    "Can't load kext %s - failed to resolve library dependencies.",
6516 		    getIdentifierCString());
6517 		result = kOSKextReturnDependencies;
6518 		goto finish;
6519 	}
6520 
6521 	/* If we are excluding just the kext being loaded now (and not its
6522 	 * dependencies), drop the exclusion level to none so dependencies
6523 	 * start and/or add their personalities.
6524 	 */
6525 	if (dependenciesStartOpt == kOSKextExcludeKext) {
6526 		dependenciesStartOpt = kOSKextExcludeNone;
6527 	}
6528 
6529 	if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
6530 		dependenciesStartMatchingOpt = kOSKextExcludeNone;
6531 	}
6532 
6533 	/* Load the dependencies, recursively.
6534 	 */
6535 	count = getNumDependencies();
6536 	for (i = 0; i < count; i++) {
6537 		OSKext * dependency = OSDynamicCast(OSKext,
6538 		    dependencies->getObject(i));
6539 		if (dependency == NULL) {
6540 			OSKextLog(this,
6541 			    kOSKextLogErrorLevel |
6542 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6543 			    "Internal error loading kext %s; dependency disappeared.",
6544 			    getIdentifierCString());
6545 			result = kOSKextReturnInternalError;
6546 			goto finish;
6547 		}
6548 
6549 		/* Dependencies must be started accorting to the opt,
6550 		 * but not given the personality names of the main kext.
6551 		 */
6552 		result = dependency->load(dependenciesStartOpt,
6553 		    dependenciesStartMatchingOpt,
6554 		    /* personalityNames */ NULL);
6555 		if (result != KERN_SUCCESS) {
6556 			OSKextLog(this,
6557 			    kOSKextLogErrorLevel |
6558 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6559 			    "Dependency %s of kext %s failed to load.",
6560 			    dependency->getIdentifierCString(),
6561 			    getIdentifierCString());
6562 
6563 			OSKext::removeKext(dependency,
6564 			    /* terminateService/removePersonalities */ true);
6565 			result = kOSKextReturnDependencyLoadError;
6566 
6567 			goto finish;
6568 		}
6569 	}
6570 
6571 	result = loadExecutable();
6572 	if (result != KERN_SUCCESS) {
6573 		goto finish;
6574 	}
6575 
6576 	pendingPgoHead.next = &pendingPgoHead;
6577 	pendingPgoHead.prev = &pendingPgoHead;
6578 
6579 	// The kernel PRNG is not initialized when the first kext is
6580 	// loaded, so use early random
6581 	uuid_generate_early_random(instance_uuid);
6582 	account = IOMallocType(OSKextAccount);
6583 
6584 	account->loadTag = kmod_info->id;
6585 	account->site.refcount = 0;
6586 	account->site.flags = VM_TAG_KMOD;
6587 
6588 #if DEVELOPMENT || DEBUG
6589 	/* Setup the task reference group. */
6590 	(void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name),
6591 	    "task_%s", getIdentifierCString());
6592 	account->task_refgrp.grp_name = account->task_refgrp_name;
6593 	account->task_refgrp.grp_parent = &task_external_refgrp;
6594 	account->task_refgrp.grp_flags = OS_REFGRP_F_ALWAYS_ENABLED;
6595 	os_ref_log_init(&account->task_refgrp);
6596 #endif /* DEVELOPMENT || DEBUG */
6597 
6598 	account->kext = this;
6599 	if (gIOSurfaceIdentifier == bundleID) {
6600 		vm_tag_alloc(&account->site);
6601 		gIOSurfaceTag = account->site.tag;
6602 	}
6603 
6604 	flags.loaded = true;
6605 
6606 	/* Add the kext to the list of loaded kexts and update the kmod_info
6607 	 * struct to point to that of the last loaded kext (which is the way
6608 	 * it's always been done, though I'd rather do them in order now).
6609 	 */
6610 	lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
6611 	sLoadedKexts->setObject(this);
6612 
6613 	/* Keep the kernel itself out of the kmod list.
6614 	 */
6615 	if (lastLoadedKext->isKernel()) {
6616 		lastLoadedKext = NULL;
6617 	}
6618 
6619 	if (lastLoadedKext) {
6620 		kmod_info->next = lastLoadedKext->kmod_info;
6621 	}
6622 
6623 	notifyKextLoadObservers(this, kmod_info);
6624 
6625 	/* Make the global kmod list point at the just-loaded kext. Note that the
6626 	 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
6627 	 * although we do report it in kextstat these days by using the newer
6628 	 * OSArray of loaded kexts, which does contain it.
6629 	 *
6630 	 * (The OSKext object representing the kernel doesn't even have a kmod_info
6631 	 * struct, though I suppose we could stick a pointer to it from the
6632 	 * static struct in OSRuntime.cpp.)
6633 	 */
6634 	kmod = kmod_info;
6635 
6636 	/* Save the list of loaded kexts in case we panic.
6637 	 */
6638 	OSKext::saveLoadedKextPanicList();
6639 
6640 	if (isExecutable()) {
6641 		OSKext::updateLoadedKextSummaries();
6642 		savePanicString(/* isLoading */ true);
6643 
6644 #if CONFIG_DTRACE
6645 		registerWithDTrace();
6646 #else
6647 		jettisonLinkeditSegment();
6648 #endif /* CONFIG_DTRACE */
6649 
6650 #if !VM_MAPPED_KEXTS
6651 		/* If there is a page (or more) worth of padding after the end
6652 		 * of the last data section but before the end of the data segment
6653 		 * then free it in the same manner the LinkeditSegment is freed
6654 		 */
6655 		jettisonDATASegmentPadding();
6656 #endif
6657 	}
6658 
6659 loaded:
6660 	if (isExecutable() && !flags.started) {
6661 		if (startOpt == kOSKextExcludeNone) {
6662 			result = start();
6663 			if (result != kOSReturnSuccess) {
6664 				OSKextLog(this,
6665 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6666 				    "Kext %s start failed (result 0x%x).",
6667 				    getIdentifierCString(), result);
6668 				result = kOSKextReturnStartStopError;
6669 			}
6670 		}
6671 	}
6672 
6673 	/* If not excluding matching, send the personalities to the kernel.
6674 	 * This never affects the result of the load operation.
6675 	 * This is a bit of a hack, because we shouldn't be handling
6676 	 * personalities within the load function.
6677 	 */
6678 	if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
6679 		result = sendPersonalitiesToCatalog(true, personalityNames);
6680 	}
6681 
6682 finish:
6683 
6684 	if (result != kOSReturnSuccess) {
6685 		OSKextLog(this,
6686 		    kOSKextLogErrorLevel |
6687 		    kOSKextLogLoadFlag,
6688 		    "Kext %s failed to load (0x%x).",
6689 		    getIdentifierCString(), (int)result);
6690 	} else if (!alreadyLoaded) {
6691 		OSKextLog(this,
6692 		    kOSKextLogProgressLevel |
6693 		    kOSKextLogLoadFlag,
6694 		    "Kext %s loaded.",
6695 		    getIdentifierCString());
6696 
6697 		queueKextNotification(kKextRequestPredicateLoadNotification,
6698 		    OSDynamicCast(OSString, bundleID.get()), getDextUniqueID());
6699 	}
6700 	return result;
6701 }
6702 
6703 #if CONFIG_KXLD
6704 /*********************************************************************
6705 *
6706 *********************************************************************/
6707 static char *
strdup(const char * string)6708 strdup(const char * string)
6709 {
6710 	char * result = NULL;
6711 	size_t size;
6712 
6713 	if (!string) {
6714 		goto finish;
6715 	}
6716 
6717 	size = 1 + strlen(string);
6718 	result = (char *)kalloc_data_tag(size, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
6719 	if (!result) {
6720 		goto finish;
6721 	}
6722 
6723 	memcpy(result, string, size);
6724 
6725 finish:
6726 	return result;
6727 }
6728 #endif // CONFIG_KXLD
6729 
6730 /*********************************************************************
6731 *
6732 *********************************************************************/
6733 
6734 kernel_section_t *
lookupSection(const char * segname,const char * secname)6735 OSKext::lookupSection(const char *segname, const char *secname)
6736 {
6737 	kernel_section_t         * found_section = NULL;
6738 	kernel_mach_header_t     * mh            = NULL;
6739 	kernel_segment_command_t * seg           = NULL;
6740 	kernel_section_t         * sec           = NULL;
6741 
6742 	if (!linkedExecutable) {
6743 		return NULL;
6744 	}
6745 
6746 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6747 
6748 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6749 		if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) {
6750 			continue;
6751 		}
6752 
6753 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6754 			if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) {
6755 				found_section = sec;
6756 				goto out;
6757 			}
6758 		}
6759 	}
6760 
6761 out:
6762 	return found_section;
6763 }
6764 
6765 /*********************************************************************
6766 *
6767 *********************************************************************/
6768 
6769 OSReturn
slidePrelinkedExecutable(bool doCoalescedSlides)6770 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides)
6771 {
6772 	OSReturn                       result           = kOSKextReturnBadData;
6773 	kernel_mach_header_t         * mh               = NULL;
6774 	kernel_segment_command_t     * seg              = NULL;
6775 	kernel_segment_command_t     * linkeditSeg      = NULL;
6776 	kernel_section_t             * sec              = NULL;
6777 	char                         * linkeditBase     = NULL;
6778 	bool                           haveLinkeditBase = false;
6779 	char                         * relocBase        = NULL;
6780 	bool                           haveRelocBase    = false;
6781 	struct dysymtab_command      * dysymtab         = NULL;
6782 	struct linkedit_data_command * segmentSplitInfo = NULL;
6783 	struct symtab_command        * symtab           = NULL;
6784 	kernel_nlist_t               * sym              = NULL;
6785 	struct relocation_info       * reloc            = NULL;
6786 	uint32_t                       i                = 0;
6787 	int                            reloc_size;
6788 	vm_offset_t                    new_kextsize;
6789 	kc_format                    format             = KCFormatUnknown;
6790 
6791 	if (linkedExecutable == NULL || flags.builtin) {
6792 		result = kOSReturnSuccess;
6793 		goto finish;
6794 	}
6795 
6796 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6797 	if (kernel_mach_header_is_in_fileset(mh)) {
6798 		// kexts in filesets are slid as part of collection sliding
6799 		result = kOSReturnSuccess;
6800 		goto finish;
6801 	}
6802 
6803 	segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
6804 
6805 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6806 		if (!seg->vmaddr) {
6807 			continue;
6808 		}
6809 
6810 		seg->vmaddr = ml_static_slide(seg->vmaddr);
6811 
6812 #if KASLR_KEXT_DEBUG
6813 		IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
6814 		    seg->segname,
6815 		    (unsigned long)ml_static_unslide(seg->vmaddr),
6816 		    (unsigned long)seg->vmaddr);
6817 #endif
6818 
6819 		if (!haveRelocBase) {
6820 			relocBase = (char *) seg->vmaddr;
6821 			haveRelocBase = true;
6822 		}
6823 		if (!strcmp(seg->segname, "__LINKEDIT")) {
6824 			linkeditBase = (char *) seg->vmaddr - seg->fileoff;
6825 			haveLinkeditBase = true;
6826 			linkeditSeg = seg;
6827 		}
6828 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6829 			sec->addr = ml_static_slide(sec->addr);
6830 
6831 #if KASLR_KEXT_DEBUG
6832 			IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
6833 			    sec->sectname,
6834 			    (unsigned long)ml_static_unslide(sec->addr),
6835 			    (unsigned long)sec->addr);
6836 #endif
6837 		}
6838 	}
6839 
6840 	dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
6841 
6842 	symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
6843 
6844 	if (symtab != NULL && doCoalescedSlides == false) {
6845 		/* Some pseudo-kexts have symbol tables without segments.
6846 		 * Ignore them. */
6847 		if (symtab->nsyms > 0 && haveLinkeditBase) {
6848 			sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
6849 			for (i = 0; i < symtab->nsyms; i++) {
6850 				if (sym[i].n_type & N_STAB) {
6851 					continue;
6852 				}
6853 				sym[i].n_value = ml_static_slide(sym[i].n_value);
6854 
6855 #if KASLR_KEXT_DEBUG
6856 #define MAX_SYMS_TO_LOG 5
6857 				if (i < MAX_SYMS_TO_LOG) {
6858 					IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
6859 					    (unsigned long)ml_static_unslide(sym[i].n_value),
6860 					    (unsigned long)sym[i].n_value);
6861 				}
6862 #endif
6863 			}
6864 		}
6865 	}
6866 
6867 	if (dysymtab != NULL && doCoalescedSlides == false) {
6868 		if (dysymtab->nextrel > 0) {
6869 			OSKextLog(this,
6870 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6871 			    kOSKextLogLinkFlag,
6872 			    "Sliding kext %s: External relocations found.",
6873 			    getIdentifierCString());
6874 			goto finish;
6875 		}
6876 
6877 		if (dysymtab->nlocrel > 0) {
6878 			if (!haveLinkeditBase) {
6879 				OSKextLog(this,
6880 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6881 				    kOSKextLogLinkFlag,
6882 				    "Sliding kext %s: No linkedit segment.",
6883 				    getIdentifierCString());
6884 				goto finish;
6885 			}
6886 
6887 			if (!haveRelocBase) {
6888 				OSKextLog(this,
6889 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6890 				    kOSKextLogLinkFlag,
6891 #if __x86_64__
6892 				    "Sliding kext %s: No writable segments.",
6893 #else
6894 				    "Sliding kext %s: No segments.",
6895 #endif
6896 				    getIdentifierCString());
6897 				goto finish;
6898 			}
6899 
6900 			reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
6901 			reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
6902 
6903 			for (i = 0; i < dysymtab->nlocrel; i++) {
6904 				if (reloc[i].r_extern != 0
6905 				    || reloc[i].r_type != 0
6906 				    || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
6907 				    ) {
6908 					OSKextLog(this,
6909 					    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6910 					    kOSKextLogLinkFlag,
6911 					    "Sliding kext %s: Unexpected relocation found.",
6912 					    getIdentifierCString());
6913 					goto finish;
6914 				}
6915 				if (reloc[i].r_pcrel != 0) {
6916 					continue;
6917 				}
6918 				uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
6919 				*relocAddr = ml_static_slide(*relocAddr);
6920 
6921 #if KASLR_KEXT_DEBUG
6922 #define MAX_DYSYMS_TO_LOG 5
6923 				if (i < MAX_DYSYMS_TO_LOG) {
6924 					IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
6925 					    (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
6926 					    (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
6927 				}
6928 #endif
6929 			}
6930 
6931 			/* We should free these relocations, not just delete the reference to them.
6932 			 * <rdar://problem/10535549> Free relocations from PIE kexts.
6933 			 *
6934 			 * For now, we do not free LINKEDIT for kexts with split segments.
6935 			 */
6936 			new_kextsize = round_page(kmod_info->size - reloc_size);
6937 			if (new_kextsize > UINT_MAX) {
6938 				OSKextLog(this,
6939 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6940 				    kOSKextLogLinkFlag,
6941 				    "Kext %s: new kext size is too large.",
6942 				    getIdentifierCString());
6943 				goto finish;
6944 			}
6945 			if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
6946 				vm_offset_t     endofkext = kmod_info->address + kmod_info->size;
6947 				vm_offset_t     new_endofkext = kmod_info->address + new_kextsize;
6948 				vm_offset_t     endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
6949 				size_t          bytes_remaining = endofkext - endofrelocInfo;
6950 				OSSharedPtr<OSData>        new_osdata;
6951 
6952 				/* fix up symbol offsets if they are after the dsymtab local relocs */
6953 				if (symtab) {
6954 					if (dysymtab->locreloff < symtab->symoff) {
6955 						symtab->symoff -= reloc_size;
6956 					}
6957 					if (dysymtab->locreloff < symtab->stroff) {
6958 						symtab->stroff -= reloc_size;
6959 					}
6960 				}
6961 				if (dysymtab->locreloff < dysymtab->extreloff) {
6962 					dysymtab->extreloff -= reloc_size;
6963 				}
6964 
6965 				/* move data behind reloc info down to new offset */
6966 				if (endofrelocInfo < endofkext) {
6967 					memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
6968 				}
6969 
6970 				/* Create a new OSData for the smaller kext object and reflect
6971 				 * new linkedit segment size.
6972 				 */
6973 				linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
6974 				linkeditSeg->filesize = linkeditSeg->vmsize;
6975 
6976 				new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize);
6977 				if (new_osdata) {
6978 					/* Fix up kmod info and linkedExecutable.
6979 					 */
6980 					kmod_info->size = new_kextsize;
6981 					/*
6982 					 * Fileset KCs are mapped as a whole by iBoot.
6983 					 * Individual kext executables should not be unmapped
6984 					 * by xnu.
6985 					 * Doing so may result in panics like rdar://85419651
6986 					 */
6987 					if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
6988 						new_osdata->setDeallocFunction(NULL);
6989 					} else { // Not from a Fileset KC
6990 #if VM_MAPPED_KEXTS
6991 						new_osdata->setDeallocFunction(osdata_kext_free);
6992 #else
6993 						new_osdata->setDeallocFunction(osdata_phys_free);
6994 #endif
6995 					}
6996 					linkedExecutable->setDeallocFunction(NULL);
6997 					linkedExecutable = os::move(new_osdata);
6998 
6999 #if VM_MAPPED_KEXTS
7000 					kext_free(new_endofkext, (endofkext - new_endofkext));
7001 #else
7002 					ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
7003 #endif
7004 				}
7005 			}
7006 			dysymtab->nlocrel = 0;
7007 			dysymtab->locreloff = 0;
7008 		}
7009 	}
7010 
7011 	result = kOSReturnSuccess;
7012 finish:
7013 	return result;
7014 }
7015 
7016 /*********************************************************************
7017 * called only by load()
7018 *********************************************************************/
7019 OSReturn
loadExecutable()7020 OSKext::loadExecutable()
7021 {
7022 	OSReturn              result             = kOSReturnError;
7023 	OSSharedPtr<OSArray>  linkDependencies;
7024 	uint32_t              num_kmod_refs      = 0;
7025 	OSData              * theExecutable      = NULL;        // do not release
7026 	OSString            * versString         = NULL;        // do not release
7027 	const char          * versCString        = NULL;        // do not free
7028 	const char          * string             = NULL;        // do not free
7029 
7030 #if CONFIG_KXLD
7031 	unsigned int          i;
7032 	uint32_t              numDirectDependencies   = 0;
7033 	kern_return_t         kxldResult;
7034 	KXLDDependency     *  kxlddeps           = NULL;        // must kfree
7035 	uint32_t              num_kxlddeps       = 0;
7036 	struct mach_header ** kxldHeaderPtr      = NULL;        // do not free
7037 	struct mach_header  * kxld_header        = NULL;        // xxx - need to free here?
7038 #endif // CONFIG_KXLD
7039 
7040 	/* We need the version string for a variety of bits below.
7041 	 */
7042 	versString = OSDynamicCast(OSString,
7043 	    getPropertyForHostArch(kCFBundleVersionKey));
7044 	if (!versString) {
7045 		goto finish;
7046 	}
7047 	versCString = versString->getCStringNoCopy();
7048 
7049 	if (isKernelComponent()) {
7050 		if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
7051 			if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
7052 				OSKextLog(this,
7053 				    kOSKextLogErrorLevel |
7054 				    kOSKextLogLoadFlag,
7055 				    "Kernel component %s has incorrect version %s; "
7056 				    "expected %s.",
7057 				    getIdentifierCString(),
7058 				    versCString, KERNEL6_VERSION);
7059 				result = kOSKextReturnInternalError;
7060 				goto finish;
7061 			} else if (strcmp(versCString, osrelease)) {
7062 				OSKextLog(this,
7063 				    kOSKextLogErrorLevel |
7064 				    kOSKextLogLoadFlag,
7065 				    "Kernel component %s has incorrect version %s; "
7066 				    "expected %s.",
7067 				    getIdentifierCString(),
7068 				    versCString, osrelease);
7069 				result = kOSKextReturnInternalError;
7070 				goto finish;
7071 			}
7072 		}
7073 	}
7074 
7075 #if defined(__x86_64__) || defined(__i386__)
7076 	if (flags.resetSegmentsFromVnode) {
7077 		/* Fixup the chains and slide the mach headers */
7078 		kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address;
7079 
7080 		if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) {
7081 			result = kOSKextReturnValidation;
7082 			goto finish;
7083 		}
7084 	}
7085 #endif //(__x86_64__) || defined(__i386__)
7086 
7087 	if (isPrelinked()) {
7088 		goto register_kmod;
7089 	}
7090 
7091 	/* <rdar://problem/21444003> all callers must be entitled */
7092 	if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) {
7093 		OSKextLog(this,
7094 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7095 		    "Not entitled to link kext '%s'",
7096 		    getIdentifierCString());
7097 		result = kOSKextReturnNotPrivileged;
7098 		goto finish;
7099 	}
7100 
7101 	theExecutable = getExecutable();
7102 	if (!theExecutable) {
7103 		if (declaresExecutable()) {
7104 			OSKextLog(this,
7105 			    kOSKextLogErrorLevel |
7106 			    kOSKextLogLoadFlag,
7107 			    "Can't load kext %s - executable is missing.",
7108 			    getIdentifierCString());
7109 			result = kOSKextReturnValidation;
7110 			goto finish;
7111 		}
7112 		goto register_kmod;
7113 	}
7114 
7115 	if (isInterface()) {
7116 		OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable);
7117 		if (executableCopy) {
7118 			setLinkedExecutable(executableCopy.get());
7119 		}
7120 		goto register_kmod;
7121 	}
7122 
7123 #if CONFIG_KXLD
7124 	numDirectDependencies = getNumDependencies();
7125 
7126 	if (flags.hasBleedthrough) {
7127 		linkDependencies = dependencies;
7128 	} else {
7129 		linkDependencies = OSArray::withArray(dependencies.get());
7130 		if (!linkDependencies) {
7131 			OSKextLog(this,
7132 			    kOSKextLogErrorLevel |
7133 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7134 			    "Can't allocate link dependencies to load kext %s.",
7135 			    getIdentifierCString());
7136 			goto finish;
7137 		}
7138 
7139 		for (i = 0; i < numDirectDependencies; ++i) {
7140 			OSKext * dependencyKext = OSDynamicCast(OSKext,
7141 			    dependencies->getObject(i));
7142 			dependencyKext->addBleedthroughDependencies(linkDependencies.get());
7143 		}
7144 	}
7145 
7146 	num_kxlddeps = linkDependencies->getCount();
7147 	if (!num_kxlddeps) {
7148 		OSKextLog(this,
7149 		    kOSKextLogErrorLevel |
7150 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
7151 		    "Can't load kext %s - it has no library dependencies.",
7152 		    getIdentifierCString());
7153 		goto finish;
7154 	}
7155 
7156 	kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
7157 	if (!kxlddeps) {
7158 		OSKextLog(this,
7159 		    kOSKextLogErrorLevel |
7160 		    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7161 		    "Can't allocate link context to load kext %s.",
7162 		    getIdentifierCString());
7163 		goto finish;
7164 	}
7165 	bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
7166 
7167 	for (i = 0; i < num_kxlddeps; ++i) {
7168 		OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
7169 
7170 		if (dependency->isInterface()) {
7171 			OSKext *interfaceTargetKext = NULL;        //do not release
7172 			OSData * interfaceTarget = NULL;        //do not release
7173 
7174 			if (dependency->isKernelComponent()) {
7175 				interfaceTargetKext = sKernelKext;
7176 				interfaceTarget = sKernelKext->linkedExecutable.get();
7177 			} else {
7178 				interfaceTargetKext = OSDynamicCast(OSKext,
7179 				    dependency->dependencies->getObject(0));
7180 
7181 				interfaceTarget = interfaceTargetKext->linkedExecutable.get();
7182 			}
7183 
7184 			if (!interfaceTarget) {
7185 				// panic?
7186 				goto finish;
7187 			}
7188 
7189 			/* The names set here aren't actually logged yet <rdar://problem/7941514>,
7190 			 * it will be useful to have them in the debugger.
7191 			 * strdup() failing isn't critical right here so we don't check that.
7192 			 */
7193 			kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
7194 			kxlddeps[i].kext_size = interfaceTarget->getLength();
7195 			kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
7196 
7197 			if (dependency->linkedExecutable != NULL) {
7198 				kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
7199 				kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
7200 			} else {
7201 				kxlddeps[i].interface = (u_char *) NULL;
7202 				kxlddeps[i].interface_size = 0;
7203 			}
7204 			kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
7205 		} else {
7206 			kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
7207 			kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
7208 			kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
7209 		}
7210 
7211 		kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
7212 	}
7213 
7214 	kxldHeaderPtr = &kxld_header;
7215 
7216 #if DEBUG
7217 	OSKextLog(this,
7218 	    kOSKextLogExplicitLevel |
7219 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7220 	    "Kext %s - calling kxld_link_file:\n"
7221 	    "    kxld_context: %p\n"
7222 	    "    executable: %p    executable_length: %d\n"
7223 	    "    user_data: %p\n"
7224 	    "    kxld_dependencies: %p    num_dependencies: %d\n"
7225 	    "    kxld_header_ptr: %p    kmod_info_ptr: %p\n",
7226 	    getIdentifierCString(), sKxldContext,
7227 	    theExecutable->getBytesNoCopy(), theExecutable->getLength(),
7228 	    this, kxlddeps, num_kxlddeps,
7229 	    kxldHeaderPtr, &kmod_info);
7230 #endif
7231 
7232 	/* After this call, the linkedExecutable instance variable
7233 	 * should exist.
7234 	 */
7235 	kxldResult = kxld_link_file(sKxldContext,
7236 	    (u_char *)theExecutable->getBytesNoCopy(),
7237 	    theExecutable->getLength(),
7238 	    getIdentifierCString(), this, kxlddeps, num_kxlddeps,
7239 	    (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
7240 
7241 	if (kxldResult != KERN_SUCCESS) {
7242 		// xxx - add kxldResult here?
7243 		OSKextLog(this,
7244 		    kOSKextLogErrorLevel |
7245 		    kOSKextLogLoadFlag,
7246 		    "Can't load kext %s - link failed.",
7247 		    getIdentifierCString());
7248 		result = kOSKextReturnLinkError;
7249 		goto finish;
7250 	}
7251 
7252 	/* We've written data & instructions into kernel memory, so flush the data
7253 	 * cache and invalidate the instruction cache.
7254 	 * I/D caches are coherent on x86
7255 	 */
7256 #if !defined(__i386__) && !defined(__x86_64__)
7257 	flush_dcache(kmod_info->address, kmod_info->size, false);
7258 	invalidate_icache(kmod_info->address, kmod_info->size, false);
7259 #endif
7260 
7261 #else // !CONFIG_KXLD
7262 	OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7263 	    "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString());
7264 	result = kOSKextReturnLinkError;
7265 	goto finish;
7266 #endif // CONFIG_KXLD
7267 
7268 register_kmod:
7269 
7270 	if (isInterface()) {
7271 		/* Whip up a fake kmod_info entry for the interface kext.
7272 		 */
7273 		kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
7274 		if (!kmod_info) {
7275 			result = KERN_MEMORY_ERROR;
7276 			goto finish;
7277 		}
7278 
7279 		/* A pseudokext has almost nothing in its kmod_info struct.
7280 		 */
7281 		kmod_info->info_version = KMOD_INFO_VERSION;
7282 
7283 		/* An interface kext doesn't have a linkedExecutable, so save a
7284 		 * copy of the UUID out of the original executable via copyUUID()
7285 		 * while we still have the original executable.
7286 		 */
7287 		interfaceUUID = copyUUID();
7288 	}
7289 
7290 	kmod_info->id = loadTag = sNextLoadTag++;
7291 	kmod_info->reference_count = 0;         // KMOD_DECL... sets it to -1 (invalid).
7292 
7293 	/* Stamp the bundle ID and version from the OSKext over anything
7294 	 * resident inside the kmod_info.
7295 	 */
7296 	string = getIdentifierCString();
7297 	strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
7298 
7299 	string = versCString;
7300 	strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
7301 
7302 	/* Add the dependencies' kmod_info structs as kmod_references.
7303 	 */
7304 	num_kmod_refs = getNumDependencies();
7305 	if (num_kmod_refs) {
7306 		kmod_info->reference_list = kalloc_type_tag(kmod_reference_t,
7307 		    num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT);
7308 		if (!kmod_info->reference_list) {
7309 			result = KERN_MEMORY_ERROR;
7310 			goto finish;
7311 		}
7312 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
7313 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
7314 			OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
7315 			ref->info = refKext->kmod_info;
7316 			ref->info->reference_count++;
7317 
7318 			if (refIndex + 1 < num_kmod_refs) {
7319 				ref->next = kmod_info->reference_list + refIndex + 1;
7320 			}
7321 		}
7322 	}
7323 
7324 	if (kmod_info->hdr_size > UINT32_MAX) {
7325 		OSKextLog(this,
7326 		    kOSKextLogErrorLevel |
7327 		    kOSKextLogLoadFlag,
7328 #if __LP64__
7329 		    "Kext %s header size is too large (%lu > UINT32_MAX).",
7330 #else
7331 		    "Kext %s header size is too large (%u > UINT32_MAX).",
7332 #endif
7333 		    kmod_info->name,
7334 		    kmod_info->hdr_size);
7335 		result = KERN_FAILURE;
7336 		goto finish;
7337 	}
7338 
7339 	if (kmod_info->size > UINT32_MAX) {
7340 		OSKextLog(this,
7341 		    kOSKextLogErrorLevel |
7342 		    kOSKextLogLoadFlag,
7343 #if __LP64__
7344 		    "Kext %s size is too large (%lu > UINT32_MAX).",
7345 #else
7346 		    "Kext %s size is too large (%u > UINT32_MAX).",
7347 #endif
7348 		    kmod_info->name,
7349 		    kmod_info->size);
7350 		result = KERN_FAILURE;
7351 		goto finish;
7352 	}
7353 
7354 	if (!isInterface() && linkedExecutable) {
7355 		OSKextLog(this,
7356 		    kOSKextLogProgressLevel |
7357 		    kOSKextLogLoadFlag,
7358 		    "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
7359 		    kmod_info->name,
7360 		    (unsigned)kmod_info->size / PAGE_SIZE,
7361 		    (unsigned long)ml_static_unslide(kmod_info->address),
7362 		    (unsigned)kmod_info->id);
7363 	}
7364 
7365 	/* VM protections and wiring for the Aux KC are done at collection loading time */
7366 	if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) {
7367 		/* if prelinked and primary KC, VM protections are already set */
7368 		result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true);
7369 		if (result != KERN_SUCCESS) {
7370 			goto finish;
7371 		}
7372 	}
7373 
7374 #if KASAN
7375 	if (linkedExecutable) {
7376 		kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
7377 		    linkedExecutable->getLength(), getIdentifierCString());
7378 	}
7379 #else
7380 	if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
7381 		OSKextLog(this,
7382 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7383 		    "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
7384 		    getIdentifierCString()
7385 		    );
7386 		result = KERN_FAILURE;
7387 		goto finish;
7388 	}
7389 #endif
7390 
7391 	result = kOSReturnSuccess;
7392 
7393 finish:
7394 
7395 #if CONFIG_KXLD
7396 	/* Clear up locally allocated dependency info.
7397 	 */
7398 	for (i = 0; i < num_kxlddeps; ++i) {
7399 		size_t size;
7400 
7401 		if (kxlddeps[i].kext_name) {
7402 			size = 1 + strlen(kxlddeps[i].kext_name);
7403 			kfree_data(kxlddeps[i].kext_name, size);
7404 		}
7405 		if (kxlddeps[i].interface_name) {
7406 			size = 1 + strlen(kxlddeps[i].interface_name);
7407 			kfree_data(kxlddeps[i].interface_name, size);
7408 		}
7409 	}
7410 	if (kxlddeps) {
7411 		kfree_type(KXLDDependency, num_kxlddeps, kxlddeps);
7412 	}
7413 #endif // CONFIG_KXLD
7414 
7415 	/* We no longer need the unrelocated executable (which the linker
7416 	 * has altered anyhow).
7417 	 */
7418 	setExecutable(NULL);
7419 
7420 	if (result != kOSReturnSuccess) {
7421 		OSKextLog(this,
7422 		    kOSKextLogErrorLevel |
7423 		    kOSKextLogLoadFlag,
7424 		    "Failed to load executable for kext %s.",
7425 		    getIdentifierCString());
7426 
7427 		if (kmod_info && kmod_info->reference_list) {
7428 			kfree_type(kmod_reference_t, num_kmod_refs,
7429 			    kmod_info->reference_list);
7430 		}
7431 		if (isInterface()) {
7432 			kfree_type(kmod_info_t, kmod_info);
7433 			kmod_info = NULL;
7434 		}
7435 		if (kc_type == KCKindUnknown) {
7436 			kmod_info = NULL;
7437 			if (linkedExecutable) {
7438 				linkedExecutable.reset();
7439 			}
7440 		}
7441 	}
7442 
7443 	return result;
7444 }
7445 
7446 /* static */
7447 void
jettisonFileSetLinkeditSegment(kernel_mach_header_t * mh)7448 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh)
7449 {
7450 	kernel_segment_command_t *linkeditseg = NULL;
7451 
7452 	linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT);
7453 	if (linkeditseg == NULL) {
7454 		panic("FileSet booted with no Linkedit segment");
7455 	}
7456 
7457 #if VM_MAPPED_KEXTS
7458 	/* BootKC on x86_64 is not vm mapped */
7459 	ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize);
7460 
7461 	OSKextLog(/* kext */ NULL,
7462 	    kOSKextLogProgressLevel |
7463 	    kOSKextLogGeneralFlag,
7464 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
7465 	    linkeditseg->vmaddr, linkeditseg->vmsize);
7466 #else
7467 	/* BootKC on arm64 is not vm mapped, but is slid */
7468 	vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase));
7469 
7470 	ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize);
7471 
7472 	OSKextLog(/* kext */ NULL,
7473 	    kOSKextLogProgressLevel |
7474 	    kOSKextLogGeneralFlag,
7475 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
7476 	    (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize);
7477 #endif /* VM_MAPPED_KEXTS */
7478 }
7479 
7480 /*********************************************************************
7481 * The linkedit segment is used by the kext linker for dependency
7482 * resolution, and by dtrace for probe initialization. We can free it
7483 * for non-library kexts, since no kexts depend on non-library kexts
7484 * by definition, once dtrace has been initialized.
7485 *********************************************************************/
7486 void
jettisonLinkeditSegment(void)7487 OSKext::jettisonLinkeditSegment(void)
7488 {
7489 	kernel_mach_header_t     * machhdr = (kernel_mach_header_t *)kmod_info->address;
7490 	kernel_segment_command_t * linkedit = NULL;
7491 	vm_offset_t                start;
7492 	vm_size_t                  linkeditsize, kextsize;
7493 	OSSharedPtr<OSData>        data;
7494 	kc_format                format    = KCFormatUnknown;
7495 
7496 	if (isInFileset()) {
7497 		return;
7498 	}
7499 
7500 #if NO_KEXTD
7501 	/* We can free symbol tables for all embedded kexts because we don't
7502 	 * support runtime kext linking.
7503 	 */
7504 	if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
7505 #else
7506 	if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
7507 #endif
7508 		goto finish;
7509 	}
7510 
7511 	/* Find the linkedit segment.  If it's not the last segment, then freeing
7512 	 * it will fragment the kext into multiple VM regions, which OSKext is not
7513 	 * designed to handle, so we'll have to skip it.
7514 	 */
7515 	linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
7516 	if (!linkedit) {
7517 		goto finish;
7518 	}
7519 
7520 	if (round_page(kmod_info->address + kmod_info->size) !=
7521 	    round_page(linkedit->vmaddr + linkedit->vmsize)) {
7522 		goto finish;
7523 	}
7524 
7525 	/* Create a new OSData for the smaller kext object.
7526 	 */
7527 	linkeditsize = round_page(linkedit->vmsize);
7528 	kextsize = kmod_info->size - linkeditsize;
7529 	start = linkedit->vmaddr;
7530 
7531 	if (kextsize > UINT_MAX) {
7532 		goto finish;
7533 	}
7534 	data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize);
7535 	if (!data) {
7536 		goto finish;
7537 	}
7538 
7539 	/* Fix the kmod info and linkedExecutable.
7540 	 */
7541 	kmod_info->size = kextsize;
7542 
7543 	/*
7544 	 * Fileset KCs are mapped as a whole by iBoot.
7545 	 * Individual kext executables should not be unmapped by xnu
7546 	 * Doing so may result in panics like rdar://85419651
7547 	 */
7548 	if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
7549 		data->setDeallocFunction(NULL);
7550 	} else { // Not from a Fileset KC
7551 #if VM_MAPPED_KEXTS
7552 		data->setDeallocFunction(osdata_kext_free);
7553 #else
7554 		data->setDeallocFunction(osdata_phys_free);
7555 #endif
7556 	}
7557 	linkedExecutable->setDeallocFunction(NULL);
7558 	linkedExecutable = os::move(data);
7559 	flags.jettisonLinkeditSeg = 1;
7560 
7561 	/* Free the linkedit segment.
7562 	 */
7563 #if VM_MAPPED_KEXTS
7564 	kext_free(start, linkeditsize);
7565 #else
7566 	ml_static_mfree(start, linkeditsize);
7567 #endif
7568 
7569 finish:
7570 	return;
7571 }
7572 
7573 /*********************************************************************
7574 * If there are whole pages that are unused betweem the last section
7575 * of the DATA segment and the end of the DATA segment then we can free
7576 * them
7577 *********************************************************************/
7578 void
7579 OSKext::jettisonDATASegmentPadding(void)
7580 {
7581 	kernel_mach_header_t * mh;
7582 	kernel_segment_command_t * dataSeg;
7583 	kernel_section_t * sec, * lastSec;
7584 	vm_offset_t dataSegEnd, lastSecEnd;
7585 	vm_size_t padSize;
7586 
7587 	if (flags.builtin) {
7588 		return;
7589 	}
7590 	mh = (kernel_mach_header_t *)kmod_info->address;
7591 
7592 	if (isInFileset()) {
7593 		return;
7594 	}
7595 
7596 	dataSeg = getsegbynamefromheader(mh, SEG_DATA);
7597 	if (dataSeg == NULL) {
7598 		return;
7599 	}
7600 
7601 	lastSec = NULL;
7602 	sec = firstsect(dataSeg);
7603 	while (sec != NULL) {
7604 		lastSec = sec;
7605 		sec = nextsect(dataSeg, sec);
7606 	}
7607 
7608 	if (lastSec == NULL) {
7609 		return;
7610 	}
7611 
7612 	if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
7613 	    (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
7614 		return;
7615 	}
7616 
7617 	dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
7618 	lastSecEnd = round_page(lastSec->addr + lastSec->size);
7619 
7620 	if (dataSegEnd <= lastSecEnd) {
7621 		return;
7622 	}
7623 
7624 	padSize = dataSegEnd - lastSecEnd;
7625 
7626 	if (padSize >= PAGE_SIZE) {
7627 #if VM_MAPPED_KEXTS
7628 		kext_free(lastSecEnd, padSize);
7629 #else
7630 		ml_static_mfree(lastSecEnd, padSize);
7631 #endif
7632 	}
7633 }
7634 
7635 /*********************************************************************
7636 *********************************************************************/
7637 void
7638 OSKext::setLinkedExecutable(OSData * anExecutable)
7639 {
7640 	if (linkedExecutable) {
7641 		panic("Attempt to set linked executable on kext "
7642 		    "that already has one (%s).\n",
7643 		    getIdentifierCString());
7644 	}
7645 	linkedExecutable.reset(anExecutable, OSRetain);
7646 	return;
7647 }
7648 
7649 #if CONFIG_DTRACE
7650 /*********************************************************************
7651 * Go through all loaded kexts and tell them to register with dtrace.
7652 * The instance method only registers if necessary.
7653 *********************************************************************/
7654 /* static */
7655 void
7656 OSKext::registerKextsWithDTrace(void)
7657 {
7658 	uint32_t count = sLoadedKexts->getCount();
7659 	uint32_t i;
7660 
7661 	IORecursiveLockLock(sKextLock);
7662 
7663 	for (i = 0; i < count; i++) {
7664 		OSKext   * thisKext     = NULL;        // do not release
7665 
7666 		thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
7667 		if (!thisKext || !thisKext->isExecutable()) {
7668 			continue;
7669 		}
7670 
7671 		thisKext->registerWithDTrace();
7672 	}
7673 
7674 	IORecursiveLockUnlock(sKextLock);
7675 
7676 	return;
7677 }
7678 
7679 extern "C" {
7680 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
7681 extern int (*dtrace_modunload)(struct kmod_info *);
7682 };
7683 
7684 /*********************************************************************
7685 *********************************************************************/
7686 void
7687 OSKext::registerWithDTrace(void)
7688 {
7689 	/* Register kext with dtrace. A dtrace_modload failure should not
7690 	 * prevent a kext from loading, so we ignore the return code.
7691 	 */
7692 	if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
7693 		uint32_t modflag = 0;
7694 		OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
7695 
7696 		if (!sKeepSymbols && kc_type == KCKindPrimary) {
7697 			if (forceInit == kOSBooleanTrue) {
7698 				OSKextLog(this,
7699 				    kOSKextLogBasicLevel |
7700 				    kOSKextLogGeneralFlag,
7701 				    "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s",
7702 				    getIdentifierCString());
7703 				forceInit = kOSBooleanFalse;
7704 			}
7705 			/* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */
7706 			modflag |= KMOD_DTRACE_NO_KERNEL_SYMS;
7707 		}
7708 
7709 		if (forceInit == kOSBooleanTrue) {
7710 			modflag |= KMOD_DTRACE_FORCE_INIT;
7711 		}
7712 		if (flags.builtin) {
7713 			modflag |= KMOD_DTRACE_STATIC_KEXT;
7714 		}
7715 
7716 		(void)(*dtrace_modload)(kmod_info, modflag);
7717 		flags.dtraceInitialized = true;
7718 		jettisonLinkeditSegment();
7719 	}
7720 	return;
7721 }
7722 /*********************************************************************
7723 *********************************************************************/
7724 void
7725 OSKext::unregisterWithDTrace(void)
7726 {
7727 	/* Unregister kext with dtrace. A dtrace_modunload failure should not
7728 	 * prevent a kext from loading, so we ignore the return code.
7729 	 */
7730 	if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
7731 		(void)(*dtrace_modunload)(kmod_info);
7732 		flags.dtraceInitialized = false;
7733 	}
7734 	return;
7735 }
7736 #endif /* CONFIG_DTRACE */
7737 
7738 
7739 /*********************************************************************
7740 * called only by loadExecutable()
7741 *********************************************************************/
7742 #if !VM_MAPPED_KEXTS
7743 #if defined(__arm__) || defined(__arm64__)
7744 static inline kern_return_t
7745 OSKext_protect(
7746 	kernel_mach_header_t *kext_mh,
7747 	vm_map_t   map,
7748 	vm_map_offset_t    start,
7749 	vm_map_offset_t    end,
7750 	vm_prot_t  new_prot,
7751 	boolean_t  set_max,
7752 	kc_kind_t  kc_type)
7753 {
7754 #pragma unused(kext_mh,map,kc_type)
7755 	assert(map == kernel_map);         // we can handle KEXTs arising from the PRELINK segment and no others
7756 	assert(start <= end);
7757 	if (start >= end) {
7758 		return KERN_SUCCESS;         // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
7759 	} else if (set_max) {
7760 		return KERN_SUCCESS;         // Punt set_max, as there's no mechanism to record that state
7761 	} else {
7762 		return ml_static_protect(start, end - start, new_prot);
7763 	}
7764 }
7765 
7766 static inline kern_return_t
7767 OSKext_wire(
7768 	kernel_mach_header_t *kext_mh,
7769 	vm_map_t   map,
7770 	vm_map_offset_t    start,
7771 	vm_map_offset_t    end,
7772 	vm_prot_t  access_type,
7773 	boolean_t       user_wire,
7774 	kc_kind_t       kc_type)
7775 {
7776 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type)
7777 	return KERN_SUCCESS;         // No-op as PRELINK kexts are cemented into physical memory at boot
7778 }
7779 #else
7780 #error Unrecognized architecture
7781 #endif
7782 #else
7783 static inline kern_return_t
7784 OSKext_protect(
7785 	kernel_mach_header_t *kext_mh,
7786 	vm_map_t   map,
7787 	vm_map_offset_t    start,
7788 	vm_map_offset_t    end,
7789 	vm_prot_t  new_prot,
7790 	boolean_t  set_max,
7791 	kc_kind_t  kc_type)
7792 {
7793 	if (start == end) {         // 10538581
7794 		return KERN_SUCCESS;
7795 	}
7796 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7797 		/*
7798 		 * XXX: This will probably need to be different for AuxKC and
7799 		 * pageableKC!
7800 		 */
7801 		return ml_static_protect(start, end - start, new_prot);
7802 	}
7803 	return vm_map_protect(map, start, end, new_prot, set_max);
7804 }
7805 
7806 static inline kern_return_t
7807 OSKext_wire(
7808 	kernel_mach_header_t *kext_mh,
7809 	vm_map_t   map,
7810 	vm_map_offset_t    start,
7811 	vm_map_offset_t    end,
7812 	vm_prot_t  access_type,
7813 	boolean_t       user_wire,
7814 	kc_kind_t       kc_type)
7815 {
7816 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7817 		/* TODO: we may need to hook this for the pageableKC */
7818 		return KERN_SUCCESS;
7819 	}
7820 	return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
7821 }
7822 #endif
7823 
7824 OSReturn
7825 OSKext::setVMAttributes(bool protect, bool wire)
7826 {
7827 	vm_map_t                    kext_map        = NULL;
7828 	kernel_segment_command_t  * seg             = NULL;
7829 	vm_map_offset_t             start_protect   = 0;
7830 	vm_map_offset_t             start_wire      = 0;
7831 	vm_map_offset_t             end_protect     = 0;
7832 	vm_map_offset_t             end_wire        = 0;
7833 	OSReturn                    result          = kOSReturnError;
7834 
7835 	if (isInterface() || !declaresExecutable() || flags.builtin) {
7836 		result = kOSReturnSuccess;
7837 		goto finish;
7838 	}
7839 
7840 	/* Get the kext's vm map */
7841 	kext_map = kext_get_vm_map(kmod_info);
7842 	if (!kext_map) {
7843 		result = KERN_MEMORY_ERROR;
7844 		goto finish;
7845 	}
7846 
7847 #if !VM_MAPPED_KEXTS
7848 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
7849 		/* This is a split kext in a prelinked kernelcache; we'll let the
7850 		 * platform code take care of protecting it.  It is already wired.
7851 		 */
7852 		/* TODO: Should this still allow protections for the first segment
7853 		 * to go through, in the event that we have a mix of split and
7854 		 * unsplit kexts?
7855 		 */
7856 		result = KERN_SUCCESS;
7857 		goto finish;
7858 	}
7859 
7860 	if (isInFileset() && kc_type != KCKindPageable) {
7861 		// kexts in filesets have protections setup as part of collection loading
7862 		result = KERN_SUCCESS;
7863 		goto finish;
7864 	}
7865 #endif
7866 
7867 	/* Protect the headers as read-only; they do not need to be wired */
7868 	result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7869 	    kext_map, kmod_info->address,
7870 	    kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type)
7871 	    : KERN_SUCCESS;
7872 	if (result != KERN_SUCCESS) {
7873 		goto finish;
7874 	}
7875 
7876 	/* Set the VM protections and wire down each of the segments */
7877 	seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7878 	while (seg) {
7879 #if __arm__
7880 		/* We build all ARM kexts, so we can ensure they are aligned */
7881 		assert((seg->vmaddr & PAGE_MASK) == 0);
7882 		assert((seg->vmsize & PAGE_MASK) == 0);
7883 #endif
7884 
7885 		/*
7886 		 * For the non page aligned segments, the range calculation for protection
7887 		 * and wiring differ as follows:
7888 		 *
7889 		 * Protection: The non page aligned data at the start or at the end of the
7890 		 * segment is excluded from the protection. This exclusion is needed to make
7891 		 * sure OSKext_protect is not called twice on same page, if the page is shared
7892 		 * between two segments.
7893 		 *
7894 		 * Wiring: The non page aligned data at the start or at the end of the
7895 		 * segment is included in the wiring range, this inclusion is needed to make sure
7896 		 * all the data of the segment is wired.
7897 		 */
7898 		start_protect = round_page(seg->vmaddr);
7899 		end_protect = trunc_page(seg->vmaddr + seg->vmsize);
7900 
7901 		start_wire = trunc_page(seg->vmaddr);
7902 		end_wire = round_page(seg->vmaddr + seg->vmsize);
7903 
7904 		/*
7905 		 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared
7906 		 * across kexts and data from kexts is not page aligned
7907 		 */
7908 		if (protect && (end_protect > start_protect) &&
7909 		    ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 &&
7910 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) ||
7911 		    (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) {
7912 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7913 			    kext_map, start_protect, end_protect, seg->maxprot, TRUE, kc_type);
7914 			if (result != KERN_SUCCESS) {
7915 				OSKextLog(this,
7916 				    kOSKextLogErrorLevel |
7917 				    kOSKextLogLoadFlag,
7918 				    "Kext %s failed to set maximum VM protections "
7919 				    "for segment %s - 0x%x.",
7920 				    getIdentifierCString(), seg->segname, (int)result);
7921 				goto finish;
7922 			}
7923 
7924 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7925 			    kext_map, start_protect, end_protect, seg->initprot, FALSE, kc_type);
7926 			if (result != KERN_SUCCESS) {
7927 				OSKextLog(this,
7928 				    kOSKextLogErrorLevel |
7929 				    kOSKextLogLoadFlag,
7930 				    "Kext %s failed to set initial VM protections "
7931 				    "for segment %s - 0x%x.",
7932 				    getIdentifierCString(), seg->segname, (int)result);
7933 				goto finish;
7934 			}
7935 		}
7936 
7937 		if (segmentShouldBeWired(seg) && wire) {
7938 			result = OSKext_wire((kernel_mach_header_t *)kmod_info->address,
7939 			    kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type);
7940 			if (result != KERN_SUCCESS) {
7941 				goto finish;
7942 			}
7943 		}
7944 
7945 		seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7946 	}
7947 
7948 finish:
7949 	return result;
7950 }
7951 
7952 /*********************************************************************
7953 *********************************************************************/
7954 boolean_t
7955 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
7956 {
7957 	return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) &&
7958 	       strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)));
7959 }
7960 
7961 /*********************************************************************
7962 *********************************************************************/
7963 OSReturn
7964 OSKext::validateKextMapping(bool startFlag)
7965 {
7966 	OSReturn                              result      = kOSReturnError;
7967 	const char                          * whichOp = startFlag ? "start" : "stop";
7968 	kern_return_t                         kern_result = 0;
7969 	vm_map_t                              kext_map    = NULL;
7970 	kernel_segment_command_t            * seg         = NULL;
7971 	mach_vm_address_t                     address     = 0;
7972 	mach_vm_size_t                        size        = 0;
7973 	uint32_t                              depth       = 0;
7974 	uint64_t                              kext_segbase = 0;
7975 	uint64_t                              kext_segsize = 0;
7976 	mach_msg_type_number_t                count;
7977 	vm_region_submap_short_info_data_64_t info;
7978 	uintptr_t                             kext_slide = PE_get_kc_slide(kc_type);
7979 
7980 	if (flags.builtin) {
7981 		return kOSReturnSuccess;
7982 	}
7983 
7984 	count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
7985 	bzero(&info, sizeof(info));
7986 
7987 	// xxx - do we need a distinct OSReturn value for these or is "bad data"
7988 	// xxx - sufficient?
7989 
7990 	/* Verify that the kmod_info and start/stop pointers are non-NULL.
7991 	 */
7992 	if (!kmod_info) {
7993 		OSKextLog(this,
7994 		    kOSKextLogErrorLevel |
7995 		    kOSKextLogLoadFlag,
7996 		    "Kext %s - NULL kmod_info pointer.",
7997 		    getIdentifierCString());
7998 		result = kOSKextReturnBadData;
7999 		goto finish;
8000 	}
8001 
8002 	if (startFlag) {
8003 		address = (mach_vm_address_t)kmod_info->start;
8004 	} else {
8005 		address = (mach_vm_address_t)kmod_info->stop;
8006 	}
8007 
8008 	if (!address) {
8009 		OSKextLog(this,
8010 		    kOSKextLogErrorLevel |
8011 		    kOSKextLogLoadFlag,
8012 		    "Kext %s - NULL module %s pointer.",
8013 		    getIdentifierCString(), whichOp);
8014 		result = kOSKextReturnBadData;
8015 		goto finish;
8016 	}
8017 
8018 	kext_map = kext_get_vm_map(kmod_info);
8019 	depth = (kernel_map == kext_map) ? 1 : 2;
8020 	if (isInFileset()) {
8021 #if defined(HAS_APPLE_PAC)
8022 		address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0);
8023 #endif /* defined(HAS_APPLE_PAC) */
8024 	}
8025 
8026 	/* Verify that the start/stop function lies within the kext's address range.
8027 	 */
8028 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) ||
8029 	    isInFileset()) {
8030 		/* This will likely be how we deal with split kexts; walk the segments to
8031 		 * check that the function lies inside one of the segments of this kext.
8032 		 */
8033 		for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8034 		    seg != NULL;
8035 		    seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
8036 			if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
8037 				kext_segbase = seg->vmaddr;
8038 				kext_segsize = seg->vmsize;
8039 				break;
8040 			}
8041 		}
8042 
8043 		if (!seg) {
8044 			OSKextLog(this,
8045 			    kOSKextLogErrorLevel |
8046 			    kOSKextLogLoadFlag,
8047 			    "Kext %s module %s pointer is outside of kext range "
8048 			    "(%s %p - kext starts at %p).",
8049 			    getIdentifierCString(),
8050 			    whichOp,
8051 			    whichOp,
8052 			    (void *)(((uintptr_t)address) - kext_slide),
8053 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide));
8054 			result = kOSKextReturnBadData;
8055 			goto finish;
8056 		}
8057 
8058 		seg = NULL;
8059 	} else {
8060 		if (address < kmod_info->address + kmod_info->hdr_size ||
8061 		    kmod_info->address + kmod_info->size <= address) {
8062 			OSKextLog(this,
8063 			    kOSKextLogErrorLevel |
8064 			    kOSKextLogLoadFlag,
8065 			    "Kext %s module %s pointer is outside of kext range "
8066 			    "(%s %p - kext at %p-%p).",
8067 			    getIdentifierCString(),
8068 			    whichOp,
8069 			    whichOp,
8070 			    (void *)(((uintptr_t)address) - kext_slide),
8071 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide),
8072 			    (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size));
8073 			result = kOSKextReturnBadData;
8074 			goto finish;
8075 		}
8076 	}
8077 
8078 	/* Only do these checks before calling the start function;
8079 	 * If anything goes wrong with the mapping while the kext is running,
8080 	 * we'll likely have panicked well before any attempt to stop the kext.
8081 	 */
8082 	if (startFlag) {
8083 		if (!isInFileset() || kc_type != KCKindPrimary) {
8084 			/*
8085 			 * Verify that the start/stop function is executable.
8086 			 */
8087 			kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
8088 			    (vm_region_recurse_info_t)&info, &count);
8089 			if (kern_result != KERN_SUCCESS) {
8090 				OSKextLog(this,
8091 				    kOSKextLogErrorLevel |
8092 				    kOSKextLogLoadFlag,
8093 				    "Kext %s - bad %s pointer %p.",
8094 				    getIdentifierCString(),
8095 				    whichOp, (void *)ml_static_unslide(address));
8096 				result = kOSKextReturnBadData;
8097 				goto finish;
8098 			}
8099 		} else {
8100 			/*
8101 			 * Since kexts loaded from the primary KC are held in memory
8102 			 * allocated by efiboot, we cannot use mach_vm_region_recurse() to
8103 			 * discover that memory's protection flags.  Instead, we need to
8104 			 * get that information from the kernel pmap itself.  Above, we
8105 			 * (potentially) saved the size of the segment in which the address
8106 			 * in question was located.  If we have a non-zero size, verify
8107 			 * that all pages in the (address, address + kext_segsize) range
8108 			 * are marked executable.  If we somehow did not record the size
8109 			 * (or the base) just verify the single page that includes the address.
8110 			 */
8111 			if (kext_segbase == 0 || kext_segsize == 0) {
8112 				kext_segbase = address & ~(uint64_t)PAGE_MASK;
8113 				kext_segsize = PAGE_SIZE;
8114 			}
8115 		}
8116 
8117 #if VM_MAPPED_KEXTS
8118 		if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) ||
8119 		    ((isInFileset() && kc_type == KCKindPrimary) &&
8120 		    ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) {
8121 			OSKextLog(this,
8122 			    kOSKextLogErrorLevel |
8123 			    kOSKextLogLoadFlag,
8124 			    "Kext %s - memory region containing module %s function "
8125 			    "is not executable.",
8126 			    getIdentifierCString(), whichOp);
8127 			result = kOSKextReturnBadData;
8128 			goto finish;
8129 		}
8130 #endif
8131 
8132 		/* Verify that the kext's segments are backed by physical memory.
8133 		 */
8134 		seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8135 		while (seg) {
8136 			if (!verifySegmentMapping(seg)) {
8137 				result = kOSKextReturnBadData;
8138 				goto finish;
8139 			}
8140 
8141 			seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8142 		}
8143 	}
8144 
8145 	result = kOSReturnSuccess;
8146 finish:
8147 	return result;
8148 }
8149 
8150 /*********************************************************************
8151 *********************************************************************/
8152 boolean_t
8153 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
8154 {
8155 	mach_vm_address_t address = 0;
8156 
8157 	if (seg->vmsize > UINT32_MAX) {
8158 		return false;
8159 	}
8160 
8161 	if (!segmentShouldBeWired(seg)) {
8162 		return true;
8163 	}
8164 
8165 	for (address = seg->vmaddr;
8166 	    address < round_page(seg->vmaddr + seg->vmsize);
8167 	    address += PAGE_SIZE) {
8168 		if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
8169 			OSKextLog(this,
8170 			    kOSKextLogErrorLevel |
8171 			    kOSKextLogLoadFlag,
8172 			    "Kext %s - page %p is not backed by physical memory.",
8173 			    getIdentifierCString(),
8174 			    (void *)address);
8175 			return false;
8176 		}
8177 	}
8178 
8179 	return true;
8180 }
8181 
8182 /*********************************************************************
8183 *********************************************************************/
8184 static void
8185 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
8186 {
8187 	uint64_t                            stamp = 0;
8188 	firehose_tracepoint_id_u            trace_id;
8189 	struct firehose_trace_uuid_info_s   uuid_info_s;
8190 	firehose_trace_uuid_info_t          uuid_info = &uuid_info_s;
8191 	size_t                              uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
8192 	OSSharedPtr<OSData>                 uuid_data;
8193 
8194 	stamp = firehose_tracepoint_time(firehose_activity_flags_default);
8195 	trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
8196 
8197 	uuid_data = aKext->copyTextUUID();
8198 	if (uuid_data) {
8199 		memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
8200 	}
8201 
8202 	uuid_info->ftui_size    = size;
8203 	if (aKext->isDriverKit()) {
8204 		uuid_info->ftui_address = address;
8205 	} else {
8206 		uuid_info->ftui_address = ml_static_unslide(address);
8207 	}
8208 	firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len);
8209 	return;
8210 }
8211 
8212 void
8213 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext)
8214 {
8215 	OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load);
8216 }
8217 
8218 /*********************************************************************
8219 *********************************************************************/
8220 OSReturn
8221 OSKext::start(bool startDependenciesFlag)
8222 {
8223 	OSReturn                            result = kOSReturnError;
8224 	kern_return_t                       (* startfunc)(kmod_info_t *, void *);
8225 	unsigned int                        i, count;
8226 	void                              * kmodStartData = NULL;
8227 
8228 	if (isStarted() || isInterface() || isKernelComponent()) {
8229 		result = kOSReturnSuccess;
8230 		goto finish;
8231 	}
8232 
8233 	if (!isLoaded()) {
8234 		OSKextLog(this,
8235 		    kOSKextLogErrorLevel |
8236 		    kOSKextLogLoadFlag,
8237 		    "Attempt to start nonloaded kext %s.",
8238 		    getIdentifierCString());
8239 		result = kOSKextReturnInvalidArgument;
8240 		goto finish;
8241 	}
8242 
8243 	if (!sLoadEnabled) {
8244 		OSKextLog(this,
8245 		    kOSKextLogErrorLevel |
8246 		    kOSKextLogLoadFlag,
8247 		    "Kext loading is disabled (attempt to start kext %s).",
8248 		    getIdentifierCString());
8249 		result = kOSKextReturnDisabled;
8250 		goto finish;
8251 	}
8252 
8253 	result = validateKextMapping(/* start? */ true);
8254 	if (result != kOSReturnSuccess) {
8255 		goto finish;
8256 	}
8257 
8258 	startfunc = kmod_info->start;
8259 
8260 	count = getNumDependencies();
8261 	for (i = 0; i < count; i++) {
8262 		OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
8263 		if (dependency == NULL) {
8264 			OSKextLog(this,
8265 			    kOSKextLogErrorLevel |
8266 			    kOSKextLogLoadFlag,
8267 			    "Kext %s start - internal error, dependency disappeared.",
8268 			    getIdentifierCString());
8269 			goto finish;
8270 		}
8271 		if (!dependency->isStarted()) {
8272 			if (startDependenciesFlag) {
8273 				OSReturn dependencyResult =
8274 				    dependency->start(startDependenciesFlag);
8275 				if (dependencyResult != KERN_SUCCESS) {
8276 					OSKextLog(this,
8277 					    kOSKextLogErrorLevel |
8278 					    kOSKextLogLoadFlag,
8279 					    "Kext %s start - dependency %s failed to start (error 0x%x).",
8280 					    getIdentifierCString(),
8281 					    dependency->getIdentifierCString(),
8282 					    dependencyResult);
8283 					goto finish;
8284 				}
8285 			} else {
8286 				OSKextLog(this,
8287 				    kOSKextLogErrorLevel |
8288 				    kOSKextLogLoadFlag,
8289 				    "Not starting %s - dependency %s not started yet.",
8290 				    getIdentifierCString(),
8291 				    dependency->getIdentifierCString());
8292 				result = kOSKextReturnStartStopError;         // xxx - make new return?
8293 				goto finish;
8294 			}
8295 		}
8296 	}
8297 
8298 	OSKextLog(this,
8299 	    kOSKextLogDetailLevel |
8300 	    kOSKextLogLoadFlag,
8301 	    "Kext %s calling module start function.",
8302 	    getIdentifierCString());
8303 
8304 	flags.starting = 1;
8305 
8306 	// Drop a log message so logd can grab the needed information to decode this kext
8307 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
8308 	result = OSRuntimeInitializeCPP(this);
8309 	if (result == KERN_SUCCESS) {
8310 		result = startfunc(kmod_info, kmodStartData);
8311 	}
8312 
8313 	flags.starting = 0;
8314 
8315 	/* On success overlap the setting of started/starting. On failure just
8316 	 * clear starting.
8317 	 */
8318 	if (result == KERN_SUCCESS) {
8319 		flags.started = 1;
8320 
8321 		// xxx - log start error from kernel?
8322 		OSKextLog(this,
8323 		    kOSKextLogProgressLevel |
8324 		    kOSKextLogLoadFlag,
8325 		    "Kext %s is now started.",
8326 		    getIdentifierCString());
8327 	} else {
8328 		invokeOrCancelRequestCallbacks(
8329 			/* result not actually used */ kOSKextReturnStartStopError,
8330 			/* invokeFlag */ false);
8331 		OSKextLog(this,
8332 		    kOSKextLogWarningLevel |
8333 		    kOSKextLogLoadFlag,
8334 		    "Kext %s did not start (return code 0x%x).",
8335 		    getIdentifierCString(), result);
8336 	}
8337 
8338 finish:
8339 	return result;
8340 }
8341 
8342 /*********************************************************************
8343 *********************************************************************/
8344 /* static */
8345 bool
8346 OSKext::canUnloadKextWithIdentifier(
8347 	OSString * kextIdentifier,
8348 	bool       checkClassesFlag)
8349 {
8350 	bool     result = false;
8351 	OSKext * aKext  = NULL;        // do not release
8352 
8353 	IORecursiveLockLock(sKextLock);
8354 
8355 	aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
8356 
8357 	if (!aKext) {
8358 		goto finish;         // can't unload what's not loaded
8359 	}
8360 
8361 	if (aKext->isLoaded()) {
8362 		if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
8363 			goto finish;
8364 		}
8365 		if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
8366 			goto finish;
8367 		}
8368 	}
8369 
8370 	result = true;
8371 
8372 finish:
8373 	IORecursiveLockUnlock(sKextLock);
8374 	return result;
8375 }
8376 
8377 /*********************************************************************
8378 *********************************************************************/
8379 OSReturn
8380 OSKext::stop(void)
8381 {
8382 	OSReturn result = kOSReturnError;
8383 	kern_return_t (*stopfunc)(kmod_info_t *, void *);
8384 
8385 	if (!isStarted() || isInterface()) {
8386 		result = kOSReturnSuccess;
8387 		goto finish;
8388 	}
8389 
8390 	if (!isLoaded()) {
8391 		OSKextLog(this,
8392 		    kOSKextLogErrorLevel |
8393 		    kOSKextLogLoadFlag,
8394 		    "Attempt to stop nonloaded kext %s.",
8395 		    getIdentifierCString());
8396 		result = kOSKextReturnInvalidArgument;
8397 		goto finish;
8398 	}
8399 
8400 	/* Refuse to stop if we have clients or instances. It is up to
8401 	 * the caller to make sure those aren't true.
8402 	 */
8403 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8404 		OSKextLog(this,
8405 		    kOSKextLogErrorLevel |
8406 		    kOSKextLogLoadFlag,
8407 		    "Kext %s - C++ instances; can't stop.",
8408 		    getIdentifierCString());
8409 		result = kOSKextReturnInUse;
8410 		goto finish;
8411 	}
8412 
8413 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8414 		OSKextLog(this,
8415 		    kOSKextLogErrorLevel |
8416 		    kOSKextLogLoadFlag,
8417 		    "Kext %s - has references (linkage or tracking object); "
8418 		    "can't stop.",
8419 		    getIdentifierCString());
8420 		result = kOSKextReturnInUse;
8421 		goto finish;
8422 	}
8423 
8424 	/* Note: If validateKextMapping fails on the stop & unload path,
8425 	 * we are in serious trouble and a kernel panic is likely whether
8426 	 * we stop & unload the kext or not.
8427 	 */
8428 	result = validateKextMapping(/* start? */ false);
8429 	if (result != kOSReturnSuccess) {
8430 		goto finish;
8431 	}
8432 
8433 	stopfunc = kmod_info->stop;
8434 	if (stopfunc) {
8435 		OSKextLog(this,
8436 		    kOSKextLogDetailLevel |
8437 		    kOSKextLogLoadFlag,
8438 		    "Kext %s calling module stop function.",
8439 		    getIdentifierCString());
8440 
8441 		flags.stopping = 1;
8442 
8443 		result = stopfunc(kmod_info, /* userData */ NULL);
8444 		if (result == KERN_SUCCESS) {
8445 			result = OSRuntimeFinalizeCPP(this);
8446 		}
8447 
8448 		flags.stopping = 0;
8449 
8450 		if (result == KERN_SUCCESS) {
8451 			flags.started = 0;
8452 
8453 			OSKextLog(this,
8454 			    kOSKextLogDetailLevel |
8455 			    kOSKextLogLoadFlag,
8456 			    "Kext %s is now stopped and ready to unload.",
8457 			    getIdentifierCString());
8458 		} else {
8459 			OSKextLog(this,
8460 			    kOSKextLogErrorLevel |
8461 			    kOSKextLogLoadFlag,
8462 			    "Kext %s did not stop (return code 0x%x).",
8463 			    getIdentifierCString(), result);
8464 			result = kOSKextReturnStartStopError;
8465 		}
8466 	}
8467 
8468 finish:
8469 	// Drop a log message so logd can update this kext's metadata
8470 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
8471 	return result;
8472 }
8473 
8474 /*********************************************************************
8475 *********************************************************************/
8476 OSReturn
8477 OSKext::unload(void)
8478 {
8479 	OSReturn        result = kOSReturnError;
8480 	unsigned int    index;
8481 	uint32_t        num_kmod_refs = 0;
8482 	OSKextAccount * freeAccount;
8483 	bool            in_fileset = false;
8484 
8485 	if (!sUnloadEnabled) {
8486 		OSKextLog(this,
8487 		    kOSKextLogErrorLevel |
8488 		    kOSKextLogLoadFlag,
8489 		    "Kext unloading is disabled (%s).",
8490 		    this->getIdentifierCString());
8491 
8492 		result = kOSKextReturnDisabled;
8493 		goto finish;
8494 	}
8495 
8496 	// cache this result so we don't need to access the kmod_info after
8497 	// it's been potentially free'd
8498 	in_fileset = isInFileset();
8499 
8500 	/* Refuse to unload if we have clients or instances. It is up to
8501 	 * the caller to make sure those aren't true.
8502 	 */
8503 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8504 		// xxx - Don't log under errors? this is more of an info thing
8505 		OSKextLog(this,
8506 		    kOSKextLogErrorLevel |
8507 		    kOSKextLogKextBookkeepingFlag,
8508 		    "Can't unload kext %s; outstanding references %d (linkage or tracking object).",
8509 		    getIdentifierCString(), getRetainCount());
8510 		result = kOSKextReturnInUse;
8511 		goto finish;
8512 	}
8513 
8514 	if (isDriverKit()) {
8515 		index = sLoadedDriverKitKexts->getNextIndexOfObject(this, 0);
8516 		if (index != (unsigned int)-1) {
8517 			sLoadedDriverKitKexts->removeObject(index);
8518 			OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
8519 			loadTag = 0;
8520 		}
8521 	}
8522 
8523 	if (!isLoaded()) {
8524 		result = kOSReturnSuccess;
8525 		goto finish;
8526 	}
8527 
8528 	if (isKernelComponent()) {
8529 		result = kOSKextReturnInvalidArgument;
8530 		goto finish;
8531 	}
8532 
8533 	if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) {
8534 		OSKextLog(this,
8535 		    kOSKextLogErrorLevel |
8536 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8537 		    "Can't unload kext %s; classes have instances:",
8538 		    getIdentifierCString());
8539 		reportOSMetaClassInstances(kOSKextLogErrorLevel |
8540 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
8541 		result = kOSKextReturnInUse;
8542 		goto finish;
8543 	}
8544 
8545 	/* Note that the kext is unloading before running any code that
8546 	 * might be in the kext (request callbacks, module stop function).
8547 	 * We will deny certain requests made against a kext in the process
8548 	 * of unloading.
8549 	 */
8550 	flags.unloading = 1;
8551 
8552 	/* Update the string describing the last kext to unload in case we panic.
8553 	 */
8554 	savePanicString(/* isLoading */ false);
8555 
8556 	if (isStarted()) {
8557 		result = stop();
8558 		if (result != KERN_SUCCESS) {
8559 			OSKextLog(this,
8560 			    kOSKextLogErrorLevel |
8561 			    kOSKextLogLoadFlag,
8562 			    "Kext %s can't unload - module stop returned 0x%x.",
8563 			    getIdentifierCString(), (unsigned)result);
8564 			result = kOSKextReturnStartStopError;
8565 			goto finish;
8566 		}
8567 	}
8568 
8569 	OSKextLog(this,
8570 	    kOSKextLogProgressLevel |
8571 	    kOSKextLogLoadFlag,
8572 	    "Kext %s unloading.",
8573 	    getIdentifierCString());
8574 
8575 	{
8576 		struct list_head *p;
8577 		struct list_head *prev;
8578 		struct list_head *next;
8579 		for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
8580 			OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
8581 			s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
8582 			prev = p->prev;
8583 			next = p->next;
8584 			prev->next = next;
8585 			next->prev = prev;
8586 			p->prev = p;
8587 			p->next = p;
8588 			IORecursiveLockWakeup(sKextLock, s, false);
8589 		}
8590 	}
8591 
8592 
8593 	/* Even if we don't call the stop function, we want to be sure we
8594 	 * have no OSMetaClass references before unloading the kext executable
8595 	 * from memory. OSMetaClasses may have pointers into the kext executable
8596 	 * and that would cause a panic on OSKext::free() when metaClasses is freed.
8597 	 */
8598 	if (metaClasses) {
8599 		metaClasses->flushCollection();
8600 	}
8601 	(void) OSRuntimeFinalizeCPP(this);
8602 
8603 	/* Remove the kext from the list of loaded kexts, patch the gap
8604 	 * in the kmod_info_t linked list, and reset "kmod" to point to the
8605 	 * last loaded kext that isn't the fake kernel kext (sKernelKext).
8606 	 */
8607 	index = sLoadedKexts->getNextIndexOfObject(this, 0);
8608 	if (index != (unsigned int)-1) {
8609 		sLoadedKexts->removeObject(index);
8610 
8611 		OSKext * nextKext = OSDynamicCast(OSKext,
8612 		    sLoadedKexts->getObject(index));
8613 
8614 		if (nextKext) {
8615 			if (index > 0) {
8616 				OSKext * gapKext = OSDynamicCast(OSKext,
8617 				    sLoadedKexts->getObject(index - 1));
8618 
8619 				nextKext->kmod_info->next = gapKext->kmod_info;
8620 			} else {         /* index == 0 */
8621 				nextKext->kmod_info->next = NULL;
8622 			}
8623 		}
8624 
8625 		OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
8626 		if (lastKext && !lastKext->isKernel()) {
8627 			kmod = lastKext->kmod_info;
8628 		} else {
8629 			kmod = NULL;         // clear the global kmod variable
8630 		}
8631 	}
8632 
8633 	/* Clear out the kmod references that we're keeping for compatibility
8634 	 * with current panic backtrace code & kgmacros.
8635 	 * xxx - will want to update those bits sometime and remove this.
8636 	 */
8637 	num_kmod_refs = getNumDependencies();
8638 	if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
8639 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
8640 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
8641 			ref->info->reference_count--;
8642 		}
8643 		kfree_type(kmod_reference_t, num_kmod_refs,
8644 		    kmod_info->reference_list);
8645 	}
8646 
8647 #if CONFIG_DTRACE
8648 	unregisterWithDTrace();
8649 #endif /* CONFIG_DTRACE */
8650 
8651 	notifyKextUnloadObservers(this);
8652 
8653 	freeAccount = NULL;
8654 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
8655 	account->kext = NULL;
8656 	if (account->site.tag) {
8657 		account->site.flags |= VM_TAG_UNLOAD;
8658 	} else {
8659 		freeAccount = account;
8660 	}
8661 
8662 #if DEVELOPMENT || DEBUG
8663 	assertf(account->task_refgrp.grp_count == 0,
8664 	    "unloading a kext with active task references");
8665 #endif /* DEVELOPMENT || DEBUG */
8666 
8667 	lck_ticket_unlock(sKextAccountsLock);
8668 	if (freeAccount) {
8669 		IOFreeType(freeAccount, OSKextAccount);
8670 	}
8671 
8672 	/* Unwire and free the linked executable.
8673 	 */
8674 	if (linkedExecutable) {
8675 #if KASAN
8676 		kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
8677 #endif
8678 
8679 #if VM_MAPPED_KEXTS
8680 		if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) {
8681 			kernel_segment_command_t *seg = NULL;
8682 			vm_map_t kext_map = kext_get_vm_map(kmod_info);
8683 
8684 			if (!kext_map) {
8685 				OSKextLog(this,
8686 				    kOSKextLogErrorLevel |
8687 				    kOSKextLogLoadFlag,
8688 				    "Failed to free kext %s; couldn't find the kext map.",
8689 				    getIdentifierCString());
8690 				result = kOSKextReturnInternalError;
8691 				goto finish;
8692 			}
8693 
8694 			OSKextLog(this,
8695 			    kOSKextLogProgressLevel |
8696 			    kOSKextLogLoadFlag,
8697 			    "Kext %s unwiring and unmapping linked executable.",
8698 			    getIdentifierCString());
8699 
8700 			seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8701 			while (seg) {
8702 				if (segmentShouldBeWired(seg)) {
8703 					vm_map_offset_t start_wire = trunc_page(seg->vmaddr);
8704 					vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize);
8705 
8706 					result = vm_map_unwire(kext_map, start_wire,
8707 					    end_wire, FALSE);
8708 					if (result != KERN_SUCCESS) {
8709 						OSKextLog(this,
8710 						    kOSKextLogErrorLevel |
8711 						    kOSKextLogLoadFlag,
8712 						    "Failed to unwire kext %s.",
8713 						    getIdentifierCString());
8714 						result = kOSKextReturnInternalError;
8715 						goto finish;
8716 					}
8717 				}
8718 
8719 				seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8720 			}
8721 #if defined(__x86_64__) || defined(__i386__)
8722 			if (in_fileset && flags.resetSegmentsFromVnode) {
8723 				IORecursiveLockLock(sKextLock);
8724 				resetKCFileSetSegments();
8725 				IORecursiveLockUnlock(sKextLock);
8726 			}
8727 #endif // (__x86_64__) || defined(__i386__)
8728 		}
8729 #endif /* VM_MAPPED_KEXTS */
8730 		if (flags.resetSegmentsFromImmutableCopy) {
8731 			result = resetMutableSegments();
8732 			if (result != kOSReturnSuccess) {
8733 				OSKextLog(this,
8734 				    kOSKextLogErrorLevel |
8735 				    kOSKextLogLoadFlag,
8736 				    "Failed to reset kext %s.",
8737 				    getIdentifierCString());
8738 				result = kOSKextReturnInternalError;
8739 				goto finish;
8740 			}
8741 		}
8742 		if (kc_type == KCKindUnknown) {
8743 			linkedExecutable.reset();
8744 		}
8745 	}
8746 
8747 	/* An interface kext has a fake kmod_info that was allocated,
8748 	 * so we have to free it.
8749 	 */
8750 	if (isInterface()) {
8751 		kfree_type(kmod_info_t, kmod_info);
8752 		kmod_info = NULL;
8753 	}
8754 
8755 	if (!in_fileset) {
8756 		kmod_info = NULL;
8757 	}
8758 
8759 	flags.loaded = false;
8760 	flushDependencies();
8761 
8762 	/* save a copy of the bundle ID for us to check when deciding to
8763 	 * rebuild the kernel cache file.  If a kext was already in the kernel
8764 	 * cache and unloaded then later loaded we do not need to rebuild the
8765 	 * kernel cache.  9055303
8766 	 */
8767 	if (isPrelinked()) {
8768 		if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) {
8769 			IORecursiveLockLock(sKextLock);
8770 			if (sUnloadedPrelinkedKexts) {
8771 				sUnloadedPrelinkedKexts->setObject(bundleID.get());
8772 			}
8773 			IORecursiveLockUnlock(sKextLock);
8774 		}
8775 	}
8776 
8777 	OSKextLog(this,
8778 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8779 	    "Kext %s unloaded.", getIdentifierCString());
8780 
8781 	queueKextNotification(kKextRequestPredicateUnloadNotification,
8782 	    OSDynamicCast(OSString, bundleID.get()), getDextUniqueID());
8783 
8784 finish:
8785 	OSKext::saveLoadedKextPanicList();
8786 	OSKext::updateLoadedKextSummaries();
8787 
8788 	flags.unloading = 0;
8789 	return result;
8790 }
8791 
8792 /*********************************************************************
8793 * Assumes sKextLock is held.
8794 *********************************************************************/
8795 /* static */
8796 OSReturn
8797 OSKext::queueKextNotification(
8798 	const char * notificationName,
8799 	OSString   * kextIdentifier,
8800 	OSData     * dextUniqueIdentifier)
8801 {
8802 	OSReturn          result               = kOSReturnError;
8803 	OSSharedPtr<OSDictionary>    loadRequest;
8804 
8805 	if (!kextIdentifier) {
8806 		result = kOSKextReturnInvalidArgument;
8807 		goto finish;
8808 	}
8809 
8810 	/* Create a new request unless one is already sitting
8811 	 * in sKernelRequests for this bundle identifier
8812 	 */
8813 	result = _OSKextCreateRequest(notificationName, loadRequest);
8814 	if (result != kOSReturnSuccess) {
8815 		goto finish;
8816 	}
8817 	if (!_OSKextSetRequestArgument(loadRequest.get(),
8818 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
8819 		result = kOSKextReturnNoMemory;
8820 		goto finish;
8821 	}
8822 	if (NULL != dextUniqueIdentifier) {
8823 		if (!_OSKextSetRequestArgument(loadRequest.get(),
8824 		    kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) {
8825 			result = kOSKextReturnNoMemory;
8826 			goto finish;
8827 		}
8828 	}
8829 	if (!sKernelRequests->setObject(loadRequest.get())) {
8830 		result = kOSKextReturnNoMemory;
8831 		goto finish;
8832 	}
8833 
8834 	/* We might want to only queue the notification if the IOKit daemon is active,
8835 	 * but that wouldn't work for embedded. Note that we don't care if
8836 	 * the ping immediately succeeds here so don't do anything with the
8837 	 * result of this call.
8838 	 */
8839 	OSKext::pingIOKitDaemon();
8840 
8841 	result = kOSReturnSuccess;
8842 
8843 finish:
8844 	return result;
8845 }
8846 
8847 
8848 #if CONFIG_KXLD
8849 /*********************************************************************
8850 *********************************************************************/
8851 static void
8852 _OSKextConsiderDestroyingLinkContext(
8853 	__unused thread_call_param_t p0,
8854 	__unused thread_call_param_t p1)
8855 {
8856 	/* Take multiple locks in the correct order.
8857 	 */
8858 	IORecursiveLockLock(sKextLock);
8859 	IORecursiveLockLock(sKextInnerLock);
8860 
8861 	/* The first time we destroy the kxldContext is in the first
8862 	 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
8863 	 * before calling this function. Thereafter any call to this function
8864 	 * will actually destroy the context.
8865 	 */
8866 	if (sConsiderUnloadsCalled && sKxldContext) {
8867 		kxld_destroy_context(sKxldContext);
8868 		sKxldContext = NULL;
8869 	}
8870 
8871 	/* Free the thread_call that was allocated to execute this function.
8872 	 */
8873 	if (sDestroyLinkContextThread) {
8874 		if (!thread_call_free(sDestroyLinkContextThread)) {
8875 			OSKextLog(/* kext */ NULL,
8876 			    kOSKextLogErrorLevel |
8877 			    kOSKextLogGeneralFlag,
8878 			    "thread_call_free() failed for kext link context.");
8879 		}
8880 		sDestroyLinkContextThread = NULL;
8881 	}
8882 
8883 	IORecursiveLockUnlock(sKextInnerLock);
8884 	IORecursiveLockUnlock(sKextLock);
8885 
8886 	return;
8887 }
8888 
8889 /*********************************************************************
8890 * Destroying the kxldContext requires checking variables under both
8891 * sKextInnerLock and sKextLock, so we do it on a separate thread
8892 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
8893 * call relationship.
8894 *
8895 * This function must be invoked with sKextInnerLock held.
8896 * Do not call any function that takes sKextLock here!
8897 *********************************************************************/
8898 /* static */
8899 void
8900 OSKext::considerDestroyingLinkContext(void)
8901 {
8902 	IORecursiveLockLock(sKextInnerLock);
8903 
8904 	/* If we have already queued a thread to destroy the link context,
8905 	 * don't bother resetting; that thread will take care of it.
8906 	 */
8907 	if (sDestroyLinkContextThread) {
8908 		goto finish;
8909 	}
8910 
8911 	/* The function to be invoked in the thread will deallocate
8912 	 * this thread_call, so don't share it around.
8913 	 */
8914 	sDestroyLinkContextThread = thread_call_allocate(
8915 		&_OSKextConsiderDestroyingLinkContext, NULL);
8916 	if (!sDestroyLinkContextThread) {
8917 		OSKextLog(/* kext */ NULL,
8918 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
8919 		    "Can't create thread to destroy kext link context.");
8920 		goto finish;
8921 	}
8922 
8923 	thread_call_enter(sDestroyLinkContextThread);
8924 
8925 finish:
8926 	IORecursiveLockUnlock(sKextInnerLock);
8927 	return;
8928 }
8929 
8930 #else // !CONFIG_KXLD
8931 
8932 /* static */
8933 void
8934 OSKext::considerDestroyingLinkContext(void)
8935 {
8936 	return;
8937 }
8938 
8939 #endif // CONFIG_KXLD
8940 
8941 #if PRAGMA_MARK
8942 #pragma mark Autounload
8943 #endif
8944 /*********************************************************************
8945 * This is a static method because the kext will be deallocated if it
8946 * does unload!
8947 *********************************************************************/
8948 /* static */
8949 OSReturn
8950 OSKext::autounloadKext(OSKext * aKext)
8951 {
8952 	OSReturn result = kOSKextReturnInUse;
8953 
8954 #if NO_KEXTD
8955 	/*
8956 	 * Do not unload prelinked kexts on platforms that do not have an
8957 	 * IOKit daemon as there is no way to reload the kext or restart
8958 	 * matching.
8959 	 */
8960 	if (aKext->isPrelinked()) {
8961 		goto finish;
8962 	}
8963 #endif /* defined(__x86_64__) */
8964 
8965 	/* Check for external references to this kext (usu. dependents),
8966 	 * instances of defined classes (or classes derived from them),
8967 	 * outstanding requests.
8968 	 */
8969 	if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
8970 	    !aKext->flags.autounloadEnabled ||
8971 	    aKext->isKernelComponent()) {
8972 		goto finish;
8973 	}
8974 
8975 	/* Skip a delay-autounload kext, once.
8976 	 */
8977 	if (aKext->flags.delayAutounload) {
8978 		OSKextLog(aKext,
8979 		    kOSKextLogProgressLevel |
8980 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8981 		    "Kext %s has delayed autounload set; skipping and clearing flag.",
8982 		    aKext->getIdentifierCString());
8983 		aKext->flags.delayAutounload = 0;
8984 		goto finish;
8985 	}
8986 
8987 	if (aKext->hasOSMetaClassInstances() ||
8988 	    aKext->countRequestCallbacks()) {
8989 		goto finish;
8990 	}
8991 
8992 	result = OSKext::removeKext(aKext);
8993 
8994 finish:
8995 	return result;
8996 }
8997 
8998 /*********************************************************************
8999 *********************************************************************/
9000 void
9001 _OSKextConsiderUnloads(
9002 	__unused thread_call_param_t p0,
9003 	__unused thread_call_param_t p1)
9004 {
9005 	bool         didUnload = false;
9006 	unsigned int count, i;
9007 
9008 	/* Take multiple locks in the correct order
9009 	 * (note also sKextSummaries lock further down).
9010 	 */
9011 	IORecursiveLockLock(sKextLock);
9012 	IORecursiveLockLock(sKextInnerLock);
9013 
9014 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
9015 
9016 	/* If the system is powering down, don't try to unload anything.
9017 	 */
9018 	if (sSystemSleep) {
9019 		goto finish;
9020 	}
9021 
9022 	OSKextLog(/* kext */ NULL,
9023 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
9024 	    "Checking for unused kexts to autounload.");
9025 
9026 	/*****
9027 	 * Remove any request callbacks marked as stale,
9028 	 * and mark as stale any currently in flight.
9029 	 */
9030 	count = sRequestCallbackRecords->getCount();
9031 	if (count) {
9032 		i = count - 1;
9033 		do {
9034 			OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
9035 			    sRequestCallbackRecords->getObject(i));
9036 			if (callbackRecord) {
9037 				OSBoolean * stale = OSDynamicCast(OSBoolean,
9038 				    callbackRecord->getObject(kKextRequestStaleKey));
9039 
9040 				if (stale == kOSBooleanTrue) {
9041 					OSKext::invokeRequestCallback(callbackRecord,
9042 					    kOSKextReturnTimeout);
9043 				} else {
9044 					callbackRecord->setObject(kKextRequestStaleKey,
9045 					    kOSBooleanTrue);
9046 				}
9047 			}
9048 		} while (i--);
9049 	}
9050 
9051 	/*****
9052 	 * Make multiple passes through the array of loaded kexts until
9053 	 * we don't unload any. This handles unwinding of dependency
9054 	 * chains. We have to go *backwards* through the array because
9055 	 * kexts are removed from it when unloaded, and we cannot make
9056 	 * a copy or we'll mess up the retain counts we rely on to
9057 	 * check whether a kext will unload. If only we could have
9058 	 * nonretaining collections like CF has....
9059 	 */
9060 	do {
9061 		didUnload = false;
9062 
9063 		count = sLoadedKexts->getCount();
9064 		if (count) {
9065 			i = count - 1;
9066 			do {
9067 				OSKext * thisKext = OSDynamicCast(OSKext,
9068 				    sLoadedKexts->getObject(i));
9069 				didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
9070 			} while (i--);
9071 		}
9072 	} while (didUnload);
9073 
9074 finish:
9075 	sConsiderUnloadsPending = false;
9076 	sConsiderUnloadsExecuted = true;
9077 
9078 	(void) OSKext::considerRebuildOfPrelinkedKernel();
9079 
9080 	IORecursiveLockUnlock(sKextInnerLock);
9081 	IORecursiveLockUnlock(sKextLock);
9082 
9083 	return;
9084 }
9085 
9086 /*********************************************************************
9087 * Do not call any function that takes sKextLock here!
9088 *********************************************************************/
9089 void
9090 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
9091 {
9092 	AbsoluteTime when;
9093 
9094 	IORecursiveLockLock(sKextInnerLock);
9095 
9096 	if (!sUnloadCallout) {
9097 		sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL);
9098 	}
9099 
9100 	/* we only reset delay value for unloading if we already have something
9101 	 * pending.  rescheduleOnlyFlag should not start the count down.
9102 	 */
9103 	if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
9104 		goto finish;
9105 	}
9106 
9107 	thread_call_cancel(sUnloadCallout);
9108 	if (OSKext::getAutounloadEnabled() && !sSystemSleep
9109 #if !NO_KEXTD
9110 	    && sIOKitDaemonActive
9111 #endif
9112 	    ) {
9113 		clock_interval_to_deadline(sConsiderUnloadDelay,
9114 		    1000 * 1000 * 1000, &when);
9115 
9116 		OSKextLog(/* kext */ NULL,
9117 		    kOSKextLogProgressLevel |
9118 		    kOSKextLogLoadFlag,
9119 		    "%scheduling %sscan for unused kexts in %lu seconds.",
9120 		    sConsiderUnloadsPending ? "Res" : "S",
9121 		    sConsiderUnloadsCalled ? "" : "initial ",
9122 		    (unsigned long)sConsiderUnloadDelay);
9123 
9124 		sConsiderUnloadsPending = true;
9125 		thread_call_enter_delayed(sUnloadCallout, when);
9126 	}
9127 
9128 finish:
9129 	/* The kxld context should be reused throughout boot.  We mark the end of
9130 	 * period as the first time considerUnloads() is called, and we destroy
9131 	 * the first kxld context in that function.  Afterwards, it will be
9132 	 * destroyed in flushNonloadedKexts.
9133 	 */
9134 	if (!sConsiderUnloadsCalled) {
9135 		sConsiderUnloadsCalled = true;
9136 		OSKext::considerDestroyingLinkContext();
9137 	}
9138 
9139 	IORecursiveLockUnlock(sKextInnerLock);
9140 	return;
9141 }
9142 
9143 /*********************************************************************
9144 * Do not call any function that takes sKextLock here!
9145 *********************************************************************/
9146 extern "C" {
9147 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
9148 IOReturn
9149 OSKextSystemSleepOrWake(UInt32 messageType)
9150 {
9151 	IORecursiveLockLock(sKextInnerLock);
9152 
9153 	/* If the system is going to sleep, cancel the reaper thread timer,
9154 	 * and note that we're in a sleep state in case it just fired but hasn't
9155 	 * taken the lock yet. If we are coming back from sleep, just
9156 	 * clear the sleep flag; IOService's normal operation will cause
9157 	 * unloads to be considered soon enough.
9158 	 */
9159 	if (messageType == kIOMessageSystemWillSleep) {
9160 		if (sUnloadCallout) {
9161 			thread_call_cancel(sUnloadCallout);
9162 		}
9163 		sSystemSleep = true;
9164 		AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
9165 	} else if (messageType == kIOMessageSystemHasPoweredOn) {
9166 		sSystemSleep = false;
9167 		clock_get_uptime(&sLastWakeTime);
9168 	}
9169 	IORecursiveLockUnlock(sKextInnerLock);
9170 
9171 	return kIOReturnSuccess;
9172 }
9173 };
9174 
9175 
9176 #if PRAGMA_MARK
9177 #pragma mark Prelinked Kernel
9178 #endif
9179 
9180 #ifdef CONFIG_KXLD
9181 /*********************************************************************
9182 * Do not access sConsiderUnloads... variables other than
9183 * sConsiderUnloadsExecuted in this function. They are guarded by a
9184 * different lock.
9185 *********************************************************************/
9186 /* static */
9187 void
9188 OSKext::considerRebuildOfPrelinkedKernel(void)
9189 {
9190 	static bool     requestedPrelink        = false;
9191 	OSReturn        checkResult             = kOSReturnError;
9192 	OSSharedPtr<OSDictionary>         prelinkRequest;
9193 	OSSharedPtr<OSCollectionIterator> kextIterator;
9194 	const OSSymbol * thisID                 = NULL;        // do not release
9195 	bool            doRebuild               = false;
9196 	AbsoluteTime    my_abstime;
9197 	UInt64          my_ns;
9198 	SInt32          delta_secs;
9199 
9200 	/* Only one auto rebuild per boot and only on boot from prelinked kernel */
9201 	if (requestedPrelink || !sPrelinkBoot) {
9202 		return;
9203 	}
9204 
9205 	/* no direct return from this point */
9206 	IORecursiveLockLock(sKextLock);
9207 
9208 	/* We need to wait for the IOKit daemon to get up and running with unloads already done
9209 	 * and any new startup kexts loaded.
9210 	 */
9211 	if (!sConsiderUnloadsExecuted ||
9212 	    !sDeferredLoadSucceeded) {
9213 		goto finish;
9214 	}
9215 
9216 	/* we really only care about boot / system start up related kexts so bail
9217 	 * if we're here after REBUILD_MAX_TIME.
9218 	 */
9219 	if (!_OSKextInPrelinkRebuildWindow()) {
9220 		OSKextLog(/* kext */ NULL,
9221 		    kOSKextLogArchiveFlag,
9222 		    "%s prebuild rebuild has expired",
9223 		    __FUNCTION__);
9224 		requestedPrelink = true;
9225 		goto finish;
9226 	}
9227 
9228 	/* we do not want to trigger a rebuild if we get here too close to waking
9229 	 * up.  (see radar 10233768)
9230 	 */
9231 	IORecursiveLockLock(sKextInnerLock);
9232 
9233 	clock_get_uptime(&my_abstime);
9234 	delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
9235 	if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
9236 		SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
9237 		absolutetime_to_nanoseconds(my_abstime, &my_ns);
9238 		delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
9239 	}
9240 	IORecursiveLockUnlock(sKextInnerLock);
9241 
9242 	if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
9243 		/* too close to time of last wake from sleep */
9244 		goto finish;
9245 	}
9246 	requestedPrelink = true;
9247 
9248 	/* Now it's time to see if we have a reason to rebuild.  We may have done
9249 	 * some loads and unloads but the kernel cache didn't actually change.
9250 	 * We will rebuild if any kext is not marked prelinked AND is not in our
9251 	 * list of prelinked kexts that got unloaded.  (see radar 9055303)
9252 	 */
9253 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
9254 	if (!kextIterator) {
9255 		goto finish;
9256 	}
9257 
9258 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
9259 		OSKext *    thisKext;        // do not release
9260 
9261 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
9262 		if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
9263 			continue;
9264 		}
9265 
9266 		if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) {
9267 			continue;
9268 		}
9269 		/* kext is loaded and was not in current kernel cache so let's rebuild
9270 		 */
9271 		doRebuild = true;
9272 		OSKextLog(/* kext */ NULL,
9273 		    kOSKextLogArchiveFlag,
9274 		    "considerRebuildOfPrelinkedKernel %s triggered rebuild",
9275 		    thisKext->bundleID->getCStringNoCopy());
9276 		break;
9277 	}
9278 	sUnloadedPrelinkedKexts->flushCollection();
9279 
9280 	if (!doRebuild) {
9281 		goto finish;
9282 	}
9283 
9284 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
9285 	    prelinkRequest);
9286 	if (checkResult != kOSReturnSuccess) {
9287 		goto finish;
9288 	}
9289 
9290 	if (!sKernelRequests->setObject(prelinkRequest.get())) {
9291 		goto finish;
9292 	}
9293 
9294 	OSKext::pingIOKitDaemon();
9295 
9296 finish:
9297 	IORecursiveLockUnlock(sKextLock);
9298 
9299 	return;
9300 }
9301 
9302 #else /* !CONFIG_KXLD */
9303 
9304 void
9305 OSKext::considerRebuildOfPrelinkedKernel(void)
9306 {
9307 	/* in a non-dynamic kext loading world, there is never a reason to rebuild */
9308 	return;
9309 }
9310 
9311 #endif /* CONFIG_KXLD */
9312 
9313 #if PRAGMA_MARK
9314 #pragma mark Dependencies
9315 #endif
9316 /*********************************************************************
9317 *********************************************************************/
9318 bool
9319 OSKext::resolveDependencies(
9320 	OSArray * loopStack)
9321 {
9322 	bool                   result                   = false;
9323 	OSSharedPtr<OSArray>   localLoopStack;
9324 	bool                   addedToLoopStack         = false;
9325 	OSDictionary         * libraries                = NULL;        // do not release
9326 	OSSharedPtr<OSCollectionIterator> libraryIterator;
9327 	OSString             * libraryID                = NULL;        // do not release
9328 	OSKext               * libraryKext              = NULL;        // do not release
9329 	bool                   hasRawKernelDependency   = false;
9330 	bool                   hasKernelDependency      = false;
9331 	bool                   hasKPIDependency         = false;
9332 	bool                   hasPrivateKPIDependency  = false;
9333 	unsigned int           count;
9334 
9335 #if CONFIG_KXLD
9336 	OSString             * infoString               = NULL;        // do not release
9337 	OSString             * readableString           = NULL;        // do not release
9338 #endif // CONFIG_KXLD
9339 
9340 	/* A kernel component will automatically have this flag set,
9341 	 * and a loaded kext should also have it set (as should all its
9342 	 * loaded dependencies).
9343 	 */
9344 	if (flags.hasAllDependencies) {
9345 		result = true;
9346 		goto finish;
9347 	}
9348 
9349 	/* Check for loops in the dependency graph.
9350 	 */
9351 	if (loopStack) {
9352 		if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
9353 			OSKextLog(this,
9354 			    kOSKextLogErrorLevel |
9355 			    kOSKextLogDependenciesFlag,
9356 			    "Kext %s has a dependency loop; can't resolve dependencies.",
9357 			    getIdentifierCString());
9358 			goto finish;
9359 		}
9360 	} else {
9361 		OSKextLog(this,
9362 		    kOSKextLogStepLevel |
9363 		    kOSKextLogDependenciesFlag,
9364 		    "Kext %s resolving dependencies.",
9365 		    getIdentifierCString());
9366 
9367 		localLoopStack = OSArray::withCapacity(6);         // any small capacity will do
9368 		if (!localLoopStack) {
9369 			OSKextLog(this,
9370 			    kOSKextLogErrorLevel |
9371 			    kOSKextLogDependenciesFlag,
9372 			    "Kext %s can't create bookkeeping stack to resolve dependencies.",
9373 			    getIdentifierCString());
9374 			goto finish;
9375 		}
9376 		loopStack = localLoopStack.get();
9377 	}
9378 	if (!loopStack->setObject(this)) {
9379 		OSKextLog(this,
9380 		    kOSKextLogErrorLevel |
9381 		    kOSKextLogDependenciesFlag,
9382 		    "Kext %s - internal error resolving dependencies.",
9383 		    getIdentifierCString());
9384 		goto finish;
9385 	}
9386 	addedToLoopStack = true;
9387 
9388 	/* Purge any existing kexts in the dependency list and start over.
9389 	 */
9390 	flushDependencies();
9391 	if (dependencies) {
9392 		OSKextLog(this,
9393 		    kOSKextLogErrorLevel |
9394 		    kOSKextLogDependenciesFlag,
9395 		    "Kext %s - internal error resolving dependencies.",
9396 		    getIdentifierCString());
9397 	}
9398 
9399 	libraries = OSDynamicCast(OSDictionary,
9400 	    getPropertyForHostArch(kOSBundleLibrariesKey));
9401 	if (libraries == NULL || libraries->getCount() == 0) {
9402 		OSKextLog(this,
9403 		    kOSKextLogErrorLevel |
9404 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9405 		    "Kext %s - can't resolve dependencies; %s missing/invalid type.",
9406 		    getIdentifierCString(), kOSBundleLibrariesKey);
9407 		goto finish;
9408 	}
9409 
9410 	/* Make a new array to hold the dependencies (flush freed the old one).
9411 	 */
9412 	dependencies = OSArray::withCapacity(libraries->getCount());
9413 	if (!dependencies) {
9414 		OSKextLog(this,
9415 		    kOSKextLogErrorLevel |
9416 		    kOSKextLogDependenciesFlag,
9417 		    "Kext %s - can't allocate dependencies array.",
9418 		    getIdentifierCString());
9419 		goto finish;
9420 	}
9421 
9422 	// xxx - compat: We used to add an implicit dependency on kernel 6.0
9423 	// xxx - compat: if none were declared.
9424 
9425 	libraryIterator = OSCollectionIterator::withCollection(libraries);
9426 	if (!libraryIterator) {
9427 		OSKextLog(this,
9428 		    kOSKextLogErrorLevel |
9429 		    kOSKextLogDependenciesFlag,
9430 		    "Kext %s - can't allocate dependencies iterator.",
9431 		    getIdentifierCString());
9432 		goto finish;
9433 	}
9434 
9435 	while ((libraryID = OSDynamicCast(OSString,
9436 	    libraryIterator->getNextObject()))) {
9437 		const char * library_id = libraryID->getCStringNoCopy();
9438 
9439 		OSString * libraryVersion = OSDynamicCast(OSString,
9440 		    libraries->getObject(libraryID));
9441 		if (libraryVersion == NULL) {
9442 			OSKextLog(this,
9443 			    kOSKextLogErrorLevel |
9444 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9445 			    "Kext %s - illegal type in OSBundleLibraries.",
9446 			    getIdentifierCString());
9447 			goto finish;
9448 		}
9449 
9450 		OSKextVersion libraryVers =
9451 		    OSKextParseVersionString(libraryVersion->getCStringNoCopy());
9452 		if (libraryVers == -1) {
9453 			OSKextLog(this,
9454 			    kOSKextLogErrorLevel |
9455 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9456 			    "Kext %s - invalid library version %s.",
9457 			    getIdentifierCString(),
9458 			    libraryVersion->getCStringNoCopy());
9459 			goto finish;
9460 		}
9461 
9462 		libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
9463 		if (libraryKext == NULL) {
9464 			OSKextLog(this,
9465 			    kOSKextLogErrorLevel |
9466 			    kOSKextLogDependenciesFlag,
9467 			    "Kext %s - library kext %s not found.",
9468 			    getIdentifierCString(), library_id);
9469 			goto finish;
9470 		}
9471 
9472 		if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
9473 			OSKextLog(this,
9474 			    kOSKextLogErrorLevel |
9475 			    kOSKextLogDependenciesFlag,
9476 			    "Kext %s - library kext %s not compatible "
9477 			    "with requested version %s.",
9478 			    getIdentifierCString(), library_id,
9479 			    libraryVersion->getCStringNoCopy());
9480 			goto finish;
9481 		}
9482 
9483 		/* If a nonprelinked library somehow got into the mix for a
9484 		 * prelinked kext, at any point in the chain, we must fail
9485 		 * because the prelinked relocs for the library will be all wrong.
9486 		 */
9487 		if (this->isPrelinked() &&
9488 		    libraryKext->declaresExecutable() &&
9489 		    !libraryKext->isPrelinked()) {
9490 			OSKextLog(this,
9491 			    kOSKextLogErrorLevel |
9492 			    kOSKextLogDependenciesFlag,
9493 			    "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
9494 			    getIdentifierCString(), library_id,
9495 			    libraryVersion->getCStringNoCopy());
9496 			goto finish;
9497 		}
9498 
9499 		if (!libraryKext->resolveDependencies(loopStack)) {
9500 			goto finish;
9501 		}
9502 
9503 		/* Add the library directly only if it has an executable to link.
9504 		 * Otherwise it's just used to collect other dependencies, so put
9505 		 * *its* dependencies on the list for this kext.
9506 		 */
9507 		// xxx - We are losing info here; would like to make fake entries or
9508 		// xxx - keep these in the dependency graph for loaded kexts.
9509 		// xxx - I really want to make kernel components not a special case!
9510 		if (libraryKext->declaresExecutable() ||
9511 		    libraryKext->isInterface()) {
9512 			if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
9513 				dependencies->setObject(libraryKext);
9514 
9515 				OSKextLog(this,
9516 				    kOSKextLogDetailLevel |
9517 				    kOSKextLogDependenciesFlag,
9518 				    "Kext %s added dependency %s.",
9519 				    getIdentifierCString(),
9520 				    libraryKext->getIdentifierCString());
9521 			}
9522 		} else {
9523 			int       numLibDependencies  = libraryKext->getNumDependencies();
9524 			OSArray * libraryDependencies = libraryKext->getDependencies();
9525 			int       index;
9526 
9527 			if (numLibDependencies) {
9528 				// xxx - this msg level should be 1 lower than the per-kext one
9529 				OSKextLog(this,
9530 				    kOSKextLogDetailLevel |
9531 				    kOSKextLogDependenciesFlag,
9532 				    "Kext %s pulling %d dependencies from codeless library %s.",
9533 				    getIdentifierCString(),
9534 				    numLibDependencies,
9535 				    libraryKext->getIdentifierCString());
9536 			}
9537 			for (index = 0; index < numLibDependencies; index++) {
9538 				OSKext * thisLibDependency = OSDynamicCast(OSKext,
9539 				    libraryDependencies->getObject(index));
9540 				if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
9541 					dependencies->setObject(thisLibDependency);
9542 					OSKextLog(this,
9543 					    kOSKextLogDetailLevel |
9544 					    kOSKextLogDependenciesFlag,
9545 					    "Kext %s added dependency %s from codeless library %s.",
9546 					    getIdentifierCString(),
9547 					    thisLibDependency->getIdentifierCString(),
9548 					    libraryKext->getIdentifierCString());
9549 				}
9550 			}
9551 		}
9552 
9553 		if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
9554 		    0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
9555 			hasRawKernelDependency = true;
9556 		} else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
9557 			hasKernelDependency = true;
9558 		} else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
9559 			hasKPIDependency = true;
9560 			if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
9561 				hasPrivateKPIDependency = true;
9562 			}
9563 		}
9564 	}
9565 
9566 	if (hasRawKernelDependency) {
9567 		OSKextLog(this,
9568 		    kOSKextLogErrorLevel |
9569 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9570 		    "Error - kext %s declares a dependency on %s, which is not permitted.",
9571 		    getIdentifierCString(), KERNEL_LIB);
9572 		goto finish;
9573 	}
9574 #if __LP64__
9575 	if (hasKernelDependency) {
9576 		OSKextLog(this,
9577 		    kOSKextLogErrorLevel |
9578 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9579 		    "Error - kext %s declares %s dependencies. "
9580 		    "Only %s* dependencies are supported for 64-bit kexts.",
9581 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
9582 		goto finish;
9583 	}
9584 	if (!hasKPIDependency) {
9585 		OSKextLog(this,
9586 		    kOSKextLogWarningLevel |
9587 		    kOSKextLogDependenciesFlag,
9588 		    "Warning - kext %s declares no %s* dependencies. "
9589 		    "If it uses any KPIs, the link may fail with undefined symbols.",
9590 		    getIdentifierCString(), KPI_LIB_PREFIX);
9591 	}
9592 #else /* __LP64__ */
9593 	// xxx - will change to flatly disallow "kernel" dependencies at some point
9594 	// xxx - is it invalid to do both "com.apple.kernel" and any
9595 	// xxx - "com.apple.kernel.*"?
9596 
9597 	if (hasKernelDependency && hasKPIDependency) {
9598 		OSKextLog(this,
9599 		    kOSKextLogWarningLevel |
9600 		    kOSKextLogDependenciesFlag,
9601 		    "Warning - kext %s has immediate dependencies on both "
9602 		    "%s* and %s* components; use only one style.",
9603 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
9604 	}
9605 
9606 	if (!hasKernelDependency && !hasKPIDependency) {
9607 		// xxx - do we want to use validation flag for these too?
9608 		OSKextLog(this,
9609 		    kOSKextLogWarningLevel |
9610 		    kOSKextLogDependenciesFlag,
9611 		    "Warning - %s declares no kernel dependencies; using %s.",
9612 		    getIdentifierCString(), KERNEL6_LIB);
9613 		OSKext * kernelKext = OSDynamicCast(OSKext,
9614 		    sKextsByID->getObject(KERNEL6_LIB));
9615 		if (kernelKext) {
9616 			dependencies->setObject(kernelKext);
9617 		} else {
9618 			OSKextLog(this,
9619 			    kOSKextLogErrorLevel |
9620 			    kOSKextLogDependenciesFlag,
9621 			    "Error - Library %s not found for %s.",
9622 			    KERNEL6_LIB, getIdentifierCString());
9623 		}
9624 	}
9625 
9626 	/* If the kext doesn't have a raw kernel or KPI dependency, then add all of
9627 	 * its indirect dependencies to simulate old-style linking.  XXX - Should
9628 	 * check for duplicates.
9629 	 */
9630 	if (!hasKPIDependency) {
9631 		unsigned int i;
9632 
9633 		flags.hasBleedthrough = true;
9634 
9635 		count = getNumDependencies();
9636 
9637 		/* We add to the dependencies array in this loop, but do not iterate
9638 		 * past its original count.
9639 		 */
9640 		for (i = 0; i < count; i++) {
9641 			OSKext * dependencyKext = OSDynamicCast(OSKext,
9642 			    dependencies->getObject(i));
9643 			dependencyKext->addBleedthroughDependencies(dependencies.get());
9644 		}
9645 	}
9646 #endif /* __LP64__ */
9647 
9648 #if CONFIG_KXLD
9649 	/*
9650 	 * If we're not dynamically linking kexts, then we don't need to check
9651 	 * copyright strings. The linker in user space has already done this.
9652 	 */
9653 	if (hasPrivateKPIDependency) {
9654 		bool hasApplePrefix = false;
9655 		bool infoCopyrightIsValid = false;
9656 		bool readableCopyrightIsValid = false;
9657 
9658 		hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
9659 		    APPLE_KEXT_PREFIX);
9660 
9661 		infoString = OSDynamicCast(OSString,
9662 		    getPropertyForHostArch("CFBundleGetInfoString"));
9663 		if (infoString) {
9664 			infoCopyrightIsValid =
9665 			    kxld_validate_copyright_string(infoString->getCStringNoCopy());
9666 		}
9667 
9668 		readableString = OSDynamicCast(OSString,
9669 		    getPropertyForHostArch("NSHumanReadableCopyright"));
9670 		if (readableString) {
9671 			readableCopyrightIsValid =
9672 			    kxld_validate_copyright_string(readableString->getCStringNoCopy());
9673 		}
9674 
9675 		if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
9676 			OSKextLog(this,
9677 			    kOSKextLogErrorLevel |
9678 			    kOSKextLogDependenciesFlag,
9679 			    "Error - kext %s declares a dependency on %s. "
9680 			    "Only Apple kexts may declare a dependency on %s.",
9681 			    getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
9682 			goto finish;
9683 		}
9684 	}
9685 #endif // CONFIG_KXLD
9686 
9687 	result = true;
9688 	flags.hasAllDependencies = 1;
9689 
9690 finish:
9691 
9692 	if (addedToLoopStack) {
9693 		count = loopStack->getCount();
9694 		if (count > 0 && (this == loopStack->getObject(count - 1))) {
9695 			loopStack->removeObject(count - 1);
9696 		} else {
9697 			OSKextLog(this,
9698 			    kOSKextLogErrorLevel |
9699 			    kOSKextLogDependenciesFlag,
9700 			    "Kext %s - internal error resolving dependencies.",
9701 			    getIdentifierCString());
9702 		}
9703 	}
9704 
9705 	if (result && localLoopStack) {
9706 		OSKextLog(this,
9707 		    kOSKextLogStepLevel |
9708 		    kOSKextLogDependenciesFlag,
9709 		    "Kext %s successfully resolved dependencies.",
9710 		    getIdentifierCString());
9711 	}
9712 
9713 	return result;
9714 }
9715 
9716 /*********************************************************************
9717 *********************************************************************/
9718 bool
9719 OSKext::addBleedthroughDependencies(OSArray * anArray)
9720 {
9721 	bool result = false;
9722 	unsigned int dependencyIndex, dependencyCount;
9723 
9724 	dependencyCount = getNumDependencies();
9725 
9726 	for (dependencyIndex = 0;
9727 	    dependencyIndex < dependencyCount;
9728 	    dependencyIndex++) {
9729 		OSKext * dependency = OSDynamicCast(OSKext,
9730 		    dependencies->getObject(dependencyIndex));
9731 		if (!dependency) {
9732 			OSKextLog(this,
9733 			    kOSKextLogErrorLevel |
9734 			    kOSKextLogDependenciesFlag,
9735 			    "Kext %s - internal error propagating compatibility dependencies.",
9736 			    getIdentifierCString());
9737 			goto finish;
9738 		}
9739 		if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
9740 			anArray->setObject(dependency);
9741 		}
9742 		dependency->addBleedthroughDependencies(anArray);
9743 	}
9744 
9745 	result = true;
9746 
9747 finish:
9748 	return result;
9749 }
9750 
9751 /*********************************************************************
9752 *********************************************************************/
9753 bool
9754 OSKext::flushDependencies(bool forceFlag)
9755 {
9756 	bool result = false;
9757 
9758 	/* Only clear the dependencies if the kext isn't loaded;
9759 	 * we need the info for loaded kexts to track references.
9760 	 */
9761 	if (!isLoaded() || forceFlag) {
9762 		if (dependencies) {
9763 			// xxx - check level
9764 			OSKextLog(this,
9765 			    kOSKextLogProgressLevel |
9766 			    kOSKextLogDependenciesFlag,
9767 			    "Kext %s flushing dependencies.",
9768 			    getIdentifierCString());
9769 			dependencies.reset();
9770 		}
9771 		if (!isKernelComponent()) {
9772 			flags.hasAllDependencies = 0;
9773 		}
9774 		result = true;
9775 	}
9776 
9777 	return result;
9778 }
9779 
9780 /*********************************************************************
9781 *********************************************************************/
9782 uint32_t
9783 OSKext::getNumDependencies(void)
9784 {
9785 	if (!dependencies) {
9786 		return 0;
9787 	}
9788 	return dependencies->getCount();
9789 }
9790 
9791 /*********************************************************************
9792 *********************************************************************/
9793 OSArray *
9794 OSKext::getDependencies(void)
9795 {
9796 	return dependencies.get();
9797 }
9798 
9799 bool
9800 OSKext::hasDependency(const OSSymbol * depID)
9801 {
9802 	bool result __block;
9803 
9804 	if (depID == getIdentifier()) {
9805 		return true;
9806 	}
9807 	if (!dependencies) {
9808 		return false;
9809 	}
9810 	result = false;
9811 	dependencies->iterateObjects(^bool (OSObject * obj) {
9812 		OSKext * kext;
9813 		kext = OSDynamicCast(OSKext, obj);
9814 		if (!kext) {
9815 		        return false;
9816 		}
9817 		result = (depID == kext->getIdentifier());
9818 		return result;
9819 	});
9820 	return result;
9821 }
9822 
9823 #if PRAGMA_MARK
9824 #pragma mark OSMetaClass Support
9825 #endif
9826 /*********************************************************************
9827 *********************************************************************/
9828 OSReturn
9829 OSKext::addClass(
9830 	OSMetaClass * aClass,
9831 	uint32_t      numClasses)
9832 {
9833 	OSReturn result = kOSMetaClassNoInsKModSet;
9834 
9835 	if (!metaClasses) {
9836 		metaClasses = OSSet::withCapacity(numClasses);
9837 		if (!metaClasses) {
9838 			goto finish;
9839 		}
9840 	}
9841 
9842 	if (metaClasses->containsObject(aClass)) {
9843 		OSKextLog(this,
9844 		    kOSKextLogWarningLevel |
9845 		    kOSKextLogLoadFlag,
9846 		    "Notice - kext %s has already registered class %s.",
9847 		    getIdentifierCString(),
9848 		    aClass->getClassName());
9849 		result = kOSReturnSuccess;
9850 		goto finish;
9851 	}
9852 
9853 	if (!metaClasses->setObject(aClass)) {
9854 		goto finish;
9855 	} else {
9856 		OSKextLog(this,
9857 		    kOSKextLogDetailLevel |
9858 		    kOSKextLogLoadFlag,
9859 		    "Kext %s registered class %s.",
9860 		    getIdentifierCString(),
9861 		    aClass->getClassName());
9862 	}
9863 
9864 	if (!flags.autounloadEnabled) {
9865 		const OSMetaClass * metaScan  = NULL;        // do not release
9866 
9867 		for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
9868 			if (metaScan == OSTypeID(IOService)) {
9869 				OSKextLog(this,
9870 				    kOSKextLogProgressLevel |
9871 				    kOSKextLogLoadFlag,
9872 				    "Kext %s has IOService subclass %s; enabling autounload.",
9873 				    getIdentifierCString(),
9874 				    aClass->getClassName());
9875 
9876 				flags.autounloadEnabled = (0 == flags.unloadUnsupported);
9877 				break;
9878 			}
9879 		}
9880 	}
9881 
9882 	notifyAddClassObservers(this, aClass, flags);
9883 
9884 	result = kOSReturnSuccess;
9885 
9886 finish:
9887 	if (result != kOSReturnSuccess) {
9888 		OSKextLog(this,
9889 		    kOSKextLogErrorLevel |
9890 		    kOSKextLogLoadFlag,
9891 		    "Kext %s failed to register class %s.",
9892 		    getIdentifierCString(),
9893 		    aClass->getClassName());
9894 	}
9895 
9896 	return result;
9897 }
9898 
9899 /*********************************************************************
9900 *********************************************************************/
9901 OSReturn
9902 OSKext::removeClass(
9903 	OSMetaClass * aClass)
9904 {
9905 	OSReturn result = kOSMetaClassNoKModSet;
9906 
9907 	if (!metaClasses) {
9908 		goto finish;
9909 	}
9910 
9911 	if (!metaClasses->containsObject(aClass)) {
9912 		OSKextLog(this,
9913 		    kOSKextLogWarningLevel |
9914 		    kOSKextLogLoadFlag,
9915 		    "Notice - kext %s asked to unregister unknown class %s.",
9916 		    getIdentifierCString(),
9917 		    aClass->getClassName());
9918 		result = kOSReturnSuccess;
9919 		goto finish;
9920 	}
9921 
9922 	OSKextLog(this,
9923 	    kOSKextLogDetailLevel |
9924 	    kOSKextLogLoadFlag,
9925 	    "Kext %s unregistering class %s.",
9926 	    getIdentifierCString(),
9927 	    aClass->getClassName());
9928 
9929 	metaClasses->removeObject(aClass);
9930 
9931 	notifyRemoveClassObservers(this, aClass, flags);
9932 
9933 	result = kOSReturnSuccess;
9934 
9935 finish:
9936 	if (result != kOSReturnSuccess) {
9937 		OSKextLog(this,
9938 		    kOSKextLogErrorLevel |
9939 		    kOSKextLogLoadFlag,
9940 		    "Failed to unregister kext %s class %s.",
9941 		    getIdentifierCString(),
9942 		    aClass->getClassName());
9943 	}
9944 	return result;
9945 }
9946 
9947 /*********************************************************************
9948 *********************************************************************/
9949 OSSet *
9950 OSKext::getMetaClasses(void)
9951 {
9952 	return metaClasses.get();
9953 }
9954 
9955 /*********************************************************************
9956 *********************************************************************/
9957 bool
9958 OSKext::hasOSMetaClassInstances(void)
9959 {
9960 	bool                   result        = false;
9961 	OSSharedPtr<OSCollectionIterator> classIterator;
9962 	OSMetaClass          * checkClass    = NULL;        // do not release
9963 
9964 	if (!metaClasses) {
9965 		goto finish;
9966 	}
9967 
9968 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9969 	if (!classIterator) {
9970 		// xxx - log alloc failure?
9971 		goto finish;
9972 	}
9973 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9974 		if (checkClass->getInstanceCount()) {
9975 			result = true;
9976 			goto finish;
9977 		}
9978 	}
9979 
9980 finish:
9981 	return result;
9982 }
9983 
9984 /*********************************************************************
9985 *********************************************************************/
9986 /* static */
9987 void
9988 OSKext::reportOSMetaClassInstances(
9989 	const char     * kextIdentifier,
9990 	OSKextLogSpec    msgLogSpec)
9991 {
9992 	OSSharedPtr<OSKext> theKext;
9993 
9994 	theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
9995 	if (!theKext) {
9996 		goto finish;
9997 	}
9998 
9999 	theKext->reportOSMetaClassInstances(msgLogSpec);
10000 finish:
10001 	return;
10002 }
10003 
10004 /*********************************************************************
10005 *********************************************************************/
10006 void
10007 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
10008 {
10009 	OSSharedPtr<OSCollectionIterator> classIterator;
10010 	OSMetaClass          * checkClass    = NULL;        // do not release
10011 
10012 	if (!metaClasses) {
10013 		goto finish;
10014 	}
10015 
10016 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
10017 	if (!classIterator) {
10018 		goto finish;
10019 	}
10020 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
10021 		if (checkClass->getInstanceCount()) {
10022 			OSKextLog(this,
10023 			    msgLogSpec,
10024 			    "    Kext %s class %s has %d instance%s.",
10025 			    getIdentifierCString(),
10026 			    checkClass->getClassName(),
10027 			    checkClass->getInstanceCount(),
10028 			    checkClass->getInstanceCount() == 1 ? "" : "s");
10029 		}
10030 	}
10031 
10032 finish:
10033 	return;
10034 }
10035 
10036 #if PRAGMA_MARK
10037 #pragma mark User-Space Requests
10038 #endif
10039 
10040 static kern_return_t
10041 patchDextLaunchRequests(task_t calling_task, OSArray *requests)
10042 {
10043 	OSReturn result = kOSReturnSuccess;
10044 	for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) {
10045 		OSDictionary * request = NULL;         //do not release
10046 		IOUserServerCheckInToken * token = NULL;         //do not release
10047 		OSString * requestPredicate = NULL;         //do not release
10048 		OSSharedPtr<OSNumber> portNameNumber;
10049 		mach_port_name_t portName = 0;
10050 		request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex));
10051 		if (!request) {
10052 			OSKextLog(/* kext */ NULL,
10053 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10054 			    "Elements of request should be of type OSDictionary");
10055 			result = kOSKextReturnInternalError;
10056 			goto finish;
10057 		}
10058 		requestPredicate = _OSKextGetRequestPredicate(request);
10059 		if (!requestPredicate) {
10060 			OSKextLog(/* kext */ NULL,
10061 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10062 			    "Failed to get request predicate");
10063 			result = kOSKextReturnInternalError;
10064 			goto finish;
10065 		}
10066 		// is this a dext launch?
10067 		if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) {
10068 			token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken));
10069 			if (!token) {
10070 				OSKextLog(/* kext */ NULL,
10071 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10072 				    "Could not find a IOUserServerCheckInToken in daemon launch request.");
10073 				result = kOSKextReturnInternalError;
10074 				goto finish;
10075 			}
10076 			portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT);
10077 			if (portName == 0 || portName == MACH_PORT_DEAD) {
10078 				OSKextLog(/* kext */ NULL,
10079 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10080 				    "Could not create send right for object.");
10081 				result = kOSKextReturnInternalError;
10082 				goto finish;
10083 			}
10084 			// Store the mach port name as a OSNumber
10085 			portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName));
10086 			if (!portNameNumber) {
10087 				OSKextLog(/* kext */ NULL,
10088 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10089 				    "Could not create OSNumber object.");
10090 				result = kOSKextReturnNoMemory;
10091 				goto finish;
10092 			}
10093 			if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) {
10094 				OSKextLog(/* kext */ NULL,
10095 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10096 				    "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken);
10097 				result = kOSKextReturnNoMemory;
10098 				goto finish;
10099 			}
10100 		}
10101 finish:
10102 		if (result != kOSReturnSuccess) {
10103 			break;
10104 		}
10105 	}
10106 	return result;
10107 }
10108 
10109 bool
10110 OSKext::iokitDaemonActive()
10111 {
10112 	bool result;
10113 	IORecursiveLockLock(sKextLock);
10114 	result = sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot;
10115 	IORecursiveLockUnlock(sKextLock);
10116 	return result;
10117 }
10118 
10119 /*********************************************************************
10120 * XXX - this function is a big ugly mess
10121 *********************************************************************/
10122 /* static */
10123 OSReturn
10124 OSKext::handleRequest(
10125 	host_priv_t     hostPriv,
10126 	OSKextLogSpec   clientLogFilter,
10127 	char          * requestBuffer,
10128 	uint32_t        requestLength,
10129 	char         ** responseOut,
10130 	uint32_t      * responseLengthOut,
10131 	char         ** logInfoOut,
10132 	uint32_t      * logInfoLengthOut)
10133 {
10134 	OSReturn       result             = kOSReturnError;
10135 	kern_return_t  kmem_result        = KERN_FAILURE;
10136 
10137 	char         * response           = NULL;        // returned by reference
10138 	uint32_t       responseLength     = 0;
10139 
10140 	bool           taskCanManageAllKCs   = false;
10141 	bool           taskOnlyManagesBootKC = false;
10142 
10143 	OSSharedPtr<OSObject>     parsedXML;
10144 	OSDictionary            * requestDict    = NULL;        // do not release
10145 	OSSharedPtr<OSString>     errorString;
10146 
10147 	OSSharedPtr<OSObject>     responseObject;
10148 
10149 	OSSharedPtr<OSSerialize>  serializer;
10150 
10151 	OSSharedPtr<OSArray>      logInfoArray;
10152 
10153 	OSString     * predicate          = NULL;        // do not release
10154 	OSString     * kextIdentifier     = NULL;        // do not release
10155 	OSArray      * kextIdentifiers    = NULL;        // do not release
10156 	OSKext       * theKext            = NULL;        // do not release
10157 	OSBoolean    * boolArg            = NULL;        // do not release
10158 
10159 
10160 	IORecursiveLockLock(sKextLock);
10161 
10162 	if (responseOut) {
10163 		*responseOut = NULL;
10164 		*responseLengthOut = 0;
10165 	}
10166 	if (logInfoOut) {
10167 		*logInfoOut = NULL;
10168 		*logInfoLengthOut = 0;
10169 	}
10170 
10171 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
10172 
10173 	/* XML must be nul-terminated.
10174 	 */
10175 	if (requestBuffer[requestLength - 1] != '\0') {
10176 		OSKextLog(/* kext */ NULL,
10177 		    kOSKextLogErrorLevel |
10178 		    kOSKextLogIPCFlag,
10179 		    "Invalid request from user space (not nul-terminated).");
10180 		result = kOSKextReturnBadData;
10181 		goto finish;
10182 	}
10183 	parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString);
10184 	if (parsedXML) {
10185 		requestDict = OSDynamicCast(OSDictionary, parsedXML.get());
10186 	}
10187 	if (!requestDict) {
10188 		const char * errorCString = "(unknown error)";
10189 
10190 		if (errorString && errorString->getCStringNoCopy()) {
10191 			errorCString = errorString->getCStringNoCopy();
10192 		} else if (parsedXML) {
10193 			errorCString = "not a dictionary";
10194 		}
10195 		OSKextLog(/* kext */ NULL,
10196 		    kOSKextLogErrorLevel |
10197 		    kOSKextLogIPCFlag,
10198 		    "Error unserializing request from user space: %s.",
10199 		    errorCString);
10200 		result = kOSKextReturnSerialization;
10201 		goto finish;
10202 	}
10203 
10204 	predicate = _OSKextGetRequestPredicate(requestDict);
10205 	if (!predicate) {
10206 		OSKextLog(/* kext */ NULL,
10207 		    kOSKextLogErrorLevel |
10208 		    kOSKextLogIPCFlag,
10209 		    "Recieved kext request from user space with no predicate.");
10210 		result = kOSKextReturnInvalidArgument;
10211 		goto finish;
10212 	}
10213 	OSKextLog(/* kext */ NULL,
10214 	    kOSKextLogDebugLevel |
10215 	    kOSKextLogIPCFlag,
10216 	    "Received '%s' request from user space.",
10217 	    predicate->getCStringNoCopy());
10218 
10219 	/*
10220 	 * All management of file sets requires an entitlement
10221 	 */
10222 	result = kOSKextReturnNotPrivileged;
10223 	if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
10224 	    predicate->isEqualTo(kKextRequestPredicateStart) ||
10225 	    predicate->isEqualTo(kKextRequestPredicateStop) ||
10226 	    predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
10227 	    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
10228 	    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
10229 	    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
10230 	    predicate->isEqualTo(kKextRequestPredicateLoadFromKC) ||
10231 	    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
10232 	    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
10233 	    predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
10234 		if (!iokitDaemonAvailable()) {
10235 			panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable");
10236 		}
10237 		if (hostPriv == HOST_PRIV_NULL) {
10238 			OSKextLog(/* kext */ NULL,
10239 			    kOSKextLogErrorLevel |
10240 			    kOSKextLogIPCFlag,
10241 			    "Access Failure - must be root user.");
10242 			goto finish;
10243 		}
10244 		taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE;
10245 		taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE;
10246 
10247 		if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) {
10248 			OSKextLog(/* kext */ NULL,
10249 			    kOSKextLogErrorLevel |
10250 			    kOSKextLogIPCFlag,
10251 			    "Access Failure - client not entitled to manage file sets.");
10252 			goto finish;
10253 		}
10254 
10255 		/*
10256 		 * The OnlyBootKC entitlement restricts the
10257 		 * collection-management entitlement to only managing kexts in
10258 		 * the BootKC. All other predicates that alter global state or
10259 		 * add new KCs are disallowed.
10260 		 */
10261 		if (taskOnlyManagesBootKC &&
10262 		    (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
10263 		    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
10264 		    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
10265 		    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
10266 		    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
10267 		    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
10268 		    predicate->isEqualTo(kKextRequestPredicateDaemonReady))) {
10269 			OSKextLog(/* kext */ NULL,
10270 			    kOSKextLogErrorLevel |
10271 			    kOSKextLogIPCFlag,
10272 			    "Access Failure - client not entitled to manage non-primary KCs");
10273 			goto finish;
10274 		}
10275 
10276 		/*
10277 		 * If we get here, then the process either has the full KC
10278 		 * management entitlement, or it has the BootKC-only
10279 		 * entitlement and the request is about the BootKC.
10280 		 */
10281 	}
10282 
10283 	/* Get common args in anticipation of use.
10284 	 */
10285 	kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
10286 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
10287 	kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
10288 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
10289 	if (kextIdentifier) {
10290 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
10291 	}
10292 	boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
10293 		    requestDict, kKextRequestArgumentValueKey));
10294 
10295 	if (taskOnlyManagesBootKC &&
10296 	    theKext &&
10297 	    theKext->isInFileset() &&
10298 	    theKext->kc_type != KCKindPrimary) {
10299 		OSKextLog(/* kext */ NULL,
10300 		    kOSKextLogErrorLevel |
10301 		    kOSKextLogIPCFlag,
10302 		    "Access Failure - client not entitled to manage kext in non-primary KC");
10303 		result = kOSKextReturnNotPrivileged;
10304 		goto finish;
10305 	}
10306 	result = kOSKextReturnInvalidArgument;
10307 
10308 	if (predicate->isEqualTo(kKextRequestPredicateStart)) {
10309 		if (!kextIdentifier) {
10310 			OSKextLog(/* kext */ NULL,
10311 			    kOSKextLogErrorLevel |
10312 			    kOSKextLogIPCFlag,
10313 			    "Invalid arguments to kext start request.");
10314 		} else if (!theKext) {
10315 			OSKextLog(/* kext */ NULL,
10316 			    kOSKextLogErrorLevel |
10317 			    kOSKextLogIPCFlag,
10318 			    "Kext %s not found for start request.",
10319 			    kextIdentifier->getCStringNoCopy());
10320 			result = kOSKextReturnNotFound;
10321 		} else {
10322 			result = theKext->start();
10323 		}
10324 	} else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
10325 		if (!kextIdentifier) {
10326 			OSKextLog(/* kext */ NULL,
10327 			    kOSKextLogErrorLevel |
10328 			    kOSKextLogIPCFlag,
10329 			    "Invalid arguments to kext stop request.");
10330 		} else if (!theKext) {
10331 			OSKextLog(/* kext */ NULL,
10332 			    kOSKextLogErrorLevel |
10333 			    kOSKextLogIPCFlag,
10334 			    "Kext %s not found for stop request.",
10335 			    kextIdentifier->getCStringNoCopy());
10336 			result = kOSKextReturnNotFound;
10337 		} else {
10338 			result = theKext->stop();
10339 		}
10340 	} else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) {
10341 		result = OSKext::setMissingAuxKCBundles(requestDict);
10342 	} else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) {
10343 		if (!kextIdentifier) {
10344 			OSKextLog(/* kext */ NULL,
10345 			    kOSKextLogErrorLevel |
10346 			    kOSKextLogIPCFlag,
10347 			    "Invalid arguments to AuxKC Bundle Available request.");
10348 		} else {
10349 			result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict);
10350 		}
10351 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) {
10352 		if (!kextIdentifier) {
10353 			OSKextLog(/* kext */ NULL,
10354 			    kOSKextLogErrorLevel |
10355 			    kOSKextLogIPCFlag,
10356 			    "Invalid arguments to kext load from KC request.");
10357 		} else if (!theKext) {
10358 			OSKextLog(/* kext */ NULL,
10359 			    kOSKextLogErrorLevel |
10360 			    kOSKextLogIPCFlag,
10361 			    "Kext %s not found for load from KC request.",
10362 			    kextIdentifier->getCStringNoCopy());
10363 			result = kOSKextReturnNotFound;
10364 		} else if (!theKext->isInFileset()) {
10365 			OSKextLog(/* kext */ NULL,
10366 			    kOSKextLogErrorLevel |
10367 			    kOSKextLogIPCFlag,
10368 			    "Kext %s does not exist in a KC: refusing to load.",
10369 			    kextIdentifier->getCStringNoCopy());
10370 			result = kOSKextReturnNotLoadable;
10371 		} else {
10372 			result = OSKext::loadKextFromKC(theKext, requestDict);
10373 		}
10374 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) {
10375 		if (!kextIdentifier) {
10376 			OSKextLog(/* kext */ NULL,
10377 			    kOSKextLogErrorLevel |
10378 			    kOSKextLogIPCFlag,
10379 			    "Invalid arguments to codeless kext load interface (missing identifier).");
10380 		} else {
10381 			result = OSKext::loadCodelessKext(kextIdentifier, requestDict);
10382 		}
10383 	} else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
10384 		if (!kextIdentifier) {
10385 			OSKextLog(/* kext */ NULL,
10386 			    kOSKextLogErrorLevel |
10387 			    kOSKextLogIPCFlag,
10388 			    "Invalid arguments to kext unload request.");
10389 		} else if (!theKext) {
10390 			OSKextLog(/* kext */ NULL,
10391 			    kOSKextLogErrorLevel |
10392 			    kOSKextLogIPCFlag,
10393 			    "Kext %s not found for unload request.",
10394 			    kextIdentifier->getCStringNoCopy());
10395 			result = kOSKextReturnNotFound;
10396 		} else {
10397 			if (theKext->isDriverKit()) {
10398 				result = OSKext::removeDext(theKext);
10399 			} else {
10400 				OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
10401 				    _OSKextGetRequestArgument(requestDict,
10402 				    kKextRequestArgumentTerminateIOServicesKey));
10403 				result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
10404 			}
10405 		}
10406 	} else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
10407 		result = OSKext::dispatchResource(requestDict);
10408 	} else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
10409 		OSNumber     *lookupNum   = NULL;
10410 		lookupNum = OSDynamicCast(OSNumber,
10411 		    _OSKextGetRequestArgument(requestDict,
10412 		    kKextRequestArgumentLookupAddressKey));
10413 
10414 		responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
10415 		if (responseObject) {
10416 			result = kOSReturnSuccess;
10417 		} else {
10418 			goto finish;
10419 		}
10420 	} else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
10421 	    predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) ||
10422 	    predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection) ||
10423 	    predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
10424 		OSBoolean    * delayAutounloadBool = NULL;
10425 		OSObject     * infoKeysRaw         = NULL;
10426 		OSArray      * infoKeys            = NULL;
10427 		uint32_t       infoKeysCount       = 0;
10428 
10429 		delayAutounloadBool = OSDynamicCast(OSBoolean,
10430 		    _OSKextGetRequestArgument(requestDict,
10431 		    kKextRequestArgumentDelayAutounloadKey));
10432 
10433 		/* If asked to delay autounload, reset the timer if it's currently set.
10434 		 * (That is, don't schedule an unload if one isn't already pending.
10435 		 */
10436 		if (delayAutounloadBool == kOSBooleanTrue) {
10437 			OSKext::considerUnloads(/* rescheduleOnly? */ true);
10438 		}
10439 
10440 		infoKeysRaw = _OSKextGetRequestArgument(requestDict,
10441 		    kKextRequestArgumentInfoKeysKey);
10442 		infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
10443 		if (infoKeysRaw && !infoKeys) {
10444 			OSKextLog(/* kext */ NULL,
10445 			    kOSKextLogErrorLevel |
10446 			    kOSKextLogIPCFlag,
10447 			    "Invalid arguments to kext info request.");
10448 			goto finish;
10449 		}
10450 
10451 		if (infoKeys) {
10452 			infoKeysCount = infoKeys->getCount();
10453 			for (uint32_t i = 0; i < infoKeysCount; i++) {
10454 				if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
10455 					OSKextLog(/* kext */ NULL,
10456 					    kOSKextLogErrorLevel |
10457 					    kOSKextLogIPCFlag,
10458 					    "Invalid arguments to kext info request.");
10459 					goto finish;
10460 				}
10461 			}
10462 		}
10463 
10464 		if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
10465 			responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
10466 		} else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
10467 			responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
10468 		} else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
10469 			responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys);
10470 		} else if (predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
10471 			responseObject = OSKext::copyDextsInfo(kextIdentifiers, infoKeys);
10472 		}
10473 
10474 		if (!responseObject) {
10475 			result = kOSKextReturnInternalError;
10476 		} else {
10477 			OSKextLog(/* kext */ NULL,
10478 			    kOSKextLogDebugLevel |
10479 			    kOSKextLogIPCFlag,
10480 			    "Returning loaded kext info.");
10481 			result = kOSReturnSuccess;
10482 		}
10483 	} else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
10484 		/* Hand the current sKernelRequests array to the caller
10485 		 * (who must release it), and make a new one.
10486 		 */
10487 		responseObject = os::move(sKernelRequests);
10488 		sKernelRequests = OSArray::withCapacity(0);
10489 		sPostedKextLoadIdentifiers->flushCollection();
10490 		OSKextLog(/* kext */ NULL,
10491 		    kOSKextLogDebugLevel |
10492 		    kOSKextLogIPCFlag,
10493 		    "Returning kernel requests.");
10494 		result = kOSReturnSuccess;
10495 	} else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
10496 		/* Return the set of all requested bundle identifiers */
10497 		responseObject = sAllKextLoadIdentifiers;
10498 		OSKextLog(/* kext */ NULL,
10499 		    kOSKextLogDebugLevel |
10500 		    kOSKextLogIPCFlag,
10501 		    "Returning load requests.");
10502 		result = kOSReturnSuccess;
10503 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) {
10504 		printf("KextLog: Loading FileSet KC(s)\n");
10505 		result = OSKext::loadFileSetKexts(requestDict);
10506 	} else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
10507 		bool active = iokitDaemonActive();
10508 		printf("KextLog: " kIOKitDaemonName " is %s\n", active ? "active" : "not active");
10509 		if (sOSKextWasResetAfterUserspaceReboot) {
10510 			printf("KextLog: was reset after userspace reboot\n");
10511 		}
10512 		result = active ? kOSReturnSuccess : kIOReturnNotReady;
10513 	} else {
10514 		OSKextLog(/* kext */ NULL,
10515 		    kOSKextLogDebugLevel |
10516 		    kOSKextLogIPCFlag,
10517 		    "Received '%s' invalid request from user space.",
10518 		    predicate->getCStringNoCopy());
10519 		goto finish;
10520 	}
10521 
10522 	/**********
10523 	 * Now we have handle the request, or not. Gather up the response & logging
10524 	 * info to ship to user space.
10525 	 *********/
10526 
10527 	/* Note: Nothing in OSKext is supposed to retain requestDict,
10528 	 * but you never know....
10529 	 */
10530 	if (requestDict->getRetainCount() > 1) {
10531 		OSKextLog(/* kext */ NULL,
10532 		    kOSKextLogWarningLevel |
10533 		    kOSKextLogIPCFlag,
10534 		    "Request from user space still retained by a kext; "
10535 		    "probable memory leak.");
10536 	}
10537 
10538 	if (responseOut && responseObject) {
10539 		serializer = OSSerialize::withCapacity(0);
10540 		if (!serializer) {
10541 			result = kOSKextReturnNoMemory;
10542 			goto finish;
10543 		}
10544 		/*
10545 		 * Before serializing the kernel requests, patch the dext launch requests so
10546 		 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the
10547 		 * IOUserServerCheckInToken kernel object.
10548 		 */
10549 		if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
10550 			OSArray * requests = OSDynamicCast(OSArray, responseObject.get());
10551 			task_t calling_task = current_task();
10552 			if (!requests) {
10553 				OSKextLog(/* kext */ NULL,
10554 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10555 				    "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests);
10556 				result = kOSKextReturnInternalError;
10557 				goto finish;
10558 			}
10559 			result = patchDextLaunchRequests(calling_task, requests);
10560 			if (result != kOSReturnSuccess) {
10561 				OSKextLog(/* kext */ NULL,
10562 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10563 				    "Failed to patch dext launch requests.");
10564 				goto finish;
10565 			}
10566 		}
10567 
10568 		if (!responseObject->serialize(serializer.get())) {
10569 			OSKextLog(/* kext */ NULL,
10570 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10571 			    "Failed to serialize response to request from user space.");
10572 			result = kOSKextReturnSerialization;
10573 			goto finish;
10574 		}
10575 
10576 		response = (char *)serializer->text();
10577 		responseLength = serializer->getLength();
10578 	}
10579 
10580 	if (responseOut && response) {
10581 		char * buffer;
10582 
10583 		/* This kmem_alloc sets the return value of the function.
10584 		 */
10585 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
10586 		    round_page(responseLength), KMA_DATA, VM_KERN_MEMORY_OSKEXT);
10587 		if (kmem_result != KERN_SUCCESS) {
10588 			OSKextLog(/* kext */ NULL,
10589 			    kOSKextLogErrorLevel |
10590 			    kOSKextLogIPCFlag,
10591 			    "Failed to copy response to request from user space.");
10592 			result = kmem_result;
10593 			goto finish;
10594 		} else {
10595 			/* 11981737 - clear uninitialized data in last page */
10596 			bzero((void *)(buffer + responseLength),
10597 			    (round_page(responseLength) - responseLength));
10598 			memcpy(buffer, response, responseLength);
10599 			*responseOut = buffer;
10600 			*responseLengthOut = responseLength;
10601 		}
10602 	}
10603 
10604 finish:
10605 
10606 	/* Gather up the collected log messages for user space. Any messages
10607 	 * messages past this call will not make it up as log messages but
10608 	 * will be in the system log. Note that we ignore the return of the
10609 	 * serialize; it has no bearing on the operation at hand even if we
10610 	 * fail to get the log messages.
10611 	 */
10612 	logInfoArray = OSKext::clearUserSpaceLogFilter();
10613 
10614 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
10615 		(void)OSKext::serializeLogInfo(logInfoArray.get(),
10616 		    logInfoOut, logInfoLengthOut);
10617 	}
10618 
10619 	IORecursiveLockUnlock(sKextLock);
10620 
10621 	return result;
10622 }
10623 
10624 #if PRAGMA_MARK
10625 #pragma mark Linked Kext Collection Support
10626 #endif
10627 
10628 static int
10629 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount)
10630 {
10631 	for (int i = 0; i < segCount; i++) {
10632 		vm_offset_t segStart = segAddrs[i];
10633 		vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i];
10634 
10635 		if (theAddr >= segStart && theAddr < segEnd) {
10636 			return i;
10637 		}
10638 	}
10639 	return -1;
10640 }
10641 
10642 static void
10643 __slideOldKaslrOffsets(kernel_mach_header_t *mh,
10644     kernel_segment_command_t *kextTextSeg,
10645     OSData *kaslrOffsets)
10646 {
10647 	static const char *plk_segNames[] = {
10648 		"__TEXT",
10649 		"__TEXT_EXEC",
10650 		"__DATA",
10651 		"__DATA_CONST",
10652 		"__LINKEDIT",
10653 		"__PRELINK_TEXT",
10654 		"__PLK_TEXT_EXEC",
10655 		"__PRELINK_DATA",
10656 		"__PLK_DATA_CONST",
10657 		"__PLK_LLVM_COV",
10658 		"__PLK_LINKEDIT",
10659 		"__PRELINK_INFO"
10660 	};
10661 	static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0]));
10662 
10663 	unsigned long plk_segSizes[num_plk_seg];
10664 	vm_offset_t   plk_segAddrs[num_plk_seg];
10665 
10666 	for (size_t i = 0; i < num_plk_seg; i++) {
10667 		plk_segSizes[i] = 0;
10668 		plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]);
10669 	}
10670 
10671 	uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr;
10672 
10673 	int slidKextAddrCount = 0;
10674 	int badSlideAddr = 0;
10675 	int badSlideTarget = 0;
10676 
10677 	struct kaslrPackedOffsets {
10678 		uint32_t    count;          /* number of offsets */
10679 		uint32_t    offsetsArray[];        /* offsets to slide */
10680 	};
10681 	const struct kaslrPackedOffsets *myOffsets = NULL;
10682 	myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy();
10683 
10684 	for (uint32_t j = 0; j < myOffsets->count; j++) {
10685 		uint64_t   slideOffset = (uint64_t)myOffsets->offsetsArray[j];
10686 		vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset);
10687 		int        slideAddrSegIndex = -1;
10688 		int        addrToSlideSegIndex = -1;
10689 
10690 		slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
10691 		if (slideAddrSegIndex >= 0) {
10692 			addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
10693 			if (addrToSlideSegIndex < 0) {
10694 				badSlideTarget++;
10695 				continue;
10696 			}
10697 		} else {
10698 			badSlideAddr++;
10699 			continue;
10700 		}
10701 
10702 		slidKextAddrCount++;
10703 		*slideAddr = ml_static_slide(*slideAddr);
10704 	}         // for ...
10705 }
10706 
10707 
10708 
10709 /********************************************************************
10710 * addKextsFromKextCollection
10711 *
10712 * Input: MachO header of kext collection. The MachO is assumed to
10713 *        have a section named 'info_seg_name,info_sect_name' that
10714 *        contains a serialized XML info dictionary. This dictionary
10715 *        contains a UUID, possibly a set of relocations (for older
10716 *        kxld-built binaries), and an array of kext personalities.
10717 *
10718 ********************************************************************/
10719 bool
10720 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10721     OSDictionary *infoDict, const char *text_seg_name,
10722     OSData **kcUUID, kc_kind_t type)
10723 {
10724 	bool result = false;
10725 
10726 	OSArray *kextArray     = NULL;        // do not release
10727 	OSData *infoDictKCUUID = NULL;         // do not release
10728 	OSData *kaslrOffsets   = NULL;        // do not release
10729 
10730 	IORegistryEntry *registryRoot = NULL;         // do not release
10731 	OSSharedPtr<OSNumber> kcKextCount;
10732 
10733 	/* extract the KC UUID from the dictionary */
10734 	infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
10735 	if (infoDictKCUUID) {
10736 		if (infoDictKCUUID->getLength() != sizeof(uuid_t)) {
10737 			panic("kcUUID length is %d, expected %lu",
10738 			    infoDictKCUUID->getLength(), sizeof(uuid_t));
10739 		}
10740 	}
10741 
10742 	/* locate the array of kext dictionaries */
10743 	kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey));
10744 	if (!kextArray) {
10745 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10746 		    "The given KC has no kext info dictionaries");
10747 		goto finish;
10748 	}
10749 
10750 	/*
10751 	 * old-style KASLR offsets may be present in the info dictionary. If
10752 	 * we find them, use them and eventually slide them.
10753 	 */
10754 	kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey));
10755 
10756 	/*
10757 	 * Before processing any kexts, locate the special kext bundle which
10758 	 * contains a list of kexts that we are to prevent from loading.
10759 	 */
10760 	createExcludeListFromPrelinkInfo(kextArray);
10761 
10762 	/*
10763 	 * Create OSKext objects for each kext we find in the array of kext
10764 	 * info plist dictionaries.
10765 	 */
10766 	for (int i = 0; i < (int)kextArray->getCount(); ++i) {
10767 		OSDictionary *kextDict = NULL;
10768 		kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i));
10769 		if (!kextDict) {
10770 			OSKextLog(/* kext */ NULL,
10771 			    kOSKextLogErrorLevel |
10772 			    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10773 			    "Kext info dictionary for kext #%d isn't a dictionary?", i);
10774 			continue;
10775 		}
10776 
10777 		/*
10778 		 * Create the kext for the entry, then release it, because the
10779 		 * kext system keeps a reference around until the kext is
10780 		 * explicitly removed.  Any creation/registration failures are
10781 		 * already logged for us.
10782 		 */
10783 		withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type);
10784 	}
10785 
10786 	/*
10787 	 * slide old-style kxld relocations
10788 	 * NOTE: this is still used on embedded KCs built with kcgen
10789 	 * TODO: Remove this once we use the new kext linker everywhere!
10790 	 */
10791 	if (kaslrOffsets && vm_kernel_slide > 0) {
10792 		kernel_segment_command_t *text_segment = NULL;
10793 		text_segment = getsegbynamefromheader(mh, text_seg_name);
10794 		if (!text_segment) {
10795 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10796 			    "Can't find a TEXT segment named '%s' in macho header", text_seg_name);
10797 			goto finish;
10798 		}
10799 
10800 		__slideOldKaslrOffsets(mh, text_segment, kaslrOffsets);
10801 		/* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */
10802 		setAllVMAttributes();
10803 	}
10804 
10805 	/* Store the number of prelinked kexts in the registry so we can tell
10806 	 * when the system has been started from a prelinked kernel.
10807 	 */
10808 	registryRoot = IORegistryEntry::getRegistryRoot();
10809 	assert(registryRoot);
10810 
10811 	kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t));
10812 	assert(kcKextCount);
10813 	if (kcKextCount) {
10814 		OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey);
10815 		OSNumber *num;
10816 		num = OSDynamicCast(OSNumber, prop.get());
10817 		if (num) {
10818 			kcKextCount->addValue(num->unsigned64BitValue());
10819 		}
10820 		registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get());
10821 	}
10822 
10823 	OSKextLog(/* kext */ NULL,
10824 	    kOSKextLogProgressLevel |
10825 	    kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
10826 	    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10827 	    "%u prelinked kexts", infoDict->getCount());
10828 
10829 
10830 	if (kcUUID && infoDictKCUUID) {
10831 		*kcUUID = OSData::withData(infoDictKCUUID).detach();
10832 	}
10833 
10834 	result = true;
10835 
10836 finish:
10837 	return result;
10838 }
10839 
10840 bool
10841 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10842     OSDictionary *infoDict, const char *text_seg_name,
10843     OSSharedPtr<OSData> &kcUUID, kc_kind_t type)
10844 {
10845 	OSData  *result = NULL;
10846 	bool success = addKextsFromKextCollection(mh,
10847 	    infoDict,
10848 	    text_seg_name,
10849 	    &result,
10850 	    type);
10851 	if (success) {
10852 		kcUUID.reset(result, OSNoRetain);
10853 	}
10854 	return success;
10855 }
10856 
10857 static OSSharedPtr<OSObject> deferredAuxKCXML;
10858 bool
10859 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh,
10860     OSSharedPtr<OSObject> &parsedXML, kc_kind_t type)
10861 {
10862 	if (type != KCKindAuxiliary) {
10863 		return false;
10864 	}
10865 
10866 	kernel_mach_header_t *_mh;
10867 	_mh = (kernel_mach_header_t*)PE_get_kc_header(type);
10868 	if (!_mh || _mh != mh) {
10869 		return false;
10870 	}
10871 
10872 	if (deferredAuxKCXML) {
10873 		/* only allow this to be called once */
10874 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10875 		    "An Aux KC has already been registered for deferred processing.");
10876 		return false;
10877 	}
10878 
10879 	OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
10880 	if (!infoDict) {
10881 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10882 		    "The Aux KC has info dictionary");
10883 		return false;
10884 	}
10885 
10886 	OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
10887 	if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) {
10888 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10889 		    "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey);
10890 		return false;
10891 	}
10892 
10893 	/*
10894 	 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid
10895 	 * sysctl can return the UUID to user space which will check this
10896 	 * value for errors.
10897 	 */
10898 	memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(),
10899 	    kcUUID->getLength());
10900 	uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
10901 	auxkc_uuid_valid = TRUE;
10902 
10903 	deferredAuxKCXML = parsedXML;
10904 
10905 	return true;
10906 }
10907 
10908 OSSharedPtr<OSObject>
10909 OSKext::consumeDeferredKextCollection(kc_kind_t type)
10910 {
10911 	if (type != KCKindAuxiliary || !deferredAuxKCXML) {
10912 		return NULL;
10913 	}
10914 
10915 	return os::move(deferredAuxKCXML);
10916 }
10917 
10918 #if PRAGMA_MARK
10919 #pragma mark Profile-Guided-Optimization Support
10920 #endif
10921 
10922 // #include <InstrProfiling.h>
10923 extern "C" {
10924 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin,
10925     const char *DataEnd,
10926     const char *CountersBegin,
10927     const char *CountersEnd,
10928     const char *NamesBegin,
10929     const char *NamesEnd);
10930 int __llvm_profile_write_buffer_internal(char *Buffer,
10931     const char *DataBegin,
10932     const char *DataEnd,
10933     const char *CountersBegin,
10934     const char *CountersEnd,
10935     const char *NamesBegin,
10936     const char *NamesEnd);
10937 }
10938 
10939 
10940 static
10941 void
10942 OSKextPgoMetadataPut(char *pBuffer,
10943     size_t *position,
10944     size_t bufferSize,
10945     uint32_t *num_pairs,
10946     const char *key,
10947     const char *value)
10948 {
10949 	size_t strlen_key = strlen(key);
10950 	size_t strlen_value = strlen(value);
10951 	size_t len = strlen(key) + 1 + strlen(value) + 1;
10952 	char *pos = pBuffer + *position;
10953 	*position += len;
10954 	if (pBuffer && bufferSize && *position <= bufferSize) {
10955 		memcpy(pos, key, strlen_key); pos += strlen_key;
10956 		*(pos++) = '=';
10957 		memcpy(pos, value, strlen_value); pos += strlen_value;
10958 		*(pos++) = 0;
10959 		if (num_pairs) {
10960 			(*num_pairs)++;
10961 		}
10962 	}
10963 }
10964 
10965 
10966 static
10967 void
10968 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
10969 {
10970 	*position += strlen(key) + 1 + value_max + 1;
10971 }
10972 
10973 
10974 static
10975 void
10976 OSKextPgoMetadataPutAll(OSKext *kext,
10977     uuid_t instance_uuid,
10978     char *pBuffer,
10979     size_t *position,
10980     size_t bufferSize,
10981     uint32_t *num_pairs)
10982 {
10983 	_static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
10984 	//log_10 2^16 ≈ 4.82
10985 	const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
10986 	const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
10987 
10988 	if (!pBuffer) {
10989 		OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
10990 		OSKextPgoMetadataPutMax(position, "UUID", 36);
10991 		OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
10992 	} else {
10993 		uuid_string_t instance_uuid_string;
10994 		uuid_unparse(instance_uuid, instance_uuid_string);
10995 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10996 		    "INSTANCE", instance_uuid_string);
10997 
10998 		OSSharedPtr<OSData> uuid_data;
10999 		uuid_t uuid;
11000 		uuid_string_t uuid_string;
11001 		uuid_data = kext->copyUUID();
11002 		if (uuid_data) {
11003 			memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
11004 			uuid_unparse(uuid, uuid_string);
11005 			OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11006 			    "UUID", uuid_string);
11007 		}
11008 
11009 		clock_sec_t secs;
11010 		clock_usec_t usecs;
11011 		clock_get_calendar_microtime(&secs, &usecs);
11012 		assert(usecs < 1000000);
11013 		char timestamp[max_timestamp_string_size + 1];
11014 		_static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
11015 		snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
11016 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11017 		    "TIMESTAMP", timestamp);
11018 	}
11019 
11020 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11021 	    "NAME", kext->getIdentifierCString());
11022 
11023 	char versionCString[kOSKextVersionMaxLength];
11024 	OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
11025 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11026 	    "VERSION", versionCString);
11027 }
11028 
11029 static
11030 size_t
11031 OSKextPgoMetadataSize(OSKext *kext)
11032 {
11033 	size_t position = 0;
11034 	uuid_t fakeuuid = {};
11035 	OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
11036 	return position;
11037 }
11038 
11039 int
11040 OSKextGrabPgoDataLocked(OSKext *kext,
11041     bool metadata,
11042     uuid_t instance_uuid,
11043     uint64_t *pSize,
11044     char *pBuffer,
11045     uint64_t bufferSize)
11046 {
11047 	int err = 0;
11048 
11049 	kernel_section_t *sect_prf_data = NULL;
11050 	kernel_section_t *sect_prf_name = NULL;
11051 	kernel_section_t *sect_prf_cnts = NULL;
11052 	uint64_t size;
11053 	size_t metadata_size = 0;
11054 	size_t offset_to_pairs = 0;
11055 
11056 	sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
11057 	sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
11058 	if (!sect_prf_name) {
11059 		// kextcache sometimes truncates the section name to 15 chars
11060 		// <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache
11061 		sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
11062 	}
11063 	sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
11064 
11065 	if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
11066 		err = ENOTSUP;
11067 		goto out;
11068 	}
11069 
11070 	size = __llvm_profile_get_size_for_buffer_internal(
11071 		(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
11072 		(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
11073 		(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
11074 
11075 	if (metadata) {
11076 		metadata_size = OSKextPgoMetadataSize(kext);
11077 		size += metadata_size;
11078 		size += sizeof(pgo_metadata_footer);
11079 	}
11080 
11081 
11082 	if (pSize) {
11083 		*pSize = size;
11084 	}
11085 
11086 	if (pBuffer && bufferSize) {
11087 		if (bufferSize < size) {
11088 			err = ERANGE;
11089 			goto out;
11090 		}
11091 
11092 		err = __llvm_profile_write_buffer_internal(
11093 			pBuffer,
11094 			(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
11095 			(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
11096 			(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
11097 
11098 		if (err) {
11099 			err = EIO;
11100 			goto out;
11101 		}
11102 
11103 		if (metadata) {
11104 			offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size;
11105 			if (offset_to_pairs > UINT32_MAX) {
11106 				err = E2BIG;
11107 				goto out;
11108 			}
11109 
11110 			char *end_of_buffer = pBuffer + size;
11111 			struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
11112 			char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
11113 
11114 			size_t metadata_position = 0;
11115 			uint32_t num_pairs = 0;
11116 			OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
11117 			while (metadata_position < metadata_size) {
11118 				metadata_buffer[metadata_position++] = 0;
11119 			}
11120 
11121 			struct pgo_metadata_footer footer;
11122 			footer.magic = htonl(0x6d657461);
11123 			footer.number_of_pairs = htonl( num_pairs );
11124 			footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs );
11125 			memcpy(footerp, &footer, sizeof(footer));
11126 		}
11127 	}
11128 
11129 out:
11130 	return err;
11131 }
11132 
11133 
11134 int
11135 OSKextGrabPgoData(uuid_t uuid,
11136     uint64_t *pSize,
11137     char *pBuffer,
11138     uint64_t bufferSize,
11139     int wait_for_unload,
11140     int metadata)
11141 {
11142 	int err = 0;
11143 	OSSharedPtr<OSKext> kext;
11144 
11145 
11146 	IORecursiveLockLock(sKextLock);
11147 
11148 	kext = OSKext::lookupKextWithUUID(uuid);
11149 	if (!kext) {
11150 		err = ENOENT;
11151 		goto out;
11152 	}
11153 
11154 	if (wait_for_unload) {
11155 		OSKextGrabPgoStruct s;
11156 
11157 		s.metadata = metadata;
11158 		s.pSize = pSize;
11159 		s.pBuffer = pBuffer;
11160 		s.bufferSize = bufferSize;
11161 		s.err = EINTR;
11162 
11163 		struct list_head *prev = &kext->pendingPgoHead;
11164 		struct list_head *next = kext->pendingPgoHead.next;
11165 
11166 		s.list_head.prev = prev;
11167 		s.list_head.next = next;
11168 
11169 		prev->next = &s.list_head;
11170 		next->prev = &s.list_head;
11171 
11172 		kext.reset();
11173 
11174 		IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
11175 
11176 		prev = s.list_head.prev;
11177 		next = s.list_head.next;
11178 
11179 		prev->next = next;
11180 		next->prev = prev;
11181 
11182 		err = s.err;
11183 	} else {
11184 		err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
11185 	}
11186 
11187 out:
11188 
11189 	IORecursiveLockUnlock(sKextLock);
11190 
11191 	return err;
11192 }
11193 
11194 void
11195 OSKextResetPgoCountersLock()
11196 {
11197 	IORecursiveLockLock(sKextLock);
11198 }
11199 
11200 void
11201 OSKextResetPgoCountersUnlock()
11202 {
11203 	IORecursiveLockUnlock(sKextLock);
11204 }
11205 
11206 
11207 extern unsigned int not_in_kdp;
11208 
11209 void
11210 OSKextResetPgoCounters()
11211 {
11212 	assert(!not_in_kdp);
11213 	uint32_t count = sLoadedKexts->getCount();
11214 	for (uint32_t i = 0; i < count; i++) {
11215 		OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
11216 		kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
11217 		if (!sect_prf_cnts) {
11218 			continue;
11219 		}
11220 		memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
11221 	}
11222 }
11223 
11224 OSSharedPtr<OSDictionary>
11225 OSKext::copyLoadedKextInfoByUUID(
11226 	OSArray * kextIdentifiers,
11227 	OSArray * infoKeys)
11228 {
11229 	OSSharedPtr<OSDictionary> result;
11230 	OSSharedPtr<OSDictionary> kextInfo;
11231 	uint32_t       max_count, i, j;
11232 	uint32_t       idCount = 0;
11233 	uint32_t       idIndex = 0;
11234 	IORecursiveLockLock(sKextLock);
11235 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
11236 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
11237 
11238 #if CONFIG_MACF
11239 	/* Is the calling process allowed to query kext info? */
11240 	if (current_task() != kernel_task) {
11241 		int                 macCheckResult      = 0;
11242 		kauth_cred_t        cred                = NULL;
11243 
11244 		cred = kauth_cred_get_with_ref();
11245 		macCheckResult = mac_kext_check_query(cred);
11246 		kauth_cred_unref(&cred);
11247 
11248 		if (macCheckResult != 0) {
11249 			OSKextLog(/* kext */ NULL,
11250 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11251 			    "Failed to query kext info (MAC policy error 0x%x).",
11252 			    macCheckResult);
11253 			goto finish;
11254 		}
11255 	}
11256 #endif
11257 
11258 	/* Empty list of UUIDs is equivalent to no list (get all).
11259 	 */
11260 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11261 		kextIdentifiers = NULL;
11262 	} else if (kextIdentifiers) {
11263 		idCount = kextIdentifiers->getCount();
11264 	}
11265 
11266 	/* Same for keys.
11267 	 */
11268 	if (infoKeys && !infoKeys->getCount()) {
11269 		infoKeys = NULL;
11270 	}
11271 
11272 	max_count = count[0] + count[1];
11273 	result = OSDictionary::withCapacity(max_count);
11274 	if (!result) {
11275 		goto finish;
11276 	}
11277 
11278 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
11279 		for (i = 0; i < count[j]; i++) {
11280 			OSKext       *thisKext     = NULL;        // do not release
11281 			Boolean       includeThis  = true;
11282 			uuid_t        thisKextUUID;
11283 			uuid_t        thisKextTextUUID;
11284 			OSSharedPtr<OSData> uuid_data;
11285 			uuid_string_t uuid_key;
11286 
11287 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
11288 			if (!thisKext) {
11289 				continue;
11290 			}
11291 
11292 			uuid_data = thisKext->copyUUID();
11293 			if (!uuid_data) {
11294 				continue;
11295 			}
11296 
11297 			memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
11298 
11299 			uuid_unparse(thisKextUUID, uuid_key);
11300 
11301 			uuid_data = thisKext->copyTextUUID();
11302 			if (!uuid_data) {
11303 				continue;
11304 			}
11305 			memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
11306 
11307 			/* Skip current kext if we have a list of UUIDs and
11308 			 * it isn't in the list.
11309 			 */
11310 			if (kextIdentifiers) {
11311 				includeThis = false;
11312 
11313 				for (idIndex = 0; idIndex < idCount; idIndex++) {
11314 					const OSString* wantedUUID = OSDynamicCast(OSString,
11315 					    kextIdentifiers->getObject(idIndex));
11316 
11317 					uuid_t uuid;
11318 					uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
11319 
11320 					if ((0 == uuid_compare(uuid, thisKextUUID))
11321 					    || (0 == uuid_compare(uuid, thisKextTextUUID))) {
11322 						includeThis = true;
11323 						/* Only need to find the first kext if multiple match,
11324 						 * ie. asking for the kernel uuid does not need to find
11325 						 * interface kexts or builtin static kexts.
11326 						 */
11327 						kextIdentifiers->removeObject(idIndex);
11328 						uuid_unparse(uuid, uuid_key);
11329 						break;
11330 					}
11331 				}
11332 			}
11333 
11334 			if (!includeThis) {
11335 				continue;
11336 			}
11337 
11338 			kextInfo = thisKext->copyInfo(infoKeys);
11339 			if (kextInfo) {
11340 				result->setObject(uuid_key, kextInfo.get());
11341 			}
11342 
11343 			if (kextIdentifiers && !kextIdentifiers->getCount()) {
11344 				goto finish;
11345 			}
11346 		}
11347 	}
11348 
11349 finish:
11350 	IORecursiveLockUnlock(sKextLock);
11351 
11352 	return result;
11353 }
11354 
11355 /*********************************************************************
11356 *********************************************************************/
11357 /* static */
11358 OSSharedPtr<OSDictionary>
11359 OSKext::copyKextCollectionInfo(
11360 	OSDictionary *requestDict,
11361 	OSArray  *infoKeys)
11362 {
11363 	OSSharedPtr<OSDictionary> result;
11364 	OSString *collectionType = NULL;
11365 	OSObject *rawLoadedState = NULL;
11366 	OSString *loadedState    = NULL;
11367 
11368 	kc_kind_t kc_request_kind = KCKindUnknown;
11369 	bool onlyLoaded = false;
11370 	bool onlyUnloaded = false;
11371 
11372 #if CONFIG_MACF
11373 	/* Is the calling process allowed to query kext info? */
11374 	if (current_task() != kernel_task) {
11375 		int                 macCheckResult      = 0;
11376 		kauth_cred_t        cred                = NULL;
11377 
11378 		cred = kauth_cred_get_with_ref();
11379 		macCheckResult = mac_kext_check_query(cred);
11380 		kauth_cred_unref(&cred);
11381 
11382 		if (macCheckResult != 0) {
11383 			OSKextLog(/* kext */ NULL,
11384 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11385 			    "Failed to query kext info (MAC policy error 0x%x).",
11386 			    macCheckResult);
11387 			goto finish;
11388 		}
11389 	}
11390 #endif
11391 
11392 	if (infoKeys && !infoKeys->getCount()) {
11393 		infoKeys = NULL;
11394 	}
11395 
11396 	collectionType = OSDynamicCast(OSString,
11397 	    _OSKextGetRequestArgument(requestDict,
11398 	    kKextRequestArgumentCollectionTypeKey));
11399 	if (!collectionType) {
11400 		OSKextLog(/* kext */ NULL,
11401 		    kOSKextLogErrorLevel |
11402 		    kOSKextLogIPCFlag,
11403 		    "Invalid '%s' argument to kext collection info request.",
11404 		    kKextRequestArgumentCollectionTypeKey);
11405 		goto finish;
11406 	}
11407 	if (collectionType->isEqualTo(kKCTypePrimary)) {
11408 		kc_request_kind = KCKindPrimary;
11409 	} else if (collectionType->isEqualTo(kKCTypeSystem)) {
11410 		kc_request_kind = KCKindPageable;
11411 	} else if (collectionType->isEqualTo(kKCTypeAuxiliary)) {
11412 		kc_request_kind = KCKindAuxiliary;
11413 	} else if (collectionType->isEqualTo(kKCTypeCodeless)) {
11414 		kc_request_kind = KCKindNone;
11415 	} else if (!collectionType->isEqualTo(kKCTypeAny)) {
11416 		OSKextLog(/* kext */ NULL,
11417 		    kOSKextLogErrorLevel |
11418 		    kOSKextLogIPCFlag,
11419 		    "Invalid '%s' argument value '%s' to kext collection info request.",
11420 		    kKextRequestArgumentCollectionTypeKey,
11421 		    collectionType->getCStringNoCopy());
11422 		goto finish;
11423 	}
11424 
11425 	rawLoadedState = _OSKextGetRequestArgument(requestDict,
11426 	    kKextRequestArgumentLoadedStateKey);
11427 	if (rawLoadedState) {
11428 		loadedState = OSDynamicCast(OSString, rawLoadedState);
11429 		if (!loadedState) {
11430 			OSKextLog(/* kext */ NULL,
11431 			    kOSKextLogErrorLevel |
11432 			    kOSKextLogIPCFlag,
11433 			    "Invalid '%s' argument to kext collection info request.",
11434 			    kKextRequestArgumentLoadedStateKey);
11435 			goto finish;
11436 		}
11437 	}
11438 	if (loadedState) {
11439 		if (loadedState->isEqualTo("Loaded")) {
11440 			onlyLoaded = true;
11441 		} else if (loadedState->isEqualTo("Unloaded")) {
11442 			onlyUnloaded = true;
11443 		} else if (!loadedState->isEqualTo("Any")) {
11444 			OSKextLog(/* kext */ NULL,
11445 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11446 			    "Invalid '%s' argument value '%s' for '%s' collection info",
11447 			    kKextRequestArgumentLoadedStateKey,
11448 			    loadedState->getCStringNoCopy(),
11449 			    collectionType->getCStringNoCopy());
11450 			goto finish;
11451 		}
11452 	}
11453 
11454 	result = OSDictionary::withCapacity(sKextsByID->getCount());
11455 	if (!result) {
11456 		goto finish;
11457 	}
11458 
11459 	IORecursiveLockLock(sKextLock);
11460 	{         // start block scope
11461 		sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11462 		{
11463 			OSKext       *thisKext    = NULL;  // do not release
11464 			OSSharedPtr<OSDictionary> kextInfo;
11465 
11466 			(void)thisKextID;
11467 
11468 			thisKext = OSDynamicCast(OSKext, obj);
11469 			if (!thisKext) {
11470 			        return false;
11471 			}
11472 
11473 			/*
11474 			 * skip the kext if it came from the wrong collection type
11475 			 * (and the caller requested a specific type)
11476 			 */
11477 			if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) {
11478 			        return false;
11479 			}
11480 
11481 			/*
11482 			 * respect the caller's desire to find only loaded or
11483 			 * unloaded kexts
11484 			 */
11485 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11486 			        return false;
11487 			}
11488 			if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11489 			        return false;
11490 			}
11491 
11492 			kextInfo = thisKext->copyInfo(infoKeys);
11493 			if (kextInfo) {
11494 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
11495 			}
11496 			return false;
11497 		});
11498 	} // end block scope
11499 	IORecursiveLockUnlock(sKextLock);
11500 
11501 finish:
11502 	return result;
11503 }
11504 
11505 /* static */
11506 OSSharedPtr<OSArray>
11507 OSKext::copyDextsInfo(
11508 	OSArray *kextIdentifiers,
11509 	OSArray *infoKeys)
11510 {
11511 	OSSharedPtr<OSArray> result = NULL;
11512 	uint32_t idCount = 0;
11513 	bool getActive = false;
11514 	bool getLoaded = false;
11515 	bool getUnloaded = false;
11516 	bool getPendingUpgrade = false;
11517 	unsigned int avgDextCount = 0;
11518 
11519 #if CONFIG_MACF
11520 	/* Is the calling process allowed to query dext info? */
11521 	if (current_task() != kernel_task) {
11522 		int                 macCheckResult      = 0;
11523 		kauth_cred_t        cred                = NULL;
11524 
11525 		cred = kauth_cred_get_with_ref();
11526 		macCheckResult = mac_kext_check_query(cred);
11527 		kauth_cred_unref(&cred);
11528 
11529 		if (macCheckResult != 0) {
11530 			OSKextLog(/* kext */ NULL,
11531 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11532 			    "Failed to query kext info (MAC policy error 0x%x).",
11533 			    macCheckResult);
11534 			goto finish;
11535 		}
11536 	}
11537 #endif
11538 	/*
11539 	 * No infoKeys means return everything we
11540 	 * know about the dexts.
11541 	 */
11542 	if (infoKeys && !infoKeys->getCount()) {
11543 		infoKeys = NULL;
11544 	}
11545 
11546 	/*
11547 	 * Empty list of bundle ids is equivalent to
11548 	 * no list (get all).
11549 	 */
11550 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11551 		kextIdentifiers = NULL;
11552 	} else if (kextIdentifiers) {
11553 		idCount = kextIdentifiers->getCount();
11554 	}
11555 
11556 	/*
11557 	 * Caller can specify which state of dexts to query.
11558 	 */
11559 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveKey)) {
11560 		getActive = true;
11561 	}
11562 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveLoadedKey)) {
11563 		getLoaded = true;
11564 	}
11565 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveUnloadedKey)) {
11566 		getUnloaded = true;
11567 	}
11568 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStatePendingUpgradeKey)) {
11569 		getPendingUpgrade = true;
11570 	}
11571 
11572 	/*
11573 	 * By default we are going to return all active and pendingUpgrade dexts
11574 	 * only.
11575 	 */
11576 	if (!(getActive || getLoaded || getUnloaded || getPendingUpgrade)) {
11577 		getActive = true;
11578 		getPendingUpgrade = true;
11579 	}
11580 
11581 	/*
11582 	 * We return a dictionary of dexts
11583 	 * for every group requested.
11584 	 */
11585 	avgDextCount = sLoadedDriverKitKexts->getCount() + sDriverKitToUpgradeByID->getCount();
11586 	result = OSArray::withCapacity(avgDextCount);
11587 	if (!result) {
11588 		goto finish;
11589 	}
11590 
11591 	IORecursiveLockLock(sKextLock);
11592 	{ // start block scope
11593 		if (getActive || getLoaded || getUnloaded) {
11594 			sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11595 			{
11596 				OSKext *thisKext = NULL;  // do not release
11597 				OSSharedPtr<OSDictionary> kextInfo;
11598 				Boolean includeThis = true;
11599 				(void)thisKextID;
11600 
11601 				thisKext = OSDynamicCast(OSKext, obj);
11602 				if (!thisKext || !thisKext->isDriverKit()) {
11603 				        return false;
11604 				}
11605 
11606 				/*
11607 				 * Skip current dext if we have a list of bundle IDs and
11608 				 * it isn't in the list.
11609 				 */
11610 				if (kextIdentifiers) {
11611 				        includeThis = false;
11612 
11613 				        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11614 				                const OSString * thisRequestID = OSDynamicCast(OSString,
11615 				                kextIdentifiers->getObject(idIndex));
11616 				                if (thisKextID->isEqualTo(thisRequestID)) {
11617 				                        includeThis = true;
11618 				                        break;
11619 						}
11620 					}
11621 				}
11622 
11623 				if (!includeThis) {
11624 				        return false;
11625 				}
11626 
11627 				OSSharedPtr<OSString> state;
11628 				if (sLoadedDriverKitKexts->getNextIndexOfObject(thisKext, 0) == -1U) {
11629 				        if (!(getActive || getUnloaded)) {
11630 				                return false;
11631 					}
11632 				        state = OSString::withCString(kOSBundleDextStateActiveUnloadedKey);
11633 				} else {
11634 				        if (!(getActive || getLoaded)) {
11635 				                return false;
11636 					}
11637 				        state = OSString::withCString(kOSBundleDextStateActiveLoadedKey);
11638 				}
11639 
11640 				kextInfo = thisKext->copyInfo(infoKeys);
11641 				if (kextInfo) {
11642 				        kextInfo->setObject(kOSBundleDextStateKey, state.get());
11643 				        result->setObject(kextInfo.get());
11644 				}
11645 
11646 				return false;
11647 			});
11648 		}
11649 
11650 		if (getPendingUpgrade) {
11651 			sDriverKitToUpgradeByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11652 			{
11653 				OSKext *thisKext = NULL;  // do not release
11654 				OSSharedPtr<OSDictionary> kextInfo;
11655 				Boolean includeThis = true;
11656 				(void)thisKextID;
11657 
11658 				thisKext = OSDynamicCast(OSKext, obj);
11659 				if (!thisKext) {
11660 				        return false;
11661 				}
11662 				__assert_only bool isDext = thisKext->isDriverKit();
11663 				assert(isDext == true);
11664 
11665 				/*
11666 				 * Skip current dext if we have a list of bundle IDs and
11667 				 * it isn't in the list.
11668 				 */
11669 				if (kextIdentifiers) {
11670 				        includeThis = false;
11671 
11672 				        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11673 				                const OSString * thisRequestID = OSDynamicCast(OSString,
11674 				                kextIdentifiers->getObject(idIndex));
11675 				                if (thisKextID->isEqualTo(thisRequestID)) {
11676 				                        includeThis = true;
11677 				                        break;
11678 						}
11679 					}
11680 				}
11681 
11682 				if (!includeThis) {
11683 				        return false;
11684 				}
11685 
11686 				kextInfo = thisKext->copyInfo(infoKeys);
11687 				if (kextInfo) {
11688 				        OSSharedPtr<OSString> state = OSString::withCString(kOSBundleDextStatePendingUpgradeKey);
11689 				        kextInfo->setObject(kOSBundleDextStateKey, state.get());
11690 				        result->setObject(kextInfo.get());
11691 				}
11692 				return false;
11693 			});
11694 		}
11695 	} // end block scope
11696 	IORecursiveLockUnlock(sKextLock);
11697 finish:
11698 	return result;
11699 }
11700 
11701 /*********************************************************************
11702 *********************************************************************/
11703 /* static */
11704 OSSharedPtr<OSDictionary>
11705 OSKext::copyLoadedKextInfo(
11706 	OSArray * kextIdentifiers,
11707 	OSArray * infoKeys)
11708 {
11709 	OSSharedPtr<OSDictionary> result;
11710 	uint32_t       idCount = 0;
11711 	bool           onlyLoaded;
11712 
11713 	IORecursiveLockLock(sKextLock);
11714 
11715 #if CONFIG_MACF
11716 	/* Is the calling process allowed to query kext info? */
11717 	if (current_task() != kernel_task) {
11718 		int                 macCheckResult      = 0;
11719 		kauth_cred_t        cred                = NULL;
11720 
11721 		cred = kauth_cred_get_with_ref();
11722 		macCheckResult = mac_kext_check_query(cred);
11723 		kauth_cred_unref(&cred);
11724 
11725 		if (macCheckResult != 0) {
11726 			OSKextLog(/* kext */ NULL,
11727 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11728 			    "Failed to query kext info (MAC policy error 0x%x).",
11729 			    macCheckResult);
11730 			goto finish;
11731 		}
11732 	}
11733 #endif
11734 
11735 	/* Empty list of bundle ids is equivalent to no list (get all).
11736 	 */
11737 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11738 		kextIdentifiers = NULL;
11739 	} else if (kextIdentifiers) {
11740 		idCount = kextIdentifiers->getCount();
11741 	}
11742 
11743 	/* Same for keys.
11744 	 */
11745 	if (infoKeys && !infoKeys->getCount()) {
11746 		infoKeys = NULL;
11747 	}
11748 
11749 	onlyLoaded =  (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
11750 
11751 	result = OSDictionary::withCapacity(128);
11752 	if (!result) {
11753 		goto finish;
11754 	}
11755 
11756 #if 0
11757 	OSKextLog(/* kext */ NULL,
11758 	    kOSKextLogErrorLevel |
11759 	    kOSKextLogGeneralFlag,
11760 	    "kaslr: vm_kernel_slide 0x%lx \n",
11761 	    vm_kernel_slide);
11762 	OSKextLog(/* kext */ NULL,
11763 	    kOSKextLogErrorLevel |
11764 	    kOSKextLogGeneralFlag,
11765 	    "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
11766 	    vm_kernel_stext, vm_kernel_etext);
11767 	OSKextLog(/* kext */ NULL,
11768 	    kOSKextLogErrorLevel |
11769 	    kOSKextLogGeneralFlag,
11770 	    "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
11771 	    vm_kernel_base, vm_kernel_top);
11772 	OSKextLog(/* kext */ NULL,
11773 	    kOSKextLogErrorLevel |
11774 	    kOSKextLogGeneralFlag,
11775 	    "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
11776 	    vm_kext_base, vm_kext_top);
11777 	OSKextLog(/* kext */ NULL,
11778 	    kOSKextLogErrorLevel |
11779 	    kOSKextLogGeneralFlag,
11780 	    "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
11781 	    vm_prelink_stext, vm_prelink_etext);
11782 	OSKextLog(/* kext */ NULL,
11783 	    kOSKextLogErrorLevel |
11784 	    kOSKextLogGeneralFlag,
11785 	    "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
11786 	    vm_prelink_sinfo, vm_prelink_einfo);
11787 	OSKextLog(/* kext */ NULL,
11788 	    kOSKextLogErrorLevel |
11789 	    kOSKextLogGeneralFlag,
11790 	    "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
11791 	    vm_slinkedit, vm_elinkedit);
11792 #endif
11793 	{         // start block scope
11794 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
11795 		{
11796 			OSKext       * thisKext     = NULL;        // do not release
11797 			Boolean        includeThis  = true;
11798 			OSSharedPtr<OSDictionary> kextInfo;
11799 
11800 			thisKext = OSDynamicCast(OSKext, obj);
11801 			if (!thisKext) {
11802 			        return false;
11803 			}
11804 
11805 			/* Skip current kext if not yet started and caller didn't request all.
11806 			 */
11807 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11808 			        return false;
11809 			}
11810 
11811 			/* Skip current kext if we have a list of bundle IDs and
11812 			 * it isn't in the list.
11813 			 */
11814 			if (kextIdentifiers) {
11815 			        includeThis = false;
11816 
11817 			        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11818 			                const OSString * thisRequestID = OSDynamicCast(OSString,
11819 			                kextIdentifiers->getObject(idIndex));
11820 			                if (thisKextID->isEqualTo(thisRequestID)) {
11821 			                        includeThis = true;
11822 			                        break;
11823 					}
11824 				}
11825 			}
11826 
11827 			if (!includeThis) {
11828 			        return false;
11829 			}
11830 
11831 			kextInfo = thisKext->copyInfo(infoKeys);
11832 			if (kextInfo) {
11833 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
11834 			}
11835 			return false;
11836 		});
11837 	}         // end block scope
11838 
11839 finish:
11840 	IORecursiveLockUnlock(sKextLock);
11841 
11842 	return result;
11843 }
11844 
11845 /*********************************************************************
11846 * Any info that needs to do allocations must goto finish on alloc
11847 * failure. Info that is just a lookup should just not set the object
11848 * if the info does not exist.
11849 *********************************************************************/
11850 #define _OSKextLoadInfoDictCapacity   (12)
11851 
11852 OSSharedPtr<OSDictionary>
11853 OSKext::copyInfo(OSArray * infoKeys)
11854 {
11855 	OSSharedPtr<OSDictionary>  result;
11856 	bool                       success                     = false;
11857 	OSSharedPtr<OSData>        headerData;
11858 	OSSharedPtr<OSData>        logData;
11859 	OSSharedPtr<OSNumber>      cpuTypeNumber;
11860 	OSSharedPtr<OSNumber>      cpuSubtypeNumber;
11861 	OSString                 * versionString               = NULL;        // do not release
11862 	OSString                 * bundleType                  = NULL;        // do not release
11863 	uint32_t                   executablePathCStringSize   = 0;
11864 	char                     * executablePathCString       = NULL;        // must kfree
11865 	OSSharedPtr<OSString>      executablePathString;
11866 	OSSharedPtr<OSData>        uuid;
11867 	OSSharedPtr<OSArray>       dependencyLoadTags;
11868 	OSSharedPtr<OSCollectionIterator>      metaClassIterator;
11869 	OSSharedPtr<OSArray>       metaClassInfo;
11870 	OSSharedPtr<OSDictionary>  metaClassDict;
11871 	OSMetaClass              * thisMetaClass               = NULL;        // do not release
11872 	OSSharedPtr<OSString>      metaClassName;
11873 	OSSharedPtr<OSString>      superclassName;
11874 	kc_format_t                kcformat;
11875 	uint32_t                   count, i;
11876 
11877 	result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
11878 	if (!result) {
11879 		goto finish;
11880 	}
11881 
11882 
11883 	/* Empty keys means no keys, but NULL is quicker to check.
11884 	 */
11885 	if (infoKeys && !infoKeys->getCount()) {
11886 		infoKeys = NULL;
11887 	}
11888 
11889 	if (!PE_get_primary_kc_format(&kcformat)) {
11890 		goto finish;
11891 	}
11892 
11893 	/* Headers, CPU type, and CPU subtype.
11894 	 */
11895 	if (!infoKeys ||
11896 	    _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
11897 	    _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
11898 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
11899 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
11900 		if (linkedExecutable && !isInterface()) {
11901 			kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
11902 			    linkedExecutable->getBytesNoCopy();
11903 
11904 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX
11905 			// do not return macho header info on shipping embedded - 19095897
11906 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
11907 				kernel_mach_header_t *  temp_kext_mach_hdr;
11908 				struct load_command *   lcp;
11909 
11910 				headerData = OSData::withBytes(kext_mach_hdr,
11911 				    (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
11912 				if (!headerData) {
11913 					goto finish;
11914 				}
11915 
11916 				// unslide any vmaddrs we return to userspace - 10726716
11917 				temp_kext_mach_hdr = (kernel_mach_header_t *)
11918 				    headerData->getBytesNoCopy();
11919 				if (temp_kext_mach_hdr == NULL) {
11920 					goto finish;
11921 				}
11922 
11923 				lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
11924 				for (i = 0; (i < temp_kext_mach_hdr->ncmds) && !flags.unslidMachO; i++) {
11925 					if (lcp->cmd == LC_SEGMENT_KERNEL) {
11926 						kernel_segment_command_t *  segp;
11927 						kernel_section_t *          secp;
11928 
11929 						segp = (kernel_segment_command_t *) lcp;
11930 						// 10543468 - if we jettisoned __LINKEDIT clear size info
11931 						if (flags.jettisonLinkeditSeg) {
11932 							if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
11933 								segp->vmsize = 0;
11934 								segp->fileoff = 0;
11935 								segp->filesize = 0;
11936 							}
11937 						}
11938 
11939 #if __arm__ || __arm64__
11940 						// iBoot disregards zero-size segments, just set their addresses to gVirtBase
11941 						// and unslide them to avoid vm assertion failures / kernel logging breakage.
11942 						if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) {
11943 							segp->vmaddr = gVirtBase;
11944 							for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
11945 								secp->size = 0; // paranoia :)
11946 								secp->addr = gVirtBase;
11947 							}
11948 						}
11949 #endif
11950 
11951 #if 0
11952 						OSKextLog(/* kext */ NULL,
11953 						    kOSKextLogErrorLevel |
11954 						    kOSKextLogGeneralFlag,
11955 						    "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
11956 						    __FUNCTION__, segp->segname, segp->vmaddr,
11957 						    VM_KERNEL_UNSLIDE(segp->vmaddr),
11958 						    segp->vmsize, segp->nsects);
11959 						if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
11960 						    (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
11961 						    (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
11962 						    (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
11963 						    (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
11964 							OSKextLog(/* kext */ NULL,
11965 							    kOSKextLogErrorLevel |
11966 							    kOSKextLogGeneralFlag,
11967 							    "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
11968 							    __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
11969 						}
11970 #endif
11971 						segp->vmaddr = ml_static_unslide(segp->vmaddr);
11972 
11973 						for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
11974 							secp->addr = ml_static_unslide(secp->addr);
11975 						}
11976 					}
11977 					lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
11978 				}
11979 				result->setObject(kOSBundleMachOHeadersKey, headerData.get());
11980 			}
11981 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX
11982 
11983 			if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
11984 				osLogDataHeaderRef *header;
11985 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
11986 
11987 				void *os_log_data               = NULL;
11988 				void *cstring_data              = NULL;
11989 				void *asan_cstring_data         = NULL;
11990 				unsigned long os_log_size       = 0;
11991 				unsigned long cstring_size      = 0;
11992 				unsigned long asan_cstring_size = 0;
11993 				uint32_t os_log_offset          = 0;
11994 				uint32_t cstring_offset         = 0;
11995 				uint32_t asan_cstring_offset    = 0;
11996 				bool res;
11997 
11998 				os_log_data         = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
11999 				cstring_data        = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
12000 				asan_cstring_data   = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size);
12001 
12002 				/*
12003 				 * If the addresses in the Mach-O header are unslid, manually
12004 				 * slide them to allow for dereferencing.
12005 				 */
12006 				if (flags.unslidMachO) {
12007 					os_log_data = (os_log_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)os_log_data) : nullptr;
12008 					cstring_data = (cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)cstring_data) : nullptr;
12009 					asan_cstring_data = (asan_cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)asan_cstring_data) : nullptr;
12010 				}
12011 
12012 				os_log_offset       = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr;
12013 				cstring_offset      = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr;
12014 				asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr;
12015 
12016 				header             = (osLogDataHeaderRef *) headerBytes;
12017 				header->version    = OS_LOG_HDR_VERSION;
12018 				header->sect_count = NUM_OS_LOG_SECTIONS;
12019 				header->sections[OS_LOG_SECT_IDX].sect_offset       = os_log_offset;
12020 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) os_log_size;
12021 				header->sections[CSTRING_SECT_IDX].sect_offset      = cstring_offset;
12022 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) cstring_size;
12023 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset;
12024 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) asan_cstring_size;
12025 
12026 
12027 				logData = OSData::withValue(*header);
12028 				if (!logData) {
12029 					goto finish;
12030 				}
12031 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
12032 				if (!res) {
12033 					goto finish;
12034 				}
12035 				if (os_log_data) {
12036 					res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
12037 					if (!res) {
12038 						goto finish;
12039 					}
12040 				}
12041 				if (cstring_data) {
12042 					res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
12043 					if (!res) {
12044 						goto finish;
12045 					}
12046 				}
12047 				if (asan_cstring_data) {
12048 					res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size);
12049 					if (!res) {
12050 						goto finish;
12051 					}
12052 				}
12053 				result->setObject(kOSBundleLogStringsKey, logData.get());
12054 			}
12055 
12056 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
12057 				cpuTypeNumber = OSNumber::withNumber(
12058 					(uint64_t) kext_mach_hdr->cputype,
12059 					8 * sizeof(kext_mach_hdr->cputype));
12060 				if (!cpuTypeNumber) {
12061 					goto finish;
12062 				}
12063 				result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get());
12064 			}
12065 
12066 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
12067 				cpuSubtypeNumber = OSNumber::withNumber(
12068 					(uint64_t) kext_mach_hdr->cpusubtype,
12069 					8 * sizeof(kext_mach_hdr->cpusubtype));
12070 				if (!cpuSubtypeNumber) {
12071 					goto finish;
12072 				}
12073 				result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get());
12074 			}
12075 		} else {
12076 			if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
12077 				osLogDataHeaderRef *header;
12078 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
12079 				bool res;
12080 
12081 				header             = (osLogDataHeaderRef *) headerBytes;
12082 				header->version    = OS_LOG_HDR_VERSION;
12083 				header->sect_count = NUM_OS_LOG_SECTIONS;
12084 				header->sections[OS_LOG_SECT_IDX].sect_offset       = 0;
12085 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) 0;
12086 				header->sections[CSTRING_SECT_IDX].sect_offset      = 0;
12087 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) 0;
12088 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0;
12089 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) 0;
12090 
12091 				logData = OSData::withValue(*header);
12092 				if (!logData) {
12093 					goto finish;
12094 				}
12095 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
12096 				if (!res) {
12097 					goto finish;
12098 				}
12099 				result->setObject(kOSBundleLogStringsKey, logData.get());
12100 			}
12101 		}
12102 	}
12103 
12104 	/* CFBundleIdentifier. We set this regardless because it's just stupid not to.
12105 	 */
12106 	result->setObject(kCFBundleIdentifierKey, bundleID.get());
12107 
12108 	/* kOSBundleDextUniqueIdentifierKey if present.
12109 	 */
12110 	if (isDriverKit() && dextUniqueID != NULL) {
12111 		result->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID.get());
12112 	}
12113 
12114 	/* CFBundlePackageType
12115 	 */
12116 	bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL;
12117 	if (bundleType) {
12118 		result->setObject(kCFBundlePackageTypeKey, bundleType);
12119 	}
12120 
12121 	/* CFBundleVersion.
12122 	 */
12123 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
12124 		versionString = OSDynamicCast(OSString,
12125 		    getPropertyForHostArch(kCFBundleVersionKey));
12126 		if (versionString) {
12127 			result->setObject(kCFBundleVersionKey, versionString);
12128 		}
12129 	}
12130 
12131 	/* OSBundleCompatibleVersion.
12132 	 */
12133 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
12134 		versionString = OSDynamicCast(OSString,
12135 		    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
12136 		if (versionString) {
12137 			result->setObject(kOSBundleCompatibleVersionKey, versionString);
12138 		}
12139 	}
12140 
12141 	/* Path.
12142 	 */
12143 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
12144 		if (path) {
12145 			result->setObject(kOSBundlePathKey, path.get());
12146 		}
12147 	}
12148 
12149 
12150 	/* OSBundleExecutablePath.
12151 	 */
12152 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
12153 		if (path && executableRelPath) {
12154 			uint32_t pathLength = path->getLength();         // gets incremented below
12155 
12156 			// +1 for slash, +1 for \0
12157 			executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
12158 
12159 			executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
12160 			    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);         // +1 for \0
12161 			if (!executablePathCString) {
12162 				goto finish;
12163 			}
12164 			strlcpy(executablePathCString, path->getCStringNoCopy(),
12165 			    executablePathCStringSize);
12166 			executablePathCString[pathLength++] = '/';
12167 			executablePathCString[pathLength++] = '\0';
12168 			strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
12169 			    executablePathCStringSize);
12170 
12171 			executablePathString = OSString::withCString(executablePathCString);
12172 
12173 			if (!executablePathString) {
12174 				goto finish;
12175 			}
12176 
12177 			result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
12178 		} else if (flags.builtin) {
12179 			result->setObject(kOSBundleExecutablePathKey, bundleID.get());
12180 		} else if (isDriverKit()) {
12181 			if (path) {
12182 				// +1 for slash, +1 for \0
12183 				uint32_t pathLength = path->getLength();
12184 				executablePathCStringSize = pathLength + 2;
12185 
12186 				executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
12187 				    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
12188 				if (!executablePathCString) {
12189 					goto finish;
12190 				}
12191 				strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize);
12192 				executablePathCString[pathLength++] = '/';
12193 				executablePathCString[pathLength++] = '\0';
12194 
12195 				executablePathString = OSString::withCString(executablePathCString);
12196 
12197 				if (!executablePathString) {
12198 					goto finish;
12199 				}
12200 
12201 				result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
12202 			}
12203 		}
12204 	}
12205 
12206 	/* UUID, if the kext has one.
12207 	 */
12208 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
12209 		uuid = copyUUID();
12210 		if (uuid) {
12211 			result->setObject(kOSBundleUUIDKey, uuid.get());
12212 		}
12213 	}
12214 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
12215 		uuid = copyTextUUID();
12216 		if (uuid) {
12217 			result->setObject(kOSBundleTextUUIDKey, uuid.get());
12218 		}
12219 	}
12220 
12221 	/*
12222 	 * Info.plist digest
12223 	 */
12224 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) {
12225 		OSData *digest;
12226 		digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL;
12227 		if (digest) {
12228 			result->setObject(kOSKextInfoPlistDigestKey, digest);
12229 		}
12230 	}
12231 
12232 	/*
12233 	 * Collection type
12234 	 */
12235 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) {
12236 		result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString()));
12237 	}
12238 
12239 	/*
12240 	 * Collection availability
12241 	 */
12242 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) {
12243 		result->setObject(kOSKextAuxKCAvailabilityKey,
12244 		    isLoadable() ? kOSBooleanTrue : kOSBooleanFalse);
12245 	}
12246 
12247 	/*
12248 	 * Allows user load
12249 	 */
12250 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) {
12251 		OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey));
12252 		if (allowUserLoad) {
12253 			result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad);
12254 		}
12255 	}
12256 
12257 	/*
12258 	 * Bundle Dependencies (OSBundleLibraries)
12259 	 */
12260 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) {
12261 		OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey));
12262 		if (libraries) {
12263 			result->setObject(kOSBundleLibrariesKey, libraries);
12264 		}
12265 	}
12266 
12267 	/*****
12268 	 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
12269 	 */
12270 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
12271 		result->setObject(kOSKernelResourceKey,
12272 		    isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
12273 	}
12274 
12275 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
12276 		result->setObject(kOSBundleIsInterfaceKey,
12277 		    isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
12278 	}
12279 
12280 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
12281 		result->setObject(kOSBundlePrelinkedKey,
12282 		    isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
12283 	}
12284 
12285 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
12286 		result->setObject(kOSBundleStartedKey,
12287 		    isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
12288 	}
12289 
12290 	/* LoadTag (Index).
12291 	 */
12292 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
12293 		OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
12294 		    /* numBits */ 8 * sizeof(loadTag));
12295 		if (!scratchNumber) {
12296 			goto finish;
12297 		}
12298 		result->setObject(kOSBundleLoadTagKey, scratchNumber.get());
12299 	}
12300 
12301 	/* LoadAddress, LoadSize.
12302 	 */
12303 	if (!infoKeys ||
12304 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
12305 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
12306 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
12307 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
12308 	    _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
12309 		bool is_dext = isDriverKit();
12310 		if (isInterface() || flags.builtin || linkedExecutable || is_dext) {
12311 			/* These go to userspace via serialization, so we don't want any doubts
12312 			 * about their size.
12313 			 */
12314 			uint64_t    loadAddress     = 0;
12315 			uint32_t    loadSize        = 0;
12316 			uint32_t    wiredSize       = 0;
12317 			uint64_t    execLoadAddress = 0;
12318 			uint32_t    execLoadSize    = 0;
12319 
12320 			/* Interfaces always report 0 load address & size.
12321 			 * Just the way they roll.
12322 			 *
12323 			 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
12324 			 * xxx - shouldn't have one!
12325 			 */
12326 
12327 			if (flags.builtin || linkedExecutable) {
12328 				kernel_mach_header_t     *mh  = NULL;
12329 				kernel_segment_command_t *seg = NULL;
12330 
12331 				if (flags.builtin) {
12332 					loadAddress = kmod_info->address;
12333 					loadSize    = (uint32_t)kmod_info->size;
12334 				} else {
12335 					loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
12336 					loadSize = linkedExecutable->getLength();
12337 				}
12338 				mh = (kernel_mach_header_t *)loadAddress;
12339 				loadAddress = ml_static_unslide(loadAddress);
12340 
12341 				/* Walk through the kext, looking for the first executable
12342 				 * segment in case we were asked for its size/address.
12343 				 */
12344 				for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
12345 					if (seg->initprot & VM_PROT_EXECUTE) {
12346 						execLoadAddress = (flags.unslidMachO) ? seg->vmaddr : ml_static_unslide(seg->vmaddr);
12347 						execLoadSize = (uint32_t)seg->vmsize;
12348 						break;
12349 					}
12350 				}
12351 
12352 				/* If we have a kmod_info struct, calculated the wired size
12353 				 * from that. Otherwise it's the full load size.
12354 				 */
12355 				if (kmod_info) {
12356 					wiredSize = loadSize - (uint32_t)kmod_info->hdr_size;
12357 				} else {
12358 					wiredSize = loadSize;
12359 				}
12360 			} else if (is_dext) {
12361 				/*
12362 				 * DriverKit userspace executables do not have a kernel linkedExecutable,
12363 				 * so we "fake" their address range with the LoadTag.
12364 				 */
12365 				if (loadTag) {
12366 					loadAddress = execLoadAddress = loadTag;
12367 					loadSize = execLoadSize = 1;
12368 				}
12369 			}
12370 
12371 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
12372 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12373 					(unsigned long long)(loadAddress),
12374 					/* numBits */ 8 * sizeof(loadAddress));
12375 				if (!scratchNumber) {
12376 					goto finish;
12377 				}
12378 				result->setObject(kOSBundleLoadAddressKey, scratchNumber.get());
12379 			}
12380 			if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) {
12381 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
12382 				    && loadAddress && loadSize) {
12383 					void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary);
12384 					if (!baseAddress) {
12385 						goto finish;
12386 					}
12387 
12388 					OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12389 						(unsigned long long)ml_static_unslide((vm_offset_t)baseAddress),
12390 						/* numBits */ 8 * sizeof(loadAddress));
12391 					if (!scratchNumber) {
12392 						goto finish;
12393 					}
12394 					result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get());
12395 				}
12396 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
12397 				    && (this == sKernelKext) && gBuiltinKmodsCount) {
12398 					result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
12399 				}
12400 			}
12401 
12402 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
12403 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12404 					(unsigned long long)(execLoadAddress),
12405 					/* numBits */ 8 * sizeof(execLoadAddress));
12406 				if (!scratchNumber) {
12407 					goto finish;
12408 				}
12409 				result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get());
12410 			}
12411 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
12412 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12413 					(unsigned long long)(loadSize),
12414 					/* numBits */ 8 * sizeof(loadSize));
12415 				if (!scratchNumber) {
12416 					goto finish;
12417 				}
12418 				result->setObject(kOSBundleLoadSizeKey, scratchNumber.get());
12419 			}
12420 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
12421 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12422 					(unsigned long long)(execLoadSize),
12423 					/* numBits */ 8 * sizeof(execLoadSize));
12424 				if (!scratchNumber) {
12425 					goto finish;
12426 				}
12427 				result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get());
12428 			}
12429 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
12430 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12431 					(unsigned long long)(wiredSize),
12432 					/* numBits */ 8 * sizeof(wiredSize));
12433 				if (!scratchNumber) {
12434 					goto finish;
12435 				}
12436 				result->setObject(kOSBundleWiredSizeKey, scratchNumber.get());
12437 			}
12438 		}
12439 	}
12440 
12441 	/* OSBundleDependencies. In descending order for
12442 	 * easy compatibility with kextstat(8).
12443 	 */
12444 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
12445 		if ((count = getNumDependencies())) {
12446 			dependencyLoadTags = OSArray::withCapacity(count);
12447 			result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get());
12448 
12449 			i = count - 1;
12450 			do {
12451 				OSKext * dependency = OSDynamicCast(OSKext,
12452 				    dependencies->getObject(i));
12453 
12454 				if (!dependency) {
12455 					continue;
12456 				}
12457 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12458 					(unsigned long long)dependency->getLoadTag(),
12459 					/* numBits*/ 8 * sizeof(loadTag));
12460 				if (!scratchNumber) {
12461 					goto finish;
12462 				}
12463 				dependencyLoadTags->setObject(scratchNumber.get());
12464 			} while (i--);
12465 		}
12466 	}
12467 
12468 	/* OSBundleMetaClasses.
12469 	 */
12470 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
12471 		if (metaClasses && metaClasses->getCount()) {
12472 			metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get());
12473 			metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
12474 			if (!metaClassIterator || !metaClassInfo) {
12475 				goto finish;
12476 			}
12477 			result->setObject(kOSBundleClassesKey, metaClassInfo.get());
12478 
12479 			while ((thisMetaClass = OSDynamicCast(OSMetaClass,
12480 			    metaClassIterator->getNextObject()))) {
12481 				metaClassDict = OSDictionary::withCapacity(3);
12482 				if (!metaClassDict) {
12483 					goto finish;
12484 				}
12485 
12486 				metaClassName = OSString::withCString(thisMetaClass->getClassName());
12487 				if (thisMetaClass->getSuperClass()) {
12488 					superclassName = OSString::withCString(
12489 						thisMetaClass->getSuperClass()->getClassName());
12490 				}
12491 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
12492 				    8 * sizeof(unsigned int));
12493 
12494 				/* Bail if any of the essentials is missing. The root class lacks a superclass,
12495 				 * of course.
12496 				 */
12497 				if (!metaClassDict || !metaClassName || !scratchNumber) {
12498 					goto finish;
12499 				}
12500 
12501 				metaClassInfo->setObject(metaClassDict.get());
12502 				metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get());
12503 				if (superclassName) {
12504 					metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get());
12505 				}
12506 				metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get());
12507 			}
12508 		}
12509 	}
12510 
12511 	/* OSBundleRetainCount.
12512 	 */
12513 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
12514 		{
12515 			int kextRetainCount = getRetainCount() - 1;
12516 			if (isLoaded()) {
12517 				kextRetainCount--;
12518 			}
12519 			OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12520 				(int)kextRetainCount,
12521 				/* numBits*/ 8 * sizeof(int));
12522 			if (scratchNumber) {
12523 				result->setObject(kOSBundleRetainCountKey, scratchNumber.get());
12524 			}
12525 		}
12526 	}
12527 
12528 	success = true;
12529 
12530 finish:
12531 	if (executablePathCString) {
12532 		kfree_data(executablePathCString, executablePathCStringSize);
12533 	}
12534 	if (!success) {
12535 		result.reset();
12536 	}
12537 	return result;
12538 }
12539 
12540 /*********************************************************************
12541 *********************************************************************/
12542 /* static */
12543 bool
12544 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
12545 {
12546 	bool ok;
12547 	OSSharedPtr<OSKext> kext;
12548 
12549 	IORecursiveLockLock(sKextLock);
12550 	kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain);
12551 	IORecursiveLockUnlock(sKextLock);
12552 
12553 	if (!kext || !kext->path || !kext->userExecutableRelPath) {
12554 		return false;
12555 	}
12556 	snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
12557 	    kext->path->getCStringNoCopy(),
12558 	    kext->userExecutableRelPath->getCStringNoCopy());
12559 	ok = true;
12560 
12561 	return ok;
12562 }
12563 
12564 /*********************************************************************
12565 *********************************************************************/
12566 /* static */
12567 OSReturn
12568 OSKext::requestResource(
12569 	const char                    * kextIdentifierCString,
12570 	const char                    * resourceNameCString,
12571 	OSKextRequestResourceCallback   callback,
12572 	void                          * context,
12573 	OSKextRequestTag              * requestTagOut)
12574 {
12575 	OSReturn                        result = kOSReturnError;
12576 	OSSharedPtr<OSKext>             callbackKext;        // looked up
12577 
12578 	OSKextRequestTag   requestTag      = -1;
12579 	OSSharedPtr<OSNumber>           requestTagNum;
12580 	OSSharedPtr<OSDictionary>       requestDict;
12581 	OSSharedPtr<OSString>           kextIdentifier;
12582 	OSSharedPtr<OSString>           resourceName;
12583 
12584 	OSSharedPtr<OSDictionary>       callbackRecord;
12585 	OSSharedPtr<OSValueObject<OSKextRequestResourceCallback> > callbackWrapper;
12586 
12587 	OSSharedPtr<OSValueObject<void *> > contextWrapper;
12588 
12589 	IORecursiveLockLock(sKextLock);
12590 
12591 	if (requestTagOut) {
12592 		*requestTagOut = kOSKextRequestTagInvalid;
12593 	}
12594 
12595 	/* If requests to user space are disabled, don't go any further */
12596 	if (!sKernelRequestsEnabled) {
12597 		OSKextLog(/* kext */ NULL,
12598 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12599 		    "Can't request resource %s for %s - requests to user space are disabled.",
12600 		    resourceNameCString,
12601 		    kextIdentifierCString);
12602 		result = kOSKextReturnDisabled;
12603 		goto finish;
12604 	}
12605 
12606 	if (!kextIdentifierCString || !resourceNameCString || !callback) {
12607 		result = kOSKextReturnInvalidArgument;
12608 		goto finish;
12609 	}
12610 
12611 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
12612 	if (!callbackKext) {
12613 		OSKextLog(/* kext */ NULL,
12614 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12615 		    "Resource request has bad callback address.");
12616 		result = kOSKextReturnInvalidArgument;
12617 		goto finish;
12618 	}
12619 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
12620 		OSKextLog(/* kext */ NULL,
12621 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12622 		    "Resource request callback is in a kext that is not started.");
12623 		result = kOSKextReturnInvalidArgument;
12624 		goto finish;
12625 	}
12626 
12627 	/* Do not allow any new requests to be made on a kext that is unloading.
12628 	 */
12629 	if (callbackKext->flags.stopping) {
12630 		result = kOSKextReturnStopping;
12631 		goto finish;
12632 	}
12633 
12634 	/* If we're wrapped the next available request tag around to the negative
12635 	 * numbers, we can't service any more requests.
12636 	 */
12637 	if (sNextRequestTag == kOSKextRequestTagInvalid) {
12638 		OSKextLog(/* kext */ NULL,
12639 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12640 		    "No more request tags available; restart required.");
12641 		result = kOSKextReturnNoResources;
12642 		goto finish;
12643 	}
12644 	requestTag = sNextRequestTag++;
12645 
12646 	result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
12647 	    requestDict);
12648 	if (result != kOSReturnSuccess) {
12649 		goto finish;
12650 	}
12651 
12652 	kextIdentifier = OSString::withCString(kextIdentifierCString);
12653 	resourceName   = OSString::withCString(resourceNameCString);
12654 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
12655 	    8 * sizeof(requestTag));
12656 	if (!kextIdentifier ||
12657 	    !resourceName ||
12658 	    !requestTagNum ||
12659 	    !_OSKextSetRequestArgument(requestDict.get(),
12660 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) ||
12661 	    !_OSKextSetRequestArgument(requestDict.get(),
12662 	    kKextRequestArgumentNameKey, resourceName.get()) ||
12663 	    !_OSKextSetRequestArgument(requestDict.get(),
12664 	    kKextRequestArgumentRequestTagKey, requestTagNum.get())) {
12665 		result = kOSKextReturnNoMemory;
12666 		goto finish;
12667 	}
12668 
12669 	callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection());
12670 	if (!callbackRecord) {
12671 		result = kOSKextReturnNoMemory;
12672 		goto finish;
12673 	}
12674 	// we validate callback address at call time
12675 	callbackWrapper = OSValueObjectWithValue(callback);
12676 	if (context) {
12677 		contextWrapper = OSValueObjectWithValue(context);
12678 	}
12679 	if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
12680 	    kKextRequestArgumentCallbackKey, callbackWrapper.get())) {
12681 		result = kOSKextReturnNoMemory;
12682 		goto finish;
12683 	}
12684 
12685 	if (context) {
12686 		if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
12687 		    kKextRequestArgumentContextKey, contextWrapper.get())) {
12688 			result = kOSKextReturnNoMemory;
12689 			goto finish;
12690 		}
12691 	}
12692 
12693 	/* Only post the requests after all the other potential failure points
12694 	 * have been passed.
12695 	 */
12696 	if (!sKernelRequests->setObject(requestDict.get()) ||
12697 	    !sRequestCallbackRecords->setObject(callbackRecord.get())) {
12698 		result = kOSKextReturnNoMemory;
12699 		goto finish;
12700 	}
12701 
12702 	OSKext::pingIOKitDaemon();
12703 
12704 	result = kOSReturnSuccess;
12705 	if (requestTagOut) {
12706 		*requestTagOut = requestTag;
12707 	}
12708 
12709 finish:
12710 
12711 	/* If we didn't succeed, yank the request & callback
12712 	 * from their holding arrays.
12713 	 */
12714 	if (result != kOSReturnSuccess) {
12715 		unsigned int index;
12716 
12717 		index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0);
12718 		if (index != (unsigned int)-1) {
12719 			sKernelRequests->removeObject(index);
12720 		}
12721 		index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0);
12722 		if (index != (unsigned int)-1) {
12723 			sRequestCallbackRecords->removeObject(index);
12724 		}
12725 	}
12726 
12727 	OSKext::considerUnloads(/* rescheduleOnly? */ true);
12728 
12729 	IORecursiveLockUnlock(sKextLock);
12730 
12731 	return result;
12732 }
12733 
12734 OSReturn
12735 OSKext::requestDaemonLaunch(
12736 	OSString *kextIdentifier,
12737 	OSString *serverName,
12738 	OSNumber *serverTag,
12739 	OSBoolean *reslide,
12740 	IOUserServerCheckInToken * checkInToken,
12741 	OSData *serverDUI)
12742 {
12743 	OSReturn       result        = kOSReturnError;
12744 	OSSharedPtr<OSDictionary> requestDict;
12745 	unsigned int size = 0;
12746 	const char *dextUniqueIDCString = NULL;
12747 
12748 	if (!kextIdentifier || !serverName || !serverTag || !checkInToken) {
12749 		return kOSKextReturnInvalidArgument;
12750 	}
12751 
12752 	if (serverDUI != NULL) {
12753 		dextUniqueIDCString = getDextUniqueIDCString(serverDUI, &size);
12754 	}
12755 
12756 	IORecursiveLockLock(sKextLock);
12757 
12758 	OSKextLog(/* kext */ NULL,
12759 	    kOSKextLogDebugLevel |
12760 	    kOSKextLogGeneralFlag,
12761 	    "Requesting daemon launch for %s %s with serverName %s and tag %llu%s",
12762 	    kextIdentifier->getCStringNoCopy(),
12763 	    (dextUniqueIDCString != NULL)?dextUniqueIDCString:"",
12764 	    serverName->getCStringNoCopy(),
12765 	    serverTag->unsigned64BitValue(),
12766 	    reslide == kOSBooleanTrue ? " with reslid shared cache" : ""
12767 	    );
12768 
12769 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict);
12770 	if (result != kOSReturnSuccess) {
12771 		goto finish;
12772 	}
12773 
12774 	if (!_OSKextSetRequestArgument(requestDict.get(),
12775 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
12776 	    !_OSKextSetRequestArgument(requestDict.get(),
12777 	    kKextRequestArgumentDriverExtensionServerName, serverName) ||
12778 	    !_OSKextSetRequestArgument(requestDict.get(),
12779 	    kKextRequestArgumentDriverExtensionServerTag, serverTag) ||
12780 	    !_OSKextSetRequestArgument(requestDict.get(),
12781 	    kKextRequestArgumentDriverExtensionReslideSharedCache, reslide) ||
12782 	    !_OSKextSetRequestArgument(requestDict.get(),
12783 	    kKextRequestArgumentCheckInToken, checkInToken)) {
12784 		result = kOSKextReturnNoMemory;
12785 		goto finish;
12786 	}
12787 
12788 	if (serverDUI) {
12789 		if (!_OSKextSetRequestArgument(requestDict.get(),
12790 		    kOSBundleDextUniqueIdentifierKey, serverDUI)) {
12791 			result = kOSKextReturnNoMemory;
12792 			goto finish;
12793 		}
12794 	}
12795 
12796 	/* Only post the requests after all the other potential failure points
12797 	 * have been passed.
12798 	 */
12799 	if (!sKernelRequests->setObject(requestDict.get())) {
12800 		result = kOSKextReturnNoMemory;
12801 		goto finish;
12802 	}
12803 	OSKext::pingIOKitDaemon();
12804 
12805 	result = kOSReturnSuccess;
12806 finish:
12807 	IORecursiveLockUnlock(sKextLock);
12808 	if (dextUniqueIDCString) {
12809 		kfree_data(dextUniqueIDCString, size);
12810 	}
12811 	return result;
12812 }
12813 
12814 OSReturn
12815 OSKext::notifyDextUpgrade(
12816 	OSString *kextIdentifier,
12817 	OSData *dextUniqueIdentifier)
12818 {
12819 	OSReturn result = kOSReturnError;
12820 	OSSharedPtr<OSDictionary> requestDict;
12821 	unsigned int size = 0;
12822 	const char *dextUniqueIDCString = getDextUniqueIDCString(dextUniqueIdentifier, &size);
12823 	assert(dextUniqueIDCString != NULL);
12824 
12825 	IORecursiveLockLock(sKextLock);
12826 
12827 	OSKextLog(NULL,
12828 	    kOSKextLogDebugLevel |
12829 	    kOSKextLogGeneralFlag,
12830 	    "Notifying of dext upgrade for %s with UniqueID %s",
12831 	    kextIdentifier->getCStringNoCopy(), dextUniqueIDCString);
12832 
12833 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonUpgradeNotification, requestDict);
12834 	if (result != kOSReturnSuccess) {
12835 		goto finish;
12836 	}
12837 
12838 	if (!_OSKextSetRequestArgument(requestDict.get(),
12839 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
12840 	    !_OSKextSetRequestArgument(requestDict.get(),
12841 	    kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) {
12842 		result = kOSKextReturnNoMemory;
12843 		goto finish;
12844 	}
12845 
12846 	/* Only post the requests after all the other potential failure points
12847 	 * have been passed.
12848 	 */
12849 	if (!sKernelRequests->setObject(requestDict.get())) {
12850 		result = kOSKextReturnNoMemory;
12851 		goto finish;
12852 	}
12853 	OSKext::pingIOKitDaemon();
12854 
12855 	result = kOSReturnSuccess;
12856 finish:
12857 	IORecursiveLockUnlock(sKextLock);
12858 
12859 	if (dextUniqueIDCString != NULL) {
12860 		kfree_data(dextUniqueIDCString, size);
12861 	}
12862 	return result;
12863 }
12864 
12865 /*********************************************************************
12866 * Assumes sKextLock is held.
12867 *********************************************************************/
12868 /* static */
12869 OSReturn
12870 OSKext::dequeueCallbackForRequestTag(
12871 	OSKextRequestTag    requestTag,
12872 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
12873 {
12874 	OSDictionary * callbackRecordOutRaw = NULL;
12875 	OSReturn result;
12876 
12877 	result = dequeueCallbackForRequestTag(requestTag,
12878 	    &callbackRecordOutRaw);
12879 
12880 	if (kOSReturnSuccess == result) {
12881 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
12882 	}
12883 
12884 	return result;
12885 }
12886 OSReturn
12887 OSKext::dequeueCallbackForRequestTag(
12888 	OSKextRequestTag    requestTag,
12889 	OSDictionary     ** callbackRecordOut)
12890 {
12891 	OSReturn   result = kOSReturnError;
12892 	OSSharedPtr<OSNumber> requestTagNum;
12893 
12894 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
12895 	    8 * sizeof(requestTag));
12896 	if (!requestTagNum) {
12897 		goto finish;
12898 	}
12899 
12900 	result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(),
12901 	    callbackRecordOut);
12902 
12903 finish:
12904 	return result;
12905 }
12906 
12907 /*********************************************************************
12908 * Assumes sKextLock is held.
12909 *********************************************************************/
12910 /* static */
12911 OSReturn
12912 OSKext::dequeueCallbackForRequestTag(
12913 	OSNumber     *    requestTagNum,
12914 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
12915 {
12916 	OSDictionary * callbackRecordOutRaw = NULL;
12917 	OSReturn result;
12918 
12919 	result = dequeueCallbackForRequestTag(requestTagNum,
12920 	    &callbackRecordOutRaw);
12921 
12922 	if (kOSReturnSuccess == result) {
12923 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
12924 	}
12925 
12926 	return result;
12927 }
12928 OSReturn
12929 OSKext::dequeueCallbackForRequestTag(
12930 	OSNumber     *    requestTagNum,
12931 	OSDictionary ** callbackRecordOut)
12932 {
12933 	OSReturn        result          = kOSKextReturnInvalidArgument;
12934 	OSDictionary  * callbackRecord  = NULL;        // retain if matched!
12935 	OSNumber      * callbackTagNum  = NULL;        // do not release
12936 	unsigned int    count, i;
12937 
12938 	result = kOSReturnError;
12939 	count = sRequestCallbackRecords->getCount();
12940 	for (i = 0; i < count; i++) {
12941 		callbackRecord = OSDynamicCast(OSDictionary,
12942 		    sRequestCallbackRecords->getObject(i));
12943 		if (!callbackRecord) {
12944 			goto finish;
12945 		}
12946 
12947 		/* If we don't find a tag, we basically have a leak here. Maybe
12948 		 * we should just remove it.
12949 		 */
12950 		callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
12951 			    callbackRecord, kKextRequestArgumentRequestTagKey));
12952 		if (!callbackTagNum) {
12953 			goto finish;
12954 		}
12955 
12956 		/* We could be even more paranoid and check that all the incoming
12957 		 * args match what's in the callback record.
12958 		 */
12959 		if (callbackTagNum->isEqualTo(requestTagNum)) {
12960 			if (callbackRecordOut) {
12961 				*callbackRecordOut = callbackRecord;
12962 				callbackRecord->retain();
12963 			}
12964 			sRequestCallbackRecords->removeObject(i);
12965 			result = kOSReturnSuccess;
12966 			goto finish;
12967 		}
12968 	}
12969 	result = kOSKextReturnNotFound;
12970 
12971 finish:
12972 	return result;
12973 }
12974 
12975 
12976 /*********************************************************************
12977 * Busy timeout triage
12978 *********************************************************************/
12979 /* static */
12980 bool
12981 OSKext::pendingIOKitDaemonRequests(void)
12982 {
12983 	return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
12984 }
12985 
12986 /*********************************************************************
12987 * Acquires and releases sKextLock
12988 *
12989 * This function is designed to be called by kernelmanagerd and driverkitd
12990 * and it gathers all codeless kext and dext personalities, and then attempts
12991 * to map a System (pageable) KC and an Auxiliary (aux) KC.
12992 *
12993 * The pageable and aux KC can be loaded only once at boot time.
12994 * Even if the pageable or aux KC fail to load - this function will
12995 * not allow a new pageable or aux KC to be installed by subsequent calls.
12996 * This is done to avoid security issues where userspace has been compromised
12997 * or the pageable kc has been tampered with and the attacker
12998 * attempts to re-load a malicious variant.
12999 * However dexts can be dynamically loaded, so this function can be used
13000 * to request the installation of a new set of dexts even after boot time.
13001 *
13002 *
13003 *
13004 * Return: if a KC fails to load the return value will contain:
13005 *         kOSKextReturnKCLoadFailure. If the pageable KC fails,
13006 *         the return value will contain kOSKextReturnKCLoadFailureSystemKC.
13007 *         Similarly, if the aux kc load fails, the return value will
13008 *         contain kOSKextReturnKCLoadFailureAuxKC. The two values
13009 *         compose with each other and with kOSKextReturnKCLoadFailure.
13010 *********************************************************************/
13011 /* static */
13012 OSReturn
13013 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused)
13014 {
13015 	static bool daemon_ready = false;
13016 
13017 	OSReturn ret = kOSKextReturnInvalidArgument;
13018 	OSReturn kcerr = 0;
13019 	bool start_matching = false;
13020 
13021 	bool allow_fileset_load = !daemon_ready;
13022 #if !(defined(__x86_64__) || defined(__i386__))
13023 	/* never allow KCs full of kexts on non-x86 machines */
13024 	allow_fileset_load = false;
13025 #endif
13026 
13027 	/*
13028 	 * Change with 70582300
13029 	 */
13030 #if 0 || !defined(VM_MAPPED_KEXTS)
13031 	/*
13032 	 * On platforms that don't support the SystemKC or a file-backed
13033 	 * AuxKC, the kext receipt for 3rd party kexts loaded by the booter
13034 	 * needs to be queried before we load any codeless kexts or release
13035 	 * any 3rd party kexts to run. On platforms that support a file-backed
13036 	 * AuxKC, this process is done via the kext audit mechanism.
13037 	 */
13038 
13039 	printf("KextLog: waiting for kext receipt to be queried.\n");
13040 	while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) {
13041 		IOSleep(30);
13042 	}
13043 #endif /* !VM_MAPPED_KEXTS */
13044 
13045 	/*
13046 	 * Get the args from the request. Right now we need the file
13047 	 * name for the pageable and the aux kext collection file sets.
13048 	 */
13049 	OSDictionary * requestArgs                = NULL;        // do not release
13050 	OSString     * pageable_filepath          = NULL;        // do not release
13051 	OSString     * aux_filepath               = NULL;        // do not release
13052 	OSArray      * codeless_kexts             = NULL;        // do not release
13053 
13054 	kernel_mach_header_t *akc_mh              = NULL;
13055 
13056 	requestArgs = OSDynamicCast(OSDictionary,
13057 	    requestDict->getObject(kKextRequestArgumentsKey));
13058 
13059 	if (requestArgs == NULL) {
13060 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13061 		    "KextLog: No arguments in plist for loading fileset kext\n");
13062 		printf("KextLog: No arguments in plist for loading fileset kext\n");
13063 		return ret;
13064 	}
13065 
13066 	ret = kOSKextReturnDisabled;
13067 
13068 	IORecursiveLockLock(sKextLock);
13069 
13070 	if (!sLoadEnabled) {
13071 		OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13072 		    "KextLog: Kext loading is disabled (attempt to load KCs).");
13073 		IORecursiveLockUnlock(sKextLock);
13074 		return ret;
13075 	}
13076 
13077 	pageable_filepath = OSDynamicCast(OSString,
13078 	    requestArgs->getObject(kKextRequestArgumentPageableKCFilename));
13079 
13080 	if (allow_fileset_load && pageable_filepath != NULL) {
13081 		printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy());
13082 
13083 		ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable);
13084 		if (ret) {
13085 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13086 			    "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
13087 
13088 			printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
13089 			ret = kOSKextReturnKCLoadFailure;
13090 			kcerr |= kOSKextReturnKCLoadFailureSystemKC;
13091 			goto try_auxkc;
13092 		}
13093 		/*
13094 		 * Even if the AuxKC fails to load, we still want to send
13095 		 * the System KC personalities to the catalog for matching
13096 		 */
13097 		start_matching = true;
13098 	} else if (pageable_filepath != NULL) {
13099 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13100 		    "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy());
13101 		ret = kOSKextReturnUnsupported;
13102 	}
13103 
13104 try_auxkc:
13105 	akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
13106 	if (akc_mh) {
13107 		/*
13108 		 * If we try to load a deferred AuxKC, then don't ever attempt
13109 		 * a filesystem map of a file
13110 		 */
13111 		allow_fileset_load = false;
13112 
13113 		/*
13114 		 * This function is only called once per boot, so we haven't
13115 		 * yet loaded an AuxKC. If we have registered the AuxKC mach
13116 		 * header, that means that the kext collection has been placed
13117 		 * in memory for us by the booter, and is waiting for us to
13118 		 * process it.  Grab the deferred XML plist of info
13119 		 * dictionaries and add all the kexts.
13120 		 */
13121 		OSSharedPtr<OSObject>  parsedXML;
13122 		OSSharedPtr<OSData>    loaded_kcUUID;
13123 		OSDictionary          *infoDict;
13124 		parsedXML = consumeDeferredKextCollection(KCKindAuxiliary);
13125 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
13126 #if !defined(VM_MAPPED_KEXTS)
13127 		/*
13128 		 * On platforms where we don't dynamically wire-down / page-in
13129 		 * kext memory, we need to maintain the invariant that if the
13130 		 * AuxKC in memory does not contain a kext receipt, then we
13131 		 * should not load any of the kexts.
13132 		 */
13133 		size_t receipt_sz = 0;
13134 		if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) {
13135 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13136 			    "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt");
13137 			ret = kOSKextReturnKCLoadFailure;
13138 			goto try_codeless;
13139 		}
13140 #endif
13141 		if (infoDict) {
13142 			bool added;
13143 			printf("KextLog: Adding kexts from in-memory AuxKC\n");
13144 			added = OSKext::addKextsFromKextCollection(akc_mh, infoDict,
13145 			    kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary);
13146 			if (!loaded_kcUUID) {
13147 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13148 				    "KextLog: WARNING: did not find UUID in deferred Aux KC!");
13149 			} else if (!added) {
13150 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13151 				    "KextLog: WARNING: Failed to load AuxKC from memory.");
13152 			}
13153 			/* only return success if the pageable load (above) was successful */
13154 			if (ret != kOSKextReturnKCLoadFailure) {
13155 				ret = kOSReturnSuccess;
13156 			}
13157 			/* the registration of the AuxKC parsed out the KC's UUID already */
13158 		} else {
13159 			if (daemon_ready) {
13160 				/*
13161 				 * Complain, but don't return an error if this isn't the first time the
13162 				 * IOKit daemon is checking in. If the daemon ever restarts, we will
13163 				 * hit this case because we've already consumed the deferred personalities.
13164 				 * We return success here so that a call to this function from a restarted
13165 				 * daemon with no codeless kexts will succeed.
13166 				 */
13167 				OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13168 				    "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart");
13169 				if (ret != kOSKextReturnKCLoadFailure) {
13170 					ret = kOSReturnSuccess;
13171 				}
13172 			} else {
13173 				/* this is a real error case */
13174 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13175 				    "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary");
13176 				printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n");
13177 				ret = kOSKextReturnKCLoadFailure;
13178 				kcerr |= kOSKextReturnKCLoadFailureAuxKC;
13179 			}
13180 		}
13181 	}
13182 
13183 	aux_filepath = OSDynamicCast(OSString,
13184 	    requestArgs->getObject(kKextRequestArgumentAuxKCFilename));
13185 	if (allow_fileset_load && aux_filepath != NULL) {
13186 		printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy());
13187 
13188 		ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary);
13189 		if (ret) {
13190 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13191 			    "KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
13192 
13193 			printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
13194 			ret = kOSKextReturnKCLoadFailure;
13195 			kcerr |= kOSKextReturnKCLoadFailureAuxKC;
13196 			goto try_codeless;
13197 		}
13198 		start_matching = true;
13199 	} else if (aux_filepath != NULL) {
13200 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13201 		    "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy());
13202 		if (ret != kOSKextReturnKCLoadFailure) {
13203 			ret = kOSKextReturnUnsupported;
13204 		}
13205 	}
13206 
13207 try_codeless:
13208 	/*
13209 	 * Load codeless kexts last so that there is no possibilty of a
13210 	 * codeless kext bundle ID preventing a kext in the system KC from
13211 	 * loading
13212 	 */
13213 	codeless_kexts = OSDynamicCast(OSArray,
13214 	    requestArgs->getObject(kKextRequestArgumentCodelessPersonalities));
13215 	if (codeless_kexts != NULL) {
13216 		uint32_t count = codeless_kexts->getCount();
13217 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13218 		    "KextLog: loading %d codeless kexts/dexts", count);
13219 		for (uint32_t i = 0; i < count; i++) {
13220 			OSDictionary *infoDict;
13221 			infoDict = OSDynamicCast(OSDictionary,
13222 			    codeless_kexts->getObject(i));
13223 			if (!infoDict) {
13224 				continue;
13225 			}
13226 			// instantiate a new kext, and don't hold a reference
13227 			// (the kext subsystem will hold one implicitly)
13228 			OSKext::withCodelessInfo(infoDict, NULL);
13229 		}
13230 		/* ignore errors that are not KC load failures */
13231 		if (ret != kOSKextReturnKCLoadFailure) {
13232 			ret = kOSReturnSuccess;
13233 		}
13234 		start_matching = true;
13235 	}
13236 
13237 	/* send personalities to the IOCatalog once */
13238 	if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) {
13239 		OSKext::sendAllKextPersonalitiesToCatalog(true);
13240 		/*
13241 		 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark
13242 		 * things as active and start all the delayed matching: the
13243 		 * dext and codeless kext personalities should have all been
13244 		 * delivered via this one call.
13245 		 */
13246 		if (!daemon_ready) {
13247 			OSKext::setIOKitDaemonActive();
13248 			OSKext::setDeferredLoadSucceeded(TRUE);
13249 			IOService::iokitDaemonLaunched();
13250 		}
13251 		if (sOSKextWasResetAfterUserspaceReboot) {
13252 			sOSKextWasResetAfterUserspaceReboot = false;
13253 			OSKext::setIOKitDaemonActive();
13254 			IOService::startDeferredMatches();
13255 		}
13256 	}
13257 
13258 	if (ret == kOSKextReturnKCLoadFailure) {
13259 		ret |= kcerr;
13260 	}
13261 
13262 	/*
13263 	 * Only allow this function to attempt to load the pageable and
13264 	 * aux KCs once per boot.
13265 	 */
13266 	daemon_ready = true;
13267 
13268 	IORecursiveLockUnlock(sKextLock);
13269 
13270 	return ret;
13271 }
13272 
13273 OSReturn
13274 OSKext::resetMutableSegments(void)
13275 {
13276 	kernel_segment_command_t *seg = NULL;
13277 	kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
13278 	u_int index = 0;
13279 	OSKextSavedMutableSegment *savedSegment = NULL;
13280 	uintptr_t kext_slide = PE_get_kc_slide(kc_type);
13281 	OSReturn err;
13282 
13283 	if (!savedMutableSegments) {
13284 		OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
13285 		    "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString());
13286 		err = kOSKextReturnInternalError;
13287 		goto finish;
13288 	}
13289 
13290 	for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) {
13291 		if (!segmentIsMutable(seg)) {
13292 			continue;
13293 		}
13294 		uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
13295 		uint64_t vmsize = seg->vmsize;
13296 		err = kOSKextReturnInternalError;
13297 		for (index = 0; index < savedMutableSegments->getCount(); index++) {
13298 			savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index));
13299 			assert(savedSegment);
13300 			if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) {
13301 				OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
13302 				    "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13303 				err = savedSegment->restoreContents(seg);
13304 				if (err != kOSReturnSuccess) {
13305 					panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13306 				}
13307 			}
13308 		}
13309 		if (err != kOSReturnSuccess) {
13310 			panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13311 		}
13312 	}
13313 	err = kOSReturnSuccess;
13314 finish:
13315 	return err;
13316 }
13317 
13318 
13319 /*********************************************************************
13320 * Assumes sKextLock is held.
13321 *********************************************************************/
13322 /* static */
13323 OSReturn
13324 OSKext::loadKCFileSet(
13325 	const char *filepath,
13326 	kc_kind_t   type)
13327 {
13328 #if VM_MAPPED_KEXTS
13329 	/* we only need to load filesets on systems that support VM_MAPPED kexts */
13330 	OSReturn err;
13331 	struct vnode *vp = NULL;
13332 	void *fileset_control;
13333 	off_t fsize;
13334 	bool pageable = (type == KCKindPageable);
13335 
13336 	if ((pageable && pageableKCloaded) ||
13337 	    (!pageable && auxKCloaded)) {
13338 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13339 		    "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux"));
13340 
13341 		return kOSKextReturnInvalidArgument;
13342 	}
13343 
13344 	/* Do not allow AuxKC to load if Pageable KC is not loaded */
13345 	if (!pageable && !pageableKCloaded) {
13346 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13347 		    "Trying to load the Aux KC without loading the Pageable KC");
13348 		return kOSKextReturnInvalidArgument;
13349 	}
13350 
13351 	fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize);
13352 
13353 	if (fileset_control == NULL) {
13354 		printf("Could not get memory control object for file %s", filepath);
13355 
13356 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13357 		    "Could not get memory control object for file %s", filepath);
13358 		return kOSKextReturnInvalidArgument;
13359 	}
13360 	if (vp == NULL) {
13361 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13362 		    "Could not find vnode for file %s", filepath);
13363 		return kOSKextReturnInvalidArgument;
13364 	}
13365 
13366 	kernel_mach_header_t *mh = NULL;
13367 	uintptr_t slide = 0;
13368 
13369 #if CONFIG_CSR
13370 	/*
13371 	 * When SIP is enabled, the KC we map must be SIP-protected
13372 	 */
13373 	if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) {
13374 		struct vnode_attr va;
13375 		int error;
13376 		VATTR_INIT(&va);
13377 		VATTR_WANTED(&va, va_flags);
13378 		error = vnode_getattr(vp, &va, vfs_context_current());
13379 		if (error) {
13380 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13381 			    "vnode_getattr(%s) failed (error=%d)", filepath, error);
13382 			err = kOSKextReturnInternalError;
13383 			goto finish;
13384 		}
13385 		if (!(va.va_flags & SF_RESTRICTED)) {
13386 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13387 			    "Path to KC '%s' is not SIP-protected", filepath);
13388 			err = kOSKextReturnInvalidArgument;
13389 			goto finish;
13390 		}
13391 	}
13392 #endif
13393 
13394 	err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL);
13395 	if (err) {
13396 		printf("KextLog: mapKCFileSet returned %d\n", err);
13397 
13398 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13399 		    "mapKCFileSet returned %d\n", err);
13400 
13401 		err = kOSKextReturnInvalidArgument;
13402 	}
13403 
13404 #if CONFIG_CSR
13405 finish:
13406 #endif
13407 	/* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */
13408 	assert(vp != NULL);
13409 	if (err == kOSReturnSuccess) {
13410 		PE_set_kc_vp(type, vp);
13411 		if (pageable) {
13412 			pageableKCloaded = true;
13413 		} else {
13414 			auxKCloaded = true;
13415 		}
13416 	} else {
13417 		vnode_put(vp);
13418 	}
13419 
13420 	return err;
13421 #else
13422 	(void)filepath;
13423 	(void)type;
13424 	return kOSKextReturnUnsupported;
13425 #endif // VM_MAPPED_KEXTS
13426 }
13427 
13428 #if defined(__x86_64__) || defined(__i386__)
13429 /*********************************************************************
13430 * Assumes sKextLock is held.
13431 *********************************************************************/
13432 /* static */
13433 OSReturn
13434 OSKext::mapKCFileSet(
13435 	void                 *control,
13436 	vm_size_t            fsize,
13437 	kernel_mach_header_t **mhp,
13438 	off_t                file_offset,
13439 	uintptr_t            *slidep,
13440 	bool                 pageable,
13441 	void                 *map_entry_list)
13442 {
13443 	bool fileset_load = false;
13444 	kern_return_t ret;
13445 	OSReturn err;
13446 	kernel_section_t *infoPlistSection = NULL;
13447 	OSDictionary *infoDict = NULL;
13448 
13449 	OSSharedPtr<OSObject> parsedXML;
13450 	OSSharedPtr<OSString> errorString;
13451 	OSSharedPtr<OSData> loaded_kcUUID;
13452 
13453 	/* Check if initial load for file set */
13454 	if (*mhp == NULL) {
13455 		fileset_load = true;
13456 
13457 		/* Get a page aligned address from kext map to map the file */
13458 		vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize);
13459 		if (pagealigned_addr == 0) {
13460 			return kOSKextReturnNoMemory;
13461 		}
13462 
13463 		*mhp = (kernel_mach_header_t *)pagealigned_addr;
13464 
13465 		/* Allocate memory for bailout mechanism */
13466 		map_entry_list = allocate_kcfileset_map_entry_list();
13467 		if (map_entry_list == NULL) {
13468 			return kOSKextReturnNoMemory;
13469 		}
13470 	}
13471 
13472 	uintptr_t *slideptr = fileset_load ? slidep : NULL;
13473 	err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list);
13474 	/* mhp and slideptr are updated by mapKCTextSegment */
13475 	if (err) {
13476 		if (fileset_load) {
13477 			deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13478 		}
13479 		return err;
13480 	}
13481 
13482 	/* Initialize the kc header globals */
13483 	if (fileset_load) {
13484 		if (pageable) {
13485 			PE_set_kc_header(KCKindPageable, *mhp, *slidep);
13486 		} else {
13487 			PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep);
13488 		}
13489 	}
13490 
13491 	/* Iterate through all the segments and map necessary segments */
13492 	struct load_command *lcp = (struct load_command *) (*mhp + 1);
13493 	for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) {
13494 		vm_map_offset_t start;
13495 		kernel_mach_header_t *k_mh = NULL;
13496 		kernel_segment_command_t * seg = NULL;
13497 		struct fileset_entry_command *fse = NULL;
13498 
13499 		if (lcp->cmd == LC_SEGMENT_KERNEL) {
13500 			seg = (kernel_segment_command_t *)lcp;
13501 			start = ((uintptr_t)(seg->vmaddr)) + *slidep;
13502 		} else if (lcp->cmd == LC_FILESET_ENTRY) {
13503 			fse = (struct fileset_entry_command *)lcp;
13504 			k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep);
13505 
13506 			/* Map the segments of the mach-o binary */
13507 			err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list);
13508 			if (err) {
13509 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13510 				return kOSKextReturnInvalidArgument;
13511 			}
13512 			continue;
13513 		} else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) {
13514 			/* Check if the Aux KC is built pageable style */
13515 			if (!pageable && !fileset_load && !auxKCloaded) {
13516 				resetAuxKCSegmentOnUnload = true;
13517 			}
13518 			continue;
13519 		} else {
13520 			continue;
13521 		}
13522 
13523 		if (fileset_load) {
13524 			if (seg->vmsize == 0) {
13525 				continue;
13526 			}
13527 
13528 			/* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */
13529 			if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 &&
13530 			    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 &&
13531 			    strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 &&
13532 			    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) {
13533 				continue;
13534 			}
13535 		} else {
13536 			if (seg->vmsize == 0) {
13537 				continue;
13538 			}
13539 
13540 			/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
13541 			if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
13542 			    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
13543 			    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
13544 				continue;
13545 			}
13546 		}
13547 
13548 		ret = vm_map_kcfileset_segment(
13549 			&start, seg->vmsize,
13550 			(memory_object_control_t)control, seg->fileoff, seg->maxprot);
13551 
13552 		if (ret != KERN_SUCCESS) {
13553 			if (fileset_load) {
13554 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13555 			}
13556 			return kOSKextReturnInvalidArgument;
13557 		}
13558 		add_kcfileset_map_entry(map_entry_list, start, seg->vmsize);
13559 	}
13560 
13561 	/* Return if regular mach-o */
13562 	if (!fileset_load) {
13563 		return 0;
13564 	}
13565 
13566 	/*
13567 	 * Fixup for the Pageable KC and the Aux KC is done by
13568 	 * i386_slide_kext_collection_mh_addrs, but it differs in
13569 	 * following ways:
13570 	 *
13571 	 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands.
13572 	 * The fixup of kext segments and kext load commands are done at kext
13573 	 * load time by calling i386_slide_individual_kext.
13574 	 *
13575 	 * AuxKC old style: Fixup all the segments and all the load commands.
13576 	 *
13577 	 * AuxKC pageable style: Same as the Pageable KC.
13578 	 */
13579 	bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false));
13580 	ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header);
13581 	if (ret != KERN_SUCCESS) {
13582 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13583 		return kOSKextReturnInvalidArgument;
13584 	}
13585 
13586 	/* Get the prelink info dictionary */
13587 	infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection);
13588 	parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
13589 	if (parsedXML) {
13590 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
13591 	}
13592 
13593 	if (!infoDict) {
13594 		const char *errorCString = "(unknown error)";
13595 
13596 		if (errorString && errorString->getCStringNoCopy()) {
13597 			errorCString = errorString->getCStringNoCopy();
13598 		} else if (parsedXML) {
13599 			errorCString = "not a dictionary";
13600 		}
13601 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13602 		    "Error unserializing kext info plist section: %s.", errorCString);
13603 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13604 		return kOSKextReturnInvalidArgument;
13605 	}
13606 
13607 	/* Validate that the Kext Collection is prelinked to the loaded KC */
13608 	err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary);
13609 	if (err) {
13610 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13611 		return kOSKextReturnInvalidArgument;
13612 	}
13613 
13614 	/* Set Protection of Segments */
13615 	OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary);
13616 
13617 	OSKext::addKextsFromKextCollection(*mhp,
13618 	    infoDict, kPrelinkTextSegment,
13619 	    loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary);
13620 
13621 	/* Copy in the KC UUID */
13622 	if (!loaded_kcUUID) {
13623 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13624 		    "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux");
13625 	} else if (pageable) {
13626 		pageablekc_uuid_valid = TRUE;
13627 		memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
13628 		uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string);
13629 	} else {
13630 		auxkc_uuid_valid = TRUE;
13631 		memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
13632 		uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
13633 	}
13634 
13635 	deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable);
13636 
13637 	return 0;
13638 }
13639 
13640 /*********************************************************************
13641 * Assumes sKextLock is held.
13642 *********************************************************************/
13643 /* static */
13644 OSReturn
13645 OSKext::mapKCTextSegment(
13646 	void                 *control,
13647 	kernel_mach_header_t **mhp,
13648 	off_t                file_offset,
13649 	uintptr_t            *slidep,
13650 	void                 *map_entry_list)
13651 {
13652 	kern_return_t ret;
13653 	vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t),
13654 	    PAGE_MASK);
13655 	vm_map_offset_t load_command_map_size = 0;
13656 	kernel_mach_header_t *base_mh = *mhp;
13657 
13658 	/* Map the mach header at start of fileset for now (vmaddr = 0) */
13659 	ret = vm_map_kcfileset_segment(
13660 		(vm_map_offset_t *)&base_mh, mach_header_map_size,
13661 		(memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE));
13662 
13663 	if (ret != KERN_SUCCESS) {
13664 		printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret);
13665 
13666 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13667 		    "Failed to map mach header of kc fileset with error %d", ret);
13668 		return kOSKextReturnInvalidArgument;
13669 	}
13670 
13671 	if (slidep) {
13672 		/* Verify that it's an MH_FILESET */
13673 		if (base_mh->filetype != MH_FILESET) {
13674 			printf("Kext Log: mapKCTextSegment mach header filetype"
13675 			    " is not an MH_FILESET, it is %x", base_mh->filetype);
13676 
13677 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13678 			    "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype);
13679 
13680 			/* Unmap the mach header */
13681 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13682 			return kOSKextReturnInvalidArgument;
13683 		}
13684 	}
13685 
13686 	/* Map the remaining pages of load commands */
13687 	if (base_mh->sizeofcmds > mach_header_map_size) {
13688 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
13689 		load_command_map_size = base_mh->sizeofcmds - mach_header_map_size;
13690 
13691 		/* Map the load commands */
13692 		ret = vm_map_kcfileset_segment(
13693 			&load_command_addr, load_command_map_size,
13694 			(memory_object_control_t)control, file_offset + mach_header_map_size,
13695 			(VM_PROT_READ | VM_PROT_WRITE));
13696 
13697 		if (ret != KERN_SUCCESS) {
13698 			printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret);
13699 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13700 			    "Failed to map load commands of kc fileset with error %d", ret);
13701 
13702 			/* Unmap the mach header */
13703 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13704 			return kOSKextReturnInvalidArgument;
13705 		}
13706 	}
13707 
13708 	kernel_segment_command_t *text_seg;
13709 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT);
13710 
13711 	/* Calculate the slide and vm addr of mach header */
13712 	if (slidep) {
13713 		*mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr);
13714 		*slidep = ((uintptr_t)*mhp) - text_seg->vmaddr;
13715 	}
13716 
13717 	/* Cache the text segment size and file offset before unmapping */
13718 	vm_map_offset_t text_segment_size = text_seg->vmsize;
13719 	vm_object_offset_t text_segment_fileoff = text_seg->fileoff;
13720 	vm_prot_t text_maxprot = text_seg->maxprot;
13721 
13722 	/* Unmap the first page and loadcommands and map the text segment */
13723 	ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13724 	assert(ret == KERN_SUCCESS);
13725 
13726 	if (load_command_map_size) {
13727 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
13728 		ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size);
13729 		assert(ret == KERN_SUCCESS);
13730 	}
13731 
13732 	/* Map the text segment at actual vm addr specified in fileset */
13733 	ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size,
13734 	    (memory_object_control_t)control, text_segment_fileoff, text_maxprot);
13735 	if (ret != KERN_SUCCESS) {
13736 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13737 		    "Failed to map Text segment of kc fileset with error %d", ret);
13738 		return kOSKextReturnInvalidArgument;
13739 	}
13740 
13741 	add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size);
13742 	return 0;
13743 }
13744 
13745 /*********************************************************************
13746 * Assumes sKextLock is held.
13747 *********************************************************************/
13748 /* static */
13749 OSReturn
13750 OSKext::protectKCFileSet(
13751 	kernel_mach_header_t *mh,
13752 	kc_kind_t            type)
13753 {
13754 	vm_map_t                    kext_map        = g_kext_map;
13755 	kernel_segment_command_t  * seg             = NULL;
13756 	vm_map_offset_t             start           = 0;
13757 	vm_map_offset_t             end             = 0;
13758 	OSReturn                    ret             = 0;
13759 
13760 	/* Set VM permissions */
13761 	seg = firstsegfromheader((kernel_mach_header_t *)mh);
13762 	while (seg) {
13763 		start = round_page(seg->vmaddr);
13764 		end = trunc_page(seg->vmaddr + seg->vmsize);
13765 
13766 		/*
13767 		 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS
13768 		 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT
13769 		 * for the Aux KC as well.
13770 		 */
13771 		if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 ||
13772 		    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 ||
13773 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 ||
13774 		    (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload &&
13775 		    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) {
13776 			ret = OSKext_protect((kernel_mach_header_t *)mh,
13777 			    kext_map, start, end, seg->maxprot, TRUE, type);
13778 			if (ret != KERN_SUCCESS) {
13779 				printf("OSKext protect failed with error %d", ret);
13780 				return kOSKextReturnInvalidArgument;
13781 			}
13782 
13783 			ret = OSKext_protect((kernel_mach_header_t *)mh,
13784 			    kext_map, start, end, seg->initprot, FALSE, type);
13785 			if (ret != KERN_SUCCESS) {
13786 				printf("OSKext protect failed with error %d", ret);
13787 				return kOSKextReturnInvalidArgument;
13788 			}
13789 
13790 			ret = OSKext_wire((kernel_mach_header_t *)mh,
13791 			    kext_map, start, end, seg->initprot, FALSE, type);
13792 			if (ret != KERN_SUCCESS) {
13793 				printf("OSKext wire failed with error %d", ret);
13794 				return kOSKextReturnInvalidArgument;
13795 			}
13796 		}
13797 
13798 		seg = nextsegfromheader((kernel_mach_header_t *) mh, seg);
13799 	}
13800 
13801 	return 0;
13802 }
13803 
13804 /*********************************************************************
13805 * Assumes sKextLock is held.
13806 *********************************************************************/
13807 /* static */
13808 void
13809 OSKext::freeKCFileSetcontrol(void)
13810 {
13811 	PE_reset_all_kc_vp();
13812 }
13813 
13814 /*********************************************************************
13815 * Assumes sKextLock is held.
13816 *
13817 * resetKCFileSetSegments: Kext start function expects data segment to
13818 * be pristine on every load, unmap the dirty segments on unload and
13819 * remap them from FileSet on disk. Remap all segments of kext since
13820 * fixups are done per kext and not per segment.
13821 *********************************************************************/
13822 OSReturn
13823 OSKext::resetKCFileSetSegments(void)
13824 {
13825 	kernel_segment_command_t *seg = NULL;
13826 	kernel_segment_command_t *text_seg;
13827 	uint32_t text_fileoff;
13828 	kernel_mach_header_t *k_mh = NULL;
13829 	uintptr_t slide;
13830 	struct vnode *vp = NULL;
13831 	void *fileset_control = NULL;
13832 	bool pageable = (kc_type == KCKindPageable);
13833 	OSReturn err;
13834 	kern_return_t kr;
13835 
13836 	/* Check the vnode reference is still available */
13837 	vp = (struct vnode *)PE_get_kc_vp(kc_type);
13838 	if (vp == NULL) {
13839 		OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
13840 		    "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString());
13841 		return kOSKextReturnInternalError;
13842 	}
13843 
13844 	fileset_control = ubc_getobject(vp, 0);
13845 	assert(fileset_control != NULL);
13846 
13847 	OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
13848 	    "Kext %s resetting all segments", getIdentifierCString());
13849 
13850 	k_mh = (kernel_mach_header_t *)kmod_info->address;
13851 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT);
13852 	text_fileoff = text_seg->fileoff;
13853 	slide = PE_get_kc_slide(kc_type);
13854 
13855 	seg = firstsegfromheader((kernel_mach_header_t *)k_mh);
13856 	while (seg) {
13857 		if (seg->vmsize == 0) {
13858 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
13859 			continue;
13860 		}
13861 
13862 		/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
13863 		if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
13864 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
13865 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
13866 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
13867 			continue;
13868 		}
13869 
13870 		kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize);
13871 		assert(kr == KERN_SUCCESS);
13872 		seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
13873 	}
13874 
13875 	/* Unmap the text segment */
13876 	kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize);
13877 	assert(kr == KERN_SUCCESS);
13878 
13879 	/* Map all the segments of the kext */
13880 	err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL);
13881 	if (err) {
13882 		panic("Could not reset segments of a mapped kext, error %x", err);
13883 	}
13884 
13885 	/* Update address in kmod_info, since it has been reset */
13886 	if (kmod_info->address) {
13887 		kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide);
13888 	}
13889 
13890 	return 0;
13891 }
13892 
13893 /*********************************************************************
13894 * Mechanism to track all segment mapping while mapping KC fileset.
13895 *********************************************************************/
13896 
13897 struct kcfileset_map_entry {
13898 	vm_map_offset_t me_start;
13899 	vm_map_offset_t me_size;
13900 };
13901 
13902 struct kcfileset_map_entry_list {
13903 	int                        kme_list_count;
13904 	int                        kme_list_index;
13905 	struct kcfileset_map_entry kme_list[];
13906 };
13907 
13908 #define KCFILESET_MAP_ENTRY_MAX (16380)
13909 
13910 static void *
13911 allocate_kcfileset_map_entry_list(void)
13912 {
13913 	struct kcfileset_map_entry_list *entry_list;
13914 
13915 	entry_list = kalloc_type(struct kcfileset_map_entry_list,
13916 	    struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO);
13917 
13918 	entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX;
13919 	entry_list->kme_list_index = 0;
13920 	return entry_list;
13921 }
13922 
13923 static void
13924 add_kcfileset_map_entry(
13925 	void            *map_entry_list,
13926 	vm_map_offset_t start,
13927 	vm_map_offset_t size)
13928 {
13929 	if (map_entry_list == NULL) {
13930 		return;
13931 	}
13932 
13933 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
13934 
13935 	if (entry_list->kme_list_index >= entry_list->kme_list_count) {
13936 		panic("Ran out of map kc fileset list");
13937 	}
13938 
13939 	entry_list->kme_list[entry_list->kme_list_index].me_start = start;
13940 	entry_list->kme_list[entry_list->kme_list_index].me_size = size;
13941 
13942 	entry_list->kme_list_index++;
13943 }
13944 
13945 static void
13946 deallocate_kcfileset_map_entry_list_and_unmap_entries(
13947 	void      *map_entry_list,
13948 	boolean_t unmap_entries,
13949 	bool      pageable)
13950 {
13951 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
13952 
13953 	if (unmap_entries) {
13954 		for (int i = 0; i < entry_list->kme_list_index; i++) {
13955 			kern_return_t ret;
13956 			ret = vm_unmap_kcfileset_segment(
13957 				&(entry_list->kme_list[i].me_start),
13958 				entry_list->kme_list[i].me_size);
13959 			assert(ret == KERN_SUCCESS);
13960 		}
13961 
13962 		PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary);
13963 	}
13964 
13965 	kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry,
13966 	    KCFILESET_MAP_ENTRY_MAX, entry_list);
13967 }
13968 
13969 /*********************************************************************
13970 * Mechanism to map kext segment.
13971 *********************************************************************/
13972 
13973 kern_return_t
13974 vm_map_kcfileset_segment(
13975 	vm_map_offset_t    *start,
13976 	vm_map_offset_t    size,
13977 	void               *control,
13978 	vm_object_offset_t fileoffset,
13979 	vm_prot_t          max_prot)
13980 {
13981 	vm_map_kernel_flags_t vmk_flags = {
13982 		.vmf_fixed = true,
13983 		.vmkf_no_copy_on_read = true,
13984 		.vmkf_cs_enforcement_override = true,
13985 		.vm_tag = VM_KERN_MEMORY_OSKEXT,
13986 	};
13987 	kern_return_t ret;
13988 
13989 	/* Add Write to max prot to allow fixups */
13990 	max_prot = max_prot | VM_PROT_WRITE;
13991 
13992 	/*
13993 	 * Map the segments from file as COPY mappings to
13994 	 * make sure changes on disk to the file does not affect
13995 	 * mapped segments.
13996 	 */
13997 	ret = vm_map_enter_mem_object_control(
13998 		g_kext_map,
13999 		start,
14000 		size,
14001 		(mach_vm_offset_t)0,
14002 		vmk_flags,
14003 		(memory_object_control_t)control,
14004 		fileoffset,
14005 		TRUE,         /* copy */
14006 		(VM_PROT_READ | VM_PROT_WRITE), max_prot,
14007 		VM_INHERIT_NONE);
14008 
14009 	return ret;
14010 }
14011 
14012 kern_return_t
14013 vm_unmap_kcfileset_segment(
14014 	vm_map_offset_t    *start,
14015 	vm_map_offset_t    size)
14016 {
14017 	return mach_vm_deallocate(g_kext_map, *start, size);
14018 }
14019 
14020 #endif //(__x86_64__) || defined(__i386__)
14021 
14022 /*********************************************************************
14023 * Assumes sKextLock is held.
14024 *********************************************************************/
14025 /* static */
14026 OSReturn
14027 OSKext::validateKCFileSetUUID(
14028 	OSDictionary         *infoDict,
14029 	kc_kind_t            type)
14030 {
14031 	OSReturn ret           = kOSReturnSuccess;
14032 
14033 	if (!kernelcache_uuid_valid) {
14034 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14035 		    "validateKCFileSetUUID Boot KC UUID was not set at boot.");
14036 		ret = kOSKextReturnInvalidArgument;
14037 		goto finish;
14038 	}
14039 	ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey);
14040 	if (ret != 0) {
14041 		goto finish;
14042 	}
14043 
14044 #if defined(__x86_64__) || defined(__i386__)
14045 	/* Check if the Aux KC is prelinked to correct Pageable KC */
14046 	if (type == KCKindAuxiliary) {
14047 		if (!pageablekc_uuid_valid) {
14048 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14049 			    "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC.");
14050 			ret = kOSKextReturnInvalidArgument;
14051 			goto finish;
14052 		}
14053 		ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey);
14054 		if (ret != 0) {
14055 			goto finish;
14056 		}
14057 	}
14058 #endif //(__x86_64__) || defined(__i386__)
14059 
14060 	printf("KextLog: Collection UUID matches with loaded KCs.\n");
14061 finish:
14062 	return ret;
14063 }
14064 
14065 /*********************************************************************
14066 * Assumes sKextLock is held.
14067 *********************************************************************/
14068 /* static */
14069 OSReturn
14070 OSKext::validateKCUUIDfromPrelinkInfo(
14071 	uuid_t               *loaded_kcuuid,
14072 	kc_kind_t             type,
14073 	OSDictionary         *infoDict,
14074 	const char           *uuid_key)
14075 {
14076 	/* extract the UUID from the dictionary */
14077 	OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key));
14078 	if (!prelinkinfoKCUUID) {
14079 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14080 		    "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key);
14081 		return kOSKextReturnInvalidArgument;
14082 	}
14083 
14084 	if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) {
14085 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14086 		    "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength());
14087 		return kOSKextReturnInvalidArgument;
14088 	}
14089 
14090 	if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(),
14091 	    prelinkinfoKCUUID->getLength())) {
14092 		OSData       *info_dict_uuid;
14093 		uuid_string_t info_dict_uuid_str = {};
14094 		uuid_string_t expected_uuid_str = {};
14095 		uuid_string_t given_uuid_str = {};
14096 		uuid_t        given_uuid;
14097 
14098 		/* extract the KC UUID from the dictionary */
14099 		info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
14100 		if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) {
14101 			uuid_t tmp_uuid;
14102 			memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid));
14103 			uuid_unparse(tmp_uuid, info_dict_uuid_str);
14104 		}
14105 
14106 		uuid_unparse(*loaded_kcuuid, expected_uuid_str);
14107 		memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid));
14108 		uuid_unparse(given_uuid, given_uuid_str);
14109 
14110 		printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
14111 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
14112 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14113 		    "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
14114 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
14115 		if (type == KCKindPageable && sPanicOnKCMismatch) {
14116 			panic("System KC UUID %s linked against %s, but %s is loaded",
14117 			    info_dict_uuid_str, given_uuid_str, expected_uuid_str);
14118 		}
14119 		return kOSKextReturnInvalidArgument;
14120 	}
14121 
14122 	return 0;
14123 }
14124 
14125 /*********************************************************************
14126 * Assumes sKextLock is held.
14127 *********************************************************************/
14128 /* static */
14129 OSReturn
14130 OSKext::dispatchResource(OSDictionary * requestDict)
14131 {
14132 	OSReturn                        result          = kOSReturnError;
14133 	OSSharedPtr<OSDictionary>       callbackRecord;
14134 	OSNumber                      * requestTag      = NULL;        // do not release
14135 	OSNumber                      * requestResult   = NULL;        // do not release
14136 	OSData                        * dataObj         = NULL;        // do not release
14137 	uint32_t                        dataLength      = 0;
14138 	const void                    * dataPtr         = NULL;        // do not free
14139 	OSValueObject<OSKextRequestResourceCallback> * callbackWrapper = nullptr; // do not release
14140 	OSKextRequestResourceCallback   callback        = NULL;
14141 	OSValueObject<void *>         * contextWrapper  = nullptr;     // do not release
14142 	void                          * context         = NULL;        // do not free
14143 	OSSharedPtr<OSKext>             callbackKext;
14144 
14145 	/* Get the args from the request. Right now we need the tag
14146 	 * to look up the callback record, and the result for invoking the callback.
14147 	 */
14148 	requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
14149 	    kKextRequestArgumentRequestTagKey));
14150 	requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
14151 	    kKextRequestArgumentResultKey));
14152 	if (!requestTag || !requestResult) {
14153 		result = kOSKextReturnInvalidArgument;
14154 		goto finish;
14155 	}
14156 
14157 	/* Look for a callback record matching this request's tag.
14158 	 */
14159 	result = dequeueCallbackForRequestTag(requestTag, callbackRecord);
14160 	if (result != kOSReturnSuccess) {
14161 		goto finish;
14162 	}
14163 
14164 	/*****
14165 	 * Get the context pointer of the callback record (if there is one).
14166 	 */
14167 	contextWrapper = OSDynamicCast(OSValueObject<void *>, _OSKextGetRequestArgument(
14168 		    callbackRecord.get(), kKextRequestArgumentContextKey));
14169 	context = _OSKextExtractPointer(contextWrapper);
14170 	if (contextWrapper && !context) {
14171 		goto finish;
14172 	}
14173 
14174 	callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14175 	    _OSKextGetRequestArgument(callbackRecord.get(),
14176 	    kKextRequestArgumentCallbackKey));
14177 	callback = _OSKextExtractCallbackPointer(callbackWrapper);
14178 	if (!callback) {
14179 		goto finish;
14180 	}
14181 
14182 	/* Check for a data obj. We might not have one and that's ok, that means
14183 	 * we didn't find the requested resource, and we still have to tell the
14184 	 * caller that via the callback.
14185 	 */
14186 	dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
14187 	    kKextRequestArgumentValueKey));
14188 	if (dataObj) {
14189 		dataPtr = dataObj->getBytesNoCopy();
14190 		dataLength = dataObj->getLength();
14191 	}
14192 
14193 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
14194 	if (!callbackKext) {
14195 		OSKextLog(/* kext */ NULL,
14196 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
14197 		    "Can't invoke callback for resource request; ");
14198 		goto finish;
14199 	}
14200 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
14201 		OSKextLog(/* kext */ NULL,
14202 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
14203 		    "Can't invoke kext resource callback; ");
14204 		goto finish;
14205 	}
14206 
14207 	(void)callback(requestTag->unsigned32BitValue(),
14208 	    (OSReturn)requestResult->unsigned32BitValue(),
14209 	    dataPtr, dataLength, context);
14210 
14211 	result = kOSReturnSuccess;
14212 
14213 finish:
14214 	return result;
14215 }
14216 
14217 /*********************************************************************
14218 * Assumes sKextLock is held.
14219 *********************************************************************/
14220 /* static */
14221 OSReturn
14222 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict)
14223 {
14224 	OSSharedPtr<OSDictionary> missingIDs;
14225 	OSArray *bundleIDList     = NULL; // do not release
14226 
14227 	bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
14228 		    requestDict, kKextRequestArgumentMissingBundleIDs));
14229 	if (!bundleIDList) {
14230 		return kOSKextReturnInvalidArgument;
14231 	}
14232 
14233 	missingIDs = OSDictionary::withCapacity(bundleIDList->getCount());
14234 	if (!missingIDs) {
14235 		return kOSKextReturnNoMemory;
14236 	}
14237 
14238 	uint32_t count, i;
14239 	count = bundleIDList->getCount();
14240 	for (i = 0; i < count; i++) {
14241 		OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i));
14242 		if (thisID) {
14243 			missingIDs->setObject(thisID, kOSBooleanFalse);
14244 		}
14245 	}
14246 
14247 	sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain);
14248 
14249 	return kOSReturnSuccess;
14250 }
14251 
14252 /*********************************************************************
14253 * Assumes sKextLock is held.
14254 *********************************************************************/
14255 /* static */
14256 OSReturn
14257 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict)
14258 {
14259 	bool loadable = true;
14260 	if (!kextIdentifier) {
14261 		return kOSKextReturnInvalidArgument;
14262 	}
14263 
14264 	if (requestDict) {
14265 		OSBoolean *loadableArg;
14266 		loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
14267 			    requestDict, kKextRequestArgumentBundleAvailability));
14268 		/* If we find the "Bundle Available" arg, and it's false, then
14269 		 * mark the bundle ID as _not_ loadable
14270 		 */
14271 		if (loadableArg && !loadableArg->getValue()) {
14272 			loadable = false;
14273 		}
14274 	}
14275 
14276 	if (!sNonLoadableKextsByID) {
14277 		sNonLoadableKextsByID = OSDictionary::withCapacity(1);
14278 	}
14279 
14280 	sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable));
14281 
14282 	OSKextLog(/* kext */ NULL,
14283 	    kOSKextLogBasicLevel | kOSKextLogIPCFlag,
14284 	    "KextLog: AuxKC bundle %s marked as %s",
14285 	    kextIdentifier->getCStringNoCopy(),
14286 	    (loadable ? "loadable" : "NOT loadable"));
14287 
14288 	return kOSReturnSuccess;
14289 }
14290 
14291 /*********************************************************************
14292 *********************************************************************/
14293 /* static */
14294 void
14295 OSKext::invokeRequestCallback(
14296 	OSDictionary * callbackRecord,
14297 	OSReturn       callbackResult)
14298 {
14299 	OSString * predicate  = _OSKextGetRequestPredicate(callbackRecord);
14300 	OSSharedPtr<OSNumber> resultNum;
14301 
14302 	if (!predicate) {
14303 		goto finish;
14304 	}
14305 
14306 	resultNum  = OSNumber::withNumber((long long unsigned int)callbackResult,
14307 	    8 * sizeof(callbackResult));
14308 	if (!resultNum) {
14309 		goto finish;
14310 	}
14311 
14312 	/* Insert the result into the callback record and dispatch it as if it
14313 	 * were the reply coming down from user space.
14314 	 */
14315 	_OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
14316 	    resultNum.get());
14317 
14318 	if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
14319 		/* This removes the pending callback record.
14320 		 */
14321 		OSKext::dispatchResource(callbackRecord);
14322 	}
14323 
14324 finish:
14325 	return;
14326 }
14327 
14328 /*********************************************************************
14329 * Assumes sKextLock is held.
14330 *********************************************************************/
14331 /* static */
14332 OSReturn
14333 OSKext::cancelRequest(
14334 	OSKextRequestTag    requestTag,
14335 	void             ** contextOut)
14336 {
14337 	OSReturn       result         = kOSKextReturnNoMemory;
14338 	OSSharedPtr<OSDictionary> callbackRecord;
14339 	OSValueObject<void *> * contextWrapper = nullptr; // do not release
14340 
14341 	IORecursiveLockLock(sKextLock);
14342 	result = OSKext::dequeueCallbackForRequestTag(requestTag,
14343 	    callbackRecord);
14344 	IORecursiveLockUnlock(sKextLock);
14345 
14346 	if (result == kOSReturnSuccess && contextOut) {
14347 		contextWrapper = OSDynamicCast(OSValueObject<void *>,
14348 		    _OSKextGetRequestArgument(callbackRecord.get(),
14349 		    kKextRequestArgumentContextKey));
14350 		*contextOut = _OSKextExtractPointer(contextWrapper);
14351 	}
14352 
14353 	return result;
14354 }
14355 
14356 /*********************************************************************
14357 * Assumes sKextLock is held.
14358 *********************************************************************/
14359 void
14360 OSKext::invokeOrCancelRequestCallbacks(
14361 	OSReturn callbackResult,
14362 	bool     invokeFlag)
14363 {
14364 	unsigned int count, i;
14365 
14366 	count = sRequestCallbackRecords->getCount();
14367 	if (!count) {
14368 		goto finish;
14369 	}
14370 
14371 	i = count - 1;
14372 	do {
14373 		OSDictionary * request = OSDynamicCast(OSDictionary,
14374 		    sRequestCallbackRecords->getObject(i));
14375 
14376 		if (!request) {
14377 			continue;
14378 		}
14379 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14380 		    _OSKextGetRequestArgument(request,
14381 		    kKextRequestArgumentCallbackKey));
14382 
14383 		if (!callbackWrapper) {
14384 			sRequestCallbackRecords->removeObject(i);
14385 			continue;
14386 		}
14387 
14388 		vm_address_t callbackAddress = (vm_address_t)
14389 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
14390 
14391 		if ((kmod_info->address <= callbackAddress) &&
14392 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
14393 			if (invokeFlag) {
14394 				/* This removes the callback record.
14395 				 */
14396 				invokeRequestCallback(request, callbackResult);
14397 			} else {
14398 				sRequestCallbackRecords->removeObject(i);
14399 			}
14400 		}
14401 	} while (i--);
14402 
14403 finish:
14404 	return;
14405 }
14406 
14407 /*********************************************************************
14408 * Assumes sKextLock is held.
14409 *********************************************************************/
14410 uint32_t
14411 OSKext::countRequestCallbacks(void)
14412 {
14413 	uint32_t     result = 0;
14414 	unsigned int count, i;
14415 
14416 	count = sRequestCallbackRecords->getCount();
14417 	if (!count) {
14418 		goto finish;
14419 	}
14420 
14421 	i = count - 1;
14422 	do {
14423 		OSDictionary * request = OSDynamicCast(OSDictionary,
14424 		    sRequestCallbackRecords->getObject(i));
14425 
14426 		if (!request) {
14427 			continue;
14428 		}
14429 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14430 		    _OSKextGetRequestArgument(request,
14431 		    kKextRequestArgumentCallbackKey));
14432 
14433 		if (!callbackWrapper) {
14434 			continue;
14435 		}
14436 
14437 		vm_address_t callbackAddress = (vm_address_t)
14438 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
14439 
14440 		if ((kmod_info->address <= callbackAddress) &&
14441 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
14442 			result++;
14443 		}
14444 	} while (i--);
14445 
14446 finish:
14447 	return result;
14448 }
14449 
14450 /*********************************************************************
14451 *********************************************************************/
14452 static OSReturn
14453 _OSKextCreateRequest(
14454 	const char    * predicate,
14455 	OSSharedPtr<OSDictionary> & requestR)
14456 {
14457 	OSReturn result = kOSKextReturnNoMemory;
14458 	OSSharedPtr<OSDictionary> request;
14459 
14460 	request = OSDictionary::withCapacity(2);
14461 	if (!request) {
14462 		goto finish;
14463 	}
14464 	result = _OSDictionarySetCStringValue(request.get(),
14465 	    kKextRequestPredicateKey, predicate);
14466 	if (result != kOSReturnSuccess) {
14467 		goto finish;
14468 	}
14469 	result = kOSReturnSuccess;
14470 
14471 finish:
14472 	if (result == kOSReturnSuccess) {
14473 		requestR = os::move(request);
14474 	}
14475 
14476 	return result;
14477 }
14478 
14479 /*********************************************************************
14480 *********************************************************************/
14481 static OSString *
14482 _OSKextGetRequestPredicate(OSDictionary * requestDict)
14483 {
14484 	return OSDynamicCast(OSString,
14485 	           requestDict->getObject(kKextRequestPredicateKey));
14486 }
14487 
14488 /*********************************************************************
14489 *********************************************************************/
14490 static OSObject *
14491 _OSKextGetRequestArgument(
14492 	OSDictionary * requestDict,
14493 	const char   * argName)
14494 {
14495 	OSDictionary * args = OSDynamicCast(OSDictionary,
14496 	    requestDict->getObject(kKextRequestArgumentsKey));
14497 	if (args) {
14498 		return args->getObject(argName);
14499 	}
14500 	return NULL;
14501 }
14502 
14503 /*********************************************************************
14504 *********************************************************************/
14505 static bool
14506 _OSKextSetRequestArgument(
14507 	OSDictionary    * requestDict,
14508 	const char      * argName,
14509 	OSMetaClassBase * value)
14510 {
14511 	OSDictionary * args = OSDynamicCast(OSDictionary,
14512 	    requestDict->getObject(kKextRequestArgumentsKey));
14513 	OSSharedPtr<OSDictionary> newArgs;
14514 	if (!args) {
14515 		newArgs = OSDictionary::withCapacity(2);
14516 		args = newArgs.get();
14517 		if (!args) {
14518 			goto finish;
14519 		}
14520 		requestDict->setObject(kKextRequestArgumentsKey, args);
14521 	}
14522 	if (args) {
14523 		return args->setObject(argName, value);
14524 	}
14525 finish:
14526 	return false;
14527 }
14528 
14529 /*********************************************************************
14530 *********************************************************************/
14531 template <typename T>
14532 static T *
14533 _OSKextExtractPointer(OSValueObject<T *> * wrapper)
14534 {
14535 	if (!wrapper) {
14536 		return nullptr;
14537 	}
14538 	return wrapper->getRef();
14539 }
14540 
14541 /*********************************************************************
14542 *********************************************************************/
14543 static OSKextRequestResourceCallback
14544 _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper)
14545 {
14546 	if (!wrapper) {
14547 		return nullptr;
14548 	}
14549 	return wrapper->getRef();
14550 }
14551 
14552 
14553 /*********************************************************************
14554 *********************************************************************/
14555 static OSReturn
14556 _OSDictionarySetCStringValue(
14557 	OSDictionary * dict,
14558 	const char   * cKey,
14559 	const char   * cValue)
14560 {
14561 	OSReturn result = kOSKextReturnNoMemory;
14562 	OSSharedPtr<const OSSymbol> key;
14563 	OSSharedPtr<OSString> value;
14564 
14565 	key = OSSymbol::withCString(cKey);
14566 	value = OSString::withCString(cValue);
14567 	if (!key || !value) {
14568 		goto finish;
14569 	}
14570 	if (dict->setObject(key.get(), value.get())) {
14571 		result = kOSReturnSuccess;
14572 	}
14573 
14574 finish:
14575 	return result;
14576 }
14577 
14578 /*********************************************************************
14579 *********************************************************************/
14580 static bool
14581 _OSArrayContainsCString(
14582 	OSArray    * array,
14583 	const char * cString)
14584 {
14585 	bool             result = false;
14586 	OSSharedPtr<const OSSymbol> symbol;
14587 	uint32_t         count, i;
14588 
14589 	if (!array || !cString) {
14590 		goto finish;
14591 	}
14592 
14593 	symbol = OSSymbol::withCStringNoCopy(cString);
14594 	if (!symbol) {
14595 		goto finish;
14596 	}
14597 
14598 	count = array->getCount();
14599 	for (i = 0; i < count; i++) {
14600 		OSObject * thisObject = array->getObject(i);
14601 		if (symbol->isEqualTo(thisObject)) {
14602 			result = true;
14603 			goto finish;
14604 		}
14605 	}
14606 
14607 finish:
14608 	return result;
14609 }
14610 
14611 #if CONFIG_KXLD
14612 /*********************************************************************
14613 * We really only care about boot / system start up related kexts.
14614 * We return true if we're less than REBUILD_MAX_TIME since start up,
14615 * otherwise return false.
14616 *********************************************************************/
14617 bool
14618 _OSKextInPrelinkRebuildWindow(void)
14619 {
14620 	static bool     outside_the_window = false;
14621 	AbsoluteTime    my_abstime;
14622 	UInt64          my_ns;
14623 	SInt32          my_secs;
14624 
14625 	if (outside_the_window) {
14626 		return false;
14627 	}
14628 	clock_get_uptime(&my_abstime);
14629 	absolutetime_to_nanoseconds(my_abstime, &my_ns);
14630 	my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
14631 	if (my_secs > REBUILD_MAX_TIME) {
14632 		outside_the_window = true;
14633 		return false;
14634 	}
14635 	return true;
14636 }
14637 #endif /* CONFIG_KXLD */
14638 
14639 /*********************************************************************
14640 *********************************************************************/
14641 bool
14642 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
14643 {
14644 	int unLoadedCount, i;
14645 	bool result = false;
14646 
14647 	IORecursiveLockLock(sKextLock);
14648 
14649 	if (sUnloadedPrelinkedKexts == NULL) {
14650 		goto finish;
14651 	}
14652 	unLoadedCount = sUnloadedPrelinkedKexts->getCount();
14653 	if (unLoadedCount == 0) {
14654 		goto finish;
14655 	}
14656 
14657 	for (i = 0; i < unLoadedCount; i++) {
14658 		const OSSymbol *    myBundleID;        // do not release
14659 
14660 		myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
14661 		if (!myBundleID) {
14662 			continue;
14663 		}
14664 		if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
14665 			result = true;
14666 			break;
14667 		}
14668 	}
14669 finish:
14670 	IORecursiveLockUnlock(sKextLock);
14671 	return result;
14672 }
14673 
14674 #if PRAGMA_MARK
14675 #pragma mark Personalities (IOKit Drivers)
14676 #endif
14677 /*********************************************************************
14678 *********************************************************************/
14679 /* static */
14680 OSSharedPtr<OSArray>
14681 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
14682 {
14683 	OSSharedPtr<OSArray>              result;
14684 	OSSharedPtr<OSCollectionIterator> kextIterator;
14685 	OSSharedPtr<OSArray>              personalities;
14686 
14687 	OSString             * kextID                = NULL;        // do not release
14688 	OSKext               * theKext               = NULL;        // do not release
14689 
14690 	IORecursiveLockLock(sKextLock);
14691 
14692 	/* Let's conservatively guess that any given kext has around 3
14693 	 * personalities for now.
14694 	 */
14695 	result = OSArray::withCapacity(sKextsByID->getCount() * 3);
14696 	if (!result) {
14697 		goto finish;
14698 	}
14699 
14700 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
14701 	if (!kextIterator) {
14702 		goto finish;
14703 	}
14704 
14705 	while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
14706 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
14707 		if (theKext->flags.requireExplicitLoad) {
14708 			OSKextLog(theKext,
14709 			    kOSKextLogDebugLevel |
14710 			    kOSKextLogLoadFlag,
14711 			    "Kext %s requires an explicit kextload; "
14712 			    "omitting its personalities.",
14713 			    theKext->getIdentifierCString());
14714 		} else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
14715 			personalities = theKext->copyPersonalitiesArray();
14716 			if (!personalities) {
14717 				continue;
14718 			}
14719 			result->merge(personalities.get());
14720 		} else {
14721 			// xxx - check for better place to put this log msg
14722 			OSKextLog(theKext,
14723 			    kOSKextLogWarningLevel |
14724 			    kOSKextLogLoadFlag,
14725 			    "Kext %s is not loadable during safe boot; "
14726 			    "omitting its personalities.",
14727 			    theKext->getIdentifierCString());
14728 		}
14729 	}
14730 
14731 finish:
14732 	IORecursiveLockUnlock(sKextLock);
14733 
14734 	return result;
14735 }
14736 
14737 /*********************************************************************
14738 *********************************************************************/
14739 /* static */
14740 void
14741 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
14742 {
14743 	int numPersonalities = 0;
14744 
14745 	OSKextLog(/* kext */ NULL,
14746 	    kOSKextLogStepLevel |
14747 	    kOSKextLogLoadFlag,
14748 	    "Sending all eligible registered kexts' personalities "
14749 	    "to the IOCatalogue %s.",
14750 	    startMatching ? "and starting matching" : "but not starting matching");
14751 
14752 	OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities(
14753 		/* filterSafeBootFlag */ true);
14754 
14755 	if (personalities) {
14756 		gIOCatalogue->addDrivers(personalities.get(), startMatching);
14757 		numPersonalities = personalities->getCount();
14758 	}
14759 
14760 	OSKextLog(/* kext */ NULL,
14761 	    kOSKextLogStepLevel |
14762 	    kOSKextLogLoadFlag,
14763 	    "%d kext personalit%s sent to the IOCatalogue; %s.",
14764 	    numPersonalities, numPersonalities > 0 ? "ies" : "y",
14765 	    startMatching ? "matching started" : "matching not started");
14766 	return;
14767 }
14768 
14769 /*********************************************************************
14770 * Do not make a deep copy, just convert the IOKitPersonalities dict
14771 * to an array for sending to the IOCatalogue.
14772 *********************************************************************/
14773 OSSharedPtr<OSArray>
14774 OSKext::copyPersonalitiesArray(void)
14775 {
14776 	OSSharedPtr<OSArray>              result;
14777 	OSDictionary         * personalities               = NULL;        // do not release
14778 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
14779 
14780 	OSString             * personalityName             = NULL;        // do not release
14781 	OSString             * personalityBundleIdentifier = NULL;        // do not release
14782 
14783 	personalities = OSDynamicCast(OSDictionary,
14784 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
14785 	if (!personalities) {
14786 		goto finish;
14787 	}
14788 
14789 	result = OSArray::withCapacity(personalities->getCount());
14790 	if (!result) {
14791 		goto finish;
14792 	}
14793 
14794 	personalitiesIterator =
14795 	    OSCollectionIterator::withCollection(personalities);
14796 	if (!personalitiesIterator) {
14797 		goto finish;
14798 	}
14799 	while ((personalityName = OSDynamicCast(OSString,
14800 	    personalitiesIterator->getNextObject()))) {
14801 		OSDictionary * personality = OSDynamicCast(OSDictionary,
14802 		    personalities->getObject(personalityName));
14803 
14804 		if (personality) {
14805 			/******
14806 			 * If the personality doesn't have a CFBundleIdentifier, or if it
14807 			 * differs from the kext's, insert the kext's ID so we can find it.
14808 			 * The publisher ID is used to remove personalities from bundles
14809 			 * correctly.
14810 			 */
14811 			personalityBundleIdentifier = OSDynamicCast(OSString,
14812 			    personality->getObject(kCFBundleIdentifierKey));
14813 
14814 			if (!personalityBundleIdentifier) {
14815 				personality->setObject(kCFBundleIdentifierKey, bundleID.get());
14816 			} else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) {
14817 				personality->setObject(kIOPersonalityPublisherKey, bundleID.get());
14818 			}
14819 		}
14820 
14821 		result->setObject(personality);
14822 	}
14823 
14824 finish:
14825 	return result;
14826 }
14827 
14828 /*********************************************************************
14829 *   Might want to change this to a bool return?
14830 *********************************************************************/
14831 OSReturn
14832 OSKext::sendPersonalitiesToCatalog(
14833 	bool      startMatching,
14834 	OSArray * personalityNames)
14835 {
14836 	OSReturn       result              = kOSReturnSuccess;
14837 	OSSharedPtr<OSArray> personalitiesToSend;
14838 	OSDictionary * kextPersonalities   = NULL;        // do not release
14839 	int            count, i;
14840 
14841 	if (!sLoadEnabled) {
14842 		OSKextLog(this,
14843 		    kOSKextLogErrorLevel |
14844 		    kOSKextLogLoadFlag,
14845 		    "Kext loading is disabled (attempt to start matching for kext %s).",
14846 		    getIdentifierCString());
14847 		result = kOSKextReturnDisabled;
14848 		goto finish;
14849 	}
14850 
14851 	if (sSafeBoot && !isLoadableInSafeBoot()) {
14852 		OSKextLog(this,
14853 		    kOSKextLogErrorLevel |
14854 		    kOSKextLogLoadFlag,
14855 		    "Kext %s is not loadable during safe boot; "
14856 		    "not sending personalities to the IOCatalogue.",
14857 		    getIdentifierCString());
14858 		result = kOSKextReturnNotLoadable;
14859 		goto finish;
14860 	}
14861 
14862 	if (!personalityNames || !personalityNames->getCount()) {
14863 		personalitiesToSend = copyPersonalitiesArray();
14864 	} else {
14865 		kextPersonalities = OSDynamicCast(OSDictionary,
14866 		    getPropertyForHostArch(kIOKitPersonalitiesKey));
14867 		if (!kextPersonalities || !kextPersonalities->getCount()) {
14868 			// not an error
14869 			goto finish;
14870 		}
14871 		personalitiesToSend = OSArray::withCapacity(0);
14872 		if (!personalitiesToSend) {
14873 			result = kOSKextReturnNoMemory;
14874 			goto finish;
14875 		}
14876 		count = personalityNames->getCount();
14877 		for (i = 0; i < count; i++) {
14878 			OSString * name = OSDynamicCast(OSString,
14879 			    personalityNames->getObject(i));
14880 			if (!name) {
14881 				continue;
14882 			}
14883 			OSDictionary * personality = OSDynamicCast(OSDictionary,
14884 			    kextPersonalities->getObject(name));
14885 			if (personality) {
14886 				personalitiesToSend->setObject(personality);
14887 			}
14888 		}
14889 	}
14890 	if (personalitiesToSend) {
14891 		unsigned numPersonalities = personalitiesToSend->getCount();
14892 		OSKextLog(this,
14893 		    kOSKextLogStepLevel |
14894 		    kOSKextLogLoadFlag,
14895 		    "Kext %s sending %d personalit%s to the IOCatalogue%s.",
14896 		    getIdentifierCString(),
14897 		    numPersonalities,
14898 		    numPersonalities > 1 ? "ies" : "y",
14899 		    startMatching ? " and starting matching" : " but not starting matching");
14900 		gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching);
14901 	}
14902 finish:
14903 	return result;
14904 }
14905 
14906 /*********************************************************************
14907 * xxx - We should allow removing the kext's declared personalities,
14908 * xxx - even with other bundle identifiers.
14909 *********************************************************************/
14910 void
14911 OSKext::removePersonalitiesFromCatalog(void)
14912 {
14913 	OSSharedPtr<OSDictionary> personality;
14914 
14915 	personality = OSDictionary::withCapacity(1);
14916 	if (!personality) {
14917 		goto finish;
14918 	}
14919 	personality->setObject(kCFBundleIdentifierKey, getIdentifier());
14920 
14921 	OSKextLog(this,
14922 	    kOSKextLogStepLevel |
14923 	    kOSKextLogLoadFlag,
14924 	    "Kext %s removing all personalities naming it from the IOCatalogue.",
14925 	    getIdentifierCString());
14926 
14927 	/* Have the IOCatalog remove all personalities matching this kext's
14928 	 * bundle ID and trigger matching anew.
14929 	 */
14930 	gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true);
14931 
14932 finish:
14933 	return;
14934 }
14935 
14936 void
14937 OSKext::updatePersonalitiesInCatalog(OSArray *upgradedPersonalities)
14938 {
14939 	if (!upgradedPersonalities || upgradedPersonalities->getCount() == 0) {
14940 		return;
14941 	}
14942 
14943 	OSSharedPtr<OSDictionary> personalityToRemove = OSDictionary::withCapacity(1);
14944 	if (!personalityToRemove) {
14945 		return;
14946 	}
14947 
14948 	/*
14949 	 * Create a personality dictionary with just the bundleID.
14950 	 * We will remove any personality that has a matching bundleID,
14951 	 * irrespective of which other keys are present on the dictionary.
14952 	 */
14953 	personalityToRemove->setObject(kCFBundleIdentifierKey, getIdentifier());
14954 	gIOCatalogue->exchangeDrivers(personalityToRemove.get(), upgradedPersonalities, true);
14955 }
14956 
14957 #if PRAGMA_MARK
14958 #pragma mark Logging
14959 #endif
14960 /*********************************************************************
14961 * Do not call any function that takes sKextLock here!
14962 *********************************************************************/
14963 /* static */
14964 OSKextLogSpec
14965 OSKext::setUserSpaceLogFilter(
14966 	OSKextLogSpec   newUserLogFilter,
14967 	bool            captureFlag)
14968 {
14969 	OSKextLogSpec result;
14970 	bool          allocError = false;
14971 
14972 	/* Do not call any function that takes sKextLoggingLock during
14973 	 * this critical block. That means do logging after.
14974 	 */
14975 	IOLockLock(sKextLoggingLock);
14976 
14977 	result = sUserSpaceKextLogFilter;
14978 	sUserSpaceKextLogFilter = newUserLogFilter;
14979 
14980 	if (newUserLogFilter && captureFlag &&
14981 	    !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
14982 		// xxx - do some measurements for a good initial capacity?
14983 		sUserSpaceLogSpecArray = OSArray::withCapacity(0);
14984 		sUserSpaceLogMessageArray = OSArray::withCapacity(0);
14985 
14986 		if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
14987 			allocError = true;
14988 		}
14989 	}
14990 
14991 	IOLockUnlock(sKextLoggingLock);
14992 
14993 	/* If the config flag itself is changing, log the state change
14994 	 * going both ways, before setting up the user-space log arrays,
14995 	 * so that this is only logged in the kernel.
14996 	 */
14997 	if (result != newUserLogFilter) {
14998 		OSKextLog(/* kext */ NULL,
14999 		    kOSKextLogDebugLevel |
15000 		    kOSKextLogGeneralFlag,
15001 		    "User-space log flags changed from 0x%x to 0x%x.",
15002 		    result, newUserLogFilter);
15003 	}
15004 	if (allocError) {
15005 		OSKextLog(/* kext */ NULL,
15006 		    kOSKextLogErrorLevel |
15007 		    kOSKextLogGeneralFlag,
15008 		    "Failed to allocate user-space log message arrays.");
15009 	}
15010 
15011 	return result;
15012 }
15013 
15014 /*********************************************************************
15015 * Do not call any function that takes sKextLock here!
15016 *********************************************************************/
15017 /* static */
15018 OSSharedPtr<OSArray>
15019 OSKext::clearUserSpaceLogFilter(void)
15020 {
15021 	OSSharedPtr<OSArray>       result;
15022 	OSKextLogSpec   oldLogFilter;
15023 	OSKextLogSpec   newLogFilter = kOSKextLogSilentFilter;
15024 
15025 	/* Do not call any function that takes sKextLoggingLock during
15026 	 * this critical block. That means do logging after.
15027 	 */
15028 	IOLockLock(sKextLoggingLock);
15029 
15030 	result = OSArray::withCapacity(2);
15031 	if (result) {
15032 		result->setObject(sUserSpaceLogSpecArray.get());
15033 		result->setObject(sUserSpaceLogMessageArray.get());
15034 	}
15035 	sUserSpaceLogSpecArray.reset();
15036 	sUserSpaceLogMessageArray.reset();
15037 
15038 	oldLogFilter = sUserSpaceKextLogFilter;
15039 	sUserSpaceKextLogFilter = newLogFilter;
15040 
15041 	IOLockUnlock(sKextLoggingLock);
15042 
15043 	/* If the config flag itself is changing, log the state change
15044 	 * going both ways, after tearing down the user-space log
15045 	 * arrays, so this is only logged within the kernel.
15046 	 */
15047 	if (oldLogFilter != newLogFilter) {
15048 		OSKextLog(/* kext */ NULL,
15049 		    kOSKextLogDebugLevel |
15050 		    kOSKextLogGeneralFlag,
15051 		    "User-space log flags changed from 0x%x to 0x%x.",
15052 		    oldLogFilter, newLogFilter);
15053 	}
15054 
15055 	return result;
15056 }
15057 
15058 
15059 /*********************************************************************
15060 * Do not call any function that takes sKextLock here!
15061 *********************************************************************/
15062 /* static */
15063 OSKextLogSpec
15064 OSKext::getUserSpaceLogFilter(void)
15065 {
15066 	OSKextLogSpec result;
15067 
15068 	IOLockLock(sKextLoggingLock);
15069 	result = sUserSpaceKextLogFilter;
15070 	IOLockUnlock(sKextLoggingLock);
15071 
15072 	return result;
15073 }
15074 
15075 /*********************************************************************
15076 * This function is called by OSMetaClass during kernel C++ setup.
15077 * Be careful what you access here; assume only OSKext::initialize()
15078 * has been called.
15079 *
15080 * Do not call any function that takes sKextLock here!
15081 *********************************************************************/
15082 #define VTRESET   "\033[0m"
15083 
15084 #define VTBOLD    "\033[1m"
15085 #define VTUNDER   "\033[4m"
15086 
15087 #define VTRED     "\033[31m"
15088 #define VTGREEN   "\033[32m"
15089 #define VTYELLOW  "\033[33m"
15090 #define VTBLUE    "\033[34m"
15091 #define VTMAGENTA "\033[35m"
15092 #define VTCYAN    "\033[36m"
15093 
15094 inline const char *
15095 colorForFlags(OSKextLogSpec flags)
15096 {
15097 	OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
15098 
15099 	switch (logLevel) {
15100 	case kOSKextLogErrorLevel:
15101 		return VTRED VTBOLD;
15102 	case kOSKextLogWarningLevel:
15103 		return VTRED;
15104 	case kOSKextLogBasicLevel:
15105 		return VTYELLOW VTUNDER;
15106 	case kOSKextLogProgressLevel:
15107 		return VTYELLOW;
15108 	case kOSKextLogStepLevel:
15109 		return VTGREEN;
15110 	case kOSKextLogDetailLevel:
15111 		return VTCYAN;
15112 	case kOSKextLogDebugLevel:
15113 		return VTMAGENTA;
15114 	default:
15115 		return "";         // white
15116 	}
15117 }
15118 
15119 inline bool
15120 logSpecMatch(
15121 	OSKextLogSpec msgLogSpec,
15122 	OSKextLogSpec logFilter)
15123 {
15124 	OSKextLogSpec filterKextGlobal  = logFilter & kOSKextLogKextOrGlobalMask;
15125 	OSKextLogSpec filterLevel       = logFilter & kOSKextLogLevelMask;
15126 	OSKextLogSpec filterFlags       = logFilter & kOSKextLogFlagsMask;
15127 
15128 	OSKextLogSpec msgKextGlobal    = msgLogSpec & kOSKextLogKextOrGlobalMask;
15129 	OSKextLogSpec msgLevel         = msgLogSpec & kOSKextLogLevelMask;
15130 	OSKextLogSpec msgFlags         = msgLogSpec & kOSKextLogFlagsMask;
15131 
15132 	/* Explicit messages always get logged.
15133 	 */
15134 	if (msgLevel == kOSKextLogExplicitLevel) {
15135 		return true;
15136 	}
15137 
15138 	/* Warnings and errors are logged regardless of the flags.
15139 	 */
15140 	if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
15141 		return true;
15142 	}
15143 
15144 	/* A verbose message that isn't for a logging-enabled kext and isn't global
15145 	 * does *not* get logged.
15146 	 */
15147 	if (!msgKextGlobal && !filterKextGlobal) {
15148 		return false;
15149 	}
15150 
15151 	/* Warnings and errors are logged regardless of the flags.
15152 	 * All other messages must fit the flags and
15153 	 * have a level at or below the filter.
15154 	 *
15155 	 */
15156 	if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
15157 		return true;
15158 	}
15159 	return false;
15160 }
15161 
15162 extern "C" {
15163 void
15164 OSKextLog(
15165 	OSKext         * aKext,
15166 	OSKextLogSpec    msgLogSpec,
15167 	const char     * format, ...)
15168 {
15169 	va_list argList;
15170 
15171 	va_start(argList, format);
15172 	OSKextVLog(aKext, msgLogSpec, format, argList);
15173 	va_end(argList);
15174 }
15175 
15176 void
15177 OSKextVLog(
15178 	OSKext         * aKext,
15179 	OSKextLogSpec    msgLogSpec,
15180 	const char     * format,
15181 	va_list          srcArgList)
15182 {
15183 	bool             logForKernel       = false;
15184 	bool             logForUser         = false;
15185 	va_list          argList;
15186 	char             stackBuffer[120];
15187 	uint32_t         length            = 0;
15188 	char           * allocBuffer       = NULL;        // must kfree
15189 	OSSharedPtr<OSNumber> logSpecNum;
15190 	OSSharedPtr<OSString> logString;
15191 	char           * buffer            = stackBuffer;        // do not free
15192 
15193 	IOLockLock(sKextLoggingLock);
15194 
15195 	/* Set the kext/global bit in the message spec if we have no
15196 	 * kext or if the kext requests logging.
15197 	 */
15198 	if (!aKext || aKext->flags.loggingEnabled) {
15199 		msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
15200 	}
15201 
15202 	logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
15203 	if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
15204 		logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
15205 	}
15206 
15207 	if (!(logForKernel || logForUser)) {
15208 		goto finish;
15209 	}
15210 
15211 	/* No goto from here until past va_end()!
15212 	 */
15213 	va_copy(argList, srcArgList);
15214 	length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
15215 	va_end(argList);
15216 
15217 	if (length + 1 >= sizeof(stackBuffer)) {
15218 		allocBuffer = (char *)kalloc_data_tag(length + 1,
15219 		    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
15220 		if (!allocBuffer) {
15221 			goto finish;
15222 		}
15223 
15224 		/* No goto from here until past va_end()!
15225 		 */
15226 		va_copy(argList, srcArgList);
15227 		vsnprintf(allocBuffer, length + 1, format, argList);
15228 		va_end(argList);
15229 
15230 		buffer = allocBuffer;
15231 	}
15232 
15233 	/* If user space wants the log message, queue it up.
15234 	 */
15235 	if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
15236 		logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
15237 		logString = OSString::withCString(buffer);
15238 		if (logSpecNum && logString) {
15239 			sUserSpaceLogSpecArray->setObject(logSpecNum.get());
15240 			sUserSpaceLogMessageArray->setObject(logString.get());
15241 		}
15242 	}
15243 
15244 	/* Always log messages from the kernel according to the kernel's
15245 	 * log flags.
15246 	 */
15247 	if (logForKernel) {
15248 		/* If we are in console mode and have a custom log filter,
15249 		 * colorize the log message.
15250 		 */
15251 		if (sBootArgLogFilterFound) {
15252 			const char * color = "";         // do not free
15253 			color = colorForFlags(msgLogSpec);
15254 			printf("%s%s%s\n", colorForFlags(msgLogSpec),
15255 			    buffer, color[0] ? VTRESET : "");
15256 		} else {
15257 			printf("%s\n", buffer);
15258 		}
15259 	}
15260 
15261 finish:
15262 	IOLockUnlock(sKextLoggingLock);
15263 
15264 	if (allocBuffer) {
15265 		kfree_data(allocBuffer, length + 1);
15266 	}
15267 	return;
15268 }
15269 
15270 #if KASLR_IOREG_DEBUG
15271 
15272 #define IOLOG_INDENT( the_indention ) \
15273 { \
15274     int     i; \
15275     for ( i = 0; i < (the_indention); i++ ) { \
15276 	IOLog(" "); \
15277     } \
15278 }
15279 
15280 extern vm_offset_t       vm_kernel_stext;
15281 extern vm_offset_t       vm_kernel_etext;
15282 extern mach_vm_offset_t kext_alloc_base;
15283 extern mach_vm_offset_t kext_alloc_max;
15284 
15285 bool ScanForAddrInObject(OSObject * theObject,
15286     int indent );
15287 
15288 bool
15289 ScanForAddrInObject(OSObject * theObject,
15290     int indent)
15291 {
15292 	const OSMetaClass *     myTypeID;
15293 	OSSharedPtr<OSCollectionIterator>  myIter;
15294 	OSSymbol *              myKey;
15295 	OSObject *              myValue;
15296 	bool                    myResult = false;
15297 
15298 	if (theObject == NULL) {
15299 		IOLog("%s: theObject is NULL \n",
15300 		    __FUNCTION__);
15301 		return myResult;
15302 	}
15303 
15304 	myTypeID = OSTypeIDInst(theObject);
15305 
15306 	if (myTypeID == OSTypeID(OSDictionary)) {
15307 		OSDictionary *      myDictionary;
15308 
15309 		myDictionary = OSDynamicCast(OSDictionary, theObject);
15310 		myIter = OSCollectionIterator::withCollection( myDictionary );
15311 		if (myIter == NULL) {
15312 			return myResult;
15313 		}
15314 
15315 		// !! reset the iterator
15316 		myIter->reset();
15317 
15318 		while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
15319 			bool    myTempResult;
15320 
15321 			myValue = myDictionary->getObject(myKey);
15322 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
15323 			if (myTempResult) {
15324 				// if we ever get a true result return true
15325 				myResult = true;
15326 				IOLOG_INDENT(indent);
15327 				IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
15328 			}
15329 		}
15330 
15331 		// !! release the iterator
15332 		myIter.reset();
15333 	} else if (myTypeID == OSTypeID(OSArray)) {
15334 		OSArray *   myArray;
15335 
15336 		myArray = OSDynamicCast(OSArray, theObject);
15337 		myIter = OSCollectionIterator::withCollection(myArray);
15338 		if (myIter == NULL) {
15339 			return myResult;
15340 		}
15341 		// !! reset the iterator
15342 		myIter->reset();
15343 
15344 		while ((myValue = myIter->getNextObject())) {
15345 			bool        myTempResult;
15346 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
15347 			if (myTempResult) {
15348 				// if we ever get a true result return true
15349 				myResult = true;
15350 				IOLOG_INDENT(indent);
15351 				IOLog("OSArray: \n");
15352 			}
15353 		}
15354 		// !! release the iterator
15355 		myIter.reset();
15356 	} else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
15357 		// should we look for addresses in strings?
15358 	} else if (myTypeID == OSTypeID(OSData)) {
15359 		void * *        myPtrPtr;
15360 		unsigned int    myLen;
15361 		OSData *        myDataObj;
15362 
15363 		myDataObj =    OSDynamicCast(OSData, theObject);
15364 		myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
15365 		myLen = myDataObj->getLength();
15366 
15367 		if (myPtrPtr && myLen && myLen > 7) {
15368 			int     i;
15369 			int     myPtrCount = (myLen / sizeof(void *));
15370 
15371 			for (i = 0; i < myPtrCount; i++) {
15372 				UInt64 numberValue = (UInt64) * (myPtrPtr);
15373 
15374 				if (kext_alloc_max != 0 &&
15375 				    numberValue >= kext_alloc_base &&
15376 				    numberValue < kext_alloc_max) {
15377 					OSSharedPtr<OSKext> myKext;
15378 					// IOLog("found OSData %p in kext map %p to %p  \n",
15379 					//       *(myPtrPtr),
15380 					//       (void *) kext_alloc_base,
15381 					//       (void *) kext_alloc_max);
15382 
15383 					myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
15384 					if (myKext) {
15385 						IOLog("found addr %p from an OSData obj within kext \"%s\"  \n",
15386 						    *(myPtrPtr),
15387 						    myKext->getIdentifierCString());
15388 					}
15389 					myResult = true;
15390 				}
15391 				if (vm_kernel_etext != 0 &&
15392 				    numberValue >= vm_kernel_stext &&
15393 				    numberValue < vm_kernel_etext) {
15394 					IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n",
15395 					    *(myPtrPtr),
15396 					    (void *) vm_kernel_stext,
15397 					    (void *) vm_kernel_etext);
15398 					myResult = true;
15399 				}
15400 				myPtrPtr++;
15401 			}
15402 		}
15403 	} else if (myTypeID == OSTypeID(OSBoolean)) {
15404 		// do nothing here...
15405 	} else if (myTypeID == OSTypeID(OSNumber)) {
15406 		OSNumber * number = OSDynamicCast(OSNumber, theObject);
15407 
15408 		UInt64 numberValue = number->unsigned64BitValue();
15409 
15410 		if (kext_alloc_max != 0 &&
15411 		    numberValue >= kext_alloc_base &&
15412 		    numberValue < kext_alloc_max) {
15413 			OSSharedPtr<OSKext> myKext;
15414 			IOLog("found OSNumber in kext map %p to %p  \n",
15415 			    (void *) kext_alloc_base,
15416 			    (void *) kext_alloc_max);
15417 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
15418 
15419 			myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
15420 			if (myKext) {
15421 				IOLog("found in kext \"%s\"  \n",
15422 				    myKext->getIdentifierCString());
15423 			}
15424 
15425 			myResult = true;
15426 		}
15427 		if (vm_kernel_etext != 0 &&
15428 		    numberValue >= vm_kernel_stext &&
15429 		    numberValue < vm_kernel_etext) {
15430 			IOLog("found OSNumber in kernel text segment %p to %p  \n",
15431 			    (void *) vm_kernel_stext,
15432 			    (void *) vm_kernel_etext);
15433 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
15434 			myResult = true;
15435 		}
15436 	}
15437 #if 0
15438 	else {
15439 		const OSMetaClass* myMetaClass = NULL;
15440 
15441 		myMetaClass = theObject->getMetaClass();
15442 		if (myMetaClass) {
15443 			IOLog("class %s \n", myMetaClass->getClassName());
15444 		} else {
15445 			IOLog("Unknown object \n" );
15446 		}
15447 	}
15448 #endif
15449 
15450 	return myResult;
15451 }
15452 #endif // KASLR_KEXT_DEBUG
15453 };         /* extern "C" */
15454 
15455 #if PRAGMA_MARK
15456 #pragma mark Backtrace Dump & kmod_get_info() support
15457 #endif
15458 /*********************************************************************
15459 * This function must be safe to call in panic context.
15460 *********************************************************************/
15461 /* static */
15462 void
15463 OSKext::printKextsInBacktrace(
15464 	vm_offset_t  * addr __unused,
15465 	unsigned int   cnt __unused,
15466 	int         (* printf_func)(const char *fmt, ...) __unused,
15467 	uint32_t       flags __unused)
15468 {
15469 	addr64_t    summary_page = 0;
15470 	addr64_t    last_summary_page = 0;
15471 	bool        found_kmod = false;
15472 	u_int       i = 0;
15473 
15474 	if (kPrintKextsLock & flags) {
15475 		if (!sKextSummariesLock) {
15476 			return;
15477 		}
15478 		IOLockLock(sKextSummariesLock);
15479 	}
15480 
15481 	if (!gLoadedKextSummaries) {
15482 		(*printf_func)("         can't perform kext scan: no kext summary");
15483 		goto finish;
15484 	}
15485 
15486 	summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
15487 	last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
15488 	for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
15489 		if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
15490 			(*printf_func)("         can't perform kext scan: "
15491 			    "missing kext summary page %p", summary_page);
15492 			goto finish;
15493 		}
15494 	}
15495 
15496 	for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15497 		OSKextLoadedKextSummary * summary;
15498 
15499 		summary = gLoadedKextSummaries->summaries + i;
15500 		if (!summary->address) {
15501 			continue;
15502 		}
15503 
15504 		if (!summaryIsInBacktrace(summary, addr, cnt)) {
15505 			continue;
15506 		}
15507 
15508 		if (!found_kmod) {
15509 			if (!(kPrintKextsTerse & flags)) {
15510 				(*printf_func)("      Kernel Extensions in backtrace:\n");
15511 			}
15512 			found_kmod = true;
15513 		}
15514 
15515 		printSummary(summary, printf_func, flags);
15516 	}
15517 
15518 finish:
15519 	if (kPrintKextsLock & flags) {
15520 		IOLockUnlock(sKextSummariesLock);
15521 	}
15522 
15523 	return;
15524 }
15525 
15526 /*********************************************************************
15527 * This function must be safe to call in panic context.
15528 *********************************************************************/
15529 /* static */
15530 boolean_t
15531 OSKext::summaryIsInBacktrace(
15532 	OSKextLoadedKextSummary   * summary,
15533 	vm_offset_t               * addr,
15534 	unsigned int                cnt)
15535 {
15536 	u_int i = 0;
15537 
15538 	for (i = 0; i < cnt; i++) {
15539 		vm_offset_t kscan_addr = addr[i];
15540 #if  __has_feature(ptrauth_calls)
15541 		kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr);
15542 #endif /*  __has_feature(ptrauth_calls) */
15543 		if ((kscan_addr >= summary->text_exec_address) &&
15544 		    (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) {
15545 			return TRUE;
15546 		}
15547 	}
15548 
15549 	return FALSE;
15550 }
15551 
15552 /*
15553  * Get the kext summary object for the kext where 'addr' lies. Must be called with
15554  * sKextSummariesLock held.
15555  */
15556 OSKextLoadedKextSummary *
15557 OSKext::summaryForAddress(uintptr_t addr)
15558 {
15559 #if  __has_feature(ptrauth_calls)
15560 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
15561 #endif /*  __has_feature(ptrauth_calls) */
15562 	for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15563 		OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
15564 		if (!summary->address) {
15565 			continue;
15566 		}
15567 
15568 #if VM_MAPPED_KEXTS
15569 		/* On our platforms that use VM_MAPPED_KEXTS, we currently do not
15570 		 * support split kexts, but we also may unmap the kexts, which can
15571 		 * race with the above codepath (see OSKext::unload).  As such,
15572 		 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
15573 		 */
15574 		if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
15575 			return summary;
15576 		}
15577 #else
15578 		kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
15579 		kernel_segment_command_t *seg;
15580 
15581 		for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
15582 			if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
15583 				return summary;
15584 			}
15585 		}
15586 #endif
15587 	}
15588 
15589 	/* addr did not map to any kext */
15590 	return NULL;
15591 }
15592 
15593 /* static */
15594 void *
15595 OSKext::kextForAddress(const void *address)
15596 {
15597 	OSKextActiveAccount * active;
15598 	OSKext              * kext = NULL;
15599 	uint32_t              baseIdx;
15600 	uint32_t              lim;
15601 	uintptr_t             addr = (uintptr_t) address;
15602 	size_t                i;
15603 
15604 	if (!addr) {
15605 		return NULL;
15606 	}
15607 #if  __has_feature(ptrauth_calls)
15608 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
15609 #endif /*  __has_feature(ptrauth_calls) */
15610 
15611 	if (sKextAccountsCount) {
15612 		lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
15613 		// bsearch sKextAccounts list
15614 		for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15615 			active = &sKextAccounts[baseIdx + (lim >> 1)];
15616 			if ((addr >= active->address) && (addr < active->address_end)) {
15617 				kext = active->account->kext;
15618 				if (kext && kext->kmod_info) {
15619 					lck_ticket_unlock(sKextAccountsLock);
15620 					return (void *)kext->kmod_info->address;
15621 				}
15622 				break;
15623 			} else if (addr > active->address) {
15624 				// move right
15625 				baseIdx += (lim >> 1) + 1;
15626 				lim--;
15627 			}
15628 			// else move left
15629 		}
15630 		lck_ticket_unlock(sKextAccountsLock);
15631 	}
15632 	if (kernel_text_contains(addr)) {
15633 		return (void *)&_mh_execute_header;
15634 	}
15635 	if (gLoadedKextSummaries) {
15636 		IOLockLock(sKextSummariesLock);
15637 		for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) {
15638 			OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
15639 			if (addr >= summary->address && addr < summary->address + summary->size) {
15640 				void *kextAddress = (void *)summary->address;
15641 				IOLockUnlock(sKextSummariesLock);
15642 				return kextAddress;
15643 			}
15644 		}
15645 		IOLockUnlock(sKextSummariesLock);
15646 	}
15647 
15648 	return NULL;
15649 }
15650 
15651 /* static */
15652 kern_return_t
15653 OSKext::summaryForAddressExt(
15654 	const void              * address,
15655 	OSKextLoadedKextSummary * summary)
15656 {
15657 	kern_return_t                   result = KERN_FAILURE;
15658 	const OSKextLoadedKextSummary * foundSummary = NULL;
15659 
15660 	/*
15661 	 * This needs to be safe to call even before the lock has been initialized
15662 	 * in OSKext::initialize(), as we might get here from the ksancov runtime
15663 	 * when instrumenting XNU itself with sanitizer coverage.
15664 	 */
15665 	if (!sKextSummariesLock) {
15666 		return result;
15667 	}
15668 
15669 	IOLockLock(sKextSummariesLock);
15670 	if (gLoadedKextSummaries) {
15671 		foundSummary = summaryForAddress((uintptr_t)address);
15672 		if (foundSummary) {
15673 			memcpy(summary, foundSummary, sizeof(*summary));
15674 			result = KERN_SUCCESS;
15675 		} else {
15676 			result = KERN_NOT_FOUND;
15677 		}
15678 	}
15679 	IOLockUnlock(sKextSummariesLock);
15680 
15681 	return result;
15682 }
15683 
15684 /*
15685  * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t *
15686  * Safe to call in panic context.
15687  */
15688 static OSKextLoadedKextSummary *
15689 findSummary(uint32_t tagID)
15690 {
15691 	OSKextLoadedKextSummary * summary;
15692 	for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15693 		summary = gLoadedKextSummaries->summaries + i;
15694 		if (summary->loadTag == tagID) {
15695 			return summary;
15696 		}
15697 	}
15698 	return NULL;
15699 }
15700 
15701 /*********************************************************************
15702 * This function must be safe to call in panic context.
15703 *********************************************************************/
15704 void
15705 OSKext::printSummary(
15706 	OSKextLoadedKextSummary * summary,
15707 	int                    (* printf_func)(const char *fmt, ...),
15708 	uint32_t                  flags)
15709 {
15710 	kmod_reference_t * kmod_ref = NULL;
15711 	uuid_string_t uuid;
15712 	char version[kOSKextVersionMaxLength];
15713 	uint64_t tmpAddr;
15714 	uint64_t tmpSize;
15715 	OSKextLoadedKextSummary *dependencySummary;
15716 
15717 	if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
15718 		strlcpy(version, "unknown version", sizeof(version));
15719 	}
15720 	(void) uuid_unparse(summary->uuid, uuid);
15721 
15722 #if defined(__arm__) || defined(__arm64__)
15723 	tmpAddr = summary->text_exec_address;
15724 	tmpSize = summary->text_exec_size;
15725 #else
15726 	tmpAddr = summary->address;
15727 	tmpSize = summary->size;
15728 #endif
15729 	if (kPrintKextsUnslide & flags) {
15730 		tmpAddr = ml_static_unslide(tmpAddr);
15731 	}
15732 	(*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
15733 	    (kPrintKextsTerse & flags) ? "" : "         ",
15734 	    summary->name, version, uuid,
15735 	    tmpAddr, tmpAddr + tmpSize - 1);
15736 
15737 	if (kPrintKextsTerse & flags) {
15738 		return;
15739 	}
15740 
15741 	/* print dependency info */
15742 	for (kmod_ref = (kmod_reference_t *) summary->reference_list;
15743 	    kmod_ref;
15744 	    kmod_ref = kmod_ref->next) {
15745 		kmod_info_t * rinfo;
15746 
15747 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
15748 			(*printf_func)("            kmod dependency scan stopped "
15749 			    "due to missing dependency page: %p\n",
15750 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
15751 			break;
15752 		}
15753 		rinfo = kmod_ref->info;
15754 
15755 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
15756 			(*printf_func)("            kmod dependency scan stopped "
15757 			    "due to missing kmod page: %p\n",
15758 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
15759 			break;
15760 		}
15761 
15762 		if (!rinfo->address) {
15763 			continue;         // skip fake entries for built-ins
15764 		}
15765 
15766 		dependencySummary = findSummary(rinfo->id);
15767 		uuid[0] = 0x00;
15768 		tmpAddr = rinfo->address;
15769 		tmpSize = rinfo->size;
15770 		if (dependencySummary) {
15771 			(void) uuid_unparse(dependencySummary->uuid, uuid);
15772 #if defined(__arm__) || defined(__arm64__)
15773 			tmpAddr = dependencySummary->text_exec_address;
15774 			tmpSize = dependencySummary->text_exec_size;
15775 #endif
15776 		}
15777 
15778 		if (kPrintKextsUnslide & flags) {
15779 			tmpAddr = ml_static_unslide(tmpAddr);
15780 		}
15781 		(*printf_func)("            dependency: %s(%s)[%s]@%p->%p\n",
15782 		    rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1);
15783 	}
15784 	return;
15785 }
15786 
15787 
15788 #if !defined(__arm__) && !defined(__arm64__)
15789 /*******************************************************************************
15790 * substitute() looks at an input string (a pointer within a larger buffer)
15791 * for a match to a substring, and on match it writes the marker & substitution
15792 * character to an output string, updating the scan (from) and
15793 * output (to) indexes as appropriate.
15794 *******************************************************************************/
15795 static int substitute(
15796 	const char * scan_string,
15797 	char       * string_out,
15798 	uint32_t   * to_index,
15799 	uint32_t   * from_index,
15800 	const char * substring,
15801 	char         marker,
15802 	char         substitution);
15803 
15804 /* string_out must be at least KMOD_MAX_NAME bytes.
15805  */
15806 static int
15807 substitute(
15808 	const char * scan_string,
15809 	char       * string_out,
15810 	uint32_t   * to_index,
15811 	uint32_t   * from_index,
15812 	const char * substring,
15813 	char         marker,
15814 	char         substitution)
15815 {
15816 	size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
15817 
15818 	/* On a substring match, append the marker (if there is one) and then
15819 	 * the substitution character, updating the output (to) index accordingly.
15820 	 * Then update the input (from) length by the length of the substring
15821 	 * that got replaced.
15822 	 */
15823 	if (!strncmp(scan_string, substring, substring_length)) {
15824 		if (marker) {
15825 			string_out[(*to_index)++] = marker;
15826 		}
15827 		string_out[(*to_index)++] = substitution;
15828 		(*from_index) += substring_length;
15829 		return 1;
15830 	}
15831 	return 0;
15832 }
15833 
15834 /*******************************************************************************
15835 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
15836 * KMOD_MAX_NAME characters and performs various substitutions of common
15837 * prefixes & substrings as defined by tables in kext_panic_report.h.
15838 *******************************************************************************/
15839 static void compactIdentifier(
15840 	const char * identifier,
15841 	char       * identifier_out,
15842 	char      ** identifier_out_end);
15843 
15844 static void
15845 compactIdentifier(
15846 	const char * identifier,
15847 	char       * identifier_out,
15848 	char      ** identifier_out_end)
15849 {
15850 	uint32_t       from_index, to_index;
15851 	uint32_t       scan_from_index = 0;
15852 	uint32_t       scan_to_index   = 0;
15853 	subs_entry_t * subs_entry    = NULL;
15854 	int            did_sub       = 0;
15855 
15856 	from_index = to_index = 0;
15857 	identifier_out[0] = '\0';
15858 
15859 	/* Replace certain identifier prefixes with shorter @+character sequences.
15860 	 * Check the return value of substitute() so we only replace the prefix.
15861 	 */
15862 	for (subs_entry = &kext_identifier_prefix_subs[0];
15863 	    subs_entry->substring && !did_sub;
15864 	    subs_entry++) {
15865 		did_sub = substitute(identifier, identifier_out,
15866 		    &scan_to_index, &scan_from_index,
15867 		    subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
15868 	}
15869 	did_sub = 0;
15870 
15871 	/* Now scan through the identifier looking for the common substrings
15872 	 * and replacing them with shorter !+character sequences via substitute().
15873 	 */
15874 	for (/* see above */;
15875 	    scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
15876 	    /* see loop */) {
15877 		const char   * scan_string = &identifier[scan_from_index];
15878 
15879 		did_sub = 0;
15880 
15881 		if (scan_from_index) {
15882 			for (subs_entry = &kext_identifier_substring_subs[0];
15883 			    subs_entry->substring && !did_sub;
15884 			    subs_entry++) {
15885 				did_sub = substitute(scan_string, identifier_out,
15886 				    &scan_to_index, &scan_from_index,
15887 				    subs_entry->substring, '!', subs_entry->substitute);
15888 			}
15889 		}
15890 
15891 		/* If we didn't substitute, copy the input character to the output.
15892 		 */
15893 		if (!did_sub) {
15894 			identifier_out[scan_to_index++] = identifier[scan_from_index++];
15895 		}
15896 	}
15897 
15898 	identifier_out[scan_to_index] = '\0';
15899 	if (identifier_out_end) {
15900 		*identifier_out_end = &identifier_out[scan_to_index];
15901 	}
15902 
15903 	return;
15904 }
15905 #endif /* !defined(__arm__) && !defined(__arm64__) */
15906 
15907 /*******************************************************************************
15908 * assemble_identifier_and_version() adds to a string buffer a compacted
15909 * bundle identifier followed by a version string.
15910 *******************************************************************************/
15911 
15912 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
15913  */
15914 static size_t assemble_identifier_and_version(
15915 	kmod_info_t * kmod_info,
15916 	char        * identPlusVers,
15917 	size_t        bufSize);
15918 
15919 static size_t
15920 assemble_identifier_and_version(
15921 	kmod_info_t * kmod_info,
15922 	char        * identPlusVers,
15923 	size_t        bufSize)
15924 {
15925 	size_t result = 0;
15926 
15927 #if defined(__arm__) || defined(__arm64__)
15928 	result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME);
15929 #else
15930 	compactIdentifier(kmod_info->name, identPlusVers, NULL);
15931 	result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
15932 #endif
15933 	identPlusVers[result++] = '\t';         // increment for real char
15934 	identPlusVers[result] = '\0';         // don't increment for nul char
15935 	result = strlcat(identPlusVers, kmod_info->version, bufSize);
15936 	if (result >= bufSize) {
15937 		identPlusVers[bufSize - 1] = '\0';
15938 		result = bufSize - 1;
15939 	}
15940 
15941 	return result;
15942 }
15943 
15944 /*******************************************************************************
15945 * Assumes sKextLock is held.
15946 *******************************************************************************/
15947 /* static */
15948 int
15949 OSKext::saveLoadedKextPanicListTyped(
15950 	const char * prefix,
15951 	int          invertFlag,
15952 	int          libsFlag,
15953 	char       * paniclist,
15954 	uint32_t     list_size)
15955 {
15956 	int             result = -1;
15957 	unsigned int    count, i;
15958 
15959 	count = sLoadedKexts->getCount();
15960 	if (!count) {
15961 		goto finish;
15962 	}
15963 
15964 	i = count - 1;
15965 	do {
15966 		OSObject    * rawKext = sLoadedKexts->getObject(i);
15967 		OSKext      * theKext = OSDynamicCast(OSKext, rawKext);
15968 		int           match;
15969 		size_t        identPlusVersLength;
15970 		size_t        tempLen;
15971 		char          identPlusVers[2 * KMOD_MAX_NAME];
15972 
15973 		if (!rawKext) {
15974 			printf("OSKext::saveLoadedKextPanicListTyped - "
15975 			    "NULL kext in loaded kext list; continuing\n");
15976 			continue;
15977 		}
15978 
15979 		if (!theKext) {
15980 			printf("OSKext::saveLoadedKextPanicListTyped - "
15981 			    "Kext type cast failed in loaded kext list; continuing\n");
15982 			continue;
15983 		}
15984 
15985 		/* Skip all built-in kexts.
15986 		 */
15987 		if (theKext->isKernelComponent()) {
15988 			continue;
15989 		}
15990 
15991 		kmod_info_t * kmod_info = theKext->kmod_info;
15992 
15993 		/* Filter for kmod name (bundle identifier).
15994 		 */
15995 		match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
15996 		if ((match && invertFlag) || (!match && !invertFlag)) {
15997 			continue;
15998 		}
15999 
16000 		/* Filter for libraries (kexts that have a compatible version).
16001 		 */
16002 		if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
16003 		    (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
16004 			continue;
16005 		}
16006 
16007 		if (!kmod_info ||
16008 		    !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
16009 			printf("kext scan stopped due to missing kmod_info page: %p\n",
16010 			    kmod_info);
16011 			goto finish;
16012 		}
16013 
16014 		identPlusVersLength = assemble_identifier_and_version(kmod_info,
16015 		    identPlusVers,
16016 		    sizeof(identPlusVers));
16017 		if (!identPlusVersLength) {
16018 			printf("error saving loaded kext info\n");
16019 			goto finish;
16020 		}
16021 
16022 		/* make sure everything fits and we null terminate.
16023 		 */
16024 		tempLen = strlcat(paniclist, identPlusVers, list_size);
16025 		if (tempLen >= list_size) {
16026 			// panic list is full, keep it and null terminate
16027 			paniclist[list_size - 1] = 0x00;
16028 			result = 0;
16029 			goto finish;
16030 		}
16031 		tempLen = strlcat(paniclist, "\n", list_size);
16032 		if (tempLen >= list_size) {
16033 			// panic list is full, keep it and null terminate
16034 			paniclist[list_size - 1] = 0x00;
16035 			result = 0;
16036 			goto finish;
16037 		}
16038 	} while (i--);
16039 
16040 	result = 0;
16041 finish:
16042 
16043 	return result;
16044 }
16045 
16046 /*********************************************************************
16047 *********************************************************************/
16048 /* static */
16049 void
16050 OSKext::saveLoadedKextPanicList(void)
16051 {
16052 	char     * newlist        = NULL;
16053 	uint32_t   newlist_size   = 0;
16054 
16055 	newlist_size = KEXT_PANICLIST_SIZE;
16056 	newlist = (char *)kalloc_data_tag(newlist_size,
16057 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
16058 
16059 	if (!newlist) {
16060 		OSKextLog(/* kext */ NULL,
16061 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
16062 		    "Couldn't allocate kext panic log buffer.");
16063 		goto finish;
16064 	}
16065 
16066 	newlist[0] = '\0';
16067 
16068 	// non-"com.apple." kexts
16069 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
16070 	    /* libs? */ -1, newlist, newlist_size) != 0) {
16071 		goto finish;
16072 	}
16073 	// "com.apple." nonlibrary kexts
16074 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
16075 	    /* libs? */ 0, newlist, newlist_size) != 0) {
16076 		goto finish;
16077 	}
16078 	// "com.apple." library kexts
16079 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
16080 	    /* libs? */ 1, newlist, newlist_size) != 0) {
16081 		goto finish;
16082 	}
16083 
16084 	if (loaded_kext_paniclist) {
16085 		kfree_data(loaded_kext_paniclist, loaded_kext_paniclist_size);
16086 	}
16087 	loaded_kext_paniclist = newlist;
16088 	newlist = NULL;
16089 	loaded_kext_paniclist_size = newlist_size;
16090 
16091 finish:
16092 	if (newlist) {
16093 		kfree_data(newlist, newlist_size);
16094 	}
16095 	return;
16096 }
16097 
16098 /*********************************************************************
16099 * Assumes sKextLock is held.
16100 *********************************************************************/
16101 void
16102 OSKext::savePanicString(bool isLoading)
16103 {
16104 	u_long len;
16105 
16106 	if (!kmod_info) {
16107 		return;         // do not goto finish here b/c of lock
16108 	}
16109 
16110 	len = assemble_identifier_and_version( kmod_info,
16111 	    (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
16112 	    (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
16113 	if (!len) {
16114 		printf("error saving unloaded kext info\n");
16115 		goto finish;
16116 	}
16117 
16118 	if (isLoading) {
16119 		last_loaded_strlen = len;
16120 		last_loaded_address = (void *)kmod_info->address;
16121 		last_loaded_size = kmod_info->size;
16122 		clock_get_uptime(&last_loaded_timestamp);
16123 	} else {
16124 		last_unloaded_strlen = len;
16125 		last_unloaded_address = (void *)kmod_info->address;
16126 		last_unloaded_size = kmod_info->size;
16127 		clock_get_uptime(&last_unloaded_timestamp);
16128 	}
16129 
16130 finish:
16131 	return;
16132 }
16133 
16134 /*********************************************************************
16135 *********************************************************************/
16136 /* static */
16137 void
16138 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
16139 {
16140 	if (last_loaded_strlen) {
16141 		printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n",
16142 		    AbsoluteTime_to_scalar(&last_loaded_timestamp),
16143 		    last_loaded_strlen, last_loaded_str_buf,
16144 		    last_loaded_address, last_loaded_size);
16145 	}
16146 
16147 	if (last_unloaded_strlen) {
16148 		printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n",
16149 		    AbsoluteTime_to_scalar(&last_unloaded_timestamp),
16150 		    last_unloaded_strlen, last_unloaded_str_buf,
16151 		    last_unloaded_address, last_unloaded_size);
16152 	}
16153 
16154 	printf_func("loaded kexts:\n");
16155 	if (loaded_kext_paniclist &&
16156 	    pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
16157 	    loaded_kext_paniclist[0]) {
16158 		printf_func("%.*s",
16159 		    strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
16160 		    loaded_kext_paniclist);
16161 	} else {
16162 		printf_func("(none)\n");
16163 	}
16164 	return;
16165 }
16166 
16167 /*********************************************************************
16168 * Assumes sKextLock is held.
16169 *********************************************************************/
16170 /* static */
16171 void
16172 OSKext::updateLoadedKextSummaries(void)
16173 {
16174 	kern_return_t result = KERN_FAILURE;
16175 	OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
16176 	OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
16177 	OSKext *aKext;
16178 	vm_map_offset_t start, end;
16179 	size_t summarySize = 0;
16180 	size_t size;
16181 	u_int count;
16182 	u_int maxKexts;
16183 	u_int i, j;
16184 	OSKextActiveAccount * accountingList;
16185 	OSKextActiveAccount * prevAccountingList;
16186 	uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
16187 
16188 	prevAccountingList = NULL;
16189 	prevAccountingListCount = 0;
16190 
16191 #if DEVELOPMENT || DEBUG
16192 	if (IORecursiveLockHaveLock(sKextLock) == false) {
16193 		panic("sKextLock must be held");
16194 	}
16195 #endif
16196 
16197 	IOLockLock(sKextSummariesLock);
16198 
16199 	count = sLoadedKexts->getCount();
16200 	for (i = 0, maxKexts = 0; i < count; ++i) {
16201 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16202 		maxKexts += (aKext && (aKext->isExecutable() || aKext->isSpecialKernelBinary()));
16203 	}
16204 
16205 	if (!maxKexts) {
16206 		goto finish;
16207 	}
16208 	if (maxKexts < kOSKextTypicalLoadCount) {
16209 		maxKexts = kOSKextTypicalLoadCount;
16210 	}
16211 
16212 	/* Calculate the size needed for the new summary headers.
16213 	 */
16214 
16215 	size = sizeof(*gLoadedKextSummaries);
16216 	size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
16217 	size = round_page(size);
16218 
16219 	if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
16220 		if (gLoadedKextSummaries) {
16221 			kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
16222 			gLoadedKextSummaries = NULL;
16223 			gLoadedKextSummariesTimestamp = mach_absolute_time();
16224 			sLoadedKextSummariesAllocSize = 0;
16225 		}
16226 		result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size,
16227 		    KMA_DATA, VM_KERN_MEMORY_OSKEXT);
16228 		if (result != KERN_SUCCESS) {
16229 			goto finish;
16230 		}
16231 		summaryHeader = summaryHeaderAlloc;
16232 		summarySize = size;
16233 	} else {
16234 		summaryHeader = gLoadedKextSummaries;
16235 		summarySize = sLoadedKextSummariesAllocSize;
16236 
16237 		start = (vm_map_offset_t) summaryHeader;
16238 		end = start + summarySize;
16239 		result = vm_map_protect(kernel_map,
16240 		    start,
16241 		    end,
16242 		    VM_PROT_DEFAULT,
16243 		    FALSE);
16244 		if (result != KERN_SUCCESS) {
16245 			goto finish;
16246 		}
16247 	}
16248 
16249 	/* Populate the summary header.
16250 	 */
16251 
16252 	bzero(summaryHeader, summarySize);
16253 	summaryHeader->version = kOSKextLoadedKextSummaryVersion;
16254 	summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
16255 
16256 	/* Populate each kext summary.
16257 	 */
16258 
16259 	count = sLoadedKexts->getCount();
16260 	accountingListAlloc = 0;
16261 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
16262 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16263 		if (!aKext || (!aKext->isExecutable() && !aKext->isSpecialKernelBinary())) {
16264 			continue;
16265 		}
16266 
16267 		aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
16268 		summaryHeader->numSummaries++;
16269 		accountingListAlloc++;
16270 	}
16271 
16272 	accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
16273 	accountingListCount = 0;
16274 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
16275 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16276 		if (!aKext || (!aKext->isExecutable() && !aKext->isSpecialKernelBinary())) {
16277 			continue;
16278 		}
16279 
16280 		OSKextActiveAccount activeAccount;
16281 		aKext->updateActiveAccount(&activeAccount);
16282 		// order by address
16283 		for (idx = 0; idx < accountingListCount; idx++) {
16284 			if (activeAccount.address < accountingList[idx].address) {
16285 				break;
16286 			}
16287 		}
16288 		bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
16289 		accountingList[idx] = activeAccount;
16290 		accountingListCount++;
16291 	}
16292 	assert(accountingListCount == accountingListAlloc);
16293 	/* Write protect the buffer and move it into place.
16294 	 */
16295 
16296 	start = (vm_map_offset_t) summaryHeader;
16297 	end = start + summarySize;
16298 
16299 	result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
16300 	if (result != KERN_SUCCESS) {
16301 		goto finish;
16302 	}
16303 
16304 	gLoadedKextSummaries = summaryHeader;
16305 	gLoadedKextSummariesTimestamp = mach_absolute_time();
16306 	sLoadedKextSummariesAllocSize = summarySize;
16307 	summaryHeaderAlloc = NULL;
16308 
16309 	/* Call the magic breakpoint function through a static function pointer so
16310 	 * the compiler can't optimize the function away.
16311 	 */
16312 	if (sLoadedKextSummariesUpdated) {
16313 		(*sLoadedKextSummariesUpdated)();
16314 	}
16315 
16316 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16317 	prevAccountingList      = sKextAccounts;
16318 	prevAccountingListCount = sKextAccountsCount;
16319 	sKextAccounts           = accountingList;
16320 	sKextAccountsCount      = accountingListCount;
16321 	lck_ticket_unlock(sKextAccountsLock);
16322 
16323 finish:
16324 	IOLockUnlock(sKextSummariesLock);
16325 
16326 	/* If we had to allocate a new buffer but failed to generate the summaries,
16327 	 * free that now.
16328 	 */
16329 	if (summaryHeaderAlloc) {
16330 		kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
16331 	}
16332 	if (prevAccountingList) {
16333 		IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
16334 	}
16335 
16336 	return;
16337 }
16338 
16339 /*********************************************************************
16340 *********************************************************************/
16341 void
16342 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
16343 {
16344 	OSSharedPtr<OSData> uuid;
16345 
16346 	strlcpy(summary->name, getIdentifierCString(),
16347 	    sizeof(summary->name));
16348 
16349 	uuid = copyUUID();
16350 	if (uuid) {
16351 		memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
16352 	}
16353 
16354 	if (flags.builtin) {
16355 //      this value will stop lldb from parsing the mach-o header
16356 //      summary->address = UINT64_MAX;
16357 //      summary->size = 0;
16358 		summary->address = kmod_info->address;
16359 		summary->size = kmod_info->size;
16360 	} else {
16361 		summary->address = kmod_info->address;
16362 		summary->size = kmod_info->size;
16363 	}
16364 	summary->version = getVersion();
16365 	summary->loadTag = kmod_info->id;
16366 	summary->flags = 0;
16367 	summary->reference_list = (uint64_t) kmod_info->reference_list;
16368 
16369 	summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size);
16370 	if (summary->text_exec_address == 0) {
16371 		// Fallback to __TEXT
16372 		summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size);
16373 	}
16374 
16375 	/**
16376 	 * If the addresses within the Mach-O are unslid, then manually slide any
16377 	 * addresses coming from the Mach-O as higher layer software using these
16378 	 * summaries expects a slid address here.
16379 	 */
16380 	if (flags.unslidMachO) {
16381 		summary->text_exec_address = (uint64_t) ml_static_slide((vm_offset_t) summary->text_exec_address);
16382 	}
16383 
16384 	return;
16385 }
16386 
16387 /*********************************************************************
16388 *********************************************************************/
16389 
16390 void
16391 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
16392 {
16393 	kernel_mach_header_t     *hdr = NULL;
16394 	kernel_segment_command_t *seg = NULL;
16395 
16396 	bzero(accountp, sizeof(*accountp));
16397 
16398 	hdr = (kernel_mach_header_t *)kmod_info->address;
16399 	if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) {
16400 		/*
16401 		 * If this kext supports split segments (or is in a new
16402 		 * MH_FILESET kext collection), use the first
16403 		 * executable segment as the range for instructions
16404 		 * (and thus for backtracing.
16405 		 */
16406 		for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
16407 			if (seg->initprot & VM_PROT_EXECUTE) {
16408 				break;
16409 			}
16410 		}
16411 	}
16412 	if (seg) {
16413 		accountp->address = seg->vmaddr;
16414 		if (accountp->address) {
16415 			accountp->address_end = seg->vmaddr + seg->vmsize;
16416 		}
16417 	} else {
16418 		/* For non-split kexts and for kexts without executable
16419 		 * segments, just use the kmod_info range (as the kext
16420 		 * is either all in one range or should not show up in
16421 		 * instruction backtraces).
16422 		 */
16423 		accountp->address = kmod_info->address;
16424 		if (accountp->address) {
16425 			accountp->address_end = kmod_info->address + kmod_info->size;
16426 		}
16427 	}
16428 
16429 	accountp->account = this->account;
16430 }
16431 
16432 bool
16433 OSKext::isDriverKit(void)
16434 {
16435 	OSString *bundleType;
16436 
16437 	if (infoDict) {
16438 		bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey));
16439 		if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) {
16440 			return TRUE;
16441 		}
16442 	}
16443 	return FALSE;
16444 }
16445 
16446 bool
16447 OSKext::isInFileset(void)
16448 {
16449 	if (!kmod_info) {
16450 		goto check_prelinked;
16451 	}
16452 
16453 	if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) {
16454 		return true;
16455 	}
16456 
16457 check_prelinked:
16458 	if (isPrelinked()) {
16459 		/*
16460 		 * If we haven't setup kmod_info yet, but we know
16461 		 * we're loading a prelinked kext in an MH_FILESET KC,
16462 		 * then return true
16463 		 */
16464 		kc_format_t kc_format;
16465 		if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
16466 			return true;
16467 		}
16468 	}
16469 	return false;
16470 }
16471 
16472 OSSharedPtr<OSDextStatistics>
16473 OSKext::copyDextStatistics(void)
16474 {
16475 	return dextStatistics;
16476 }
16477 
16478 bool
16479 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg)
16480 {
16481 	kern_return_t result;
16482 	if (!super::init()) {
16483 		return false;
16484 	}
16485 	if (seg == nullptr) {
16486 		return false;
16487 	}
16488 	result = kmem_alloc(kernel_map, (vm_offset_t *)&data, seg->vmsize,
16489 	    KMA_PAGEABLE, VM_KERN_MEMORY_KEXT);
16490 	if (result != KERN_SUCCESS) {
16491 		return false;
16492 	}
16493 	memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize);
16494 	savedSegment = seg;
16495 	vmsize = seg->vmsize;
16496 	vmaddr = seg->vmaddr;
16497 	return true;
16498 }
16499 
16500 OSSharedPtr<OSKextSavedMutableSegment>
16501 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg)
16502 {
16503 	OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>();
16504 	if (me && !me->initWithSegment(seg)) {
16505 		return nullptr;
16506 	}
16507 	return me;
16508 }
16509 
16510 void
16511 OSKextSavedMutableSegment::free(void)
16512 {
16513 	if (data) {
16514 		kmem_free(kernel_map, (vm_offset_t)data, vmsize);
16515 	}
16516 }
16517 
16518 vm_offset_t
16519 OSKextSavedMutableSegment::getVMAddr() const
16520 {
16521 	return vmaddr;
16522 }
16523 
16524 vm_offset_t
16525 OSKextSavedMutableSegment::getVMSize() const
16526 {
16527 	return vmsize;
16528 }
16529 
16530 OSReturn
16531 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg)
16532 {
16533 	if (seg != savedSegment) {
16534 		return kOSKextReturnInvalidArgument;
16535 	}
16536 	if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) {
16537 		return kOSKextReturnInvalidArgument;
16538 	}
16539 	memcpy((void *)seg->vmaddr, data, vmsize);
16540 	return kOSReturnSuccess;
16541 }
16542 
16543 extern "C" kern_return_t
16544 OSKextSetReceiptQueried(void)
16545 {
16546 	OSKextLog(/* kext */ NULL,
16547 	    kOSKextLogStepLevel | kOSKextLogGeneralFlag,
16548 	    "Setting kext receipt as queried");
16549 
16550 	IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue);
16551 	return KERN_SUCCESS;
16552 }
16553 
16554 extern "C" const vm_allocation_site_t *
16555 OSKextGetAllocationSiteForCaller(uintptr_t address)
16556 {
16557 	OSKextActiveAccount *  active;
16558 	vm_allocation_site_t * site;
16559 	vm_allocation_site_t * releasesite;
16560 
16561 	uint32_t baseIdx;
16562 	uint32_t lim;
16563 #if  __has_feature(ptrauth_calls)
16564 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
16565 #endif /*  __has_feature(ptrauth_calls) */
16566 
16567 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16568 	site = releasesite = NULL;
16569 
16570 	// bsearch sKextAccounts list
16571 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
16572 		active = &sKextAccounts[baseIdx + (lim >> 1)];
16573 		if ((address >= active->address) && (address < active->address_end)) {
16574 			site = &active->account->site;
16575 			if (!site->tag) {
16576 				vm_tag_alloc_locked(site, &releasesite);
16577 			}
16578 			break;
16579 		} else if (address > active->address) {
16580 			// move right
16581 			baseIdx += (lim >> 1) + 1;
16582 			lim--;
16583 		}
16584 		// else move left
16585 	}
16586 	lck_ticket_unlock(sKextAccountsLock);
16587 	if (releasesite) {
16588 		kern_allocation_name_release(releasesite);
16589 	}
16590 
16591 	return site;
16592 }
16593 
16594 #if DEVELOPMENT || DEBUG
16595 extern "C" void
16596 OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *))
16597 {
16598 	OSKextActiveAccount *  active;
16599 
16600 	uint32_t baseIdx;
16601 	uint32_t lim;
16602 #if  __has_feature(ptrauth_calls)
16603 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
16604 #endif /*  __has_feature(ptrauth_calls) */
16605 
16606 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16607 
16608 	// bsearch sKextAccounts list
16609 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
16610 		active = &sKextAccounts[baseIdx + (lim >> 1)];
16611 		if ((address >= active->address) && (address < active->address_end)) {
16612 			cb(&active->account->task_refgrp);
16613 			break;
16614 		} else if (address > active->address) {
16615 			// move right
16616 			baseIdx += (lim >> 1) + 1;
16617 			lim--;
16618 		}
16619 		// else move left
16620 	}
16621 	lck_ticket_unlock(sKextAccountsLock);
16622 }
16623 #endif /* DEVELOPMENT || DEBUG */
16624 
16625 extern "C" uint32_t
16626 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
16627 {
16628 	OSKextAccount * account = (typeof(account))site;
16629 	const char    * kname;
16630 
16631 	if (name) {
16632 		if (account->kext) {
16633 			kname = account->kext->getIdentifierCString();
16634 		} else {
16635 			kname = "<>";
16636 		}
16637 		strlcpy(name, kname, namelen);
16638 	}
16639 
16640 	return account->loadTag;
16641 }
16642 
16643 extern "C" void
16644 OSKextFreeSite(vm_allocation_site_t * site)
16645 {
16646 	OSKextAccount * freeAccount = (typeof(freeAccount))site;
16647 	IOFreeType(freeAccount, OSKextAccount);
16648 }
16649 
16650 /*********************************************************************
16651 *********************************************************************/
16652 
16653 #if CONFIG_IMAGEBOOT
16654 int
16655 OSKextGetUUIDForName(const char *name, uuid_t uuid)
16656 {
16657 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name);
16658 	if (!kext) {
16659 		return 1;
16660 	}
16661 
16662 	OSSharedPtr<OSData> uuid_data = kext->copyUUID();
16663 	if (uuid_data) {
16664 		memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
16665 		return 0;
16666 	}
16667 
16668 	return 1;
16669 }
16670 #endif
16671 
16672 
16673 
16674 class OSDextCrash : public OSObject {
16675 	OSDeclareDefaultStructors(OSDextCrash);
16676 public:
16677 	static OSPtr<OSDextCrash> withTimestamp(uint64_t timestamp);
16678 	uint64_t getTimestamp();
16679 
16680 private:
16681 	virtual bool initWithTimestamp(uint64_t timestamp);
16682 	uint64_t fTimestamp;
16683 };
16684 
16685 OSDefineMetaClassAndStructors(OSDextCrash, OSObject);
16686 
16687 OSSharedPtr<OSDextCrash>
16688 OSDextCrash::withTimestamp(uint64_t timestamp)
16689 {
16690 	OSSharedPtr<OSDextCrash> result = OSMakeShared<OSDextCrash>();
16691 	if (!result->initWithTimestamp(timestamp)) {
16692 		return NULL;
16693 	}
16694 	return result;
16695 }
16696 
16697 bool
16698 OSDextCrash::initWithTimestamp(uint64_t timestamp)
16699 {
16700 	if (!OSObject::init()) {
16701 		return false;
16702 	}
16703 	fTimestamp = timestamp;
16704 	return true;
16705 }
16706 
16707 uint64_t
16708 OSDextCrash::getTimestamp()
16709 {
16710 	return fTimestamp;
16711 }
16712 
16713 OSSharedPtr<OSDextStatistics>
16714 OSDextStatistics::create()
16715 {
16716 	OSSharedPtr<OSDextStatistics> result = OSMakeShared<OSDextStatistics>();
16717 	if (!result->init()) {
16718 		return NULL;
16719 	}
16720 	return result;
16721 }
16722 
16723 bool
16724 OSDextStatistics::init()
16725 {
16726 	if (!OSObject::init()) {
16727 		return false;
16728 	}
16729 
16730 	lock = IOLockAlloc();
16731 	crashes = OSArray::withCapacity(kMaxDextCrashesInOneDay);
16732 	return true;
16733 }
16734 
16735 void
16736 OSDextStatistics::free()
16737 {
16738 	if (lock) {
16739 		IOLockFree(lock);
16740 	}
16741 	crashes.reset();
16742 	OSObject::free();
16743 }
16744 
16745 OSDextCrashPolicy
16746 OSDextStatistics::recordCrash()
16747 {
16748 	size_t i = 0;
16749 	uint64_t timestamp = mach_continuous_time();
16750 	uint64_t interval;
16751 	nanoseconds_to_absolutetime(86400 * NSEC_PER_SEC /* 1 day */, &interval);
16752 	uint64_t lastTimestamp = timestamp > interval ? timestamp - interval : 0;
16753 	OSDextCrashPolicy policy;
16754 
16755 	IOLockLock(lock);
16756 	OSSharedPtr<OSDextCrash> crash = OSDextCrash::withTimestamp(timestamp);
16757 	for (i = 0; i < crashes->getCount();) {
16758 		OSDextCrash * current = OSDynamicCast(OSDextCrash, crashes->getObject(i));
16759 		assert(current != NULL);
16760 		if (current->getTimestamp() < lastTimestamp) {
16761 			crashes->removeObject(i);
16762 		} else {
16763 			i++;
16764 		}
16765 	}
16766 
16767 	crashes->setObject(crash);
16768 
16769 	if (crashes->getCount() > kMaxDextCrashesInOneDay) {
16770 		policy = kOSDextCrashPolicyReboot;
16771 	} else {
16772 		policy = kOSDextCrashPolicyNone;
16773 	}
16774 
16775 	IOLockUnlock(lock);
16776 
16777 	return policy;
16778 }
16779 
16780 size_t
16781 OSDextStatistics::getCrashCount()
16782 {
16783 	size_t result = 0;
16784 	IOLockLock(lock);
16785 	result = crashes->getCount();
16786 	IOLockUnlock(lock);
16787 	return result;
16788 }
16789 
16790 static int
16791 sysctl_willuserspacereboot
16792 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
16793 {
16794 	int new_value = 0, old_value = 0, changed = 0;
16795 	int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
16796 	if (error) {
16797 		return error;
16798 	}
16799 	if (changed) {
16800 		OSKext::willUserspaceReboot();
16801 	}
16802 	return 0;
16803 }
16804 
16805 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot,
16806     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
16807     NULL, 0, sysctl_willuserspacereboot, "I", "");
16808