xref: /xnu-8792.61.2/libkern/c++/OSKext.cpp (revision 42e220869062b56f8d7d0726fd4c88954f87902c)
1 /*
2  * Copyright (c) 2008-2021 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #define IOKIT_ENABLE_SHARED_PTR
30 
31 extern "C" {
32 #include <string.h>
33 #include <kern/clock.h>
34 #include <kern/host.h>
35 #include <kern/kext_alloc.h>
36 #include <firehose/tracepoint_private.h>
37 #include <firehose/chunk_private.h>
38 #include <os/firehose_buffer_private.h>
39 #include <vm/vm_map.h>
40 #include <kextd/kextd_mach.h>
41 #include <libkern/kernel_mach_header.h>
42 #include <libkern/kext_panic_report.h>
43 #include <libkern/kext_request_keys.h>
44 #include <libkern/mkext.h>
45 #include <libkern/prelink.h>
46 #include <libkern/version.h>
47 #include <libkern/zlib.h>
48 #include <mach/host_special_ports.h>
49 #include <mach/mach_vm.h>
50 #include <mach/mach_time.h>
51 #include <uuid/uuid.h>
52 #include <sys/random.h>
53 #include <pexpert/pexpert.h>
54 
55 #include <sys/pgo.h>
56 
57 #if CONFIG_CSR
58 #include <sys/csr.h>
59 #include <sys/stat.h>
60 #include <sys/vnode.h>
61 #endif /* CONFIG_CSR */
62 };
63 
64 #if CONFIG_MACF
65 #include <sys/kauth.h>
66 #include <security/mac_framework.h>
67 #endif
68 
69 #include <vm/vm_kern.h>
70 #include <sys/sysctl.h>
71 #include <kern/task.h>
72 #include <os/cpp_util.h>
73 
74 #include <libkern/OSKextLibPrivate.h>
75 #include <libkern/c++/OSKext.h>
76 #include <libkern/c++/OSLib.h>
77 
78 #include <IOKit/IOLib.h>
79 #include <IOKit/IOCatalogue.h>
80 #include <IOKit/IORegistryEntry.h>
81 #include <IOKit/IOService.h>
82 #include <IOKit/IOUserServer.h>
83 
84 #include <IOKit/IOStatisticsPrivate.h>
85 #include <IOKit/IOBSD.h>
86 #include <IOKit/IOPlatformExpert.h>
87 
88 #include <san/kasan.h>
89 
90 #if PRAGMA_MARK
91 #pragma mark External & Internal Function Protos
92 #endif
93 /*********************************************************************
94 *********************************************************************/
95 extern "C" {
96 extern int  IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
97 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
98 
99 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
100 extern int dtrace_keep_kernel_symbols(void);
101 
102 #if defined(__x86_64__) || defined(__i386__)
103 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide);
104 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers);
105 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size);
106 static void *allocate_kcfileset_map_entry_list(void);
107 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size);
108 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable);
109 int vnode_put(struct vnode *vp);
110 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size,
111     void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot);
112 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size);
113 void * ubc_getobject(struct vnode *vp, __unused int flags);
114 #endif //(__x86_64__) || defined(__i386__)
115 }
116 
117 extern unsigned long gVirtBase;
118 extern unsigned long gPhysBase;
119 extern vm_map_t g_kext_map;
120 
121 bool pageableKCloaded = false;
122 bool auxKCloaded = false;
123 bool resetAuxKCSegmentOnUnload = false;
124 
125 extern boolean_t pageablekc_uuid_valid;
126 extern uuid_t pageablekc_uuid;
127 extern uuid_string_t pageablekc_uuid_string;
128 
129 extern boolean_t auxkc_uuid_valid;
130 extern uuid_t auxkc_uuid;
131 extern uuid_string_t auxkc_uuid_string;
132 
133 static OSReturn _OSKextCreateRequest(
134 	const char    * predicate,
135 	OSSharedPtr<OSDictionary> & requestP);
136 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
137 static OSObject * _OSKextGetRequestArgument(
138 	OSDictionary * requestDict,
139 	const char   * argName);
140 static bool _OSKextSetRequestArgument(
141 	OSDictionary    * requestDict,
142 	const char      * argName,
143 	OSMetaClassBase * value);
144 template <typename T>
145 static T * _OSKextExtractPointer(OSValueObject<T *> * wrapper);
146 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper);
147 static OSReturn _OSDictionarySetCStringValue(
148 	OSDictionary * dict,
149 	const char   * key,
150 	const char   * value);
151 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
152 #if CONFIG_KXLD
153 static bool _OSKextInPrelinkRebuildWindow(void);
154 #endif
155 
156 // We really should add containsObject() & containsCString to OSCollection & subclasses.
157 // So few pad slots, though....
158 static bool _OSArrayContainsCString(OSArray * array, const char * cString);
159 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code);
160 
161 static const char *getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size);
162 
163 /* Prelinked arm kexts do not have VM entries because the method we use to
164  * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
165  * not work on ARM.  To get around that, we must free prelinked kext
166  * executables with ml_static_mfree() instead of kext_free().
167  */
168 #if __i386__ || __x86_64__
169 #define VM_MAPPED_KEXTS 1
170 #define KASLR_KEXT_DEBUG 0
171 #define KASLR_IOREG_DEBUG 0
172 #elif __arm__ || __arm64__
173 #define VM_MAPPED_KEXTS 0
174 #define KASLR_KEXT_DEBUG 0
175 #else
176 #error Unsupported architecture
177 #endif
178 
179 #if PRAGMA_MARK
180 #pragma mark Constants & Macros
181 #endif
182 /*********************************************************************
183 * Constants & Macros
184 *********************************************************************/
185 
186 /* Use this number to create containers.
187  */
188 #define kOSKextTypicalLoadCount      (150)
189 #define kOSKextTypicalUpgradeCount     (5)
190 
191 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
192  * A loaded kext will no dependents or external retains will have 2 retains.
193  */
194 #define kOSKextMinRetainCount        (1)
195 #define kOSKextMinLoadedRetainCount  (2)
196 
197 #define kOSKextMaxDextLaunchedCount  (~((uint32_t)0))
198 #define KOSBundleDextUniqueIdentifierMaxStringLength (KOSBundleDextUniqueIdentifierMaxLength * 2 +1)
199 
200 /**********
201  * Strings and substrings used in dependency resolution.
202  */
203 #define APPLE_KEXT_PREFIX            "com.apple."
204 #define KERNEL_LIB                   "com.apple.kernel"
205 
206 #define PRIVATE_KPI                  "com.apple.kpi.private"
207 
208 /* Version for compatbility pseudokexts (com.apple.kernel.*),
209  * compatible back to v6.0.
210  */
211 #define KERNEL6_LIB                  "com.apple.kernel.6.0"
212 #define KERNEL6_VERSION              "7.9.9"
213 
214 #define KERNEL_LIB_PREFIX            "com.apple.kernel."
215 #define KPI_LIB_PREFIX               "com.apple.kpi."
216 
217 #define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0)
218 
219 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
220 #define MINIMUM_WAKEUP_SECONDS (30)
221 
222 /*********************************************************************
223 * infoDict keys for internally-stored data. Saves on ivar slots for
224 * objects we don't keep around past boot time or during active load.
225 *********************************************************************/
226 
227 /* A usable, uncompressed file is stored under this key.
228  */
229 #define _kOSKextExecutableKey                "_OSKextExecutable"
230 
231 /* An indirect reference to the executable file from an mkext
232  * is stored under this key.
233  */
234 #define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference"
235 
236 /* If the file is contained in a larger buffer laid down by the booter or
237  * sent from user space, the OSKext stores that OSData under this key so that
238  * references are properly tracked. This is always an mkext, right now.
239  */
240 #define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData"
241 
242 #define OS_LOG_HDR_VERSION  1
243 #define NUM_OS_LOG_SECTIONS 3
244 
245 #define OS_LOG_SECT_IDX         0
246 #define CSTRING_SECT_IDX        1
247 #define ASAN_CSTRING_SECT_IDX   2
248 
249 #if PRAGMA_MARK
250 #pragma mark Typedefs
251 #endif
252 /*********************************************************************
253 * Typedefs
254 *********************************************************************/
255 
256 /*********************************************************************
257 * osLogDataHeaderRef describes the header information of an OSData
258 * object that is returned when querying for kOSBundleLogStringsKey.
259 * We currently return information regarding 2 sections - os_log and
260 * cstring. In the case that the os_log section doesn't exist, we just
261 * return an offset and length of 0 for that section.
262 *********************************************************************/
263 typedef struct osLogDataHeader {
264 	uint32_t version;
265 	uint32_t sect_count;
266 	struct {
267 		uint32_t sect_offset;
268 		uint32_t sect_size;
269 	} sections[0];
270 } osLogDataHeaderRef;
271 
272 /*********************************************************************
273 * MkextEntryRef describes the contents of an OSData object
274 * referencing a file entry from an mkext so that we can uncompress
275 * (if necessary) and extract it on demand.
276 *
277 * It contains the mkextVersion in case we ever wind up supporting
278 * multiple mkext formats. Mkext format 1 is officially retired as of
279 * Snow Leopard.
280 *********************************************************************/
281 typedef struct MkextEntryRef {
282 	mkext_basic_header * mkext; // beginning of whole mkext file
283 	void               * fileinfo;// mkext2_file_entry or equiv; see mkext.h
284 } MkextEntryRef;
285 
286 #if PRAGMA_MARK
287 #pragma mark Global and static Module Variables
288 #endif
289 /*********************************************************************
290 * Global & static variables, used to keep track of kexts.
291 *********************************************************************/
292 
293 static  bool                sPrelinkBoot               = false;
294 static  bool                sSafeBoot                  = false;
295 static  bool                sKeepSymbols               = false;
296 static  bool                sPanicOnKCMismatch         = false;
297 static  bool                sOSKextWasResetAfterUserspaceReboot = false;
298 
299 /*********************************************************************
300  * sKextLock is the principal lock for OSKext, and guards all static
301  * and global variables not owned by other locks (declared further
302  * below). It must be taken by any entry-point method or function,
303  * including internal functions called on scheduled threads.
304  *
305  * sKextLock and sKextInnerLock are recursive due to multiple functions
306  * that are called both externally and internally. The other locks are
307  * nonrecursive.
308  *
309  * Which locks are taken depends on what they protect, but if more than
310  * one must be taken, they must always be locked in this order
311  * (and unlocked in reverse order) to prevent deadlocks:
312  *
313  *    1. sKextLock
314  *    2. sKextInnerLock
315  *    3. sKextSummariesLock
316  *    4. sKextLoggingLock
317  */
318 static IORecursiveLock    * sKextLock                  = NULL;
319 
320 static OSSharedPtr<OSDictionary>   sKextsByID;
321 static OSSharedPtr<OSDictionary>   sExcludeListByID;
322 static OSKextVersion               sExcludeListVersion        = 0;
323 static OSSharedPtr<OSArray>        sLoadedKexts;
324 static OSSharedPtr<OSDictionary>   sNonLoadableKextsByID;
325 static OSSharedPtr<OSArray>        sUnloadedPrelinkedKexts;
326 static OSSharedPtr<OSArray>        sLoadedDriverKitKexts;
327 static OSSharedPtr<OSDictionary>   sDriverKitToUpgradeByID;
328 
329 // Requests to the IOKit daemon waiting to be picked up.
330 static OSSharedPtr<OSArray>        sKernelRequests;
331 // Identifier of kext load requests in sKernelRequests
332 static OSSharedPtr<OSSet>          sPostedKextLoadIdentifiers;
333 static OSSharedPtr<OSArray>        sRequestCallbackRecords;
334 
335 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
336 static OSSharedPtr<OSSet>          sAllKextLoadIdentifiers;
337 #if CONFIG_KXLD
338 static KXLDContext        * sKxldContext               = NULL;
339 #endif
340 static uint32_t             sNextLoadTag               = 0;
341 static uint32_t             sNextRequestTag            = 0;
342 
343 static bool                 sUserLoadsActive           = false;
344 static bool                 sIOKitDaemonActive         = false;
345 static bool                 sDeferredLoadSucceeded     = false;
346 static bool                 sConsiderUnloadsExecuted   = false;
347 
348 #if NO_KEXTD
349 static bool                 sKernelRequestsEnabled     = false;
350 #else
351 static bool                 sKernelRequestsEnabled     = true;
352 #endif
353 static bool                 sLoadEnabled               = true;
354 static bool                 sUnloadEnabled             = true;
355 
356 /*********************************************************************
357  * Stuff for the OSKext representing the kernel itself.
358  **********/
359 static OSKext          * sKernelKext             = NULL;
360 
361 /* Set up a fake kmod_info struct for the kernel.
362  * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
363  * before OSKext is initialized; that call only needs the name
364  * and address to be set correctly.
365  *
366  * We don't do much else with the kerne's kmod_info; we never
367  * put it into the kmod list, never adjust the reference count,
368  * and never have kernel components reference it.
369  * For that matter, we don't do much with kmod_info structs
370  * at all anymore! We just keep them filled in for gdb and
371  * binary compability.
372  */
373 kmod_info_t g_kernel_kmod_info = {
374 	.next =            NULL,
375 	.info_version =    KMOD_INFO_VERSION,
376 	.id =              0,             // loadTag: kernel is always 0
377 	.name =            kOSKextKernelIdentifier,// bundle identifier
378 	.version =         "0",           // filled in in OSKext::initialize()
379 	.reference_count = -1,            // never adjusted; kernel never unloads
380 	.reference_list =  NULL,
381 	.address =         0,
382 	.size =            0,             // filled in in OSKext::initialize()
383 	.hdr_size =        0,
384 	.start =           NULL,
385 	.stop =            NULL
386 };
387 
388 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
389 
390 kmod_info_t invalid_kmod_info = {
391 	.next =            NULL,
392 	.info_version =    KMOD_INFO_VERSION,
393 	.id =              UINT32_MAX,
394 	.name =            "invalid",
395 	.version =         "0",
396 	.reference_count = -1,
397 	.reference_list =  NULL,
398 	.address =         0,
399 	.size =            0,
400 	.hdr_size =        0,
401 	.start =           NULL,
402 	.stop =            NULL
403 };
404 
405 extern "C" {
406 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
407 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
408 // misc_protos.h, db_low_trace.c, kgmacros
409 // 'kmod' is a holdover from the old kmod system, we can't rename it.
410 kmod_info_t * kmod = NULL;
411 
412 #define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE)
413 
414 
415 static char     * loaded_kext_paniclist         = NULL;
416 static uint32_t   loaded_kext_paniclist_size    = 0;
417 
418 AbsoluteTime      last_loaded_timestamp;
419 static char       last_loaded_str_buf[2 * KMOD_MAX_NAME];
420 static u_long     last_loaded_strlen            = 0;
421 static void     * last_loaded_address           = NULL;
422 static u_long     last_loaded_size              = 0;
423 
424 AbsoluteTime      last_unloaded_timestamp;
425 static char       last_unloaded_str_buf[2 * KMOD_MAX_NAME];
426 static u_long     last_unloaded_strlen          = 0;
427 static void     * last_unloaded_address         = NULL;
428 static u_long     last_unloaded_size            = 0;
429 
430 // Statically linked kmods described by several mach-o sections:
431 //
432 // kPrelinkInfoSegment:kBuiltinInfoSection
433 // Array of pointers to kmod_info_t structs.
434 //
435 // kPrelinkInfoSegment:kBuiltinInfoSection
436 // Array of pointers to an embedded mach-o header.
437 //
438 // __DATA:kBuiltinInitSection, kBuiltinTermSection
439 // Structors for all kmods. Has to be filtered by proc address.
440 //
441 
442 static uint32_t gBuiltinKmodsCount;
443 static kernel_section_t * gBuiltinKmodsSectionInfo;
444 static kernel_section_t * gBuiltinKmodsSectionStart;
445 
446 const OSSymbol              * gIOSurfaceIdentifier;
447 vm_tag_t                      gIOSurfaceTag;
448 
449 /*********************************************************************
450  * sKextInnerLock protects against cross-calls with IOService and
451  * IOCatalogue, and owns the variables declared immediately below.
452  *
453  * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
454  *
455  * When both sKextLock and sKextInnerLock need to be taken,
456  * always lock sKextLock first and unlock it second. Never take both
457  * locks in an entry point to OSKext; if you need to do so, you must
458  * spawn an independent thread to avoid potential deadlocks for threads
459  * calling into OSKext.
460  **********/
461 static IORecursiveLock *    sKextInnerLock             = NULL;
462 
463 #if XNU_TARGET_OS_OSX
464 static bool                 sAutounloadEnabled         = true;
465 #endif
466 static bool                 sConsiderUnloadsCalled     = false;
467 static bool                 sConsiderUnloadsPending    = false;
468 
469 static unsigned int         sConsiderUnloadDelay       = 60;     // seconds
470 static thread_call_t        sUnloadCallout             = NULL;
471 #if CONFIG_KXLD
472 static thread_call_t        sDestroyLinkContextThread  = NULL;   // one-shot, one-at-a-time thread
473 #endif // CONFIG_KXLD
474 static bool                 sSystemSleep               = false;  // true when system going to sleep
475 static AbsoluteTime         sLastWakeTime;                       // last time we woke up
476 
477 /*********************************************************************
478  * Backtraces can be printed at various times so we need a tight lock
479  * on data used for that. sKextSummariesLock protects the variables
480  * declared immediately below.
481  *
482  * gLoadedKextSummaries is accessed by other modules, but only during
483  * a panic so the lock isn't needed then.
484  *
485  * gLoadedKextSummaries has the "used" attribute in order to ensure
486  * that it remains visible even when we are performing extremely
487  * aggressive optimizations, as it is needed to allow the debugger
488  * to automatically parse the list of loaded kexts.
489  **********/
490 static IOLock                 * sKextSummariesLock                = NULL;
491 extern "C" lck_ticket_t         vm_allocation_sites_lock;
492 static lck_ticket_t           * sKextAccountsLock = &vm_allocation_sites_lock;
493 
494 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
495 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
496 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
497 static size_t sLoadedKextSummariesAllocSize = 0;
498 
499 static OSKextActiveAccount    * sKextAccounts;
500 static uint32_t                 sKextAccountsCount;
501 };
502 
503 /*********************************************************************
504  * sKextLoggingLock protects the logging variables declared immediately below.
505  **********/
506 static IOLock                 * sKextLoggingLock           = NULL;
507 
508 static  const OSKextLogSpec     kDefaultKernelLogFilter    = kOSKextLogBasicLevel |
509     kOSKextLogVerboseFlagsMask;
510 static  OSKextLogSpec           sKernelLogFilter           = kDefaultKernelLogFilter;
511 static  bool                    sBootArgLogFilterFound     = false;
512 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
513     0, "kernel kext logging");
514 
515 static  OSKextLogSpec           sUserSpaceKextLogFilter    = kOSKextLogSilentFilter;
516 static  OSSharedPtr<OSArray>    sUserSpaceLogSpecArray;
517 static  OSSharedPtr<OSArray>    sUserSpaceLogMessageArray;
518 
519 /*********
520  * End scope for sKextInnerLock-protected variables.
521  *********************************************************************/
522 
523 /*********************************************************************
524  * OSValueObject concrete type instantiations
525  **********/
526 OSDefineValueObjectForDependentType(void*)
527 OSDefineValueObjectForDependentType(OSKextRequestResourceCallback)
528 
529 
530 /**********************************************************************/
531 
532 TUNABLE(uint32_t, kMaxDextCrashesInOneDay, "daily_max_dext_crashes", kMaxDextCrashesInOneDayDefault);
533 
534 /*********************************************************************
535  *  helper function used for collecting PGO data upon unload of a kext
536  */
537 
538 static int OSKextGrabPgoDataLocked(OSKext *kext,
539     bool metadata,
540     uuid_t instance_uuid,
541     uint64_t *pSize,
542     char *pBuffer,
543     uint64_t bufferSize);
544 
545 /**********************************************************************/
546 
547 
548 
549 #if PRAGMA_MARK
550 #pragma mark OSData callbacks (need to move to OSData)
551 #endif
552 /*********************************************************************
553 * C functions used for callbacks.
554 *********************************************************************/
555 extern "C" {
556 void
osdata_kmem_free(void * ptr,unsigned int length)557 osdata_kmem_free(void * ptr, unsigned int length)
558 {
559 	kmem_free(kernel_map, (vm_address_t)ptr, length);
560 	return;
561 }
562 
563 void
osdata_phys_free(void * ptr,unsigned int length)564 osdata_phys_free(void * ptr, unsigned int length)
565 {
566 	ml_static_mfree((vm_offset_t)ptr, length);
567 	return;
568 }
569 
570 void
osdata_vm_deallocate(void * ptr,unsigned int length)571 osdata_vm_deallocate(void * ptr, unsigned int length)
572 {
573 	(void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
574 	return;
575 }
576 
577 void
osdata_kext_free(void * ptr,unsigned int length)578 osdata_kext_free(void * ptr, unsigned int length)
579 {
580 	(void)kext_free((vm_offset_t)ptr, length);
581 }
582 };
583 
584 #if PRAGMA_MARK
585 #pragma mark KXLD Allocation Callback
586 #endif
587 #if CONFIG_KXLD
588 /*********************************************************************
589 * KXLD Allocation Callback
590 *********************************************************************/
591 kxld_addr_t
kern_allocate(u_long size,KXLDAllocateFlags * flags,void * user_data)592 kern_allocate(
593 	u_long              size,
594 	KXLDAllocateFlags * flags,
595 	void              * user_data)
596 {
597 	vm_address_t  result       = 0; // returned
598 	kern_return_t mach_result  = KERN_FAILURE;
599 	bool          success      = false;
600 	OSKext      * theKext      = (OSKext *)user_data;
601 	unsigned int  roundSize    = 0;
602 	OSSharedPtr<OSData>      linkBuffer;
603 
604 	if (round_page(size) > UINT_MAX) {
605 		OSKextLog(theKext,
606 		    kOSKextLogErrorLevel |
607 		    kOSKextLogGeneralFlag,
608 		    "%s: Requested memory size is greater than UINT_MAX.",
609 		    theKext->getIdentifierCString());
610 		goto finish;
611 	}
612 
613 	roundSize = (unsigned int)round_page(size);
614 
615 	mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
616 	if (mach_result != KERN_SUCCESS) {
617 		OSKextLog(theKext,
618 		    kOSKextLogErrorLevel |
619 		    kOSKextLogGeneralFlag,
620 		    "Can't allocate kernel memory to link %s.",
621 		    theKext->getIdentifierCString());
622 		goto finish;
623 	}
624 
625 	/* Create an OSData wrapper for the allocated buffer.
626 	 */
627 	linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
628 	if (!linkBuffer) {
629 		OSKextLog(theKext,
630 		    kOSKextLogErrorLevel |
631 		    kOSKextLogGeneralFlag,
632 		    "Can't allocate linked executable wrapper for %s.",
633 		    theKext->getIdentifierCString());
634 		goto finish;
635 	}
636 	linkBuffer->setDeallocFunction(osdata_kext_free);
637 	OSKextLog(theKext,
638 	    kOSKextLogProgressLevel |
639 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
640 	    "Allocated link buffer for kext %s at %p (%lu bytes).",
641 	    theKext->getIdentifierCString(),
642 	    (void *)result, (unsigned long)roundSize);
643 
644 	theKext->setLinkedExecutable(linkBuffer.get());
645 
646 	*flags = kKxldAllocateWritable;
647 	success = true;
648 
649 finish:
650 	if (!success && result) {
651 		kext_free(result, roundSize);
652 		result = 0;
653 	}
654 
655 	return (kxld_addr_t)result;
656 }
657 
658 /*********************************************************************
659 *********************************************************************/
660 void
kxld_log_callback(KXLDLogSubsystem subsystem,KXLDLogLevel level,const char * format,va_list argList,void * user_data)661 kxld_log_callback(
662 	KXLDLogSubsystem    subsystem,
663 	KXLDLogLevel        level,
664 	const char        * format,
665 	va_list             argList,
666 	void              * user_data)
667 {
668 	OSKext *theKext = (OSKext *) user_data;
669 	OSKextLogSpec logSpec = 0;
670 
671 	switch (subsystem) {
672 	case kKxldLogLinking:
673 		logSpec |= kOSKextLogLinkFlag;
674 		break;
675 	case kKxldLogPatching:
676 		logSpec |= kOSKextLogPatchFlag;
677 		break;
678 	}
679 
680 	switch (level) {
681 	case kKxldLogExplicit:
682 		logSpec |= kOSKextLogExplicitLevel;
683 		break;
684 	case kKxldLogErr:
685 		logSpec |= kOSKextLogErrorLevel;
686 		break;
687 	case kKxldLogWarn:
688 		logSpec |= kOSKextLogWarningLevel;
689 		break;
690 	case kKxldLogBasic:
691 		logSpec |= kOSKextLogProgressLevel;
692 		break;
693 	case kKxldLogDetail:
694 		logSpec |= kOSKextLogDetailLevel;
695 		break;
696 	case kKxldLogDebug:
697 		logSpec |= kOSKextLogDebugLevel;
698 		break;
699 	}
700 
701 	OSKextVLog(theKext, logSpec, format, argList);
702 }
703 #endif // CONFIG_KXLD
704 
705 #if PRAGMA_MARK
706 #pragma mark IOStatistics defines
707 #endif
708 
709 #if IOKITSTATS
710 
711 #define notifyKextLoadObservers(kext, kmod_info) \
712 do { \
713     IOStatistics::onKextLoad(kext, kmod_info); \
714 } while (0)
715 
716 #define notifyKextUnloadObservers(kext) \
717 do { \
718     IOStatistics::onKextUnload(kext); \
719 } while (0)
720 
721 #define notifyAddClassObservers(kext, addedClass, flags) \
722 do { \
723     IOStatistics::onClassAdded(kext, addedClass); \
724 } while (0)
725 
726 #define notifyRemoveClassObservers(kext, removedClass, flags) \
727 do { \
728     IOStatistics::onClassRemoved(kext, removedClass); \
729 } while (0)
730 
731 #else
732 
733 #define notifyKextLoadObservers(kext, kmod_info)
734 #define notifyKextUnloadObservers(kext)
735 #define notifyAddClassObservers(kext, addedClass, flags)
736 #define notifyRemoveClassObservers(kext, removedClass, flags)
737 
738 #endif /* IOKITSTATS */
739 
740 #if PRAGMA_MARK
741 #pragma mark Module Config (Startup & Shutdown)
742 #endif
743 /*********************************************************************
744 * Module Config (Class Definition & Class Methods)
745 *********************************************************************/
746 #define super OSObject
747 OSDefineMetaClassAndStructors(OSKext, OSObject)
748 
749 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject);
750 
751 OSDefineMetaClassAndStructors(OSDextStatistics, OSObject);
752 
753 /*********************************************************************
754 *********************************************************************/
755 /* static */
756 void
initialize(void)757 OSKext::initialize(void)
758 {
759 	OSSharedPtr<OSData>     kernelExecutable   = NULL;// do not release
760 	u_char          * kernelStart        = NULL;// do not free
761 	size_t            kernelLength       = 0;
762 	IORegistryEntry * registryRoot       = NULL;// do not release
763 	OSSharedPtr<OSNumber> kernelCPUType;
764 	OSSharedPtr<OSNumber> kernelCPUSubtype;
765 	OSKextLogSpec     bootLogFilter      = kOSKextLogSilentFilter;
766 	bool              setResult          = false;
767 	uint64_t        * timestamp          = NULL;
768 	__unused char     bootArgBuffer[16];// for PE_parse_boot_argn w/strings
769 
770 	/* This must be the first thing allocated. Everything else grabs this lock.
771 	 */
772 	sKextLock = IORecursiveLockAlloc();
773 	sKextInnerLock = IORecursiveLockAlloc();
774 	sKextSummariesLock = IOLockAlloc();
775 	sKextLoggingLock = IOLockAlloc();
776 	assert(sKextLock);
777 	assert(sKextInnerLock);
778 	assert(sKextSummariesLock);
779 	assert(sKextLoggingLock);
780 
781 	sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
782 	sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
783 	sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
784 	sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
785 	sKernelRequests = OSArray::withCapacity(0);
786 	sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
787 	sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
788 	sRequestCallbackRecords = OSArray::withCapacity(0);
789 	sDriverKitToUpgradeByID = OSDictionary::withCapacity(kOSKextTypicalUpgradeCount);
790 
791 	assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests &&
792 	    sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
793 	    sRequestCallbackRecords && sUnloadedPrelinkedKexts && sDriverKitToUpgradeByID);
794 
795 	/* Read the log flag boot-args and set the log flags.
796 	 */
797 	if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
798 		sBootArgLogFilterFound = true;
799 		sKernelLogFilter = bootLogFilter;
800 		// log this if any flags are set
801 		OSKextLog(/* kext */ NULL,
802 		    kOSKextLogBasicLevel |
803 		    kOSKextLogFlagsMask,
804 		    "Kernel kext log filter 0x%x per kextlog boot arg.",
805 		    (unsigned)sKernelLogFilter);
806 	}
807 
808 #if !defined(__arm__) && !defined(__arm64__)
809 	/*
810 	 * On our ARM targets, the kernelcache/boot kernel collection contains
811 	 * the set of kexts required to boot, as specified by KCB.  Safeboot is
812 	 * either unsupported, or is supported by the bootloader only loading
813 	 * the boot kernel collection; as a result OSKext has no role to play
814 	 * in safeboot policy on ARM.
815 	 */
816 	sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
817 	    sizeof(bootArgBuffer)) ? true : false;
818 #endif /* defined(__arm__) && defined(__arm64__) */
819 
820 	if (sSafeBoot) {
821 		OSKextLog(/* kext */ NULL,
822 		    kOSKextLogWarningLevel |
823 		    kOSKextLogGeneralFlag,
824 		    "SAFE BOOT DETECTED - "
825 		    "only valid OSBundleRequired kexts will be loaded.");
826 	}
827 
828 	PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
829 #if CONFIG_DTRACE
830 	if (dtrace_keep_kernel_symbols()) {
831 		sKeepSymbols = true;
832 	}
833 #endif /* CONFIG_DTRACE */
834 #if KASAN_DYNAMIC_BLACKLIST
835 	/* needed for function lookup */
836 	sKeepSymbols = true;
837 #endif
838 
839 	/*
840 	 * Should we panic when the SystemKC is not linked against the
841 	 * BootKC that was loaded by the booter? By default: yes, if the
842 	 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic
843 	 * on mis-match and instead just print an error and continue.
844 	 */
845 	sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer,
846 	    sizeof(bootArgBuffer)) ? false : true;
847 
848 	/* Set up an OSKext instance to represent the kernel itself.
849 	 */
850 	sKernelKext = new OSKext;
851 	assert(sKernelKext);
852 
853 	kernelStart = (u_char *)&_mh_execute_header;
854 	kernelLength = getlastaddr() - (vm_offset_t)kernelStart;
855 	assert(kernelLength <= UINT_MAX);
856 	kernelExecutable = OSData::withBytesNoCopy(
857 		kernelStart, (unsigned int)kernelLength);
858 	assert(kernelExecutable);
859 
860 #if KASLR_KEXT_DEBUG
861 	IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %lu (0x%016lx) \n",
862 	    (unsigned long)kernelStart,
863 	    (unsigned long)getlastaddr(),
864 	    kernelLength,
865 	    (unsigned long)vm_kernel_slide,
866 	    (unsigned long)vm_kernel_slide);
867 #endif
868 
869 	sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0
870 	sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier);
871 
872 	sKernelKext->version = OSKextParseVersionString(osrelease);
873 	sKernelKext->compatibleVersion = sKernelKext->version;
874 	sKernelKext->linkedExecutable = os::move(kernelExecutable);
875 	sKernelKext->interfaceUUID = sKernelKext->copyUUID();
876 
877 	sKernelKext->flags.hasAllDependencies = 1;
878 	sKernelKext->flags.kernelComponent = 1;
879 	sKernelKext->flags.prelinked = 0;
880 	sKernelKext->flags.loaded = 1;
881 	sKernelKext->flags.started = 1;
882 	sKernelKext->flags.CPPInitialized = 0;
883 	sKernelKext->flags.jettisonLinkeditSeg = 0;
884 
885 	sKernelKext->kmod_info = &g_kernel_kmod_info;
886 	strlcpy(g_kernel_kmod_info.version, osrelease,
887 	    sizeof(g_kernel_kmod_info.version));
888 	g_kernel_kmod_info.size = kernelLength;
889 	g_kernel_kmod_info.id = sKernelKext->loadTag;
890 
891 	/* Cons up an info dict, so we don't have to have special-case
892 	 * checking all over.
893 	 */
894 	sKernelKext->infoDict = OSDictionary::withCapacity(5);
895 	assert(sKernelKext->infoDict);
896 	setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey,
897 	    sKernelKext->bundleID.get());
898 	assert(setResult);
899 	setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey,
900 	    kOSBooleanTrue);
901 	assert(setResult);
902 
903 	{
904 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease));
905 		assert(scratchString);
906 		setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey,
907 		    scratchString.get());
908 		assert(setResult);
909 	}
910 
911 	{
912 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy("mach_kernel"));
913 		assert(scratchString);
914 		setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey,
915 		    scratchString.get());
916 		assert(setResult);
917 	}
918 
919 	/* Add the kernel kext to the bookkeeping dictionaries. Note that
920 	 * the kernel kext doesn't have a kmod_info struct. copyInfo()
921 	 * gathers info from other places anyhow.
922 	 */
923 	setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext);
924 	assert(setResult);
925 	setResult = sLoadedKexts->setObject(sKernelKext);
926 	assert(setResult);
927 
928 	// XXX: better way with OSSharedPtr?
929 	// sKernelKext remains a valid pointer even after the decref
930 	sKernelKext->release();
931 
932 	registryRoot = IORegistryEntry::getRegistryRoot();
933 	kernelCPUType = OSNumber::withNumber(
934 		(long long unsigned int)_mh_execute_header.cputype,
935 		8 * sizeof(_mh_execute_header.cputype));
936 	kernelCPUSubtype = OSNumber::withNumber(
937 		(long long unsigned int)_mh_execute_header.cpusubtype,
938 		8 * sizeof(_mh_execute_header.cpusubtype));
939 	assert(registryRoot && kernelCPUSubtype && kernelCPUType);
940 
941 	registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get());
942 	registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get());
943 
944 	gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
945 	if (gBuiltinKmodsSectionInfo) {
946 		uint32_t count;
947 
948 		assert(gBuiltinKmodsSectionInfo->addr);
949 		assert(gBuiltinKmodsSectionInfo->size);
950 		assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX);
951 		gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
952 
953 		gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
954 		assert(gBuiltinKmodsSectionStart);
955 		assert(gBuiltinKmodsSectionStart->addr);
956 		assert(gBuiltinKmodsSectionStart->size);
957 		assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX);
958 		count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
959 		// one extra pointer for the end of last kmod
960 		assert(count == (gBuiltinKmodsCount + 1));
961 
962 		vm_kernel_builtinkmod_text     = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
963 		vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
964 	}
965 
966 	// Don't track this object -- it's never released
967 	gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach();
968 
969 	timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
970 	*timestamp = 0;
971 	timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
972 	*timestamp = 0;
973 	timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
974 	*timestamp = 0;
975 
976 	OSKextLog(/* kext */ NULL,
977 	    kOSKextLogProgressLevel |
978 	    kOSKextLogGeneralFlag,
979 	    "Kext system initialized.");
980 
981 	notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
982 
983 	return;
984 }
985 
986 /*********************************************************************
987 * This is expected to be called exactly once, from exactly one thread
988 * context, during kernel bootstrap.
989 *********************************************************************/
990 /* static */
991 OSReturn
removeKextBootstrap(void)992 OSKext::removeKextBootstrap(void)
993 {
994 	OSReturn                   result                = kOSReturnError;
995 
996 	const char               * dt_kernel_header_name = "Kernel-__HEADER";
997 	const char               * dt_kernel_symtab_name = "Kernel-__SYMTAB";
998 	kernel_mach_header_t     * dt_mach_header        = NULL;
999 	int                        dt_mach_header_size   = 0;
1000 	struct symtab_command    * dt_symtab             = NULL;
1001 	int                        dt_symtab_size        = 0;
1002 	int                        dt_result             = 0;
1003 
1004 	kernel_segment_command_t * seg_kld               = NULL;
1005 	kernel_segment_command_t * seg_klddata           = NULL;
1006 	kernel_segment_command_t * seg_linkedit          = NULL;
1007 
1008 	const char __unused      * dt_segment_name       = NULL;
1009 	void       __unused      * segment_paddress      = NULL;
1010 	int        __unused        segment_size          = 0;
1011 
1012 	OSKextLog(/* kext */ NULL,
1013 	    kOSKextLogProgressLevel |
1014 	    kOSKextLogGeneralFlag,
1015 	    "Jettisoning kext bootstrap segments.");
1016 
1017 	/*
1018 	 * keep the linkedit segment around when booted from a new MH_FILESET
1019 	 * KC because all the kexts shared a linkedit segment.
1020 	 */
1021 	kc_format_t kc_format;
1022 	if (!PE_get_primary_kc_format(&kc_format)) {
1023 		OSKextLog(/* kext */ NULL,
1024 		    kOSKextLogErrorLevel |
1025 		    kOSKextLogGeneralFlag,
1026 		    "Unable to determine primary KC format");
1027 	}
1028 
1029 	/*****
1030 	 * Dispose of unnecessary stuff that the booter didn't need to load.
1031 	 */
1032 	dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
1033 	    (void **)&dt_mach_header, &dt_mach_header_size);
1034 	if (dt_result == 0 && dt_mach_header) {
1035 		IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
1036 		    round_page_32(dt_mach_header_size));
1037 	}
1038 	dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
1039 	    (void **)&dt_symtab, &dt_symtab_size);
1040 	if (dt_result == 0 && dt_symtab) {
1041 		IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
1042 		    round_page_32(dt_symtab_size));
1043 	}
1044 
1045 	/*****
1046 	 * KLD & KLDDATA bootstrap segments.
1047 	 */
1048 	// xxx - should rename KLD segment
1049 	seg_kld = getsegbyname("__KLD");
1050 	seg_klddata = getsegbyname("__KLDDATA");
1051 	if (seg_klddata) {
1052 		// __mod_term_func is part of __KLDDATA
1053 		OSRuntimeUnloadCPPForSegment(seg_klddata);
1054 	}
1055 
1056 #if __arm__ || __arm64__
1057 	/* Free the memory that was set up by iBoot.
1058 	 */
1059 #if !defined(KERNEL_INTEGRITY_KTRR) && !defined(KERNEL_INTEGRITY_CTRR)
1060 	/* We cannot free the KLD segment with CTRR enabled as it contains text and
1061 	 * is covered by the contiguous rorgn.
1062 	 */
1063 	dt_segment_name = "Kernel-__KLD";
1064 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1065 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1066 		    (int)segment_size); // calls ml_static_mfree
1067 	} else if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1068 		/* With fileset KCs, the Kernel KLD segment is not recorded in the DT. */
1069 		ml_static_mfree(ml_static_ptovirt(seg_kld->vmaddr - gVirtBase + gPhysBase),
1070 		    seg_kld->vmsize);
1071 	}
1072 #endif
1073 	dt_segment_name = "Kernel-__KLDDATA";
1074 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1075 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1076 		    (int)segment_size);  // calls ml_static_mfree
1077 	} else if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1078 		/* With fileset KCs, the Kernel KLDDATA segment is not recorded in the DT. */
1079 		ml_static_mfree(ml_static_ptovirt(seg_klddata->vmaddr - gVirtBase + gPhysBase),
1080 		    seg_klddata->vmsize);
1081 	}
1082 #elif __i386__ || __x86_64__
1083 	/* On x86, use the mapping data from the segment load command to
1084 	 * unload KLD & KLDDATA directly.
1085 	 * This may invalidate any assumptions about  "avail_start"
1086 	 * defining the lower bound for valid physical addresses.
1087 	 */
1088 	if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1089 		bzero((void *)seg_kld->vmaddr, seg_kld->vmsize);
1090 		ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize);
1091 	}
1092 	if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1093 		bzero((void *)seg_klddata->vmaddr, seg_klddata->vmsize);
1094 		ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize);
1095 	}
1096 #else
1097 #error arch
1098 #endif
1099 
1100 	/*****
1101 	 * Prelinked kernel's symtab (if there is one).
1102 	 */
1103 	if (kc_format != KCFormatFileset) {
1104 		kernel_section_t * sect;
1105 		sect = getsectbyname("__PRELINK", "__symtab");
1106 		if (sect && sect->addr && sect->size) {
1107 			ml_static_mfree(sect->addr, sect->size);
1108 		}
1109 	}
1110 
1111 	seg_linkedit = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
1112 
1113 	/* kxld always needs the kernel's __LINKEDIT segment, but we can make it
1114 	 * pageable, unless keepsyms is set.  To do that, we have to copy it from
1115 	 * its booter-allocated memory, free the booter memory, reallocate proper
1116 	 * managed memory, then copy the segment back in.
1117 	 *
1118 	 * NOTE: This optimization is not valid for fileset KCs because each
1119 	 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment
1120 	 * that points to one fileset-global LINKEDIT segment. This
1121 	 * optimization is also only valid for platforms that support vm
1122 	 * mapped kexts or mapped kext collections (pageable KCs)
1123 	 */
1124 #if VM_MAPPED_KEXTS
1125 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1126 		kern_return_t mem_result;
1127 		void *seg_copy = NULL;
1128 		void *seg_data = NULL;
1129 		vm_map_offset_t seg_offset = 0;
1130 		vm_map_offset_t seg_copy_offset = 0;
1131 		vm_map_size_t seg_length = 0;
1132 
1133 		seg_data = (void *) seg_linkedit->vmaddr;
1134 		seg_offset = (vm_map_offset_t) seg_linkedit->vmaddr;
1135 		seg_length = (vm_map_size_t) seg_linkedit->vmsize;
1136 
1137 		/* Allocate space for the LINKEDIT copy.
1138 		 */
1139 		mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
1140 		    seg_length, KMA_ZERO, VM_KERN_MEMORY_KEXT);
1141 		if (mem_result != KERN_SUCCESS) {
1142 			OSKextLog(/* kext */ NULL,
1143 			    kOSKextLogErrorLevel |
1144 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1145 			    "Can't copy __LINKEDIT segment for VM reassign.");
1146 			return result;
1147 		}
1148 		seg_copy_offset = (vm_map_offset_t) seg_copy;
1149 
1150 		/* Copy it out.
1151 		 */
1152 		memcpy(seg_copy, seg_data, seg_length);
1153 
1154 		/* Dump the booter memory.
1155 		 */
1156 		ml_static_mfree(seg_offset, seg_length);
1157 
1158 		/* Set up the VM region.
1159 		 */
1160 		mem_result = vm_map_enter_mem_object(
1161 			kernel_map,
1162 			&seg_offset,
1163 			seg_length, /* mask */ 0,
1164 			VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
1165 			VM_MAP_KERNEL_FLAGS_NONE,
1166 			VM_KERN_MEMORY_NONE,
1167 			(ipc_port_t)NULL,
1168 			(vm_object_offset_t) 0,
1169 			/* copy */ FALSE,
1170 			/* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
1171 			/* max_protection */ VM_PROT_ALL,
1172 			/* inheritance */ VM_INHERIT_DEFAULT);
1173 		if ((mem_result != KERN_SUCCESS) ||
1174 		    (seg_offset != (vm_map_offset_t) seg_data)) {
1175 			OSKextLog(/* kext */ NULL,
1176 			    kOSKextLogErrorLevel |
1177 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1178 			    "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1179 			    seg_data, seg_length, mem_result);
1180 			return result;
1181 		}
1182 
1183 		/* And copy it back.
1184 		 */
1185 		memcpy(seg_data, seg_copy, seg_length);
1186 
1187 		/* Free the copy.
1188 		 */
1189 		kmem_free(kernel_map, seg_copy_offset, seg_length);
1190 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1191 		/* Remove the linkedit segment of the Boot KC */
1192 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1193 		OSKext::jettisonFileSetLinkeditSegment(mh);
1194 	}
1195 #else // !VM_MAPPED_KEXTS
1196 	/*****
1197 	 * Dump the LINKEDIT segment, unless keepsyms is set.
1198 	 */
1199 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1200 		dt_segment_name = "Kernel-__LINKEDIT";
1201 		if (0 == IODTGetLoaderInfo(dt_segment_name,
1202 		    &segment_paddress, &segment_size)) {
1203 #ifdef SECURE_KERNEL
1204 			vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
1205 			bzero((void*)vmaddr, segment_size);
1206 #endif
1207 			IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1208 			    (int)segment_size);
1209 		}
1210 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1211 		/* Remove the linkedit segment of the Boot KC */
1212 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1213 		OSKext::jettisonFileSetLinkeditSegment(mh);
1214 	} else {
1215 		OSKextLog(/* kext */ NULL,
1216 		    kOSKextLogBasicLevel |
1217 		    kOSKextLogGeneralFlag,
1218 		    "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1219 	}
1220 #endif // VM_MAPPED_KEXTS
1221 
1222 	result = kOSReturnSuccess;
1223 
1224 	return result;
1225 }
1226 
1227 #if CONFIG_KXLD
1228 /*********************************************************************
1229 *********************************************************************/
1230 void
flushNonloadedKexts(Boolean flushPrelinkedKexts)1231 OSKext::flushNonloadedKexts(
1232 	Boolean flushPrelinkedKexts)
1233 {
1234 	OSSharedPtr<OSSet>                keepKexts;
1235 
1236 	/* TODO: make this more efficient with MH_FILESET kexts */
1237 
1238 	// Do not unload prelinked kexts on arm because the kernelcache is not
1239 	// structured in a way that allows them to be unmapped
1240 #if !defined(__x86_64__)
1241 	flushPrelinkedKexts = false;
1242 #endif /* defined(__x86_64__) */
1243 
1244 	IORecursiveLockLock(sKextLock);
1245 
1246 	OSKextLog(/* kext */ NULL,
1247 	    kOSKextLogProgressLevel |
1248 	    kOSKextLogKextBookkeepingFlag,
1249 	    "Flushing nonloaded kexts and other unused data.");
1250 
1251 	OSKext::considerDestroyingLinkContext();
1252 
1253 	/* If we aren't flushing unused prelinked kexts, we have to put them
1254 	 * aside while we flush everything else so make a container for them.
1255 	 */
1256 	keepKexts = OSSet::withCapacity(16);
1257 	if (!keepKexts) {
1258 		goto finish;
1259 	}
1260 
1261 	/* Set aside prelinked kexts (in-use or not) and break
1262 	 * any lingering inter-kext references for nonloaded kexts
1263 	 * so they have min. retain counts.
1264 	 */
1265 	{
1266 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1267 			OSKext * thisKext = OSDynamicCast(OSKext, obj);
1268 			if (!thisKext) {
1269 			        return false;
1270 			}
1271 			if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
1272 			        keepKexts->setObject(thisKext);
1273 			} else if (!thisKext->declaresExecutable()) {
1274 			        /*
1275 			         * Don't unload codeless kexts, because they never appear in the loadedKexts array.
1276 			         * Requesting one from the IOKit daemon will load it and then immediately remove it by calling
1277 			         * flushNonloadedKexts().
1278 			         * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
1279 			         */
1280 			        keepKexts->setObject(thisKext);
1281 			} else if (thisKext->isInFileset()) {
1282 			        /* keep all kexts in the new MH_FILESET KC */
1283 			        keepKexts->setObject(thisKext);
1284 			}
1285 
1286 			thisKext->flushDependencies(/* forceIfLoaded */ false);
1287 			return false;
1288 		});
1289 	}
1290 	/* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1291 	 */
1292 	sKextsByID->flushCollection();
1293 
1294 	/* Now put the loaded kexts back into the ID dictionary.
1295 	 */
1296 	sLoadedKexts->iterateObjects(^bool (OSObject * obj) {
1297 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1298 		if (!thisKext) {
1299 		        return false;
1300 		}
1301 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1302 		return false;
1303 	});
1304 
1305 	/* Finally, put back the kept kexts if we saved any.
1306 	 */
1307 	keepKexts->iterateObjects(^bool (OSObject * obj) {
1308 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1309 		if (!thisKext) {
1310 		        return false;
1311 		}
1312 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1313 		return false;
1314 	});
1315 
1316 finish:
1317 	IORecursiveLockUnlock(sKextLock);
1318 	return;
1319 }
1320 #else /* !CONFIG_KXLD */
1321 
1322 void
flushNonloadedKexts(Boolean flushPrelinkedKexts __unused)1323 OSKext::flushNonloadedKexts(
1324 	Boolean flushPrelinkedKexts __unused)
1325 {
1326 	IORecursiveLockLock(sKextLock);
1327 
1328 	OSKextLog(/* kext */ NULL,
1329 	    kOSKextLogProgressLevel |
1330 	    kOSKextLogKextBookkeepingFlag,
1331 	    "Flushing dependency info for non-loaded kexts.");
1332 
1333 	/*
1334 	 * In a world where we don't dynamically link kexts, they all come
1335 	 * from a kext collection that's either in wired memory, or
1336 	 * wire-on-demand. We don't need to mess around with moving kexts in
1337 	 * and out of the sKextsByID array - they can all just stay there.
1338 	 * Here we just flush the dependency list for kexts that are not
1339 	 * loaded.
1340 	 */
1341 	sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1342 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1343 		if (!thisKext) {
1344 		        return false;
1345 		}
1346 		thisKext->flushDependencies(/* forceIfLoaded */ false);
1347 		return false;
1348 	});
1349 
1350 	IORecursiveLockUnlock(sKextLock);
1351 	return;
1352 }
1353 
1354 #endif /* CONFIG_KXLD */
1355 
1356 /*********************************************************************
1357 *********************************************************************/
1358 /* static */
1359 void
setIOKitDaemonActive(bool active)1360 OSKext::setIOKitDaemonActive(bool active)
1361 {
1362 	IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
1363 	IORecursiveLockLock(sKextLock);
1364 	sIOKitDaemonActive = active;
1365 	if (sKernelRequests->getCount()) {
1366 		OSKext::pingIOKitDaemon();
1367 	}
1368 	IORecursiveLockUnlock(sKextLock);
1369 
1370 	return;
1371 }
1372 
1373 /*********************************************************************
1374 * OSKextLib.cpp might need access to this someday but for now it's
1375 * private.
1376 *********************************************************************/
1377 extern "C" {
1378 extern void ipc_port_release_send(ipc_port_t);
1379 };
1380 
1381 /* static */
1382 OSReturn
pingIOKitDaemon(void)1383 OSKext::pingIOKitDaemon(void)
1384 {
1385 	OSReturn    result     = kOSReturnError;
1386 #if !NO_KEXTD
1387 	mach_port_t kextd_port = IPC_PORT_NULL;
1388 
1389 	if (!sIOKitDaemonActive) {
1390 		result = kOSKextReturnDisabled; // basically unavailable
1391 		goto finish;
1392 	}
1393 
1394 	result = host_get_kextd_port(host_priv_self(), &kextd_port);
1395 	if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1396 		OSKextLog(/* kext */ NULL,
1397 		    kOSKextLogErrorLevel |
1398 		    kOSKextLogIPCFlag,
1399 		    "Can't get " kIOKitDaemonName " port.");
1400 		goto finish;
1401 	}
1402 
1403 	result = kextd_ping(kextd_port);
1404 	if (result != KERN_SUCCESS) {
1405 		OSKextLog(/* kext */ NULL,
1406 		    kOSKextLogErrorLevel |
1407 		    kOSKextLogIPCFlag,
1408 		    kIOKitDaemonName " ping failed (0x%x).", (int)result);
1409 		goto finish;
1410 	}
1411 
1412 finish:
1413 	if (IPC_PORT_VALID(kextd_port)) {
1414 		ipc_port_release_send(kextd_port);
1415 	}
1416 #endif
1417 
1418 	return result;
1419 }
1420 
1421 /*********************************************************************
1422 *********************************************************************/
1423 /* static */
1424 bool
iokitDaemonAvailable(void)1425 OSKext::iokitDaemonAvailable(void)
1426 {
1427 	int notused;
1428 	if (PE_parse_boot_argn("-restore", &notused, sizeof(notused))) {
1429 		return false;
1430 	}
1431 	return true;
1432 }
1433 
1434 /*********************************************************************
1435 *********************************************************************/
1436 /* static */
1437 void
setDeferredLoadSucceeded(Boolean succeeded)1438 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1439 {
1440 	IORecursiveLockLock(sKextLock);
1441 	sDeferredLoadSucceeded = succeeded;
1442 	IORecursiveLockUnlock(sKextLock);
1443 
1444 	return;
1445 }
1446 
1447 /*********************************************************************
1448 * Called from IOSystemShutdownNotification.
1449 *********************************************************************/
1450 /* static */
1451 void
willShutdown(void)1452 OSKext::willShutdown(void)
1453 {
1454 #if !NO_KEXTD
1455 	OSReturn       checkResult = kOSReturnError;
1456 #endif
1457 	OSSharedPtr<OSDictionary> exitRequest;
1458 
1459 	IORecursiveLockLock(sKextLock);
1460 
1461 	OSKext::setLoadEnabled(false);
1462 	OSKext::setUnloadEnabled(false);
1463 	OSKext::setAutounloadsEnabled(false);
1464 	OSKext::setKernelRequestsEnabled(false);
1465 
1466 #if defined(__x86_64__) || defined(__i386__)
1467 	if (IOPMRootDomainGetWillShutdown()) {
1468 		OSKext::freeKCFileSetcontrol();
1469 	}
1470 #endif // (__x86_64__) || defined(__i386__)
1471 
1472 #if !NO_KEXTD
1473 	OSKextLog(/* kext */ NULL,
1474 	    kOSKextLogProgressLevel |
1475 	    kOSKextLogGeneralFlag,
1476 	    "System shutdown; requesting immediate " kIOKitDaemonName " exit.");
1477 
1478 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit,
1479 	    exitRequest);
1480 	if (checkResult != kOSReturnSuccess) {
1481 		goto finish;
1482 	}
1483 	if (!sKernelRequests->setObject(exitRequest.get())) {
1484 		goto finish;
1485 	}
1486 
1487 	OSKext::pingIOKitDaemon();
1488 
1489 finish:
1490 #endif
1491 
1492 	IORecursiveLockUnlock(sKextLock);
1493 	return;
1494 }
1495 
1496 void
willUserspaceReboot(void)1497 OSKext::willUserspaceReboot(void)
1498 {
1499 	OSKext::willShutdown();
1500 	IOService::userSpaceWillReboot();
1501 	gIOCatalogue->terminateDriversForUserspaceReboot();
1502 }
1503 
1504 void
resetAfterUserspaceReboot(void)1505 OSKext::resetAfterUserspaceReboot(void)
1506 {
1507 	OSSharedPtr<OSArray> arr = OSArray::withCapacity(1);
1508 	IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */);
1509 
1510 	IORecursiveLockLock(sKextLock);
1511 	gIOCatalogue->resetAfterUserspaceReboot();
1512 	IOService::userSpaceDidReboot();
1513 	OSKext::removeDaemonExitRequests();
1514 	OSKext::setLoadEnabled(true);
1515 	OSKext::setUnloadEnabled(true);
1516 	OSKext::setAutounloadsEnabled(true);
1517 	OSKext::setKernelRequestsEnabled(true);
1518 	sOSKextWasResetAfterUserspaceReboot = true;
1519 	IORecursiveLockUnlock(sKextLock);
1520 }
1521 
1522 extern "C" void
OSKextResetAfterUserspaceReboot(void)1523 OSKextResetAfterUserspaceReboot(void)
1524 {
1525 	OSKext::resetAfterUserspaceReboot();
1526 }
1527 
1528 /*
1529  * Remove daemon exit requests from sKernelRequests
1530  *
1531  * If we sent a daemon exit request during a userspace reboot and launchd
1532  * killed the IOKit daemon before it was able to dequeue the exit request, the
1533  * next time the daemon starts up it will immediately exit as it gets the old exit request.
1534  *
1535  * This removes exit requests so that this does not happen.
1536  */
1537 void
removeDaemonExitRequests(void)1538 OSKext::removeDaemonExitRequests(void)
1539 {
1540 	OSDictionary * current = NULL;
1541 	OSString     * predicate = NULL;
1542 	size_t         index     = 0;
1543 	OSSharedPtr<const OSSymbol> predicateKey = OSSymbol::withCString(kKextRequestPredicateKey);
1544 
1545 	while (index < sKernelRequests->getCount()) {
1546 		current = OSDynamicCast(OSDictionary, sKernelRequests->getObject(index));
1547 		if (current) {
1548 			predicate = OSDynamicCast(OSString, current->getObject(predicateKey.get()));
1549 			if (predicate && predicate->isEqualTo(kKextRequestPredicateRequestDaemonExit)) {
1550 				sKernelRequests->removeObject(index);
1551 				continue;
1552 			}
1553 		}
1554 		index++;
1555 	}
1556 }
1557 
1558 /*********************************************************************
1559 *********************************************************************/
1560 /* static */
1561 bool
getLoadEnabled(void)1562 OSKext::getLoadEnabled(void)
1563 {
1564 	bool result;
1565 
1566 	IORecursiveLockLock(sKextLock);
1567 	result = sLoadEnabled;
1568 	IORecursiveLockUnlock(sKextLock);
1569 	return result;
1570 }
1571 
1572 /*********************************************************************
1573 *********************************************************************/
1574 /* static */
1575 bool
setLoadEnabled(bool flag)1576 OSKext::setLoadEnabled(bool flag)
1577 {
1578 	bool result;
1579 
1580 	IORecursiveLockLock(sKextLock);
1581 	result = sLoadEnabled;
1582 	sLoadEnabled = (flag ? true : false);
1583 
1584 	if (sLoadEnabled != result) {
1585 		OSKextLog(/* kext */ NULL,
1586 		    kOSKextLogBasicLevel |
1587 		    kOSKextLogLoadFlag,
1588 		    "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1589 	}
1590 
1591 	IORecursiveLockUnlock(sKextLock);
1592 
1593 	return result;
1594 }
1595 
1596 /*********************************************************************
1597 *********************************************************************/
1598 /* static */
1599 bool
getUnloadEnabled(void)1600 OSKext::getUnloadEnabled(void)
1601 {
1602 	bool result;
1603 
1604 	IORecursiveLockLock(sKextLock);
1605 	result = sUnloadEnabled;
1606 	IORecursiveLockUnlock(sKextLock);
1607 	return result;
1608 }
1609 
1610 /*********************************************************************
1611 *********************************************************************/
1612 /* static */
1613 bool
setUnloadEnabled(bool flag)1614 OSKext::setUnloadEnabled(bool flag)
1615 {
1616 	bool result;
1617 
1618 	IORecursiveLockLock(sKextLock);
1619 	result = sUnloadEnabled;
1620 	sUnloadEnabled = (flag ? true : false);
1621 	IORecursiveLockUnlock(sKextLock);
1622 
1623 	if (sUnloadEnabled != result) {
1624 		OSKextLog(/* kext */ NULL,
1625 		    kOSKextLogBasicLevel |
1626 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1627 		    "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1628 	}
1629 
1630 	return result;
1631 }
1632 
1633 /*********************************************************************
1634 * Do not call any function that takes sKextLock here!
1635 *********************************************************************/
1636 /* static */
1637 bool
getAutounloadEnabled(void)1638 OSKext::getAutounloadEnabled(void)
1639 {
1640 #if XNU_TARGET_OS_OSX
1641 	bool result;
1642 
1643 	IORecursiveLockLock(sKextInnerLock);
1644 	result = sAutounloadEnabled ? true : false;
1645 	IORecursiveLockUnlock(sKextInnerLock);
1646 	return result;
1647 #else
1648 	return false;
1649 #endif /* XNU_TARGET_OS_OSX */
1650 }
1651 
1652 /*********************************************************************
1653 * Do not call any function that takes sKextLock here!
1654 *********************************************************************/
1655 /* static */
1656 bool
setAutounloadsEnabled(bool flag)1657 OSKext::setAutounloadsEnabled(bool flag)
1658 {
1659 #if XNU_TARGET_OS_OSX
1660 	bool result;
1661 
1662 	IORecursiveLockLock(sKextInnerLock);
1663 
1664 	result = sAutounloadEnabled;
1665 	sAutounloadEnabled = (flag ? true : false);
1666 	if (!sAutounloadEnabled && sUnloadCallout) {
1667 		thread_call_cancel(sUnloadCallout);
1668 	}
1669 
1670 	if (sAutounloadEnabled != result) {
1671 		OSKextLog(/* kext */ NULL,
1672 		    kOSKextLogBasicLevel |
1673 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1674 		    "Kext autounloading now %sabled.",
1675 		    sAutounloadEnabled ? "en" : "dis");
1676 	}
1677 
1678 	IORecursiveLockUnlock(sKextInnerLock);
1679 
1680 	return result;
1681 #else
1682 	(void)flag;
1683 	return false;
1684 #endif /* XNU_TARGET_OS_OSX */
1685 }
1686 
1687 /*********************************************************************
1688 *********************************************************************/
1689 /* instance method operating on OSKext field */
1690 bool
setAutounloadEnabled(bool flag)1691 OSKext::setAutounloadEnabled(bool flag)
1692 {
1693 	bool result = flags.autounloadEnabled ? true : false;
1694 	flags.autounloadEnabled = flag ? (0 == flags.unloadUnsupported) : 0;
1695 
1696 	if (result != (flag ? true : false)) {
1697 		OSKextLog(this,
1698 		    kOSKextLogProgressLevel |
1699 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1700 		    "Autounloading for kext %s now %sabled.",
1701 		    getIdentifierCString(),
1702 		    flags.autounloadEnabled ? "en" : "dis");
1703 	}
1704 	return result;
1705 }
1706 
1707 /*********************************************************************
1708 *********************************************************************/
1709 /* static */
1710 bool
setKernelRequestsEnabled(bool flag)1711 OSKext::setKernelRequestsEnabled(bool flag)
1712 {
1713 	bool result;
1714 
1715 	IORecursiveLockLock(sKextLock);
1716 	result = sKernelRequestsEnabled;
1717 	sKernelRequestsEnabled = flag ? true : false;
1718 
1719 	if (sKernelRequestsEnabled != result) {
1720 		OSKextLog(/* kext */ NULL,
1721 		    kOSKextLogBasicLevel |
1722 		    kOSKextLogGeneralFlag,
1723 		    "Kernel requests now %sabled.",
1724 		    sKernelRequestsEnabled ? "en" : "dis");
1725 	}
1726 	IORecursiveLockUnlock(sKextLock);
1727 	return result;
1728 }
1729 
1730 /*********************************************************************
1731 *********************************************************************/
1732 /* static */
1733 bool
getKernelRequestsEnabled(void)1734 OSKext::getKernelRequestsEnabled(void)
1735 {
1736 	bool result;
1737 
1738 	IORecursiveLockLock(sKextLock);
1739 	result = sKernelRequestsEnabled;
1740 	IORecursiveLockUnlock(sKextLock);
1741 	return result;
1742 }
1743 
1744 static bool
segmentIsMutable(kernel_segment_command_t * seg)1745 segmentIsMutable(kernel_segment_command_t *seg)
1746 {
1747 	/* Mutable segments have to have VM_PROT_WRITE */
1748 	if ((seg->maxprot & VM_PROT_WRITE) == 0) {
1749 		return false;
1750 	}
1751 	/* Exclude the __DATA_CONST segment */
1752 	if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) {
1753 		return false;
1754 	}
1755 	/* Exclude __LINKEDIT */
1756 	if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) {
1757 		return false;
1758 	}
1759 	return true;
1760 }
1761 
1762 #if PRAGMA_MARK
1763 #pragma mark Kext Life Cycle
1764 #endif
1765 /*********************************************************************
1766 *********************************************************************/
1767 OSSharedPtr<OSKext>
withPrelinkedInfoDict(OSDictionary * anInfoDict,bool doCoalescedSlides,kc_kind_t type)1768 OSKext::withPrelinkedInfoDict(
1769 	OSDictionary * anInfoDict,
1770 	bool doCoalescedSlides,
1771 	kc_kind_t type)
1772 {
1773 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
1774 
1775 	if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) {
1776 		return NULL;
1777 	}
1778 
1779 	return newKext;
1780 }
1781 
1782 OSData *
parseDextUniqueID(OSDictionary * anInfoDict,const char * dextIDCS)1783 OSKext::parseDextUniqueID(
1784 	OSDictionary * anInfoDict,
1785 	const char *dextIDCS)
1786 {
1787 	OSData *ret = NULL;
1788 	OSData *data_duid = OSDynamicCast(OSData, anInfoDict->getObject(kOSBundleDextUniqueIdentifierKey));
1789 	if (data_duid != NULL) {
1790 		if (data_duid->getLength() > KOSBundleDextUniqueIdentifierMaxLength) {
1791 			OSKextLog(NULL,
1792 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
1793 			    "Dext %s DextUniqueIdentifier too long.",
1794 			    dextIDCS);
1795 		} else {
1796 			/*
1797 			 * If the DextUniqueID exists it should be
1798 			 * present also into the personalities.
1799 			 */
1800 			setDextUniqueIDInPersonalities(anInfoDict, data_duid);
1801 			ret = data_duid;
1802 		}
1803 	} else {
1804 		OSKextLog(NULL,
1805 		    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
1806 		    "Dext %s does not have a DextUniqueIdentifier",
1807 		    dextIDCS);
1808 	}
1809 	return ret;
1810 }
1811 
1812 void
setDextUniqueIDInPersonalities(OSDictionary * anInfoDict,OSData * dextUniqueID)1813 OSKext::setDextUniqueIDInPersonalities(
1814 	OSDictionary * anInfoDict,
1815 	OSData * dextUniqueID)
1816 {
1817 	OSDictionary * dextPersonalities = NULL;
1818 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
1819 	OSString * personalityName = NULL;
1820 
1821 	dextPersonalities = OSDynamicCast(OSDictionary,
1822 	    anInfoDict->getObject(kIOKitPersonalitiesKey));
1823 	if (!dextPersonalities || !dextPersonalities->getCount()) {
1824 		return;
1825 	}
1826 
1827 	personalitiesIterator =
1828 	    OSCollectionIterator::withCollection(dextPersonalities);
1829 	if (!personalitiesIterator) {
1830 		return;
1831 	}
1832 	while ((personalityName = OSDynamicCast(OSString,
1833 	    personalitiesIterator->getNextObject()))) {
1834 		OSDictionary * personality = OSDynamicCast(OSDictionary,
1835 		    dextPersonalities->getObject(personalityName));
1836 		if (personality) {
1837 			OSObject *duid = personality->getObject(kOSBundleDextUniqueIdentifierKey);
1838 			if (duid == NULL) {
1839 				personality->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID);
1840 			}
1841 		}
1842 	}
1843 }
1844 /*********************************************************************
1845 *********************************************************************/
1846 bool
initWithPrelinkedInfoDict(OSDictionary * anInfoDict,bool doCoalescedSlides,kc_kind_t type)1847 OSKext::initWithPrelinkedInfoDict(
1848 	OSDictionary * anInfoDict,
1849 	bool doCoalescedSlides,
1850 	kc_kind_t type)
1851 {
1852 	bool            result              = false;
1853 	OSString      * kextPath            = NULL;                // do not release
1854 	OSNumber      * addressNum          = NULL;                // reused; do not release
1855 	OSNumber      * lengthNum           = NULL;                // reused; do not release
1856 	OSBoolean     * scratchBool         = NULL;                // do not release
1857 	void          * data                = NULL;                // do not free
1858 	void          * srcData             = NULL;                // do not free
1859 	OSSharedPtr<OSData>        prelinkedExecutable;
1860 	uint32_t        length              = 0;                // reused
1861 	uintptr_t       kext_slide          = PE_get_kc_slide(type);
1862 	bool            shouldSaveSegments  = false;
1863 	kc_format     format                = KCFormatUnknown;
1864 
1865 	if (!super::init()) {
1866 		goto finish;
1867 	}
1868 
1869 	/* Get the path. Don't look for an arch-specific path property.
1870 	 */
1871 	kextPath = OSDynamicCast(OSString,
1872 	    anInfoDict->getObject(kPrelinkBundlePathKey));
1873 
1874 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
1875 		goto finish;
1876 	}
1877 
1878 #if KASLR_KEXT_DEBUG
1879 	IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString());
1880 #endif
1881 
1882 	/* Also get the executable's bundle-relative path if present.
1883 	 * Don't look for an arch-specific path property.
1884 	 */
1885 	executableRelPath.reset(OSDynamicCast(OSString,
1886 	    anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain);
1887 	userExecutableRelPath.reset(OSDynamicCast(OSString,
1888 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
1889 
1890 	/* Don't need the paths to be in the info dictionary any more.
1891 	 */
1892 	anInfoDict->removeObject(kPrelinkBundlePathKey);
1893 	anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
1894 
1895 	scratchBool = OSDynamicCast(OSBoolean,
1896 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
1897 	if (scratchBool == kOSBooleanTrue) {
1898 		flags.requireExplicitLoad = 1;
1899 	}
1900 
1901 	/* Create an OSData wrapper around the linked executable.
1902 	 */
1903 	addressNum = OSDynamicCast(OSNumber,
1904 	    anInfoDict->getObject(kPrelinkExecutableLoadKey));
1905 	if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) {
1906 		lengthNum = OSDynamicCast(OSNumber,
1907 		    anInfoDict->getObject(kPrelinkExecutableSizeKey));
1908 		if (!lengthNum) {
1909 			OSKextLog(this,
1910 			    kOSKextLogErrorLevel |
1911 			    kOSKextLogArchiveFlag,
1912 			    "Kext %s can't find prelinked kext executable size.",
1913 			    getIdentifierCString());
1914 			return result;
1915 		}
1916 
1917 		data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1918 		length = (uint32_t) (lengthNum->unsigned32BitValue());
1919 
1920 #if KASLR_KEXT_DEBUG
1921 		IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1922 		    (unsigned long)ml_static_unslide((vm_offset_t)data),
1923 		    (unsigned long)data,
1924 		    length);
1925 #endif
1926 
1927 		anInfoDict->removeObject(kPrelinkExecutableLoadKey);
1928 		anInfoDict->removeObject(kPrelinkExecutableSizeKey);
1929 
1930 		/* If the kext's load address differs from its source address, allocate
1931 		 * space in the kext map at the load address and copy the kext over.
1932 		 */
1933 		addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
1934 		if (addressNum) {
1935 			srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
1936 
1937 #if KASLR_KEXT_DEBUG
1938 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1939 			    (unsigned long)ml_static_unslide((vm_offset_t)srcData),
1940 			    (unsigned long)srcData);
1941 #endif
1942 
1943 			if (data != srcData) {
1944 #if __LP64__
1945 				kern_return_t alloc_result;
1946 
1947 				alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
1948 				if (alloc_result != KERN_SUCCESS) {
1949 					OSKextLog(this,
1950 					    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1951 					    "Failed to allocate space for prelinked kext %s.",
1952 					    getIdentifierCString());
1953 					goto finish;
1954 				}
1955 				memcpy(data, srcData, length);
1956 #else
1957 				OSKextLog(this,
1958 				    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1959 				    "Error: prelinked kext %s - source and load addresses "
1960 				    "differ on ILP32 architecture.",
1961 				    getIdentifierCString());
1962 				goto finish;
1963 #endif /* __LP64__ */
1964 			}
1965 
1966 			anInfoDict->removeObject(kPrelinkExecutableSourceKey);
1967 		}
1968 
1969 		prelinkedExecutable = OSData::withBytesNoCopy(data, length);
1970 		if (!prelinkedExecutable) {
1971 			OSKextLog(this,
1972 			    kOSKextLogErrorLevel |
1973 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1974 			    "Kext %s failed to create executable wrapper.",
1975 			    getIdentifierCString());
1976 			goto finish;
1977 		}
1978 
1979 		/*
1980 		 * Fileset KCs are mapped as a whole by iBoot.
1981 		 * Individual kext executables should not be unmapped
1982 		 * by xnu.
1983 		 * Doing so may result in panics like rdar://85419651
1984 		 */
1985 		if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
1986 			prelinkedExecutable->setDeallocFunction(NULL);
1987 		} else { // Not from a Fileset KC
1988 #if VM_MAPPED_KEXTS
1989 			prelinkedExecutable->setDeallocFunction(osdata_kext_free);
1990 #else
1991 			prelinkedExecutable->setDeallocFunction(osdata_phys_free);
1992 #endif
1993 		}
1994 		setLinkedExecutable(prelinkedExecutable.get());
1995 		addressNum = OSDynamicCast(OSNumber,
1996 		    anInfoDict->getObject(kPrelinkKmodInfoKey));
1997 		if (!addressNum) {
1998 			OSKextLog(this,
1999 			    kOSKextLogErrorLevel |
2000 			    kOSKextLogArchiveFlag,
2001 			    "Kext %s can't find prelinked kext kmod_info address.",
2002 			    getIdentifierCString());
2003 			goto finish;
2004 		}
2005 
2006 		if (addressNum->unsigned64BitValue() != 0) {
2007 			kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
2008 			if (kmod_info->address) {
2009 				kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide);
2010 			} else {
2011 				kmod_info->address = (uintptr_t)data;
2012 				kmod_info->size = length;
2013 			}
2014 #if KASLR_KEXT_DEBUG
2015 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
2016 			    (unsigned long)((vm_offset_t)kmod_info) - kext_slide,
2017 			    (unsigned long)kmod_info);
2018 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
2019 			    (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide,
2020 			    (unsigned long)kmod_info->address);
2021  #endif
2022 		}
2023 
2024 		anInfoDict->removeObject(kPrelinkKmodInfoKey);
2025 	}
2026 
2027 	if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) {
2028 		uintptr_t builtinTextStart;
2029 		uintptr_t builtinTextEnd;
2030 
2031 		flags.builtin = true;
2032 		builtinKmodIdx = addressNum->unsigned32BitValue();
2033 		assert(builtinKmodIdx < gBuiltinKmodsCount);
2034 
2035 		builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx];
2036 		builtinTextEnd   = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1];
2037 
2038 		kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx];
2039 		kmod_info->address = builtinTextStart;
2040 		kmod_info->size    = builtinTextEnd - builtinTextStart;
2041 	}
2042 
2043 	/* If the plist has a UUID for an interface, save that off.
2044 	 */
2045 	if (isInterface()) {
2046 		interfaceUUID.reset(OSDynamicCast(OSData,
2047 		    anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain);
2048 		if (interfaceUUID) {
2049 			anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
2050 		}
2051 	}
2052 
2053 	result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides));
2054 	if (!result) {
2055 		goto finish;
2056 	}
2057 
2058 	kc_type = type;
2059 	/* Exclude builtin and codeless kexts */
2060 	if (prelinkedExecutable && kmod_info) {
2061 		switch (kc_type) {
2062 		case KCKindPrimary:
2063 			shouldSaveSegments = (
2064 				getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue ||
2065 				getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue);
2066 			if (shouldSaveSegments) {
2067 				flags.resetSegmentsFromImmutableCopy = 1;
2068 			} else {
2069 				flags.unloadUnsupported = 1;
2070 			}
2071 			break;
2072 		case KCKindPageable:
2073 			flags.resetSegmentsFromVnode = 1;
2074 			break;
2075 		case KCKindAuxiliary:
2076 			if (!pageableKCloaded) {
2077 				flags.resetSegmentsFromImmutableCopy = 1;
2078 			} else if (resetAuxKCSegmentOnUnload) {
2079 				flags.resetSegmentsFromVnode = 1;
2080 			} else {
2081 				flags.unloadUnsupported = 1;
2082 			}
2083 			break;
2084 		default:
2085 			break;
2086 		}
2087 	}
2088 
2089 	if (flags.resetSegmentsFromImmutableCopy) {
2090 		/* Save a pristine copy of the mutable segments */
2091 		kernel_segment_command_t *seg = NULL;
2092 		kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
2093 
2094 		savedMutableSegments = OSArray::withCapacity(0);
2095 
2096 		for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) {
2097 			if (!segmentIsMutable(seg)) {
2098 				continue;
2099 			}
2100 			uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
2101 			uint64_t vmsize = seg->vmsize;
2102 			OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2103 			    "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2104 			OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg);
2105 			if (!savedSegment) {
2106 				OSKextLog(this,
2107 				    kOSKextLogErrorLevel |
2108 				    kOSKextLogGeneralFlag,
2109 				    "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2110 				result = false;
2111 				goto finish;
2112 			}
2113 			savedMutableSegments->setObject(savedSegment);
2114 		}
2115 	}
2116 
2117 	if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) {
2118 		/*
2119 		 * set VM protections now, wire pages for the old style Aux KC now,
2120 		 * wire pages for the rest of the KC types at load time.
2121 		 */
2122 		result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false));
2123 		if (!result) {
2124 			goto finish;
2125 		}
2126 	}
2127 
2128 	flags.prelinked = true;
2129 
2130 	if (isDriverKit()) {
2131 		dextStatistics = OSDextStatistics::create();
2132 		dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
2133 		dextLaunchedCount = 0;
2134 	}
2135 
2136 	/* If we created a kext from prelink info,
2137 	 * we must be booting from a prelinked kernel.
2138 	 */
2139 	sPrelinkBoot = true;
2140 
2141 	result = (registerIdentifier() == kOSKextInitialized);
2142 finish:
2143 	return result;
2144 }
2145 
2146 /*********************************************************************
2147 *********************************************************************/
2148 /* static */
2149 OSSharedPtr<OSKext>
withCodelessInfo(OSDictionary * anInfoDict,OSKextInitResult * result)2150 OSKext::withCodelessInfo(OSDictionary * anInfoDict, OSKextInitResult *result)
2151 {
2152 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
2153 	if (!newKext) {
2154 		return NULL;
2155 	}
2156 
2157 	OSKextInitResult ret = newKext->initWithCodelessInfo(anInfoDict);
2158 	if (result != NULL) {
2159 		*result = ret;
2160 	}
2161 	if (ret != kOSKextInitialized) {
2162 		return NULL;
2163 	}
2164 
2165 	return newKext;
2166 }
2167 
2168 /*********************************************************************
2169 *********************************************************************/
2170 OSKextInitResult
initWithCodelessInfo(OSDictionary * anInfoDict)2171 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict)
2172 {
2173 	OSKextInitResult result          = kOSKextInitFailure;
2174 	OSString  * kextPath             = NULL;        // do not release
2175 	OSBoolean * scratchBool          = NULL;        // do not release
2176 
2177 	if (anInfoDict == NULL || !super::init()) {
2178 		goto finish;
2179 	}
2180 
2181 	/*
2182 	 * Get the path. Don't look for an arch-specific path property.
2183 	 */
2184 	kextPath = OSDynamicCast(OSString,
2185 	    anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey));
2186 	if (!kextPath) {
2187 		OSKextLog(NULL,
2188 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2189 		    "Requested codeless kext dictionary does not contain the '%s' key",
2190 		    kKextRequestArgumentCodelessInfoBundlePathKey);
2191 		goto finish;
2192 	}
2193 
2194 	uniquePersonalityProperties(anInfoDict);
2195 
2196 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2197 		goto finish;
2198 	}
2199 
2200 	/*
2201 	 * This path is meant to initialize codeless kexts only. Refuse
2202 	 * anything that looks like it has an executable and/or declares
2203 	 * itself as a kernel component.
2204 	 */
2205 	if (declaresExecutable() || isKernelComponent()) {
2206 		OSKextLog(NULL,
2207 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2208 		    "Refusing to register codeless kext that declares an executable/kernel component: %s",
2209 		    getIdentifierCString());
2210 		goto finish;
2211 	}
2212 
2213 	if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
2214 		boolean_t updated = updateExcludeList(infoDict.get());
2215 		if (updated) {
2216 			OSKextLog(this,
2217 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2218 			    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
2219 		}
2220 	}
2221 
2222 	kc_type = KCKindNone;
2223 
2224 	scratchBool = OSDynamicCast(OSBoolean,
2225 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
2226 	if (scratchBool == kOSBooleanTrue) {
2227 		flags.requireExplicitLoad = 1;
2228 	}
2229 
2230 	/* Also get the executable's bundle-relative path if present.
2231 	 * Don't look for an arch-specific path property.
2232 	 */
2233 	userExecutableRelPath.reset(OSDynamicCast(OSString,
2234 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
2235 
2236 	/* remove unnecessary paths from the info dict */
2237 	anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey);
2238 
2239 	if (isDriverKit()) {
2240 		dextStatistics = OSDextStatistics::create();
2241 		dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
2242 		dextLaunchedCount = 0;
2243 	}
2244 
2245 	result = registerIdentifier();
2246 
2247 finish:
2248 	return result;
2249 }
2250 
2251 /*********************************************************************
2252 *********************************************************************/
2253 /* static */
2254 void
setAllVMAttributes(void)2255 OSKext::setAllVMAttributes(void)
2256 {
2257 	OSSharedPtr<OSCollectionIterator> kextIterator;
2258 	const OSSymbol * thisID                 = NULL;        // do not release
2259 
2260 	IORecursiveLockLock(sKextLock);
2261 
2262 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
2263 	if (!kextIterator) {
2264 		goto finish;
2265 	}
2266 
2267 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
2268 		OSKext *    thisKext;        // do not release
2269 
2270 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
2271 		if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
2272 			continue;
2273 		}
2274 
2275 		if (!thisKext->flags.resetSegmentsFromVnode) {
2276 			/*
2277 			 * set VM protections now, wire pages for the old style Aux KC now,
2278 			 * wire pages for the rest of the KC types at load time.
2279 			 */
2280 			thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false);
2281 		}
2282 	}
2283 
2284 finish:
2285 	IORecursiveLockUnlock(sKextLock);
2286 
2287 	return;
2288 }
2289 
2290 /*********************************************************************
2291 *********************************************************************/
2292 OSSharedPtr<OSKext>
withBooterData(OSString * deviceTreeName,OSData * booterData)2293 OSKext::withBooterData(
2294 	OSString * deviceTreeName,
2295 	OSData   * booterData)
2296 {
2297 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
2298 
2299 	if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
2300 		return NULL;
2301 	}
2302 
2303 	return newKext;
2304 }
2305 
2306 /*********************************************************************
2307 *********************************************************************/
2308 typedef struct _BooterKextFileInfo {
2309 	uint32_t  infoDictPhysAddr;
2310 	uint32_t  infoDictLength;
2311 	uint32_t  executablePhysAddr;
2312 	uint32_t  executableLength;
2313 	uint32_t  bundlePathPhysAddr;
2314 	uint32_t  bundlePathLength;
2315 } _BooterKextFileInfo;
2316 
2317 bool
initWithBooterData(OSString * deviceTreeName,OSData * booterData)2318 OSKext::initWithBooterData(
2319 	OSString * deviceTreeName,
2320 	OSData   * booterData)
2321 {
2322 	bool                  result         = false;
2323 	_BooterKextFileInfo * kextFileInfo   = NULL;        // do not free
2324 	char                * infoDictAddr   = NULL;        // do not free
2325 	void                * executableAddr = NULL;        // do not free
2326 	char                * bundlePathAddr = NULL;        // do not free
2327 
2328 	OSDictionary        * theInfoDict    = NULL;        // do not release
2329 	OSSharedPtr<OSObject> parsedXML;
2330 	OSSharedPtr<OSString> kextPath;
2331 
2332 	OSSharedPtr<OSString> errorString;
2333 	OSSharedPtr<OSData>   executable;
2334 
2335 	if (!super::init()) {
2336 		goto finish;
2337 	}
2338 
2339 	kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
2340 	if (!kextFileInfo) {
2341 		OSKextLog(this,
2342 		    kOSKextLogErrorLevel |
2343 		    kOSKextLogGeneralFlag,
2344 		    "No booter-provided data for kext device tree entry %s.",
2345 		    deviceTreeName->getCStringNoCopy());
2346 		goto finish;
2347 	}
2348 
2349 	/* The info plist must exist or we can't read the kext.
2350 	 */
2351 	if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
2352 		OSKextLog(this,
2353 		    kOSKextLogErrorLevel |
2354 		    kOSKextLogGeneralFlag,
2355 		    "No kext info dictionary for booter device tree entry %s.",
2356 		    deviceTreeName->getCStringNoCopy());
2357 		goto finish;
2358 	}
2359 
2360 	infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
2361 	if (!infoDictAddr) {
2362 		OSKextLog(this,
2363 		    kOSKextLogErrorLevel |
2364 		    kOSKextLogGeneralFlag,
2365 		    "Can't translate physical address 0x%x of kext info dictionary "
2366 		    "for device tree entry %s.",
2367 		    (int)kextFileInfo->infoDictPhysAddr,
2368 		    deviceTreeName->getCStringNoCopy());
2369 		goto finish;
2370 	}
2371 
2372 	parsedXML = OSUnserializeXML(infoDictAddr, errorString);
2373 	if (parsedXML) {
2374 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
2375 	}
2376 	if (!theInfoDict) {
2377 		const char * errorCString = "(unknown error)";
2378 
2379 		if (errorString && errorString->getCStringNoCopy()) {
2380 			errorCString = errorString->getCStringNoCopy();
2381 		} else if (parsedXML) {
2382 			errorCString = "not a dictionary";
2383 		}
2384 		OSKextLog(this,
2385 		    kOSKextLogErrorLevel |
2386 		    kOSKextLogGeneralFlag,
2387 		    "Error unserializing info dictionary for device tree entry %s: %s.",
2388 		    deviceTreeName->getCStringNoCopy(), errorCString);
2389 		goto finish;
2390 	}
2391 
2392 	/* A bundle path is not mandatory.
2393 	 */
2394 	if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
2395 		bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
2396 		if (!bundlePathAddr) {
2397 			OSKextLog(this,
2398 			    kOSKextLogErrorLevel |
2399 			    kOSKextLogGeneralFlag,
2400 			    "Can't translate physical address 0x%x of kext bundle path "
2401 			    "for device tree entry %s.",
2402 			    (int)kextFileInfo->bundlePathPhysAddr,
2403 			    deviceTreeName->getCStringNoCopy());
2404 			goto finish;
2405 		}
2406 		bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0';         // just in case!
2407 
2408 		kextPath = OSString::withCString(bundlePathAddr);
2409 		if (!kextPath) {
2410 			OSKextLog(this,
2411 			    kOSKextLogErrorLevel |
2412 			    kOSKextLogGeneralFlag,
2413 			    "Failed to create wrapper for device tree entry %s kext path %s.",
2414 			    deviceTreeName->getCStringNoCopy(), bundlePathAddr);
2415 			goto finish;
2416 		}
2417 	}
2418 
2419 	if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) {
2420 		goto finish;
2421 	}
2422 
2423 	/* An executable is not mandatory.
2424 	 */
2425 	if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
2426 		executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
2427 		if (!executableAddr) {
2428 			OSKextLog(this,
2429 			    kOSKextLogErrorLevel |
2430 			    kOSKextLogGeneralFlag,
2431 			    "Can't translate physical address 0x%x of kext executable "
2432 			    "for device tree entry %s.",
2433 			    (int)kextFileInfo->executablePhysAddr,
2434 			    deviceTreeName->getCStringNoCopy());
2435 			goto finish;
2436 		}
2437 
2438 		executable = OSData::withBytesNoCopy(executableAddr,
2439 		    kextFileInfo->executableLength);
2440 		if (!executable) {
2441 			OSKextLog(this,
2442 			    kOSKextLogErrorLevel |
2443 			    kOSKextLogGeneralFlag,
2444 			    "Failed to create executable wrapper for device tree entry %s.",
2445 			    deviceTreeName->getCStringNoCopy());
2446 			goto finish;
2447 		}
2448 
2449 		/* A kext with an executable needs to retain the whole booterData
2450 		 * object to keep the executable in memory.
2451 		 */
2452 		if (!setExecutable(executable.get(), booterData)) {
2453 			OSKextLog(this,
2454 			    kOSKextLogErrorLevel |
2455 			    kOSKextLogGeneralFlag,
2456 			    "Failed to set kext executable for device tree entry %s.",
2457 			    deviceTreeName->getCStringNoCopy());
2458 			goto finish;
2459 		}
2460 	}
2461 
2462 	if (isDriverKit()) {
2463 		dextStatistics = OSDextStatistics::create();
2464 		dextUniqueID.reset(parseDextUniqueID(theInfoDict, getIdentifierCString()), OSRetain);
2465 		dextLaunchedCount = 0;
2466 	}
2467 
2468 	result = (registerIdentifier() == kOSKextInitialized);
2469 
2470 finish:
2471 	return result;
2472 }
2473 
2474 /*********************************************************************
2475 *********************************************************************/
2476 OSKextInitResult
registerIdentifier(void)2477 OSKext::registerIdentifier(void)
2478 {
2479 	OSKextInitResult  result                  = kOSKextInitFailure;
2480 	OSKext        * existingKext              = NULL;        // do not release
2481 	bool            existingIsLoaded          = false;
2482 	bool            existingIsPrelinked       = false;
2483 	bool            existingIsCodeless        = false;
2484 	bool            existingIsDext            = false;
2485 	OSKextVersion   newVersion                = -1;
2486 	OSKextVersion   existingVersion           = -1;
2487 	char            newVersionCString[kOSKextVersionMaxLength];
2488 	char            existingVersionCString[kOSKextVersionMaxLength];
2489 	OSSharedPtr<OSData> newUUID;
2490 	OSSharedPtr<OSData> existingUUID;
2491 	const char *newDextUniqueIDCString = NULL;
2492 	const char *existingDextUniqueIDCString = NULL;
2493 	unsigned int newDextUniqueIDCStringSize = 0;
2494 	unsigned int existingDextUniqueIDCStringSize = 0;
2495 
2496 	IORecursiveLockLock(sKextLock);
2497 
2498 	/* Get the new kext's version for checks & log messages.
2499 	 */
2500 	newVersion = getVersion();
2501 	OSKextVersionGetString(newVersion, newVersionCString,
2502 	    kOSKextVersionMaxLength);
2503 
2504 	/* If we don't have an existing kext with this identifier,
2505 	 * just record the new kext and we're done!
2506 	 */
2507 	existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get()));
2508 	if (!existingKext) {
2509 		sKextsByID->setObject(bundleID.get(), this);
2510 		result = kOSKextInitialized;
2511 		goto finish;
2512 	}
2513 
2514 	/* Get the existing kext's version for checks & log messages.
2515 	 */
2516 	existingVersion = existingKext->getVersion();
2517 	OSKextVersionGetString(existingVersion,
2518 	    existingVersionCString, kOSKextVersionMaxLength);
2519 
2520 	existingIsLoaded = existingKext->isLoaded();
2521 	existingIsPrelinked = existingKext->isPrelinked();
2522 	existingIsDext = existingKext->isDriverKit();
2523 	existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext;
2524 
2525 	/*
2526 	 * Check if we are trying to upgrade a dext
2527 	 * with another dext.
2528 	 */
2529 	if (isDriverKit() && existingIsDext) {
2530 		OSData *newDextUID = getDextUniqueID();
2531 		if (!newDextUID) {
2532 			OSKextLog(this,
2533 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2534 			    "New dext %s, v%s requested does not have a unique dext identifier\n",
2535 			    getIdentifierCString(), newVersionCString);
2536 			goto finish;
2537 		}
2538 		newDextUniqueIDCString = getDextUniqueIDCString(newDextUID, &newDextUniqueIDCStringSize);
2539 		assert(newDextUniqueIDCString != NULL);
2540 
2541 		OSData *existingDextUID = existingKext->getDextUniqueID();
2542 		if (!existingDextUID) {
2543 			OSKextLog(this,
2544 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2545 			    "Found a dext %s, v%s: with no unique dext identifier\n",
2546 			    existingKext->getIdentifierCString(), existingVersionCString);
2547 			goto finish;
2548 		}
2549 		existingDextUniqueIDCString = getDextUniqueIDCString(existingDextUID, &existingDextUniqueIDCStringSize);
2550 		assert(existingDextUniqueIDCString != NULL);
2551 
2552 		/*
2553 		 * We might get multiple requests to save the same dext.
2554 		 * Check if we already have saved it or if this is an upgrade
2555 		 * for a dext with the same BundleID.
2556 		 * Dexts are uniquely identified by DextUniqueID, if a new DextUniqueID
2557 		 * is requested for a BundleID we are going to upgrade to the newest
2558 		 * received irrespective from the dext version.
2559 		 */
2560 		if (newDextUID->isEqualTo(existingDextUID) && existingKext->flags.dextToReplace == 0) {
2561 			OSKextLog(this,
2562 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2563 			    "Refusing new dext %s, v%s:"
2564 			    "a dext v %s with the same unique dext identifier (%s) already exists\n",
2565 			    getIdentifierCString(), newVersionCString,
2566 			    existingVersionCString, newDextUniqueIDCString);
2567 			result = kOSKextAlreadyExist;
2568 			goto finish;
2569 		}
2570 
2571 		bool upgraded = upgradeDext(existingKext, this);
2572 		if (upgraded) {
2573 			/* If the dext was upgraded existingKext might have been deallocated */
2574 			existingKext = NULL;
2575 			OSKextLog(this,
2576 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2577 			    "Dext %s, v%s , unique dext identifier %s "
2578 			    "Upgraded to v%s, unique dext identifier %s \n",
2579 			    getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
2580 			    newVersionCString, newDextUniqueIDCString);
2581 			result = kOSKextInitialized;
2582 		} else {
2583 			OSKextLog(this,
2584 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2585 			    "Upgrade delayed for %s v%s, unique dext identifier %s "
2586 			    "with v%s, unique dext identifier %s.\n",
2587 			    getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
2588 			    newVersionCString, newDextUniqueIDCString);
2589 			result = kOSKextAlreadyExist;
2590 		}
2591 
2592 		goto finish;
2593 	}
2594 
2595 	/* If we have a non-codeless kext with this identifier that's already
2596 	 * loaded/prelinked, we can't use the new one, but let's be really
2597 	 * thorough and check how the two are related for a precise diagnostic
2598 	 * log message.
2599 	 *
2600 	 * This check is valid for kexts that declare an executable and for
2601 	 * dexts, but not for codeless kexts - we can just replace those.
2602 	 */
2603 	if ((!existingIsCodeless || existingIsDext) &&
2604 	    (existingIsLoaded || existingIsPrelinked)) {
2605 		bool sameVersion = (newVersion == existingVersion);
2606 		bool sameExecutable = true;         // assume true unless we have UUIDs
2607 
2608 		/* Only get the UUID if the existing kext is loaded. Doing so
2609 		 * might have to uncompress an mkext executable and we shouldn't
2610 		 * take that hit when neither kext is loaded.
2611 		 *
2612 		 * Note: there is no decompression that happens when all kexts
2613 		 * are loaded from kext collecitons.
2614 		 */
2615 		newUUID = copyUUID();
2616 		existingUUID = existingKext->copyUUID();
2617 
2618 		if (existingIsDext && !isDriverKit()) {
2619 			OSKextLog(this,
2620 			    kOSKextLogWarningLevel |
2621 			    kOSKextLogKextBookkeepingFlag,
2622 			    "Notice - new kext %s, v%s matches a %s dext"
2623 			    "with the same bundle ID, v%s.",
2624 			    getIdentifierCString(), newVersionCString,
2625 			    (existingIsLoaded ? "loaded" : "prelinked"),
2626 			    existingVersionCString);
2627 			goto finish;
2628 		}
2629 
2630 		/* I'm entirely too paranoid about checking equivalence of executables,
2631 		 * but I remember nasty problems with it in the past.
2632 		 *
2633 		 * - If we have UUIDs for both kexts, compare them.
2634 		 * - If only one kext has a UUID, they're definitely different.
2635 		 */
2636 		if (newUUID && existingUUID) {
2637 			sameExecutable = newUUID->isEqualTo(existingUUID.get());
2638 		} else if (newUUID || existingUUID) {
2639 			sameExecutable = false;
2640 		}
2641 
2642 		if (!newUUID && !existingUUID) {
2643 			/* If there are no UUIDs, we can't really tell that the executables
2644 			 * are *different* without a lot of work; the loaded kext's
2645 			 * unrelocated executable is no longer around (and we never had it
2646 			 * in-kernel for a prelinked kext). We certainly don't want to do
2647 			 * a whole fake link for the new kext just to compare, either.
2648 			 */
2649 			OSKextLog(this,
2650 			    kOSKextLogWarningLevel |
2651 			    kOSKextLogKextBookkeepingFlag,
2652 			    "Notice - new kext %s, v%s matches %s kext "
2653 			    "but can't determine if executables are the same (no UUIDs).",
2654 			    getIdentifierCString(),
2655 			    newVersionCString,
2656 			    (existingIsLoaded ? "loaded" : "prelinked"));
2657 		}
2658 
2659 		if (sameVersion && sameExecutable) {
2660 			OSKextLog(this,
2661 			    (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
2662 			    kOSKextLogKextBookkeepingFlag,
2663 			    "Refusing new kext %s, v%s: a %s copy is already present "
2664 			    "(same version and executable).",
2665 			    getIdentifierCString(), newVersionCString,
2666 			    (existingIsLoaded ? "loaded" : "prelinked"));
2667 		} else {
2668 			if (!sameVersion) {
2669 				/* This condition is significant so log it under warnings.
2670 				 */
2671 				OSKextLog(this,
2672 				    kOSKextLogWarningLevel |
2673 				    kOSKextLogKextBookkeepingFlag,
2674 				    "Refusing new kext %s, v%s: already have %s v%s.",
2675 				    getIdentifierCString(),
2676 				    newVersionCString,
2677 				    (existingIsLoaded ? "loaded" : "prelinked"),
2678 				    existingVersionCString);
2679 			} else {
2680 				/* This condition is significant so log it under warnings.
2681 				 */
2682 				OSKextLog(this,
2683 				    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2684 				    "Refusing new kext %s, v%s: a %s copy with a different "
2685 				    "executable UUID is already present.",
2686 				    getIdentifierCString(), newVersionCString,
2687 				    (existingIsLoaded ? "loaded" : "prelinked"));
2688 			}
2689 		}
2690 		goto finish;
2691 	} /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */
2692 
2693 	/* Refuse to allow an existing loaded codeless kext be replaced by a
2694 	 * normal kext with the same bundle ID.
2695 	 */
2696 	if (existingIsCodeless && declaresExecutable()) {
2697 		OSKextLog(this,
2698 		    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2699 		    "Refusing new kext %s, v%s: a codeless copy is already %s",
2700 		    getIdentifierCString(), newVersionCString,
2701 		    (existingIsLoaded ? "loaded" : "prelinked"));
2702 		goto finish;
2703 	}
2704 
2705 	/* Dexts packaged in the BootKC will be protected against replacement
2706 	 * by non-dexts by the logic above which checks if they are prelinked.
2707 	 * Dexts which are prelinked into the System KC will be registered
2708 	 * before any other kexts in the AuxKC are registered, and we never
2709 	 * put dexts in the AuxKC. Therefore, there is no need to check if an
2710 	 * existing object is a dext and is being replaced by a non-dext.
2711 	 * The scenario cannot happen by construction.
2712 	 *
2713 	 * See: OSKext::loadFileSetKexts()
2714 	 */
2715 
2716 
2717 	/* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2718 	 * user loads are happening or if we're still in early boot. User agents are
2719 	 * supposed to resolve dependencies topside and include only the exact
2720 	 * kexts needed; so we always accept the new kext (in fact we should never
2721 	 * see an older unloaded copy hanging around).
2722 	 */
2723 	if (sUserLoadsActive) {
2724 		sKextsByID->setObject(bundleID.get(), this);
2725 		result = kOSKextInitialized;
2726 
2727 		OSKextLog(this,
2728 		    kOSKextLogStepLevel |
2729 		    kOSKextLogKextBookkeepingFlag,
2730 		    "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2731 		    getIdentifierCString(),
2732 		    existingVersionCString,
2733 		    newVersionCString);
2734 
2735 		goto finish;
2736 	}
2737 
2738 	/* During early boot, the kext with the highest version always wins out.
2739 	 * Prelinked kernels will never hit this, but mkexts and booter-read
2740 	 * kexts might have duplicates.
2741 	 */
2742 	if (newVersion > existingVersion) {
2743 		sKextsByID->setObject(bundleID.get(), this);
2744 		result = kOSKextInitialized;
2745 
2746 		OSKextLog(this,
2747 		    kOSKextLogStepLevel |
2748 		    kOSKextLogKextBookkeepingFlag,
2749 		    "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2750 		    existingVersionCString,
2751 		    getIdentifierCString(),
2752 		    newVersionCString);
2753 	} else {
2754 		OSKextLog(this,
2755 		    kOSKextLogStepLevel |
2756 		    kOSKextLogKextBookkeepingFlag,
2757 		    "Kext %s is already registered with a higher/same version (v%s); "
2758 		    "dropping newly-added (v%s).",
2759 		    getIdentifierCString(),
2760 		    existingVersionCString,
2761 		    newVersionCString);
2762 	}
2763 
2764 	/* result has been set appropriately by now. */
2765 
2766 finish:
2767 
2768 	IORecursiveLockUnlock(sKextLock);
2769 
2770 	if (newDextUniqueIDCString != NULL) {
2771 		kfree_data(newDextUniqueIDCString, newDextUniqueIDCStringSize);
2772 	}
2773 	if (existingDextUniqueIDCString != NULL) {
2774 		kfree_data(existingDextUniqueIDCString, existingDextUniqueIDCStringSize);
2775 	}
2776 
2777 	if (result == kOSKextInitialized) {
2778 		OSKextLog(this,
2779 		    kOSKextLogStepLevel |
2780 		    kOSKextLogKextBookkeepingFlag,
2781 		    "Kext %s, v%s registered and available for loading.",
2782 		    getIdentifierCString(), newVersionCString);
2783 	}
2784 
2785 	return result;
2786 }
2787 
2788 /*********************************************************************
2789  * Does the bare minimum validation to look up a kext.
2790  * All other validation is done on the spot as needed.
2791  **********************************************************************/
2792 bool
setInfoDictionaryAndPath(OSDictionary * aDictionary,OSString * aPath)2793 OSKext::setInfoDictionaryAndPath(
2794 	OSDictionary * aDictionary,
2795 	OSString     * aPath)
2796 {
2797 	bool           result                   = false;
2798 	OSString     * bundleIDString           = NULL;        // do not release
2799 	OSString     * versionString            = NULL;        // do not release
2800 	OSString     * compatibleVersionString  = NULL;        // do not release
2801 	const char   * versionCString           = NULL;        // do not free
2802 	const char   * compatibleVersionCString = NULL;        // do not free
2803 	OSBoolean    * scratchBool              = NULL;        // do not release
2804 	OSDictionary * scratchDict              = NULL;        // do not release
2805 
2806 	if (infoDict) {
2807 		panic("Attempt to set info dictionary on a kext "
2808 		    "that already has one (%s).",
2809 		    getIdentifierCString());
2810 	}
2811 
2812 	if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
2813 		goto finish;
2814 	}
2815 
2816 	infoDict.reset(aDictionary, OSRetain);
2817 
2818 	/* Check right away if the info dictionary has any log flags.
2819 	 */
2820 	scratchBool = OSDynamicCast(OSBoolean,
2821 	    getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
2822 	if (scratchBool == kOSBooleanTrue) {
2823 		flags.loggingEnabled = 1;
2824 	}
2825 
2826 	/* The very next thing to get is the bundle identifier. Unlike
2827 	 * in user space, a kext with no bundle identifier gets axed
2828 	 * immediately.
2829 	 */
2830 	bundleIDString = OSDynamicCast(OSString,
2831 	    getPropertyForHostArch(kCFBundleIdentifierKey));
2832 	if (!bundleIDString) {
2833 		OSKextLog(this,
2834 		    kOSKextLogErrorLevel |
2835 		    kOSKextLogValidationFlag,
2836 		    "CFBundleIdentifier missing/invalid type in kext %s.",
2837 		    aPath ? aPath->getCStringNoCopy() : "(unknown)");
2838 		goto finish;
2839 	}
2840 	bundleID = OSSymbol::withString(bundleIDString);
2841 	if (!bundleID) {
2842 		OSKextLog(this,
2843 		    kOSKextLogErrorLevel |
2844 		    kOSKextLogValidationFlag,
2845 		    "Can't copy bundle identifier as symbol for kext %s.",
2846 		    bundleIDString->getCStringNoCopy());
2847 		goto finish;
2848 	}
2849 
2850 	/* Save the path if we got one (it should always be available but it's
2851 	 * just something nice to have for bookkeeping).
2852 	 */
2853 	if (aPath) {
2854 		path.reset(aPath, OSRetain);
2855 	}
2856 
2857 	/*****
2858 	 * Minimal validation to initialize. We'll do other validation on the spot.
2859 	 */
2860 	if (bundleID->getLength() >= KMOD_MAX_NAME) {
2861 		OSKextLog(this,
2862 		    kOSKextLogErrorLevel |
2863 		    kOSKextLogValidationFlag,
2864 		    "Kext %s error - CFBundleIdentifier over max length %d.",
2865 		    getIdentifierCString(), KMOD_MAX_NAME - 1);
2866 		goto finish;
2867 	}
2868 
2869 	version = compatibleVersion = -1;
2870 
2871 	versionString = OSDynamicCast(OSString,
2872 	    getPropertyForHostArch(kCFBundleVersionKey));
2873 	if (!versionString) {
2874 		OSKextLog(this,
2875 		    kOSKextLogErrorLevel |
2876 		    kOSKextLogValidationFlag,
2877 		    "Kext %s error - CFBundleVersion missing/invalid type.",
2878 		    getIdentifierCString());
2879 		goto finish;
2880 	}
2881 	versionCString = versionString->getCStringNoCopy();
2882 	version = OSKextParseVersionString(versionCString);
2883 	if (version < 0) {
2884 		OSKextLog(this,
2885 		    kOSKextLogErrorLevel |
2886 		    kOSKextLogValidationFlag,
2887 		    "Kext %s error - CFBundleVersion bad value '%s'.",
2888 		    getIdentifierCString(), versionCString);
2889 		goto finish;
2890 	}
2891 
2892 	compatibleVersion = -1;         // set to illegal value for kexts that don't have
2893 
2894 	compatibleVersionString = OSDynamicCast(OSString,
2895 	    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
2896 	if (compatibleVersionString) {
2897 		compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
2898 		compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
2899 		if (compatibleVersion < 0) {
2900 			OSKextLog(this,
2901 			    kOSKextLogErrorLevel |
2902 			    kOSKextLogValidationFlag,
2903 			    "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2904 			    getIdentifierCString(), compatibleVersionCString);
2905 			goto finish;
2906 		}
2907 
2908 		if (compatibleVersion > version) {
2909 			OSKextLog(this,
2910 			    kOSKextLogErrorLevel |
2911 			    kOSKextLogValidationFlag,
2912 			    "Kext %s error - %s %s > %s %s (must be <=).",
2913 			    getIdentifierCString(),
2914 			    kOSBundleCompatibleVersionKey, compatibleVersionCString,
2915 			    kCFBundleVersionKey, versionCString);
2916 			goto finish;
2917 		}
2918 	}
2919 
2920 	/* Check to see if this kext is in exclude list */
2921 	if (isInExcludeList()) {
2922 		OSKextLog(this,
2923 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2924 		    "Kext %s is in exclude list, not loadable",
2925 		    getIdentifierCString());
2926 		goto finish;
2927 	}
2928 
2929 	/* Set flags for later use if the infoDict gets flushed. We only
2930 	 * check for true values, not false ones(!)
2931 	 */
2932 	scratchBool = OSDynamicCast(OSBoolean,
2933 	    getPropertyForHostArch(kOSBundleIsInterfaceKey));
2934 	if (scratchBool == kOSBooleanTrue) {
2935 		flags.interface = 1;
2936 	}
2937 
2938 	scratchBool = OSDynamicCast(OSBoolean,
2939 	    getPropertyForHostArch(kOSKernelResourceKey));
2940 	if (scratchBool == kOSBooleanTrue) {
2941 		flags.kernelComponent = 1;
2942 		flags.interface = 1;         // xxx - hm. the kernel itself isn't an interface...
2943 		flags.started = 1;
2944 
2945 		/* A kernel component has one implicit dependency on the kernel.
2946 		 */
2947 		flags.hasAllDependencies = 1;
2948 	}
2949 
2950 	/* Make sure common string values in personalities are uniqued to OSSymbols.
2951 	 */
2952 	scratchDict = OSDynamicCast(OSDictionary,
2953 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
2954 	if (scratchDict) {
2955 		uniquePersonalityProperties(scratchDict);
2956 	}
2957 
2958 	result = true;
2959 
2960 finish:
2961 
2962 	return result;
2963 }
2964 
2965 /*********************************************************************
2966 * Not used for prelinked kernel boot as there is no unrelocated
2967 * executable.
2968 *********************************************************************/
2969 bool
setExecutable(OSData * anExecutable,OSData * externalData,bool externalDataIsMkext)2970 OSKext::setExecutable(
2971 	OSData * anExecutable,
2972 	OSData * externalData,
2973 	bool     externalDataIsMkext)
2974 {
2975 	bool         result        = false;
2976 	const char * executableKey = NULL;         // do not free
2977 
2978 	if (!anExecutable) {
2979 		infoDict->removeObject(_kOSKextExecutableKey);
2980 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
2981 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
2982 		result = true;
2983 		goto finish;
2984 	}
2985 
2986 	if (infoDict->getObject(_kOSKextExecutableKey) ||
2987 	    infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
2988 		panic("Attempt to set an executable on a kext "
2989 		    "that already has one (%s).",
2990 		    getIdentifierCString());
2991 		goto finish;
2992 	}
2993 
2994 	if (externalDataIsMkext) {
2995 		executableKey = _kOSKextMkextExecutableReferenceKey;
2996 	} else {
2997 		executableKey = _kOSKextExecutableKey;
2998 	}
2999 
3000 	if (anExecutable) {
3001 		infoDict->setObject(executableKey, anExecutable);
3002 		if (externalData) {
3003 			infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
3004 		}
3005 	}
3006 
3007 	result = true;
3008 
3009 finish:
3010 	return result;
3011 }
3012 
3013 /*********************************************************************
3014 *********************************************************************/
3015 static void
uniqueStringPlistProperty(OSDictionary * dict,const char * key)3016 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
3017 {
3018 	OSObject       * value       = NULL;        // do not release
3019 	OSString       * stringValue = NULL;        // do not release
3020 	OSSharedPtr<const OSSymbol> symbolValue;
3021 
3022 	value = dict->getObject(key);
3023 	if (!value) {
3024 		goto finish;
3025 	}
3026 	if (OSDynamicCast(OSSymbol, value)) {
3027 		/* this is already an OSSymbol: we're good */
3028 		goto finish;
3029 	}
3030 
3031 	stringValue = OSDynamicCast(OSString, value);
3032 	if (!stringValue) {
3033 		goto finish;
3034 	}
3035 
3036 	symbolValue = OSSymbol::withString(stringValue);
3037 	if (!symbolValue) {
3038 		goto finish;
3039 	}
3040 
3041 	dict->setObject(key, symbolValue.get());
3042 
3043 finish:
3044 	return;
3045 }
3046 
3047 /*********************************************************************
3048 *********************************************************************/
3049 static void
uniqueStringPlistProperty(OSDictionary * dict,const OSString * key)3050 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
3051 {
3052 	OSObject       * value       = NULL;        // do not release
3053 	OSString       * stringValue = NULL;        // do not release
3054 	OSSharedPtr<const OSSymbol> symbolValue;
3055 
3056 	value = dict->getObject(key);
3057 	if (!value) {
3058 		goto finish;
3059 	}
3060 	if (OSDynamicCast(OSSymbol, value)) {
3061 		/* this is already an OSSymbol: we're good */
3062 		goto finish;
3063 	}
3064 
3065 	stringValue = OSDynamicCast(OSString, value);
3066 	if (!stringValue) {
3067 		goto finish;
3068 	}
3069 
3070 	symbolValue = OSSymbol::withString(stringValue);
3071 	if (!symbolValue) {
3072 		goto finish;
3073 	}
3074 
3075 	dict->setObject(key, symbolValue.get());
3076 
3077 finish:
3078 	return;
3079 }
3080 
3081 void
uniquePersonalityProperties(OSDictionary * personalityDict)3082 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
3083 {
3084 	OSKext::uniquePersonalityProperties(personalityDict, true);
3085 }
3086 
3087 /*********************************************************************
3088 * Replace common personality property values with uniqued instances
3089 * to save on wired memory.
3090 *********************************************************************/
3091 /* static */
3092 void
uniquePersonalityProperties(OSDictionary * personalityDict,bool defaultAddKernelBundleIdentifier)3093 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier)
3094 {
3095 	/* Properties every personality has.
3096 	 */
3097 	uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
3098 	uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
3099 	uniqueStringPlistProperty(personalityDict, gIOClassKey.get());
3100 	if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) {
3101 		uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey);
3102 	} else if (defaultAddKernelBundleIdentifier) {
3103 		personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey));
3104 	}
3105 
3106 	/* Other commonly used properties.
3107 	 */
3108 	uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
3109 	uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
3110 	uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
3111 
3112 	uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
3113 	uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
3114 	uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
3115 	uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
3116 	uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
3117 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
3118 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
3119 	uniqueStringPlistProperty(personalityDict, "Vendor");
3120 	uniqueStringPlistProperty(personalityDict, "Vendor Identification");
3121 	uniqueStringPlistProperty(personalityDict, "Vendor Name");
3122 	uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
3123 	uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
3124 	uniqueStringPlistProperty(personalityDict, "idProduct");
3125 
3126 	return;
3127 }
3128 
3129 /*********************************************************************
3130 *********************************************************************/
3131 void
free(void)3132 OSKext::free(void)
3133 {
3134 	if (isLoaded()) {
3135 		panic("Attempt to free loaded kext %s.", getIdentifierCString());
3136 	}
3137 
3138 	if (isDriverKit()) {
3139 		if (dextLaunchedCount > 0) {
3140 			panic("Freeing dext %s but dextLaunchedCount is %d\n", getIdentifierCString(), dextLaunchedCount);
3141 		}
3142 	}
3143 
3144 	infoDict.reset();
3145 	bundleID.reset();
3146 	path.reset();
3147 	executableRelPath.reset();
3148 	userExecutableRelPath.reset();
3149 	dependencies.reset();
3150 	linkedExecutable.reset();
3151 	metaClasses.reset();
3152 	interfaceUUID.reset();
3153 	driverKitUUID.reset();
3154 	dextStatistics.reset();
3155 	dextUniqueID.reset();
3156 
3157 	if (isInterface() && kmod_info) {
3158 		kfree_type(kmod_info_t, kmod_info);
3159 	}
3160 
3161 	super::free();
3162 	return;
3163 }
3164 
3165 #if PRAGMA_MARK
3166 #pragma mark Mkext files
3167 #endif
3168 
3169 #if CONFIG_KXLD
3170 /*
3171  * mkext archives are really only relevant on kxld-enabled kernels.
3172  * Without a dynamic kernel linker, we don't need to support any mkexts.
3173  */
3174 
3175 /*********************************************************************
3176 *********************************************************************/
3177 OSReturn
readMkextArchive(OSData * mkextData,uint32_t * checksumPtr)3178 OSKext::readMkextArchive(OSData * mkextData,
3179     uint32_t * checksumPtr)
3180 {
3181 	OSReturn       result       = kOSKextReturnBadData;
3182 	uint32_t       mkextLength  = 0;
3183 	mkext_header * mkextHeader  = NULL;        // do not free
3184 	uint32_t       mkextVersion = 0;
3185 
3186 	/* Note default return of kOSKextReturnBadData above.
3187 	 */
3188 	mkextLength = mkextData->getLength();
3189 	if (mkextLength < sizeof(mkext_basic_header)) {
3190 		OSKextLog(/* kext */ NULL,
3191 		    kOSKextLogErrorLevel |
3192 		    kOSKextLogArchiveFlag,
3193 		    "Mkext archive too small to be valid.");
3194 		goto finish;
3195 	}
3196 
3197 	mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
3198 
3199 	if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
3200 	    MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
3201 		OSKextLog(/* kext */ NULL,
3202 		    kOSKextLogErrorLevel |
3203 		    kOSKextLogArchiveFlag,
3204 		    "Mkext archive has invalid magic or signature.");
3205 		goto finish;
3206 	}
3207 
3208 	if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
3209 		OSKextLog(/* kext */ NULL,
3210 		    kOSKextLogErrorLevel |
3211 		    kOSKextLogArchiveFlag,
3212 		    "Mkext archive recorded length doesn't match actual file length.");
3213 		goto finish;
3214 	}
3215 
3216 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3217 
3218 	if (mkextVersion == MKEXT_VERS_2) {
3219 		result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
3220 	} else {
3221 		OSKextLog(/* kext */ NULL,
3222 		    kOSKextLogErrorLevel |
3223 		    kOSKextLogArchiveFlag,
3224 		    "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
3225 		result = kOSKextReturnUnsupported;
3226 	}
3227 
3228 finish:
3229 	return result;
3230 }
3231 
3232 /*********************************************************************
3233 * Assumes magic, signature, version, length have been checked.
3234 * xxx - need to add further bounds checking for each file entry
3235 *
3236 * Should keep track of all kexts created so far, and if we hit a
3237 * fatal error halfway through, remove those kexts. If we've dropped
3238 * an older version that had already been read, whoops! Might want to
3239 * add a level of buffering?
3240 *********************************************************************/
3241 /* static */
3242 OSReturn
readMkext2Archive(OSData * mkextData,OSDictionary ** mkextPlistOut,uint32_t * checksumPtr)3243 OSKext::readMkext2Archive(
3244 	OSData        * mkextData,
3245 	OSDictionary ** mkextPlistOut,
3246 	uint32_t      * checksumPtr)
3247 {
3248 	OSReturn        result                     = kOSReturnError;
3249 	uint32_t        mkextLength;
3250 	mkext2_header * mkextHeader                = NULL;        // do not free
3251 	void          * mkextEnd                   = NULL;        // do not free
3252 	uint32_t        mkextVersion;
3253 	uint8_t       * crc_address                = NULL;
3254 	size_t          crc_buffer_size            = 0;
3255 	uint32_t        checksum;
3256 	uint32_t        mkextPlistOffset;
3257 	uint32_t        mkextPlistCompressedSize;
3258 	char          * mkextPlistEnd              = NULL;        // do not free
3259 	uint32_t        mkextPlistFullSize;
3260 	OSSharedPtr<OSString>     errorString;
3261 	OSSharedPtr<OSData>       mkextPlistUncompressedData;
3262 	const char    * mkextPlistDataBuffer       = NULL;        // do not free
3263 	OSSharedPtr<OSObject>      parsedXML;
3264 	OSDictionary  * mkextPlist                 = NULL;        // do not release
3265 	OSArray       * mkextInfoDictArray         = NULL;        // do not release
3266 	uint32_t        count, i;
3267 	kc_format_t kc_format;
3268 
3269 	if (!PE_get_primary_kc_format(&kc_format)) {
3270 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3271 		    "Unable to determine primary KC format");
3272 		goto finish;
3273 	}
3274 
3275 	mkextLength = mkextData->getLength();
3276 	mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
3277 	mkextEnd = (char *)mkextHeader + mkextLength;
3278 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3279 
3280 	crc_address = (u_int8_t *)&mkextHeader->version;
3281 	crc_buffer_size = (uintptr_t)mkextHeader +
3282 	    MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address;
3283 	if (crc_buffer_size > INT32_MAX) {
3284 		OSKextLog(/* kext */ NULL,
3285 		    kOSKextLogErrorLevel |
3286 		    kOSKextLogArchiveFlag,
3287 		    "Mkext archive size is too large (%lu > INT32_MAX).",
3288 		    crc_buffer_size);
3289 		result = kOSKextReturnBadData;
3290 		goto finish;
3291 	}
3292 	checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size);
3293 
3294 	if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
3295 		OSKextLog(/* kext */ NULL,
3296 		    kOSKextLogErrorLevel |
3297 		    kOSKextLogArchiveFlag,
3298 		    "Mkext archive has bad checksum.");
3299 		result = kOSKextReturnBadData;
3300 		goto finish;
3301 	}
3302 
3303 	if (checksumPtr) {
3304 		*checksumPtr = checksum;
3305 	}
3306 
3307 	/* Check that the CPU type & subtype match that of the running kernel. */
3308 	if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
3309 		OSKextLog(/* kext */ NULL,
3310 		    kOSKextLogErrorLevel |
3311 		    kOSKextLogArchiveFlag,
3312 		    "Mkext archive must have a specific CPU type.");
3313 		result = kOSKextReturnBadData;
3314 		goto finish;
3315 	} else {
3316 		if ((UInt32)_mh_execute_header.cputype !=
3317 		    MKEXT_GET_CPUTYPE(mkextHeader)) {
3318 			OSKextLog(/* kext */ NULL,
3319 			    kOSKextLogErrorLevel |
3320 			    kOSKextLogArchiveFlag,
3321 			    "Mkext archive does not match the running kernel's CPU type.");
3322 			result = kOSKextReturnArchNotFound;
3323 			goto finish;
3324 		}
3325 	}
3326 
3327 	mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
3328 	mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
3329 	mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
3330 	    mkextPlistCompressedSize;
3331 	if (mkextPlistEnd > mkextEnd) {
3332 		OSKextLog(/* kext */ NULL,
3333 		    kOSKextLogErrorLevel |
3334 		    kOSKextLogArchiveFlag,
3335 		    "Mkext archive file overrun.");
3336 		result = kOSKextReturnBadData;
3337 	}
3338 
3339 	mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
3340 	if (mkextPlistCompressedSize) {
3341 		mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
3342 			(UInt8 *)mkextHeader + mkextPlistOffset,
3343 			"plist",
3344 			mkextPlistCompressedSize, mkextPlistFullSize);
3345 		if (!mkextPlistUncompressedData) {
3346 			goto finish;
3347 		}
3348 		mkextPlistDataBuffer = (const char *)
3349 		    mkextPlistUncompressedData->getBytesNoCopy();
3350 	} else {
3351 		mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
3352 	}
3353 
3354 	/* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
3355 	 */
3356 	parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString);
3357 	if (parsedXML) {
3358 		mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get());
3359 	}
3360 	if (!mkextPlist) {
3361 		const char * errorCString = "(unknown error)";
3362 
3363 		if (errorString && errorString->getCStringNoCopy()) {
3364 			errorCString = errorString->getCStringNoCopy();
3365 		} else if (parsedXML) {
3366 			errorCString = "not a dictionary";
3367 		}
3368 		OSKextLog(/* kext */ NULL,
3369 		    kOSKextLogErrorLevel |
3370 		    kOSKextLogArchiveFlag,
3371 		    "Error unserializing mkext plist: %s.", errorCString);
3372 		goto finish;
3373 	}
3374 
3375 	mkextInfoDictArray = OSDynamicCast(OSArray,
3376 	    mkextPlist->getObject(kMKEXTInfoDictionariesKey));
3377 	if (!mkextInfoDictArray) {
3378 		OSKextLog(/* kext */ NULL,
3379 		    kOSKextLogErrorLevel |
3380 		    kOSKextLogArchiveFlag,
3381 		    "Mkext archive contains no kext info dictionaries.");
3382 		goto finish;
3383 	}
3384 
3385 	count = mkextInfoDictArray->getCount();
3386 	for (i = 0; i < count; i++) {
3387 		OSDictionary * infoDict;
3388 
3389 
3390 		infoDict = OSDynamicCast(OSDictionary,
3391 		    mkextInfoDictArray->getObject(i));
3392 
3393 		/* Create the kext for the entry, then release it, because the
3394 		 * kext system keeps them around until explicitly removed.
3395 		 * Any creation/registration failures are already logged for us.
3396 		 */
3397 		if (infoDict) {
3398 			OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData);
3399 
3400 			/* Fail dynamic loading of a kext when booted from MH_FILESET */
3401 			if (kc_format == KCFormatFileset &&
3402 			    newKext &&
3403 			    !(newKext->isPrelinked()) &&
3404 			    newKext->declaresExecutable()) {
3405 				result = kOSReturnError;
3406 				printf("Kext LOG: Dynamic loading of kext denied for kext %s\n",
3407 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3408 
3409 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
3410 				    "Dynamic loading of kext denied for kext %s\n",
3411 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3412 				goto finish;
3413 			}
3414 		}
3415 	}
3416 
3417 	/* If the caller needs the plist, hand them back our copy
3418 	 */
3419 	if (mkextPlistOut) {
3420 		*mkextPlistOut = mkextPlist;
3421 		parsedXML.detach();
3422 	}
3423 
3424 	/* Even if we didn't keep any kexts from the mkext, we may have a load
3425 	 * request to process, so we are successful (no errors occurred).
3426 	 */
3427 	result = kOSReturnSuccess;
3428 
3429 finish:
3430 	return result;
3431 }
3432 
3433 /* static */
3434 OSReturn
readMkext2Archive(OSData * mkextData,OSSharedPtr<OSDictionary> & mkextPlistOut,uint32_t * checksumPtr)3435 OSKext::readMkext2Archive(
3436 	OSData        * mkextData,
3437 	OSSharedPtr<OSDictionary> &mkextPlistOut,
3438 	uint32_t      * checksumPtr)
3439 {
3440 	OSDictionary * mkextPlist = NULL;
3441 	OSReturn ret;
3442 
3443 	if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData,
3444 	    &mkextPlist,
3445 	    checksumPtr))) {
3446 		mkextPlistOut.reset(mkextPlist, OSNoRetain);
3447 	}
3448 	return ret;
3449 }
3450 
3451 /*********************************************************************
3452 *********************************************************************/
3453 /* static */
3454 OSSharedPtr<OSKext>
withMkext2Info(OSDictionary * anInfoDict,OSData * mkextData)3455 OSKext::withMkext2Info(
3456 	OSDictionary * anInfoDict,
3457 	OSData       * mkextData)
3458 {
3459 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
3460 
3461 	if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
3462 		return NULL;
3463 	}
3464 
3465 	return newKext;
3466 }
3467 
3468 /*********************************************************************
3469 *********************************************************************/
3470 bool
initWithMkext2Info(OSDictionary * anInfoDict,OSData * mkextData)3471 OSKext::initWithMkext2Info(
3472 	OSDictionary * anInfoDict,
3473 	OSData       * mkextData)
3474 {
3475 	bool                   result              = false;
3476 	OSString             * kextPath            = NULL;        // do not release
3477 	OSNumber             * executableOffsetNum = NULL;        // do not release
3478 	OSSharedPtr<OSData>               executable;
3479 
3480 	if (anInfoDict == NULL || !super::init()) {
3481 		goto finish;
3482 	}
3483 
3484 	/* Get the path. Don't look for an arch-specific path property.
3485 	 */
3486 	kextPath = OSDynamicCast(OSString,
3487 	    anInfoDict->getObject(kMKEXTBundlePathKey));
3488 
3489 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
3490 		goto finish;
3491 	}
3492 
3493 	/* If we have a path to the executable, save it.
3494 	 */
3495 	executableRelPath.reset(OSDynamicCast(OSString,
3496 	    anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain);
3497 
3498 	/* Don't need the paths to be in the info dictionary any more.
3499 	 */
3500 	anInfoDict->removeObject(kMKEXTBundlePathKey);
3501 	anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
3502 
3503 	executableOffsetNum = OSDynamicCast(OSNumber,
3504 	    infoDict->getObject(kMKEXTExecutableKey));
3505 	if (executableOffsetNum) {
3506 		executable = createMkext2FileEntry(mkextData,
3507 		    executableOffsetNum, "executable");
3508 		infoDict->removeObject(kMKEXTExecutableKey);
3509 		if (!executable) {
3510 			goto finish;
3511 		}
3512 		if (!setExecutable(executable.get(), mkextData, true)) {
3513 			goto finish;
3514 		}
3515 	}
3516 
3517 	result = (registerIdentifier() == kOSKextInitialized);
3518 finish:
3519 	return result;
3520 }
3521 
3522 /*********************************************************************
3523 *********************************************************************/
3524 OSSharedPtr<OSData>
createMkext2FileEntry(OSData * mkextData,OSNumber * offsetNum,const char * name)3525 OSKext::createMkext2FileEntry(
3526 	OSData     * mkextData,
3527 	OSNumber   * offsetNum,
3528 	const char * name)
3529 {
3530 	OSSharedPtr<OSData> result;
3531 	MkextEntryRef   entryRef;
3532 	uint8_t       * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
3533 	uint32_t        entryOffset = offsetNum->unsigned32BitValue();
3534 
3535 	result = OSData::withCapacity(sizeof(entryRef));
3536 	if (!result) {
3537 		goto finish;
3538 	}
3539 
3540 	entryRef.mkext = (mkext_basic_header *)mkextBuffer;
3541 	entryRef.fileinfo = mkextBuffer + entryOffset;
3542 	if (!result->appendValue(entryRef)) {
3543 		result.reset();
3544 		goto finish;
3545 	}
3546 
3547 finish:
3548 	if (!result) {
3549 		OSKextLog(this,
3550 		    kOSKextLogErrorLevel |
3551 		    kOSKextLogArchiveFlag,
3552 		    "Can't create wrapper for mkext file entry '%s' of kext %s.",
3553 		    name, getIdentifierCString());
3554 	}
3555 	return result;
3556 }
3557 
3558 /*********************************************************************
3559 *********************************************************************/
3560 extern "C" {
3561 static void * z_alloc(void *, u_int items, u_int size);
3562 static void   z_free(void *, void *ptr);
3563 
3564 typedef struct z_mem {
3565 	uint32_t alloc_size;
3566 	uint8_t  data[0];
3567 } z_mem;
3568 
3569 /*
3570  * Space allocation and freeing routines for use by zlib routines.
3571  */
3572 void *
z_alloc(void * notused __unused,u_int num_items,u_int size)3573 z_alloc(void * notused __unused, u_int num_items, u_int size)
3574 {
3575 	void     * result = NULL;
3576 	z_mem    * zmem = NULL;
3577 
3578 	uint64_t   total = ((uint64_t)num_items) * ((uint64_t)size);
3579 	//Check for overflow due to multiplication
3580 	if (total > UINT32_MAX) {
3581 		panic("z_alloc(%p, %x, %x): overflow caused by %x * %x",
3582 		    notused, num_items, size, num_items, size);
3583 	}
3584 
3585 	uint64_t   allocSize64 =  total + ((uint64_t)sizeof(zmem));
3586 	//Check for overflow due to addition
3587 	if (allocSize64 > UINT32_MAX) {
3588 		panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx",
3589 		    notused, num_items, size, (uint32_t)total, sizeof(zmem));
3590 	}
3591 	uint32_t allocSize = (uint32_t)allocSize64;
3592 
3593 	zmem = (z_mem *)kalloc_data_tag(allocSize, Z_WAITOK,
3594 	    VM_KERN_MEMORY_OSKEXT);
3595 	if (!zmem) {
3596 		goto finish;
3597 	}
3598 	zmem->alloc_size = allocSize;
3599 	result = (void *)&(zmem->data);
3600 finish:
3601 	return result;
3602 }
3603 
3604 void
z_free(void * notused __unused,void * ptr)3605 z_free(void * notused __unused, void * ptr)
3606 {
3607 	uint32_t * skipper = (uint32_t *)ptr - 1;
3608 	z_mem    * zmem = (z_mem *)skipper;
3609 	kfree_data(zmem, zmem->alloc_size);
3610 }
3611 };
3612 
3613 OSSharedPtr<OSData>
extractMkext2FileData(UInt8 * data,const char * name,uint32_t compressedSize,uint32_t fullSize)3614 OSKext::extractMkext2FileData(
3615 	UInt8      * data,
3616 	const char * name,
3617 	uint32_t     compressedSize,
3618 	uint32_t     fullSize)
3619 {
3620 	OSSharedPtr<OSData>      result;
3621 	OSSharedPtr<OSData>      uncompressedData;        // release on error
3622 
3623 	uint8_t     * uncompressedDataBuffer = NULL;        // do not free
3624 	unsigned long uncompressedSize;
3625 	z_stream      zstream;
3626 	bool          zstream_inited = false;
3627 	int           zlib_result;
3628 
3629 	/* If the file isn't compressed, we want to make a copy
3630 	 * so that we don't have the tie to the larger mkext file buffer any more.
3631 	 */
3632 	if (!compressedSize) {
3633 		uncompressedData = OSData::withBytes(data, fullSize);
3634 		// xxx - no check for failure?
3635 		result = uncompressedData;
3636 		goto finish;
3637 	}
3638 
3639 	if (KERN_SUCCESS != kmem_alloc(kernel_map,
3640 	    (vm_offset_t*)&uncompressedDataBuffer, fullSize,
3641 	    KMA_DATA, VM_KERN_MEMORY_OSKEXT)) {
3642 		/* How's this for cheesy? The kernel is only asked to extract
3643 		 * kext plists so we tailor the log messages.
3644 		 */
3645 		if (isKernel()) {
3646 			OSKextLog(this,
3647 			    kOSKextLogErrorLevel |
3648 			    kOSKextLogArchiveFlag,
3649 			    "Allocation failure extracting %s from mkext.", name);
3650 		} else {
3651 			OSKextLog(this,
3652 			    kOSKextLogErrorLevel |
3653 			    kOSKextLogArchiveFlag,
3654 			    "Allocation failure extracting %s from mkext for kext %s.",
3655 			    name, getIdentifierCString());
3656 		}
3657 
3658 		goto finish;
3659 	}
3660 	uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
3661 	if (!uncompressedData) {
3662 		if (isKernel()) {
3663 			OSKextLog(this,
3664 			    kOSKextLogErrorLevel |
3665 			    kOSKextLogArchiveFlag,
3666 			    "Allocation failure extracting %s from mkext.", name);
3667 		} else {
3668 			OSKextLog(this,
3669 			    kOSKextLogErrorLevel |
3670 			    kOSKextLogArchiveFlag,
3671 			    "Allocation failure extracting %s from mkext for kext %s.",
3672 			    name, getIdentifierCString());
3673 		}
3674 		goto finish;
3675 	}
3676 	uncompressedData->setDeallocFunction(&osdata_kmem_free);
3677 
3678 	if (isKernel()) {
3679 		OSKextLog(this,
3680 		    kOSKextLogDetailLevel |
3681 		    kOSKextLogArchiveFlag,
3682 		    "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3683 		    name, compressedSize, fullSize);
3684 	} else {
3685 		OSKextLog(this,
3686 		    kOSKextLogDetailLevel |
3687 		    kOSKextLogArchiveFlag,
3688 		    "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3689 		    getIdentifierCString(), name, compressedSize, fullSize);
3690 	}
3691 
3692 	bzero(&zstream, sizeof(zstream));
3693 	zstream.next_in   = (UInt8 *)data;
3694 	zstream.avail_in  = compressedSize;
3695 
3696 	zstream.next_out  = uncompressedDataBuffer;
3697 	zstream.avail_out = fullSize;
3698 
3699 	zstream.zalloc    = z_alloc;
3700 	zstream.zfree     = z_free;
3701 
3702 	zlib_result = inflateInit(&zstream);
3703 	if (Z_OK != zlib_result) {
3704 		if (isKernel()) {
3705 			OSKextLog(this,
3706 			    kOSKextLogErrorLevel |
3707 			    kOSKextLogArchiveFlag,
3708 			    "Mkext error; zlib inflateInit failed (%d) for %s.",
3709 			    zlib_result, name);
3710 		} else {
3711 			OSKextLog(this,
3712 			    kOSKextLogErrorLevel |
3713 			    kOSKextLogArchiveFlag,
3714 			    "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3715 			    getIdentifierCString(), zlib_result, name);
3716 		}
3717 		goto finish;
3718 	} else {
3719 		zstream_inited = true;
3720 	}
3721 
3722 	zlib_result = inflate(&zstream, Z_FINISH);
3723 
3724 	if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
3725 		uncompressedSize = zstream.total_out;
3726 	} else {
3727 		if (isKernel()) {
3728 			OSKextLog(this,
3729 			    kOSKextLogErrorLevel |
3730 			    kOSKextLogArchiveFlag,
3731 			    "Mkext error; zlib inflate failed (%d) for %s.",
3732 			    zlib_result, name);
3733 		} else {
3734 			OSKextLog(this,
3735 			    kOSKextLogErrorLevel |
3736 			    kOSKextLogArchiveFlag,
3737 			    "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3738 			    getIdentifierCString(), zlib_result, name);
3739 		}
3740 		if (zstream.msg) {
3741 			OSKextLog(this,
3742 			    kOSKextLogErrorLevel |
3743 			    kOSKextLogArchiveFlag,
3744 			    "zlib error: %s.", zstream.msg);
3745 		}
3746 		goto finish;
3747 	}
3748 
3749 	if (uncompressedSize != fullSize) {
3750 		if (isKernel()) {
3751 			OSKextLog(this,
3752 			    kOSKextLogErrorLevel |
3753 			    kOSKextLogArchiveFlag,
3754 			    "Mkext error; zlib inflate discrepancy for %s, "
3755 			    "uncompressed size != original size.", name);
3756 		} else {
3757 			OSKextLog(this,
3758 			    kOSKextLogErrorLevel |
3759 			    kOSKextLogArchiveFlag,
3760 			    "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3761 			    "uncompressed size != original size.",
3762 			    getIdentifierCString(), name);
3763 		}
3764 		goto finish;
3765 	}
3766 
3767 	result = os::move(uncompressedData);
3768 
3769 finish:
3770 	/* Don't bother checking return, nothing we can do on fail.
3771 	 */
3772 	if (zstream_inited) {
3773 		inflateEnd(&zstream);
3774 	}
3775 
3776 	return result;
3777 }
3778 
3779 /*********************************************************************
3780 *********************************************************************/
3781 /* static */
3782 OSReturn
loadFromMkext(OSKextLogSpec clientLogFilter,char * mkextBuffer,uint32_t mkextBufferLength,char ** logInfoOut,uint32_t * logInfoLengthOut)3783 OSKext::loadFromMkext(
3784 	OSKextLogSpec   clientLogFilter,
3785 	char          * mkextBuffer,
3786 	uint32_t        mkextBufferLength,
3787 	char         ** logInfoOut,
3788 	uint32_t      * logInfoLengthOut)
3789 {
3790 	OSReturn         result                      = kOSReturnError;
3791 	OSReturn         tempResult                  = kOSReturnError;
3792 
3793 	OSSharedPtr<OSData>        mkextData;
3794 	OSSharedPtr<OSDictionary>  mkextPlist;
3795 
3796 	OSSharedPtr<OSArray>       logInfoArray;
3797 	OSSharedPtr<OSSerialize>   serializer;
3798 
3799 	OSString       * predicate                   = NULL;        // do not release
3800 	OSDictionary   * requestArgs                 = NULL;        // do not release
3801 
3802 	OSString       * kextIdentifier              = NULL;        // do not release
3803 	OSNumber       * startKextExcludeNum         = NULL;        // do not release
3804 	OSNumber       * startMatchingExcludeNum     = NULL;        // do not release
3805 	OSBoolean      * delayAutounloadBool         = NULL;        // do not release
3806 	OSArray        * personalityNames            = NULL;        // do not release
3807 
3808 	/* Default values for these two options: regular autounload behavior,
3809 	 * load all kexts, send no personalities.
3810 	 */
3811 	Boolean            delayAutounload           = false;
3812 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
3813 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3814 
3815 	IORecursiveLockLock(sKextLock);
3816 
3817 	if (logInfoOut) {
3818 		*logInfoOut = NULL;
3819 		*logInfoLengthOut = 0;
3820 	}
3821 
3822 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3823 
3824 	OSKextLog(/* kext */ NULL,
3825 	    kOSKextLogDebugLevel |
3826 	    kOSKextLogIPCFlag,
3827 	    "Received kext load request from user space.");
3828 
3829 	/* Regardless of processing, the fact that we have gotten here means some
3830 	 * user-space program is up and talking to us, so we'll switch our kext
3831 	 * registration to reflect that.
3832 	 */
3833 	if (!sUserLoadsActive) {
3834 		OSKextLog(/* kext */ NULL,
3835 		    kOSKextLogProgressLevel |
3836 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3837 		    "Switching to late startup (user-space) kext loading policy.");
3838 
3839 		sUserLoadsActive = true;
3840 	}
3841 
3842 	if (!sLoadEnabled) {
3843 		OSKextLog(/* kext */ NULL,
3844 		    kOSKextLogErrorLevel |
3845 		    kOSKextLogLoadFlag,
3846 		    "Kext loading is disabled.");
3847 		result = kOSKextReturnDisabled;
3848 		goto finish;
3849 	}
3850 
3851 	/* Note that we do not set a dealloc function on this OSData
3852 	 * object! No references to it can remain after the loadFromMkext()
3853 	 * call since we are in a MIG function, and will vm_deallocate()
3854 	 * the buffer.
3855 	 */
3856 	mkextData = OSData::withBytesNoCopy(mkextBuffer,
3857 	    mkextBufferLength);
3858 	if (!mkextData) {
3859 		OSKextLog(/* kext */ NULL,
3860 		    kOSKextLogErrorLevel |
3861 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3862 		    "Failed to create wrapper for kext load request.");
3863 		result = kOSKextReturnNoMemory;
3864 		goto finish;
3865 	}
3866 
3867 	result = readMkext2Archive(mkextData.get(), mkextPlist, NULL);
3868 	if (result != kOSReturnSuccess) {
3869 		OSKextLog(/* kext */ NULL,
3870 		    kOSKextLogErrorLevel |
3871 		    kOSKextLogLoadFlag,
3872 		    "Failed to read kext load request.");
3873 		goto finish;
3874 	}
3875 
3876 	predicate = _OSKextGetRequestPredicate(mkextPlist.get());
3877 	if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3878 		OSKextLog(/* kext */ NULL,
3879 		    kOSKextLogErrorLevel |
3880 		    kOSKextLogLoadFlag,
3881 		    "Received kext load request with no predicate; skipping.");
3882 		result = kOSKextReturnInvalidArgument;
3883 		goto finish;
3884 	}
3885 
3886 	requestArgs = OSDynamicCast(OSDictionary,
3887 	    mkextPlist->getObject(kKextRequestArgumentsKey));
3888 	if (!requestArgs || !requestArgs->getCount()) {
3889 		OSKextLog(/* kext */ NULL,
3890 		    kOSKextLogErrorLevel |
3891 		    kOSKextLogLoadFlag,
3892 		    "Received kext load request with no arguments.");
3893 		result = kOSKextReturnInvalidArgument;
3894 		goto finish;
3895 	}
3896 
3897 	kextIdentifier = OSDynamicCast(OSString,
3898 	    requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3899 
3900 	if (!kextIdentifier) {
3901 		OSKextLog(/* kext */ NULL,
3902 		    kOSKextLogErrorLevel |
3903 		    kOSKextLogLoadFlag,
3904 		    "Received kext load request with no kext identifier.");
3905 		result = kOSKextReturnInvalidArgument;
3906 		goto finish;
3907 	}
3908 
3909 	startKextExcludeNum = OSDynamicCast(OSNumber,
3910 	    requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3911 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
3912 	    requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3913 	delayAutounloadBool = OSDynamicCast(OSBoolean,
3914 	    requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3915 	personalityNames = OSDynamicCast(OSArray,
3916 	    requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3917 
3918 	if (delayAutounloadBool) {
3919 		delayAutounload = delayAutounloadBool->getValue();
3920 	}
3921 	if (startKextExcludeNum) {
3922 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3923 	}
3924 	if (startMatchingExcludeNum) {
3925 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3926 	}
3927 
3928 	OSKextLog(/* kext */ NULL,
3929 	    kOSKextLogProgressLevel |
3930 	    kOSKextLogIPCFlag,
3931 	    "Received request from user space to load kext %s.",
3932 	    kextIdentifier->getCStringNoCopy());
3933 
3934 	/* Load the kext, with no deferral, since this is a load from outside
3935 	 * the kernel.
3936 	 * xxx - Would like a better way to handle the default values for the
3937 	 * xxx - start/match opt args.
3938 	 */
3939 	result = OSKext::loadKextWithIdentifier(
3940 		kextIdentifier,
3941 		/* kextRef */ NULL,
3942 		/* allowDefer */ false,
3943 		delayAutounload,
3944 		startKextExcludeLevel,
3945 		startMatchingExcludeLevel,
3946 		personalityNames);
3947 	if (result != kOSReturnSuccess) {
3948 		goto finish;
3949 	}
3950 	/* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue
3951 	 * for matching via a separate IOKit calldown.
3952 	 */
3953 
3954 finish:
3955 
3956 	/* Gather up the collected log messages for user space. Any
3957 	 * error messages past this call will not make it up as log messages
3958 	 * but will be in the system log.
3959 	 */
3960 	logInfoArray = OSKext::clearUserSpaceLogFilter();
3961 
3962 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
3963 		tempResult = OSKext::serializeLogInfo(logInfoArray.get(),
3964 		    logInfoOut, logInfoLengthOut);
3965 		if (tempResult != kOSReturnSuccess) {
3966 			result = tempResult;
3967 		}
3968 	}
3969 
3970 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3971 
3972 	IORecursiveLockUnlock(sKextLock);
3973 
3974 	/* Note: mkextDataObject will have been retained by every kext w/an
3975 	 * executable in it. That should all have been flushed out at the
3976 	 * and of the load operation, but you never know....
3977 	 */
3978 	if (mkextData && mkextData->getRetainCount() > 1) {
3979 		OSKextLog(/* kext */ NULL,
3980 		    kOSKextLogErrorLevel |
3981 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3982 		    "Kext load request buffer from user space still retained by a kext; "
3983 		    "probable memory leak.");
3984 	}
3985 
3986 	return result;
3987 }
3988 
3989 #endif // CONFIG_KXLD
3990 
3991 /*********************************************************************
3992 *********************************************************************/
3993 /* static */
3994 OSReturn
serializeLogInfo(OSArray * logInfoArray,char ** logInfoOut,uint32_t * logInfoLengthOut)3995 OSKext::serializeLogInfo(
3996 	OSArray   * logInfoArray,
3997 	char     ** logInfoOut,
3998 	uint32_t  * logInfoLengthOut)
3999 {
4000 	OSReturn        result      = kOSReturnError;
4001 	char          * buffer      = NULL;
4002 	kern_return_t   kmem_result = KERN_FAILURE;
4003 	OSSharedPtr<OSSerialize>  serializer;
4004 	char         * logInfo            = NULL;        // returned by reference
4005 	uint32_t       logInfoLength      = 0;
4006 
4007 	if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
4008 		OSKextLog(/* kext */ NULL,
4009 		    kOSKextLogErrorLevel |
4010 		    kOSKextLogIPCFlag,
4011 		    "Internal error; invalid arguments to OSKext::serializeLogInfo().");
4012 		/* Bad programmer. */
4013 		result = kOSKextReturnInvalidArgument;
4014 		goto finish;
4015 	}
4016 
4017 	serializer = OSSerialize::withCapacity(0);
4018 	if (!serializer) {
4019 		OSKextLog(/* kext */ NULL,
4020 		    kOSKextLogErrorLevel |
4021 		    kOSKextLogIPCFlag,
4022 		    "Failed to create serializer on log info for request from user space.");
4023 		/* Incidental error; we're going to (try to) allow the request
4024 		 * itself to succeed. */
4025 	}
4026 
4027 	if (!logInfoArray->serialize(serializer.get())) {
4028 		OSKextLog(/* kext */ NULL,
4029 		    kOSKextLogErrorLevel |
4030 		    kOSKextLogIPCFlag,
4031 		    "Failed to serialize log info for request from user space.");
4032 		/* Incidental error; we're going to (try to) allow the request
4033 		 * itself to succeed. */
4034 	} else {
4035 		logInfo = serializer->text();
4036 		logInfoLength = serializer->getLength();
4037 
4038 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength),
4039 		    KMA_DATA, VM_KERN_MEMORY_OSKEXT);
4040 		if (kmem_result != KERN_SUCCESS) {
4041 			OSKextLog(/* kext */ NULL,
4042 			    kOSKextLogErrorLevel |
4043 			    kOSKextLogIPCFlag,
4044 			    "Failed to copy log info for request from user space.");
4045 			/* Incidental error; we're going to (try to) allow the request
4046 			 * to succeed. */
4047 		} else {
4048 			/* 11981737 - clear uninitialized data in last page */
4049 			bzero((void *)(buffer + logInfoLength),
4050 			    (round_page(logInfoLength) - logInfoLength));
4051 			memcpy(buffer, logInfo, logInfoLength);
4052 			*logInfoOut = buffer;
4053 			*logInfoLengthOut = logInfoLength;
4054 		}
4055 	}
4056 
4057 	result = kOSReturnSuccess;
4058 finish:
4059 	return result;
4060 }
4061 
4062 #if PRAGMA_MARK
4063 #pragma mark Instance Management Methods
4064 #endif
4065 /*********************************************************************
4066 *********************************************************************/
4067 OSSharedPtr<OSKext>
lookupKextWithIdentifier(const char * kextIdentifier)4068 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
4069 {
4070 	OSSharedPtr<OSKext> foundKext;
4071 
4072 	IORecursiveLockLock(sKextLock);
4073 	foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain);
4074 	IORecursiveLockUnlock(sKextLock);
4075 
4076 	return foundKext;
4077 }
4078 
4079 /*********************************************************************
4080 *********************************************************************/
4081 OSSharedPtr<OSKext>
lookupKextWithIdentifier(OSString * kextIdentifier)4082 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
4083 {
4084 	return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
4085 }
4086 
4087 /*********************************************************************
4088 *********************************************************************/
4089 OSSharedPtr<OSKext>
lookupDextWithIdentifier(OSString * dextIdentifier,OSData * dextUniqueIdentifier)4090 OSKext::lookupDextWithIdentifier(OSString * dextIdentifier, OSData *dextUniqueIdentifier)
4091 {
4092 	OSSharedPtr<OSKext> foundDext;
4093 	foundDext.reset();
4094 
4095 	IORecursiveLockLock(sKextLock);
4096 	OSKext *dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIdentifier->getCStringNoCopy()));
4097 	if (dext != NULL && dext->isDriverKit()) {
4098 		if (dext->dextUniqueID == NULL || dext->dextUniqueID->isEqualTo(dextUniqueIdentifier)) {
4099 			foundDext.reset(dext, OSRetain);
4100 		}
4101 	}
4102 	IORecursiveLockUnlock(sKextLock);
4103 
4104 	return foundDext;
4105 }
4106 
4107 /*********************************************************************
4108 *********************************************************************/
4109 OSSharedPtr<OSKext>
lookupKextWithLoadTag(uint32_t aTag)4110 OSKext::lookupKextWithLoadTag(uint32_t aTag)
4111 {
4112 	OSSharedPtr<OSKext> foundKext;             // returned
4113 	uint32_t i, j;
4114 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4115 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4116 
4117 	IORecursiveLockLock(sKextLock);
4118 
4119 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4120 		for (i = 0; i < count[j]; i++) {
4121 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4122 			if (thisKext->getLoadTag() == aTag) {
4123 				foundKext.reset(thisKext, OSRetain);
4124 				goto finish;
4125 			}
4126 		}
4127 	}
4128 
4129 finish:
4130 	IORecursiveLockUnlock(sKextLock);
4131 
4132 	return foundKext;
4133 }
4134 
4135 /*********************************************************************
4136 *********************************************************************/
4137 OSSharedPtr<OSKext>
lookupKextWithAddress(vm_address_t address)4138 OSKext::lookupKextWithAddress(vm_address_t address)
4139 {
4140 	OSSharedPtr<OSKext> foundKext;             // returned
4141 	uint32_t count, i;
4142 	kmod_info_t *kmod_info;
4143 	vm_address_t originalAddress;
4144 #if defined(__arm64__)
4145 	uint64_t   textExecBase;
4146 	size_t     textExecSize;
4147 #endif /* defined(__arm64__) */
4148 
4149 	originalAddress = address;
4150 #if  __has_feature(ptrauth_calls)
4151 	address = (vm_address_t)VM_KERNEL_STRIP_PTR(address);
4152 #endif /*  __has_feature(ptrauth_calls) */
4153 
4154 	IORecursiveLockLock(sKextLock);
4155 
4156 	count = sLoadedKexts->getCount();
4157 	for (i = 0; i < count; i++) {
4158 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
4159 		if (thisKext == sKernelKext) {
4160 			continue;
4161 		}
4162 		if (thisKext->kmod_info && thisKext->kmod_info->address) {
4163 			kmod_info = thisKext->kmod_info;
4164 			vm_address_t kext_start = kmod_info->address;
4165 			vm_address_t kext_end = kext_start + kmod_info->size;
4166 			if ((kext_start <= address) && (address < kext_end)) {
4167 				foundKext.reset(thisKext, OSRetain);
4168 				goto finish;
4169 			}
4170 #if defined(__arm64__)
4171 			textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize);
4172 			if ((textExecBase <= address) && (address < textExecBase + textExecSize)) {
4173 				foundKext.reset(thisKext, OSRetain);
4174 				goto finish;
4175 			}
4176 #endif /* defined (__arm64__) */
4177 		}
4178 	}
4179 	if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) {
4180 		foundKext.reset(sKernelKext, OSRetain);
4181 		goto finish;
4182 	}
4183 	/*
4184 	 * DriverKit userspace executables do not have a kernel linkedExecutable,
4185 	 * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address
4186 	 * here, so use the original address passed to this method.
4187 	 *
4188 	 * This is supposed to be used for logging reasons only. When logd
4189 	 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
4190 	 * remove it here before checking it against the LoadTag.
4191 	 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
4192 	 */
4193 
4194 	address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
4195 	count = sLoadedDriverKitKexts->getCount();
4196 	for (i = 0; i < count; i++) {
4197 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
4198 		if (thisKext->getLoadTag() == address) {
4199 			foundKext.reset(thisKext, OSRetain);
4200 		}
4201 	}
4202 
4203 finish:
4204 	IORecursiveLockUnlock(sKextLock);
4205 
4206 	return foundKext;
4207 }
4208 
4209 OSSharedPtr<OSData>
copyKextUUIDForAddress(OSNumber * address)4210 OSKext::copyKextUUIDForAddress(OSNumber *address)
4211 {
4212 	OSSharedPtr<OSData>   uuid;
4213 	OSSharedPtr<OSKext>   kext;
4214 
4215 	if (!address) {
4216 		return NULL;
4217 	}
4218 
4219 #if CONFIG_MACF
4220 	/* Is the calling process allowed to query kext info? */
4221 	if (current_task() != kernel_task) {
4222 		int macCheckResult = 0;
4223 		kauth_cred_t cred = NULL;
4224 
4225 		cred = kauth_cred_get_with_ref();
4226 		macCheckResult = mac_kext_check_query(cred);
4227 		kauth_cred_unref(&cred);
4228 
4229 		if (macCheckResult != 0) {
4230 			OSKextLog(/* kext */ NULL,
4231 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
4232 			    "Failed to query kext UUID (MAC policy error 0x%x).",
4233 			    macCheckResult);
4234 			return NULL;
4235 		}
4236 	}
4237 #endif
4238 
4239 	uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue());
4240 	if (slidAddress != 0) {
4241 		kext = lookupKextWithAddress(slidAddress);
4242 		if (kext) {
4243 			uuid = kext->copyTextUUID();
4244 		}
4245 	}
4246 
4247 	if (!uuid) {
4248 		/*
4249 		 * If we still don't have a UUID, then we failed to match the slid + stripped address with
4250 		 * a kext. This might have happened because the log message came from a dext.
4251 		 *
4252 		 * Try again with the original address.
4253 		 */
4254 		kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue());
4255 		if (kext && kext->isDriverKit()) {
4256 			uuid = kext->copyTextUUID();
4257 		}
4258 	}
4259 
4260 	return uuid;
4261 }
4262 
4263 /*********************************************************************
4264 *********************************************************************/
4265 OSSharedPtr<OSKext>
lookupKextWithUUID(uuid_t wanted)4266 OSKext::lookupKextWithUUID(uuid_t wanted)
4267 {
4268 	OSSharedPtr<OSKext> foundKext;             // returned
4269 	uint32_t j, i;
4270 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4271 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4272 
4273 
4274 	IORecursiveLockLock(sKextLock);
4275 
4276 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4277 		for (i = 0; i < count[j]; i++) {
4278 			OSKext   * thisKext     = NULL;
4279 
4280 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4281 			if (!thisKext) {
4282 				continue;
4283 			}
4284 
4285 			OSSharedPtr<OSData> uuid_data = thisKext->copyUUID();
4286 			if (!uuid_data) {
4287 				continue;
4288 			}
4289 
4290 			uuid_t uuid;
4291 			memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
4292 
4293 			if (0 == uuid_compare(wanted, uuid)) {
4294 				foundKext.reset(thisKext, OSRetain);
4295 				goto finish;
4296 			}
4297 		}
4298 	}
4299 finish:
4300 	IORecursiveLockUnlock(sKextLock);
4301 
4302 	return foundKext;
4303 }
4304 
4305 
4306 
4307 
4308 /*********************************************************************
4309 *********************************************************************/
4310 /* static */
4311 bool
isKextWithIdentifierLoaded(const char * kextIdentifier)4312 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
4313 {
4314 	bool result = false;
4315 	OSKext * foundKext = NULL;             // returned
4316 
4317 	IORecursiveLockLock(sKextLock);
4318 
4319 	foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4320 	if (foundKext && foundKext->isLoaded()) {
4321 		result = true;
4322 	}
4323 
4324 	IORecursiveLockUnlock(sKextLock);
4325 
4326 	return result;
4327 }
4328 
4329 /*********************************************************************
4330 * xxx - should spawn a separate thread so a kext can safely have
4331 * xxx - itself unloaded.
4332 *********************************************************************/
4333 /* static */
4334 OSReturn
removeKext(OSKext * aKext,__unused bool terminateServicesAndRemovePersonalitiesFlag)4335 OSKext::removeKext(
4336 	OSKext * aKext,
4337 #if CONFIG_EMBEDDED
4338 	__unused
4339 #endif
4340 	bool     terminateServicesAndRemovePersonalitiesFlag)
4341 {
4342 #if CONFIG_EMBEDDED
4343 	if (!aKext->isDriverKit()) {
4344 		OSKextLog(aKext,
4345 		    kOSKextLogErrorLevel |
4346 		    kOSKextLogKextBookkeepingFlag,
4347 		    "removeKext() called for %s, only supported on embedded for DriverKit dexts",
4348 		    aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
4349 
4350 		return kOSReturnSuccess;
4351 	}
4352 #endif /* CONFIG_EMBEDDED */
4353 	OSReturn result    = kOSKextReturnInUse;
4354 	OSKext * checkKext = NULL;         // do not release
4355 #if CONFIG_MACF
4356 	int macCheckResult = 0;
4357 	kauth_cred_t cred  = NULL;
4358 #endif
4359 
4360 	IORecursiveLockLock(sKextLock);
4361 
4362 	/* If the kext has no identifier, it failed to init
4363 	 * so isn't in sKextsByID and it isn't loaded.
4364 	 */
4365 	if (!aKext->getIdentifier()) {
4366 		result = kOSReturnSuccess;
4367 		goto finish;
4368 	}
4369 
4370 	checkKext = OSDynamicCast(OSKext,
4371 	    sKextsByID->getObject(aKext->getIdentifier()));
4372 	if (checkKext != aKext) {
4373 		result = kOSKextReturnNotFound;
4374 		goto finish;
4375 	}
4376 
4377 	if (aKext->isLoaded() || aKext->isDriverKit()) {
4378 #if CONFIG_MACF
4379 		if (current_task() != kernel_task) {
4380 			cred = kauth_cred_get_with_ref();
4381 			macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
4382 			kauth_cred_unref(&cred);
4383 		}
4384 
4385 		if (macCheckResult != 0) {
4386 			result = kOSReturnError;
4387 			OSKextLog(aKext,
4388 			    kOSKextLogErrorLevel |
4389 			    kOSKextLogKextBookkeepingFlag,
4390 			    "Failed to remove kext %s (MAC policy error 0x%x).",
4391 			    aKext->getIdentifierCString(), macCheckResult);
4392 			goto finish;
4393 		}
4394 #endif
4395 
4396 		/* make sure there are no resource requests in flight - 17187548 */
4397 		if (aKext->declaresExecutable() && aKext->countRequestCallbacks()) {
4398 			goto finish;
4399 		}
4400 		if (aKext->flags.unloadUnsupported) {
4401 			result = kOSKextReturnInUse;
4402 			OSKextLog(aKext,
4403 			    kOSKextLogErrorLevel |
4404 			    kOSKextLogKextBookkeepingFlag,
4405 			    "Can't remove kext %s; unsupported by cache.",
4406 			    aKext->getIdentifierCString());
4407 			goto finish;
4408 		}
4409 
4410 		/* If we are terminating, send the request to the IOCatalogue
4411 		 * (which will actually call us right back but that's ok we have
4412 		 * a recursive lock don't you know) but do not ask the IOCatalogue
4413 		 * to call back with an unload, we'll do that right here.
4414 		 */
4415 		if (terminateServicesAndRemovePersonalitiesFlag) {
4416 			result = gIOCatalogue->terminateDriversForModule(
4417 				aKext->getIdentifierCString(), /* unload */ false);
4418 			if (result != kOSReturnSuccess) {
4419 				OSKextLog(aKext,
4420 				    kOSKextLogErrorLevel |
4421 				    kOSKextLogKextBookkeepingFlag,
4422 				    "Can't remove kext %s; services failed to terminate - 0x%x.",
4423 				    aKext->getIdentifierCString(), result);
4424 				goto finish;
4425 			}
4426 		}
4427 
4428 		result = aKext->unload();
4429 		if (result != kOSReturnSuccess) {
4430 			OSKextLog(aKext,
4431 			    kOSKextLogErrorLevel |
4432 			    kOSKextLogKextBookkeepingFlag,
4433 			    "Can't remove kext %s; kext failed to unload - 0x%x.",
4434 			    aKext->getIdentifierCString(), result);
4435 			goto finish;
4436 		}
4437 	}
4438 
4439 	/* Remove personalities as requested. This is a bit redundant for a loaded
4440 	 * kext as IOCatalogue::terminateDriversForModule() removes driver
4441 	 * personalities, but it doesn't restart matching, which we always want
4442 	 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
4443 	 * that happens.
4444 	 */
4445 	if (terminateServicesAndRemovePersonalitiesFlag) {
4446 		aKext->removePersonalitiesFromCatalog();
4447 	}
4448 
4449 	if (aKext->isInFileset()) {
4450 		OSKextLog(aKext,
4451 		    kOSKextLogProgressLevel |
4452 		    kOSKextLogKextBookkeepingFlag,
4453 		    "Fileset kext %s unloaded.",
4454 		    aKext->getIdentifierCString());
4455 	} else {
4456 		OSKextLog(aKext,
4457 		    kOSKextLogProgressLevel |
4458 		    kOSKextLogKextBookkeepingFlag,
4459 		    "Removing kext %s.",
4460 		    aKext->getIdentifierCString());
4461 
4462 		sKextsByID->removeObject(aKext->getIdentifier());
4463 	}
4464 	result = kOSReturnSuccess;
4465 
4466 finish:
4467 	IORecursiveLockUnlock(sKextLock);
4468 	return result;
4469 }
4470 
4471 /*********************************************************************
4472 *********************************************************************/
4473 /* static */
4474 OSReturn
removeKextWithIdentifier(const char * kextIdentifier,bool terminateServicesAndRemovePersonalitiesFlag)4475 OSKext::removeKextWithIdentifier(
4476 	const char * kextIdentifier,
4477 	bool         terminateServicesAndRemovePersonalitiesFlag)
4478 {
4479 	OSReturn result = kOSReturnError;
4480 
4481 	IORecursiveLockLock(sKextLock);
4482 
4483 	OSKext * aKext = OSDynamicCast(OSKext,
4484 	    sKextsByID->getObject(kextIdentifier));
4485 	if (!aKext) {
4486 		result = kOSKextReturnNotFound;
4487 		OSKextLog(/* kext */ NULL,
4488 		    kOSKextLogErrorLevel |
4489 		    kOSKextLogKextBookkeepingFlag,
4490 		    "Can't remove kext %s - not found.",
4491 		    kextIdentifier);
4492 		goto finish;
4493 	}
4494 
4495 	result = OSKext::removeKext(aKext,
4496 	    terminateServicesAndRemovePersonalitiesFlag);
4497 
4498 finish:
4499 	IORecursiveLockUnlock(sKextLock);
4500 
4501 	return result;
4502 }
4503 
4504 /*********************************************************************
4505 *********************************************************************/
4506 /* static */
4507 OSReturn
removeKextWithLoadTag(OSKextLoadTag loadTag,bool terminateServicesAndRemovePersonalitiesFlag)4508 OSKext::removeKextWithLoadTag(
4509 	OSKextLoadTag loadTag,
4510 	bool          terminateServicesAndRemovePersonalitiesFlag)
4511 {
4512 	OSReturn result    = kOSReturnError;
4513 	OSKext * foundKext = NULL;
4514 	uint32_t i, j;
4515 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4516 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4517 
4518 
4519 	IORecursiveLockLock(sKextLock);
4520 
4521 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4522 		for (i = 0; i < count[j]; i++) {
4523 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4524 			if (thisKext->loadTag == loadTag) {
4525 				foundKext = thisKext;
4526 				break;
4527 			}
4528 		}
4529 	}
4530 
4531 	if (!foundKext) {
4532 		result = kOSKextReturnNotFound;
4533 		OSKextLog(/* kext */ NULL,
4534 		    kOSKextLogErrorLevel |
4535 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4536 		    "Can't remove kext with load tag %d - not found.",
4537 		    loadTag);
4538 		goto finish;
4539 	}
4540 
4541 	result = OSKext::removeKext(foundKext,
4542 	    terminateServicesAndRemovePersonalitiesFlag);
4543 
4544 finish:
4545 	IORecursiveLockUnlock(sKextLock);
4546 
4547 	return result;
4548 }
4549 
4550 /*********************************************************************
4551 *********************************************************************/
4552 OSSharedPtr<OSDictionary>
copyKexts(void)4553 OSKext::copyKexts(void)
4554 {
4555 	OSSharedPtr<OSDictionary> result;
4556 
4557 	IORecursiveLockLock(sKextLock);
4558 	result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection());
4559 	IORecursiveLockUnlock(sKextLock);
4560 
4561 	return result;
4562 }
4563 
4564 /*********************************************************************
4565 *********************************************************************/
4566 #define BOOTER_KEXT_PREFIX   "Driver-"
4567 
4568 typedef struct _DeviceTreeBuffer {
4569 	uint32_t paddr;
4570 	uint32_t length;
4571 } _DeviceTreeBuffer;
4572 
4573 /*********************************************************************
4574 * Create a dictionary of excluded kexts from the given booter data.
4575 *********************************************************************/
4576 /* static */
4577 void
createExcludeListFromBooterData(OSDictionary * theDictionary,OSCollectionIterator * theIterator)4578 OSKext::createExcludeListFromBooterData(
4579 	OSDictionary *          theDictionary,
4580 	OSCollectionIterator *  theIterator )
4581 {
4582 	OSString                  * deviceTreeName      = NULL;        // do not release
4583 	const _DeviceTreeBuffer   * deviceTreeBuffer    = NULL;        // do not release
4584 	char                      * booterDataPtr       = NULL;        // do not release
4585 	_BooterKextFileInfo       * kextFileInfo        = NULL;        // do not release
4586 	char                      * infoDictAddr        = NULL;        // do not release
4587 	OSSharedPtr<OSObject>       parsedXML;
4588 	OSDictionary              * theInfoDict         = NULL;        // do not release
4589 
4590 	theIterator->reset();
4591 
4592 	/* look for AppleKextExcludeList.kext */
4593 	while ((deviceTreeName =
4594 	    OSDynamicCast(OSString, theIterator->getNextObject()))) {
4595 		const char *    devTreeNameCString;
4596 		OSData *        deviceTreeEntry;        // do not release
4597 		OSString *      myBundleID;        // do not release
4598 
4599 		deviceTreeEntry =
4600 		    OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
4601 		if (!deviceTreeEntry) {
4602 			continue;
4603 		}
4604 
4605 		/* Make sure it is a kext */
4606 		devTreeNameCString = deviceTreeName->getCStringNoCopy();
4607 		if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
4608 		    (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
4609 			OSKextLog(NULL,
4610 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4611 			    "\"%s\" not a kext",
4612 			    devTreeNameCString);
4613 			continue;
4614 		}
4615 
4616 		deviceTreeBuffer = (const _DeviceTreeBuffer *)
4617 		    deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
4618 		if (!deviceTreeBuffer) {
4619 			continue;
4620 		}
4621 
4622 		booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
4623 		if (!booterDataPtr) {
4624 			continue;
4625 		}
4626 
4627 		kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
4628 		if (!kextFileInfo->infoDictPhysAddr ||
4629 		    !kextFileInfo->infoDictLength) {
4630 			continue;
4631 		}
4632 
4633 		infoDictAddr = (char *)
4634 		    ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
4635 		if (!infoDictAddr) {
4636 			continue;
4637 		}
4638 
4639 		parsedXML = OSUnserializeXML(infoDictAddr);
4640 		if (!parsedXML) {
4641 			continue;
4642 		}
4643 
4644 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
4645 		if (!theInfoDict) {
4646 			continue;
4647 		}
4648 
4649 		myBundleID =
4650 		    OSDynamicCast(OSString,
4651 		    theInfoDict->getObject(kCFBundleIdentifierKey));
4652 		if (myBundleID &&
4653 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4654 			boolean_t updated = updateExcludeList(theInfoDict);
4655 			if (!updated) {
4656 				/* 25322874 */
4657 				panic("Missing OSKextExcludeList dictionary");
4658 			}
4659 			break;
4660 		}
4661 	}         // while ( (deviceTreeName = ...) )
4662 
4663 	return;
4664 }
4665 
4666 /*********************************************************************
4667 * Create a dictionary of excluded kexts from the given prelink
4668 * info (kernelcache).
4669 *********************************************************************/
4670 /* static */
4671 void
createExcludeListFromPrelinkInfo(OSArray * theInfoArray)4672 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
4673 {
4674 	OSDictionary *  myInfoDict = NULL;        // do not release
4675 	OSString *      myBundleID;        // do not release
4676 	u_int           i;
4677 
4678 	/* Find the Apple Kext Exclude List. */
4679 	for (i = 0; i < theInfoArray->getCount(); i++) {
4680 		myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
4681 		if (!myInfoDict) {
4682 			continue;
4683 		}
4684 		myBundleID =
4685 		    OSDynamicCast(OSString,
4686 		    myInfoDict->getObject(kCFBundleIdentifierKey));
4687 		if (myBundleID &&
4688 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4689 			boolean_t updated = updateExcludeList(myInfoDict);
4690 			if (!updated) {
4691 				/* 25322874 */
4692 				panic("Missing OSKextExcludeList dictionary");
4693 			}
4694 			break;
4695 		}
4696 	}         // for (i = 0; i < theInfoArray->getCount()...
4697 
4698 	return;
4699 }
4700 
4701 /* static */
4702 boolean_t
updateExcludeList(OSDictionary * infoDict)4703 OSKext::updateExcludeList(OSDictionary *infoDict)
4704 {
4705 	OSDictionary *myTempDict = NULL;         // do not free
4706 	OSString     *myTempString = NULL;        // do not free
4707 	OSKextVersion newVersion = 0;
4708 	boolean_t updated = false;
4709 
4710 	if (!infoDict) {
4711 		return false;
4712 	}
4713 
4714 	myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
4715 	if (!myTempDict) {
4716 		return false;
4717 	}
4718 
4719 	myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
4720 	if (!myTempString) {
4721 		return false;
4722 	}
4723 
4724 	newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
4725 	if (newVersion == 0) {
4726 		return false;
4727 	}
4728 
4729 	IORecursiveLockLock(sKextLock);
4730 
4731 	if (newVersion > sExcludeListVersion) {
4732 		sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
4733 		sExcludeListVersion = newVersion;
4734 		updated = true;
4735 	}
4736 
4737 	IORecursiveLockUnlock(sKextLock);
4738 	return updated;
4739 }
4740 
4741 #if PRAGMA_MARK
4742 #pragma mark Accessors
4743 #endif
4744 /*********************************************************************
4745 *********************************************************************/
4746 const OSSymbol *
getIdentifier(void)4747 OSKext::getIdentifier(void)
4748 {
4749 	return bundleID.get();
4750 }
4751 
4752 /*********************************************************************
4753 * A kext must have a bundle identifier to even survive initialization;
4754 * this is guaranteed to exist past then.
4755 *********************************************************************/
4756 const char *
getIdentifierCString(void)4757 OSKext::getIdentifierCString(void)
4758 {
4759 	return bundleID->getCStringNoCopy();
4760 }
4761 
4762 /*********************************************************************
4763 *********************************************************************/
4764 OSKextVersion
getVersion(void)4765 OSKext::getVersion(void)
4766 {
4767 	return version;
4768 }
4769 
4770 /*********************************************************************
4771 *********************************************************************/
4772 OSKextVersion
getCompatibleVersion(void)4773 OSKext::getCompatibleVersion(void)
4774 {
4775 	return compatibleVersion;
4776 }
4777 
4778 /*********************************************************************
4779 *********************************************************************/
4780 bool
isLibrary(void)4781 OSKext::isLibrary(void)
4782 {
4783 	return getCompatibleVersion() > 0;
4784 }
4785 
4786 /*********************************************************************
4787 *********************************************************************/
4788 bool
isCompatibleWithVersion(OSKextVersion aVersion)4789 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
4790 {
4791 	if ((compatibleVersion > -1 && version > -1) &&
4792 	    (compatibleVersion <= version && aVersion <= version)) {
4793 		return true;
4794 	}
4795 	return false;
4796 }
4797 
4798 /*********************************************************************
4799 *********************************************************************/
4800 bool
declaresExecutable(void)4801 OSKext::declaresExecutable(void)
4802 {
4803 	if (isDriverKit()) {
4804 		return false;
4805 	}
4806 	return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
4807 }
4808 
4809 /*********************************************************************
4810 *********************************************************************/
4811 OSData *
getExecutable(void)4812 OSKext::getExecutable(void)
4813 {
4814 	OSData * result              = NULL;
4815 	OSSharedPtr<OSData> extractedExecutable;
4816 
4817 	if (flags.builtin) {
4818 		return sKernelKext->linkedExecutable.get();
4819 	}
4820 
4821 	result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
4822 	if (result) {
4823 		return result;
4824 	}
4825 
4826 #if CONFIG_KXLD
4827 	OSData * mkextExecutableRef  = NULL;        // do not release
4828 	mkextExecutableRef = OSDynamicCast(OSData,
4829 	    getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
4830 
4831 	if (mkextExecutableRef) {
4832 		MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
4833 		    mkextExecutableRef->getBytesNoCopy();
4834 		uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
4835 		if (mkextVersion == MKEXT_VERS_2) {
4836 			mkext2_file_entry * fileinfo =
4837 			    (mkext2_file_entry *)mkextEntryRef->fileinfo;
4838 			uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
4839 			uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
4840 			extractedExecutable = extractMkext2FileData(
4841 				MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
4842 				compressedSize, fullSize);
4843 		} else {
4844 			OSKextLog(this, kOSKextLogErrorLevel |
4845 			    kOSKextLogArchiveFlag,
4846 			    "Kext %s - unknown mkext version 0x%x for executable.",
4847 			    getIdentifierCString(), mkextVersion);
4848 		}
4849 
4850 		/* Regardless of success, remove the mkext executable,
4851 		 * and drop one reference on the mkext.  (setExecutable() does not
4852 		 * replace, it removes, or panics if asked to replace.)
4853 		 */
4854 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4855 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4856 
4857 		if (extractedExecutable && extractedExecutable->getLength()) {
4858 			if (!setExecutable(extractedExecutable.get())) {
4859 				goto finish;
4860 			}
4861 			result = extractedExecutable.get();
4862 		} else {
4863 			goto finish;
4864 		}
4865 	}
4866 
4867 finish:
4868 #endif // CONFIG_KXLD
4869 	return result;
4870 }
4871 
4872 /*********************************************************************
4873 *********************************************************************/
4874 bool
isInterface(void)4875 OSKext::isInterface(void)
4876 {
4877 	return flags.interface;
4878 }
4879 
4880 /*********************************************************************
4881 *********************************************************************/
4882 bool
isKernel(void)4883 OSKext::isKernel(void)
4884 {
4885 	return this == sKernelKext;
4886 }
4887 
4888 /*********************************************************************
4889 *********************************************************************/
4890 bool
isKernelComponent(void)4891 OSKext::isKernelComponent(void)
4892 {
4893 	return flags.kernelComponent ? true : false;
4894 }
4895 
4896 /*********************************************************************
4897 *********************************************************************/
4898 bool
isExecutable(void)4899 OSKext::isExecutable(void)
4900 {
4901 	return !isKernel() && !isInterface() && declaresExecutable();
4902 }
4903 
4904 /*********************************************************************
4905 * We might want to check this recursively for all dependencies,
4906 * since a subtree of dependencies could get loaded before we hit
4907 * a dependency that isn't safe-boot-loadable.
4908 *
4909 * xxx - Might want to return false if OSBundleEnableKextLogging or
4910 * OSBundleDebugLevel
4911 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4912 * the point except it's usually development drivers, which might
4913 * cause panics on startup, that have those properties). Heh; could
4914 * use a "kx" boot-arg!
4915 *********************************************************************/
4916 bool
isLoadableInSafeBoot(void)4917 OSKext::isLoadableInSafeBoot(void)
4918 {
4919 	bool       result   = false;
4920 	OSString * required = NULL;         // do not release
4921 
4922 	if (isKernel()) {
4923 		result = true;
4924 		goto finish;
4925 	}
4926 
4927 	if (isDriverKit()) {
4928 		result = true;
4929 		goto finish;
4930 	}
4931 
4932 	required = OSDynamicCast(OSString,
4933 	    getPropertyForHostArch(kOSBundleRequiredKey));
4934 	if (!required) {
4935 		goto finish;
4936 	}
4937 	if (required->isEqualTo(kOSBundleRequiredRoot) ||
4938 	    required->isEqualTo(kOSBundleRequiredLocalRoot) ||
4939 	    required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
4940 	    required->isEqualTo(kOSBundleRequiredSafeBoot) ||
4941 	    required->isEqualTo(kOSBundleRequiredConsole)) {
4942 		result = true;
4943 	}
4944 
4945 finish:
4946 	return result;
4947 }
4948 
4949 /*********************************************************************
4950 *********************************************************************/
4951 bool
isPrelinked(void)4952 OSKext::isPrelinked(void)
4953 {
4954 	return flags.prelinked ? true : false;
4955 }
4956 
4957 /*********************************************************************
4958 *********************************************************************/
4959 bool
isLoaded(void)4960 OSKext::isLoaded(void)
4961 {
4962 	return flags.loaded ? true : false;
4963 }
4964 
4965 /*********************************************************************
4966 *********************************************************************/
4967 bool
isStarted(void)4968 OSKext::isStarted(void)
4969 {
4970 	return flags.started ? true : false;
4971 }
4972 
4973 /*********************************************************************
4974 *********************************************************************/
4975 bool
isCPPInitialized(void)4976 OSKext::isCPPInitialized(void)
4977 {
4978 	return flags.CPPInitialized;
4979 }
4980 
4981 /*********************************************************************
4982 *********************************************************************/
4983 void
setCPPInitialized(bool initialized)4984 OSKext::setCPPInitialized(bool initialized)
4985 {
4986 	flags.CPPInitialized = initialized;
4987 }
4988 
4989 /*********************************************************************
4990 *********************************************************************/
4991 uint32_t
getLoadTag(void)4992 OSKext::getLoadTag(void)
4993 {
4994 	return loadTag;
4995 }
4996 
4997 /*********************************************************************
4998 *********************************************************************/
4999 void
getSizeInfo(uint32_t * loadSize,uint32_t * wiredSize)5000 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
5001 {
5002 	if (linkedExecutable) {
5003 		*loadSize = linkedExecutable->getLength();
5004 
5005 		/* If we have a kmod_info struct, calculated the wired size
5006 		 * from that. Otherwise it's the full load size.
5007 		 */
5008 		if (kmod_info) {
5009 			*wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size;
5010 		} else {
5011 			*wiredSize = *loadSize;
5012 		}
5013 	} else {
5014 		*wiredSize = 0;
5015 		*loadSize = 0;
5016 	}
5017 }
5018 
5019 /*********************************************************************
5020 *********************************************************************/
5021 OSSharedPtr<OSData>
copyUUID(void)5022 OSKext::copyUUID(void)
5023 {
5024 	OSSharedPtr<OSData>          result;
5025 	OSData                     * theExecutable = NULL;        // do not release
5026 	const kernel_mach_header_t * header;
5027 
5028 	/* An interface kext doesn't have a linked executable with an LC_UUID,
5029 	 * we create one when it's linked.
5030 	 */
5031 	if (interfaceUUID) {
5032 		result = interfaceUUID;
5033 		goto finish;
5034 	}
5035 
5036 	if (flags.builtin || isInterface()) {
5037 		return sKernelKext->copyUUID();
5038 	}
5039 
5040 	if (isDriverKit() && infoDict) {
5041 		return driverKitUUID;
5042 	}
5043 
5044 	/* For real kexts, try to get the UUID from the linked executable,
5045 	 * or if is hasn't been linked yet, the unrelocated executable.
5046 	 */
5047 	theExecutable = linkedExecutable.get();
5048 	if (!theExecutable) {
5049 		theExecutable = getExecutable();
5050 	}
5051 
5052 	if (!theExecutable) {
5053 		goto finish;
5054 	}
5055 
5056 	header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
5057 	result = copyMachoUUID(header);
5058 
5059 finish:
5060 	return result;
5061 }
5062 
5063 /*********************************************************************
5064 *********************************************************************/
5065 OSSharedPtr<OSData>
copyTextUUID(void)5066 OSKext::copyTextUUID(void)
5067 {
5068 	if (flags.builtin) {
5069 		return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
5070 	}
5071 	return copyUUID();
5072 }
5073 
5074 /*********************************************************************
5075 *********************************************************************/
5076 OSSharedPtr<OSData>
copyMachoUUID(const kernel_mach_header_t * header)5077 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
5078 {
5079 	OSSharedPtr<OSData>                     result;
5080 	const struct load_command  * load_cmd      = NULL;
5081 	const struct uuid_command  * uuid_cmd      = NULL;
5082 	uint32_t                     i;
5083 
5084 	load_cmd = (const struct load_command *)&header[1];
5085 
5086 	if (header->magic != MH_MAGIC_KERNEL) {
5087 		OSKextLog(NULL,
5088 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
5089 		    "%s: bad header %p",
5090 		    __func__,
5091 		    header);
5092 		goto finish;
5093 	}
5094 
5095 	for (i = 0; i < header->ncmds; i++) {
5096 		if (load_cmd->cmd == LC_UUID) {
5097 			uuid_cmd = (struct uuid_command *)load_cmd;
5098 			result = OSData::withValue(uuid_cmd->uuid);
5099 			goto finish;
5100 		}
5101 		load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
5102 	}
5103 
5104 finish:
5105 	return result;
5106 }
5107 
5108 void
setDriverKitUUID(OSData * uuid)5109 OSKext::setDriverKitUUID(OSData *uuid)
5110 {
5111 	if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
5112 		OSSafeReleaseNULL(uuid);
5113 	}
5114 }
5115 
5116 OSData *
getDextUniqueID(void)5117 OSKext::getDextUniqueID(void)
5118 {
5119 	if (isDriverKit() && dextUniqueID != NULL) {
5120 		return dextUniqueID.get();
5121 	}
5122 
5123 	return NULL;
5124 }
5125 
5126 /*
5127  * In case a DextUniqueID exists this function returns
5128  * an allocated char* with the hexadecimal represantition of
5129  * DextUniqueID.
5130  * The returned pinter needs to be freed with kfree_data, the
5131  * size of the allocated buffer is returned in size.
5132  */
5133 static const char *
getDextUniqueIDCString(OSData * dextUniqueID,unsigned int * size)5134 getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size)
5135 {
5136 	if (dextUniqueID != NULL) {
5137 		char *s_buffer = NULL;
5138 		unsigned int d_length = dextUniqueID->getLength();
5139 		/*
5140 		 * We are converting in hex, so for every byte we will have
5141 		 * 2 hex chars and one last \0.
5142 		 */
5143 		unsigned int s_length = d_length * 2 + 1;
5144 		s_buffer = (char *) kalloc_data(s_length, Z_WAITOK_ZERO);
5145 
5146 		char *uid = (char*) dextUniqueID->getBytesNoCopy();
5147 		int cpos = 0;
5148 		for (unsigned int i = 0; i < d_length && cpos < (s_length - 1); i++) {
5149 			int ret = snprintf(s_buffer + cpos, s_length - cpos - 1, "%02X", uid[i]);
5150 			if (ret <= 0) {
5151 				break;
5152 			}
5153 			cpos += ret;
5154 		}
5155 		*size = s_length;
5156 
5157 		return s_buffer;
5158 	}
5159 
5160 	return NULL;
5161 }
5162 
5163 /*
5164  * Atomically swaps the olddext with newdext.
5165  * olddext will be unloaded, so it might be freed
5166  * after this call unless it was previously retained.
5167  *
5168  * If newdext is NULL, this unloads olddext and does not perform an upgrade
5169  */
5170 void
replaceDextInternal(OSKext * olddext,OSKext * newdext)5171 OSKext::replaceDextInternal(OSKext *olddext, OSKext *newdext)
5172 {
5173 	OSReturn result;
5174 	const OSSymbol * dextID = olddext->getIdentifier();
5175 	OSSharedPtr<OSArray> new_personalities;
5176 	OSSharedPtr<OSString> kextIdentifier;
5177 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5178 	assert(lock_held);
5179 
5180 	// The old dext will be unloaded and release dextID, so we need to retain dextID here
5181 	dextID->retain();
5182 
5183 	if (newdext != NULL) {
5184 		__assert_only bool eq = dextID->isEqualTo(newdext->getIdentifier());
5185 		assert(eq);
5186 	}
5187 
5188 	if (newdext != NULL) {
5189 		/*
5190 		 * Swap the catalog personalities.
5191 		 */
5192 		new_personalities = newdext->copyPersonalitiesArray();
5193 		olddext->updatePersonalitiesInCatalog(new_personalities.get());
5194 	}
5195 
5196 	/*
5197 	 * Unload the dext.
5198 	 */
5199 	result = olddext->unload();
5200 	if (result != kOSReturnSuccess) {
5201 		OSKextLog(NULL,
5202 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5203 		    "Cannot unload dext for upgrade %s: %d\n",
5204 		    dextID->getCStringNoCopy(), result);
5205 	}
5206 
5207 	if (newdext != NULL) {
5208 		/*
5209 		 * Swap the dexts on the OSKext dictionary.
5210 		 * This might free the dext.
5211 		 */
5212 		sKextsByID->setObject(dextID, newdext);
5213 	} else {
5214 		/*
5215 		 * Remove the old dext
5216 		 */
5217 		removeKext(olddext, true);
5218 	}
5219 
5220 	/*
5221 	 * Inform userspace.
5222 	 */
5223 	if (newdext != NULL) {
5224 		result = notifyDextUpgrade(OSDynamicCast(OSString, dextID), newdext->getDextUniqueID());
5225 		if (result != kOSReturnSuccess) {
5226 			OSKextLog(NULL,
5227 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5228 			    "Cannot send upgrade notification for %s\n",
5229 			    dextID->getCStringNoCopy());
5230 		}
5231 	} else {
5232 		// notify dext removal
5233 		queueKextNotification(kKextRequestPredicateUnloadNotification, OSDynamicCast(OSString, dextID));
5234 	}
5235 
5236 	OSSafeReleaseNULL(dextID);
5237 }
5238 
5239 /*
5240  * To be called with sKextLock held.
5241  * NOTE: this could unload the olddext.
5242  */
5243 bool
upgradeDext(OSKext * olddext,OSKext * newdext)5244 OSKext::upgradeDext(OSKext *olddext, OSKext *newdext)
5245 {
5246 	const char * dextIDCS = newdext->getIdentifierCString();
5247 	__assert_only bool old_isDext = olddext->isDriverKit();
5248 	__assert_only bool new_isDext = newdext->isDriverKit();
5249 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5250 
5251 	assert(old_isDext && new_isDext);
5252 	assert(lock_held);
5253 
5254 	/*
5255 	 * New dext and old dext have the same ID.
5256 	 * We use this ID as key on the OSKext
5257 	 * dictionarys/arrays.
5258 	 */
5259 	const OSSymbol * dextID = newdext->getIdentifier();
5260 	__assert_only bool eq = dextID->isEqualTo(olddext->getIdentifier());
5261 	assert(eq);
5262 
5263 	/*
5264 	 * Set this OSKect as to update.
5265 	 * Note that this flags will never be removed once set.
5266 	 * When a OSKext is marked, it will be substitued by a new
5267 	 * OSKext, and every subsystem having a reference on this
5268 	 * OSKext need to know they have check if they can use
5269 	 * this OSKext or look for a new one.
5270 	 */
5271 	olddext->flags.dextToReplace = 1;
5272 
5273 	/*
5274 	 * Check if the current OSKext has any
5275 	 * userspace processes launched.
5276 	 * In this case we cannot upgrade and we have to
5277 	 * delay the upgrade until all processes
5278 	 * are done.
5279 	 */
5280 	if (olddext->dextLaunchedCount == 0) {
5281 		/*
5282 		 * Be sure that if there are no launched dexts, no
5283 		 * pending upgrades exist.
5284 		 * This is an error if it happens, as the decrement
5285 		 * should have removed the dext from sDriverKitToUpgradeByID
5286 		 * in case it reached 0.
5287 		 */
5288 		OSObject *pending_upgdare = sDriverKitToUpgradeByID->getObject(dextID);
5289 		if (pending_upgdare != NULL) {
5290 			OSKextLog(NULL,
5291 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5292 			    "Pending upgrade found for %s but dextLaunchedCount is 0!\n",
5293 			    dextIDCS);
5294 			goto out;
5295 		}
5296 
5297 		replaceDextInternal(olddext, newdext);
5298 		return true;
5299 	}
5300 
5301 out:
5302 
5303 	/*
5304 	 * Delay the upgrade.
5305 	 * Make the new dext available in sDriverKitToUpgradeByID.
5306 	 * In case there was already a pending upgrade, this will
5307 	 * overwrite it.
5308 	 */
5309 	sDriverKitToUpgradeByID->setObject(dextID, newdext);
5310 	return false;
5311 }
5312 
5313 /*
5314  * To be called with sKextLock held.
5315  * NOTE: this could unload the dext.
5316  */
5317 bool
removeDext(OSKext * dext)5318 OSKext::removeDext(OSKext *dext)
5319 {
5320 	__assert_only bool dext_isDext = dext->isDriverKit();
5321 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5322 	IOReturn result;
5323 
5324 	assert(dext_isDext);
5325 	assert(lock_held);
5326 
5327 	/*
5328 	 * Set this OSKext to be unloaded when all running instances exit.
5329 	 */
5330 	dext->flags.dextToReplace = 1;
5331 
5332 	result = gIOCatalogue->terminateDriversForModule(
5333 		dext->getIdentifierCString(), /* unload */ false, /* asynchronous */ true);
5334 	if (result != kOSReturnSuccess) {
5335 		OSKextLog(dext,
5336 		    kOSKextLogErrorLevel |
5337 		    kOSKextLogKextBookkeepingFlag,
5338 		    "%s services failed to terminate - 0x%x.",
5339 		    dext->getIdentifierCString(), result);
5340 	}
5341 
5342 	dext->removePersonalitiesFromCatalog();
5343 	sDriverKitToUpgradeByID->removeObject(dext->getIdentifier());
5344 
5345 	/*
5346 	 * Check if the current OSKext has any
5347 	 * userspace processes launched.
5348 	 * In this case we cannot unload and we have to
5349 	 * delay the unload until all processes
5350 	 * are done.
5351 	 */
5352 	if (dext->dextLaunchedCount == 0) {
5353 		replaceDextInternal(dext, NULL);
5354 		return true;
5355 	}
5356 
5357 	return false;
5358 }
5359 
5360 bool
incrementDextLaunchCount(OSKext * dext,OSData * dextUniqueIDToMatch)5361 OSKext::incrementDextLaunchCount(OSKext *dext, OSData *dextUniqueIDToMatch)
5362 {
5363 	bool ret = false;
5364 	__assert_only bool isDext = dext->isDriverKit();
5365 	assert(isDext);
5366 
5367 	const char * dextIDCS = dext->getIdentifierCString();
5368 	OSData *myDextUniqueID = dext->getDextUniqueID();
5369 
5370 	if (!myDextUniqueID || !dextUniqueIDToMatch) {
5371 		OSKextLog(dext,
5372 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5373 		    "Cannot find dext UniqueID for %s, cannot increment dext launches\n",
5374 		    dextIDCS);
5375 		return ret;
5376 	}
5377 
5378 	unsigned int dextUniqueIDCStringSize = 0, dextUniqueIDToMatchCStringSize = 0;
5379 	const char *dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
5380 	const char *dextUniqueIDToMatchCString = getDextUniqueIDCString(dextUniqueIDToMatch, &dextUniqueIDToMatchCStringSize);
5381 	assert(dextUniqueIDCString != NULL);
5382 	assert(dextUniqueIDToMatchCString != NULL);
5383 
5384 	IORecursiveLockLock(sKextLock);
5385 
5386 	/*
5387 	 * Check that the dext we are referencing is the same
5388 	 * looked for the match.
5389 	 */
5390 	if (myDextUniqueID->isEqualTo(dextUniqueIDToMatch)) {
5391 		if (dext->flags.dextToReplace == 0 || dext->dextLaunchedCount > 0) {
5392 			if (dext->dextLaunchedCount == kOSKextMaxDextLaunchedCount) {
5393 				OSKextLog(dext,
5394 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5395 				    "Too many dexts launched for %s UniqueID %s\n",
5396 				    dextIDCS, dextUniqueIDCString);
5397 			} else {
5398 				dext->dextLaunchedCount++;
5399 				ret = true;
5400 
5401 				OSKextLog(dext,
5402 				    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5403 				    "New dext launched for  %s UniqueID %s",
5404 				    dextIDCS, dextUniqueIDCString);
5405 			}
5406 		} else {
5407 			OSKextLog(dext,
5408 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5409 			    "Dext %s UniqueID %s requires update, cannot launch a new dext\n",
5410 			    dextIDCS, dextUniqueIDCString);
5411 		}
5412 	} else {
5413 		OSKextLog(dext,
5414 		    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5415 		    "Dext %s: UniqueID %s does not match UniqueID looked for %s, cannot launch a new dext\n",
5416 		    dextIDCS, dextUniqueIDCString, dextUniqueIDToMatchCString);
5417 	}
5418 
5419 	IORecursiveLockUnlock(sKextLock);
5420 
5421 	if (dextUniqueIDCString != NULL) {
5422 		kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
5423 	}
5424 	if (dextUniqueIDToMatchCString != NULL) {
5425 		kfree_data(dextUniqueIDToMatchCString, dextUniqueIDToMatchCStringSize);
5426 	}
5427 	return ret;
5428 }
5429 
5430 bool
decrementDextLaunchCount(OSString * bundleID)5431 OSKext::decrementDextLaunchCount(OSString *bundleID)
5432 {
5433 	bool ret = false;
5434 	const char * dextIDCS;
5435 	OSData *myDextUniqueID;
5436 	unsigned int dextUniqueIDCStringSize = 0;
5437 	const char * dextUniqueIDCString = NULL;
5438 	OSKext* dext = NULL;
5439 
5440 	if (!bundleID) {
5441 		return ret;
5442 	}
5443 	dextIDCS = bundleID->getCStringNoCopy();
5444 
5445 	IORecursiveLockLock(sKextLock);
5446 
5447 	/*
5448 	 * Look for the dext with the bundle it. This
5449 	 * call is triggered only if a previous increment was
5450 	 * performed. It means that the dext could have not
5451 	 * been upgraded as its dextLaunchedCount was at least 1.
5452 	 * Because of this it still needs to be available
5453 	 * in sKextsByID.
5454 	 */
5455 	dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIDCS));
5456 	if (!dext || !dext->isDriverKit()) {
5457 		OSKextLog(NULL,
5458 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5459 		    "Cannot find dext for %s, cannot decrement dext launches\n",
5460 		    dextIDCS);
5461 
5462 		goto out_locked;
5463 	}
5464 
5465 	myDextUniqueID = dext->getDextUniqueID();
5466 	if (!myDextUniqueID) {
5467 		OSKextLog(dext,
5468 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5469 		    "Cannot find dext UniqueID for %s, cannot decrement dext launches\n",
5470 		    dextIDCS);
5471 
5472 		goto out_locked;
5473 	}
5474 	dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
5475 	assert(dextUniqueIDCString != NULL);
5476 
5477 	if (dext->dextLaunchedCount == 0) {
5478 		OSKextLog(dext,
5479 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5480 		    "Over decrementing dext launch for %s UniqueID %s\n",
5481 		    dextIDCS, dextUniqueIDCString);
5482 
5483 		goto out_locked;
5484 	}
5485 
5486 	dext->dextLaunchedCount--;
5487 
5488 	OSKextLog(dext,
5489 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5490 	    "Dext terminated for %s UniqueID %s",
5491 	    dextIDCS, dextUniqueIDCString);
5492 
5493 	if (dext->dextLaunchedCount == 0 && dext->flags.dextToReplace == 1) {
5494 		/*
5495 		 * Find the upgraded dext.
5496 		 */
5497 		OSKext *newdext = OSDynamicCast(OSKext, sDriverKitToUpgradeByID->getObject(dextIDCS));
5498 		if (newdext) {
5499 			OSKextLog(dext,
5500 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5501 			    "Dext upgrade for %s UniqueID %s",
5502 			    dextIDCS, dextUniqueIDCString);
5503 			replaceDextInternal(dext, newdext);
5504 			/* NOTE dext could have been freed past this point */
5505 
5506 			sDriverKitToUpgradeByID->removeObject(dextIDCS);
5507 		} else {
5508 			OSKextLog(dext,
5509 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5510 			    "Dext unload for %s UniqueID %s",
5511 			    dextIDCS, dextUniqueIDCString);
5512 			replaceDextInternal(dext, NULL);
5513 		}
5514 
5515 		ret = true;
5516 	}
5517 out_locked:
5518 	IORecursiveLockUnlock(sKextLock);
5519 
5520 	if (dextUniqueIDCString != NULL) {
5521 		kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
5522 	}
5523 
5524 	return ret;
5525 }
5526 
5527 /*********************************************************************
5528 *********************************************************************/
5529 #if defined (__arm__)
5530 #include <arm/arch.h>
5531 #endif
5532 
5533 #if   defined (__x86_64__)
5534 #define ARCHNAME "x86_64"
5535 #elif defined (__arm64__)
5536 #define ARCHNAME "arm64"
5537 #elif defined (__arm__)
5538 
5539 #if defined (__ARM_ARCH_7S__)
5540 #define ARCHNAME "armv7s"
5541 #elif defined (__ARM_ARCH_7F__)
5542 #define ARCHNAME "armv7f"
5543 #elif defined (__ARM_ARCH_7K__)
5544 #define ARCHNAME "armv7k"
5545 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
5546 #define ARCHNAME "armv7"
5547 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
5548 #define ARCHNAME "armv6"
5549 #endif
5550 
5551 #elif defined (__arm64__)
5552 #define ARCHNAME "arm64"
5553 #else
5554 #error architecture not supported
5555 #endif
5556 
5557 #define ARCH_SEPARATOR_CHAR  '_'
5558 
5559 static char *
makeHostArchKey(const char * key,size_t * keySizeOut)5560 makeHostArchKey(const char * key, size_t * keySizeOut)
5561 {
5562 	char     * result = NULL;
5563 	size_t     keyLength = strlen(key);
5564 	size_t     keySize;
5565 
5566 	/* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
5567 	 */
5568 	keySize = 1 + 1 + keyLength + strlen(ARCHNAME);
5569 	result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
5570 
5571 	if (!result) {
5572 		goto finish;
5573 	}
5574 	strlcpy(result, key, keySize);
5575 	result[keyLength++] = ARCH_SEPARATOR_CHAR;
5576 	result[keyLength] = '\0';
5577 	strlcat(result, ARCHNAME, keySize);
5578 	*keySizeOut = keySize;
5579 
5580 finish:
5581 	return result;
5582 }
5583 
5584 /*********************************************************************
5585 *********************************************************************/
5586 OSObject *
getPropertyForHostArch(const char * key)5587 OSKext::getPropertyForHostArch(const char * key)
5588 {
5589 	OSObject * result           = NULL;// do not release
5590 	size_t     hostArchKeySize  = 0;
5591 	char     * hostArchKey      = NULL;// must kfree
5592 
5593 	if (!key || !infoDict) {
5594 		goto finish;
5595 	}
5596 
5597 	/* Some properties are not allowed to be arch-variant:
5598 	 * - Any CFBundle... property.
5599 	 * - OSBundleIsInterface.
5600 	 * - OSKernelResource.
5601 	 */
5602 	if (STRING_HAS_PREFIX(key, "OS") ||
5603 	    STRING_HAS_PREFIX(key, "IO")) {
5604 		hostArchKey = makeHostArchKey(key, &hostArchKeySize);
5605 		if (!hostArchKey) {
5606 			OSKextLog(/* kext (this isn't about a kext) */ NULL,
5607 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
5608 			    "Allocation failure.");
5609 			goto finish;
5610 		}
5611 		result = infoDict->getObject(hostArchKey);
5612 	}
5613 
5614 	if (!result) {
5615 		result = infoDict->getObject(key);
5616 	}
5617 
5618 finish:
5619 	if (hostArchKey) {
5620 		kfree_data(hostArchKey, hostArchKeySize);
5621 	}
5622 	return result;
5623 }
5624 
5625 #if PRAGMA_MARK
5626 #pragma mark Load/Start/Stop/Unload
5627 #endif
5628 
5629 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
5630 
5631 /*********************************************************************
5632 * sExcludeListByID is a dictionary with keys / values of:
5633 *  key = bundleID string of kext we will not allow to load
5634 *  value = version string(s) of the kext that is to be denied loading.
5635 *      The version strings can be comma delimited.  For example if kext
5636 *      com.foocompany.fookext has two versions that we want to deny
5637 *      loading then the version strings might look like:
5638 *      1.0.0, 1.0.1
5639 *      If the current fookext has a version of 1.0.0 OR 1.0.1 we will
5640 *      not load the kext.
5641 *
5642 *      Value may also be in the form of "LE 2.0.0" (version numbers
5643 *      less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
5644 *      number less than 2.0.0 will not load)
5645 *
5646 *      NOTE - we cannot use the characters "<=" or "<" because we have code
5647 *      that serializes plists and treats '<' as a special character.
5648 *********************************************************************/
5649 bool
isInExcludeList(void)5650 OSKext::isInExcludeList(void)
5651 {
5652 	OSString *      versionString           = NULL;        // do not release
5653 	char *          versionCString          = NULL;        // do not free
5654 	size_t          i;
5655 	boolean_t       wantLessThan = false;
5656 	boolean_t       wantLessThanEqualTo = false;
5657 	boolean_t       isInExcludeList = true;
5658 	char            myBuffer[32];
5659 
5660 	IORecursiveLockLock(sKextLock);
5661 
5662 	if (!sExcludeListByID) {
5663 		isInExcludeList = false;
5664 	} else {
5665 		/* look up by bundleID in our exclude list and if found get version
5666 		 * string (or strings) that we will not allow to load
5667 		 */
5668 		versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get()));
5669 		if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
5670 			isInExcludeList = false;
5671 		}
5672 	}
5673 
5674 	IORecursiveLockUnlock(sKextLock);
5675 
5676 	if (!isInExcludeList) {
5677 		return false;
5678 	}
5679 
5680 	/* parse version strings */
5681 	versionCString = (char *) versionString->getCStringNoCopy();
5682 
5683 	/* look for "LT" or "LE" form of version string, must be in first two
5684 	 * positions.
5685 	 */
5686 	if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
5687 		wantLessThan = true;
5688 		versionCString += 2;
5689 	} else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
5690 		wantLessThanEqualTo = true;
5691 		versionCString += 2;
5692 	}
5693 
5694 	for (i = 0; *versionCString != 0x00; versionCString++) {
5695 		/* skip whitespace */
5696 		if (isWhiteSpace(*versionCString)) {
5697 			continue;
5698 		}
5699 
5700 		/* peek ahead for version string separator or null terminator */
5701 		if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
5702 			/* OK, we have a version string */
5703 			myBuffer[i++] = *versionCString;
5704 			myBuffer[i] = 0x00;
5705 
5706 			OSKextVersion excludeVers;
5707 			excludeVers = OSKextParseVersionString(myBuffer);
5708 
5709 			if (wantLessThanEqualTo) {
5710 				if (version <= excludeVers) {
5711 					return true;
5712 				}
5713 			} else if (wantLessThan) {
5714 				if (version < excludeVers) {
5715 					return true;
5716 				}
5717 			} else if (version == excludeVers) {
5718 				return true;
5719 			}
5720 
5721 			/* reset for the next (if any) version string */
5722 			i = 0;
5723 			wantLessThan = false;
5724 			wantLessThanEqualTo = false;
5725 		} else {
5726 			/* save valid version character */
5727 			myBuffer[i++] = *versionCString;
5728 
5729 			/* make sure bogus version string doesn't overrun local buffer */
5730 			if (i >= sizeof(myBuffer)) {
5731 				break;
5732 			}
5733 		}
5734 	}
5735 
5736 	return false;
5737 }
5738 
5739 /*********************************************************************
5740 * sNonLoadableKextsByID is a dictionary with keys / values of:
5741 *  key = bundleID string of kext we will not allow to load
5742 *  value = boolean (true == loadable, false == not loadable)
5743 *
5744 *  Only kexts which are in the AuxKC will be marked as "not loadble,"
5745 *  i.e., the value for the kext's bundleID will be false. All kexts in
5746 *  the primary and system KCs will always be marked as "loadable."
5747 *
5748 *  This list ultimately comes from kexts which have been uninstalled
5749 *  in user space by deleting the kext from disk, but which have not
5750 *  yet been removed from the AuxKC. Because the user could choose to
5751 *  re-install the exact same version of the kext, we need to keep
5752 *  a dictionary of boolean values so that user space only needs to
5753 *  keep a simple list of "uninstalled" or "missing" bundles. When
5754 *  a bundle is re-installed, the iokit daemon can use the
5755 *  AucKCBundleAvailable  predicate to set the individual kext's
5756 *  availability to true.
5757 *********************************************************************/
5758 bool
isLoadable(void)5759 OSKext::isLoadable(void)
5760 {
5761 	bool isLoadable = true;
5762 
5763 	if (kc_type != KCKindAuxiliary) {
5764 		/* this filtering only applies to kexts in the auxkc */
5765 		return true;
5766 	}
5767 
5768 	IORecursiveLockLock(sKextLock);
5769 
5770 	if (sNonLoadableKextsByID) {
5771 		/* look up by bundleID in our exclude list and if found get version
5772 		 * string (or strings) that we will not allow to load
5773 		 */
5774 		OSBoolean *loadableVal;
5775 		loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get()));
5776 		if (loadableVal && !loadableVal->getValue()) {
5777 			isLoadable = false;
5778 		}
5779 	}
5780 	IORecursiveLockUnlock(sKextLock);
5781 
5782 	return isLoadable;
5783 }
5784 
5785 /*********************************************************************
5786 *********************************************************************/
5787 /* static */
5788 OSReturn
loadKextWithIdentifier(const char * kextIdentifierCString,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5789 OSKext::loadKextWithIdentifier(
5790 	const char       * kextIdentifierCString,
5791 	Boolean            allowDeferFlag,
5792 	Boolean            delayAutounloadFlag,
5793 	OSKextExcludeLevel startOpt,
5794 	OSKextExcludeLevel startMatchingOpt,
5795 	OSArray          * personalityNames)
5796 {
5797 	OSReturn   result         = kOSReturnError;
5798 	OSSharedPtr<OSString> kextIdentifier;
5799 
5800 	kextIdentifier = OSString::withCString(kextIdentifierCString);
5801 	if (!kextIdentifier) {
5802 		result = kOSKextReturnNoMemory;
5803 		goto finish;
5804 	}
5805 	result = OSKext::loadKextWithIdentifier(kextIdentifier.get(),
5806 	    NULL /* kextRef */,
5807 	    allowDeferFlag, delayAutounloadFlag,
5808 	    startOpt, startMatchingOpt, personalityNames);
5809 
5810 finish:
5811 	return result;
5812 }
5813 
5814 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSSharedPtr<OSObject> & kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5815 OSKext::loadKextWithIdentifier(
5816 	OSString          * kextIdentifier,
5817 	OSSharedPtr<OSObject>         &kextRef,
5818 	Boolean             allowDeferFlag,
5819 	Boolean             delayAutounloadFlag,
5820 	OSKextExcludeLevel  startOpt,
5821 	OSKextExcludeLevel  startMatchingOpt,
5822 	OSArray           * personalityNames)
5823 {
5824 	OSObject * kextRefRaw = NULL;
5825 	OSReturn result;
5826 
5827 	result = loadKextWithIdentifier(kextIdentifier,
5828 	    &kextRefRaw,
5829 	    allowDeferFlag,
5830 	    delayAutounloadFlag,
5831 	    startOpt,
5832 	    startMatchingOpt,
5833 	    personalityNames);
5834 	if ((kOSReturnSuccess == result) && kextRefRaw) {
5835 		kextRef.reset(kextRefRaw, OSNoRetain);
5836 	}
5837 	return result;
5838 }
5839 
5840 /*********************************************************************
5841 *********************************************************************/
5842 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSObject ** kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)5843 OSKext::loadKextWithIdentifier(
5844 	OSString          * kextIdentifier,
5845 	OSObject         ** kextRef,
5846 	Boolean             allowDeferFlag,
5847 	Boolean             delayAutounloadFlag,
5848 	OSKextExcludeLevel  startOpt,
5849 	OSKextExcludeLevel  startMatchingOpt,
5850 	OSArray           * personalityNames)
5851 {
5852 	OSReturn          result               = kOSReturnError;
5853 	OSReturn          pingResult           = kOSReturnError;
5854 	OSKext          * theKext              = NULL;        // do not release
5855 	OSSharedPtr<OSDictionary>   loadRequest;
5856 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
5857 
5858 	if (kextRef) {
5859 		*kextRef = NULL;
5860 	}
5861 
5862 	IORecursiveLockLock(sKextLock);
5863 
5864 	if (!kextIdentifier) {
5865 		result = kOSKextReturnInvalidArgument;
5866 		goto finish;
5867 	}
5868 
5869 	OSKext::recordIdentifierRequest(kextIdentifier);
5870 
5871 	theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
5872 	if (!theKext) {
5873 		if (!allowDeferFlag) {
5874 			OSKextLog(/* kext */ NULL,
5875 			    kOSKextLogErrorLevel |
5876 			    kOSKextLogLoadFlag,
5877 			    "Can't load kext %s - not found.",
5878 			    kextIdentifier->getCStringNoCopy());
5879 			goto finish;
5880 		}
5881 
5882 		if (!sKernelRequestsEnabled) {
5883 			OSKextLog(theKext,
5884 			    kOSKextLogErrorLevel |
5885 			    kOSKextLogLoadFlag,
5886 			    "Can't load kext %s - requests to user space are disabled.",
5887 			    kextIdentifier->getCStringNoCopy());
5888 			result = kOSKextReturnDisabled;
5889 			goto finish;
5890 		}
5891 
5892 		/* Create a new request unless one is already sitting
5893 		 * in sKernelRequests for this bundle identifier
5894 		 */
5895 		kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
5896 		if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
5897 			result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
5898 			    loadRequest);
5899 			if (result != kOSReturnSuccess) {
5900 				goto finish;
5901 			}
5902 			if (!_OSKextSetRequestArgument(loadRequest.get(),
5903 			    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
5904 				result = kOSKextReturnNoMemory;
5905 				goto finish;
5906 			}
5907 			if (!sKernelRequests->setObject(loadRequest.get())) {
5908 				result = kOSKextReturnNoMemory;
5909 				goto finish;
5910 			}
5911 
5912 			if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
5913 				result = kOSKextReturnNoMemory;
5914 				goto finish;
5915 			}
5916 
5917 			OSKextLog(theKext,
5918 			    kOSKextLogDebugLevel |
5919 			    kOSKextLogLoadFlag,
5920 			    "Kext %s not found; queued load request to user space.",
5921 			    kextIdentifier->getCStringNoCopy());
5922 		}
5923 
5924 		pingResult = OSKext::pingIOKitDaemon();
5925 		if (pingResult == kOSKextReturnDisabled) {
5926 			OSKextLog(/* kext */ NULL,
5927 			    ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
5928 			    kOSKextLogLoadFlag,
5929 			    "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.",
5930 			    kextIdentifier->getCStringNoCopy());
5931 		}
5932 
5933 		result = kOSKextReturnDeferred;
5934 		goto finish;
5935 	}
5936 
5937 	result = theKext->load(startOpt, startMatchingOpt, personalityNames);
5938 
5939 	if (result != kOSReturnSuccess) {
5940 		OSKextLog(theKext,
5941 		    kOSKextLogErrorLevel |
5942 		    kOSKextLogLoadFlag,
5943 		    "Failed to load kext %s (error 0x%x).",
5944 		    kextIdentifier->getCStringNoCopy(), (int)result);
5945 
5946 		if (theKext->kc_type == KCKindUnknown) {
5947 			OSKext::removeKext(theKext,
5948 			    /* terminateService/removePersonalities */ true);
5949 		}
5950 		goto finish;
5951 	}
5952 
5953 	if (delayAutounloadFlag) {
5954 		OSKextLog(theKext,
5955 		    kOSKextLogProgressLevel |
5956 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
5957 		    "Setting delayed autounload for %s.",
5958 		    kextIdentifier->getCStringNoCopy());
5959 		theKext->flags.delayAutounload = 1;
5960 	}
5961 
5962 finish:
5963 	if ((kOSReturnSuccess == result) && kextRef) {
5964 		*kextRef = theKext;
5965 		theKext->matchingRefCount++;
5966 		theKext->retain();
5967 	}
5968 
5969 	IORecursiveLockUnlock(sKextLock);
5970 
5971 	return result;
5972 }
5973 
5974 /*********************************************************************
5975 *********************************************************************/
5976 /* static */
5977 OSReturn
loadKextFromKC(OSKext * theKext,OSDictionary * requestDict)5978 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict)
5979 {
5980 	OSReturn  result = kOSReturnError;
5981 
5982 	OSBoolean *delayAutounloadBool     = NULL; // do not release
5983 	OSNumber  *startKextExcludeNum     = NULL; // do not release
5984 	OSNumber  *startMatchingExcludeNum = NULL; // do not release
5985 	OSArray   *personalityNames        = NULL; // do not release
5986 
5987 	/*
5988 	 * Default values for these options:
5989 	 *      regular autounload behavior
5990 	 *      start the kext
5991 	 *      send all personalities to the catalog
5992 	 */
5993 	Boolean            delayAutounload           = false;
5994 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
5995 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone;
5996 
5997 	IORecursiveLockLock(sKextLock);
5998 
5999 	OSKextLog(/* kext */ NULL,
6000 	    kOSKextLogDebugLevel |
6001 	    kOSKextLogIPCFlag,
6002 	    "Received kext KC load request from user space.");
6003 
6004 	/* Regardless of processing, the fact that we have gotten here means some
6005 	 * user-space program is up and talking to us, so we'll switch our kext
6006 	 * registration to reflect that.
6007 	 */
6008 	if (!sUserLoadsActive) {
6009 		OSKextLog(/* kext */ NULL,
6010 		    kOSKextLogProgressLevel |
6011 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6012 		    "Switching to late startup (user-space) kext loading policy.");
6013 		sUserLoadsActive = true;
6014 	}
6015 
6016 	delayAutounloadBool = OSDynamicCast(OSBoolean,
6017 	    _OSKextGetRequestArgument(requestDict,
6018 	    kKextRequestArgumentDelayAutounloadKey));
6019 	startKextExcludeNum = OSDynamicCast(OSNumber,
6020 	    _OSKextGetRequestArgument(requestDict,
6021 	    kKextRequestArgumentStartExcludeKey));
6022 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
6023 	    _OSKextGetRequestArgument(requestDict,
6024 	    kKextRequestArgumentStartMatchingExcludeKey));
6025 	personalityNames = OSDynamicCast(OSArray,
6026 	    _OSKextGetRequestArgument(requestDict,
6027 	    kKextRequestArgumentPersonalityNamesKey));
6028 
6029 	if (delayAutounloadBool) {
6030 		delayAutounload = delayAutounloadBool->getValue();
6031 	}
6032 	if (startKextExcludeNum) {
6033 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
6034 	}
6035 	if (startMatchingExcludeNum) {
6036 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
6037 	}
6038 
6039 	OSKextLog(/* kext */ NULL,
6040 	    kOSKextLogProgressLevel |
6041 	    kOSKextLogIPCFlag,
6042 	    "Received request from user space to load KC kext %s.",
6043 	    theKext->getIdentifierCString());
6044 
6045 	/* this could be in the Auxiliary KC, so record the load request */
6046 	OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier()));
6047 
6048 	/*
6049 	 * Load the kext
6050 	 */
6051 	result = theKext->load(startKextExcludeLevel,
6052 	    startMatchingExcludeLevel, personalityNames);
6053 
6054 	if (result != kOSReturnSuccess) {
6055 		OSKextLog(theKext,
6056 		    kOSKextLogErrorLevel |
6057 		    kOSKextLogLoadFlag,
6058 		    "Failed to load kext %s (error 0x%x).",
6059 		    theKext->getIdentifierCString(), (int)result);
6060 
6061 		OSKext::removeKext(theKext,
6062 		    /* terminateService/removePersonalities */ true);
6063 		goto finish;
6064 	} else {
6065 		OSKextLog(theKext,
6066 		    kOSKextLogProgressLevel |
6067 		    kOSKextLogLoadFlag,
6068 		    "Kext %s Loaded successfully from %s KC",
6069 		    theKext->getIdentifierCString(), theKext->getKCTypeString());
6070 	}
6071 
6072 	if (delayAutounload) {
6073 		OSKextLog(theKext,
6074 		    kOSKextLogProgressLevel |
6075 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6076 		    "Setting delayed autounload for %s.",
6077 		    theKext->getIdentifierCString());
6078 		theKext->flags.delayAutounload = 1;
6079 	}
6080 
6081 finish:
6082 	IORecursiveLockUnlock(sKextLock);
6083 
6084 	return result;
6085 }
6086 
6087 /*********************************************************************
6088 *********************************************************************/
6089 /* static */
6090 OSReturn
loadCodelessKext(OSString * kextIdentifier,OSDictionary * requestDict)6091 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict)
6092 {
6093 	OSReturn  result = kOSReturnError;
6094 	OSDictionary *anInfoDict = NULL; // do not release
6095 
6096 	anInfoDict = OSDynamicCast(OSDictionary,
6097 	    _OSKextGetRequestArgument(requestDict,
6098 	    kKextRequestArgumentCodelessInfoKey));
6099 	if (anInfoDict == NULL) {
6100 		OSKextLog(/* kext */ NULL,
6101 		    kOSKextLogErrorLevel |
6102 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6103 		    "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.",
6104 		    kextIdentifier->getCStringNoCopy());
6105 		return kOSKextReturnInvalidArgument;
6106 	}
6107 
6108 	IORecursiveLockLock(sKextLock);
6109 
6110 	OSKextLog(/* kext */ NULL,
6111 	    kOSKextLogProgressLevel |
6112 	    kOSKextLogIPCFlag,
6113 	    "Received request from user space to load codeless kext %s.",
6114 	    kextIdentifier->getCStringNoCopy());
6115 
6116 	{
6117 		// instantiate a new kext, and don't hold a reference
6118 		// (the kext subsystem will hold one implicitly)
6119 		OSKextInitResult ret;
6120 		OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict, &ret);
6121 		if (!newKext) {
6122 			/*
6123 			 * We might have failed to create a new OSKext
6124 			 * because the old one should still be used.
6125 			 * Check if that is the case.
6126 			 */
6127 			if (ret != kOSKextInitFailure) {
6128 				result = kOSReturnSuccess;
6129 				goto finish;
6130 			}
6131 			OSKextLog(/* kext */ NULL,
6132 			    kOSKextLogErrorLevel |
6133 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6134 			    "Could not instantiate codeless kext.");
6135 			result = kOSKextReturnNotLoadable;
6136 			goto finish;
6137 		}
6138 		if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) {
6139 			OSKextLog(/* kext */ NULL,
6140 			    kOSKextLogErrorLevel |
6141 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6142 			    "Codeless kext identifiers don't match '%s' != '%s'",
6143 			    kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString());
6144 
6145 			OSKext::removeKext(newKext.get(), false);
6146 			result = kOSKextReturnInvalidArgument;
6147 			goto finish;
6148 		}
6149 
6150 		/* Record the request for the codeless kext */
6151 		OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier()));
6152 
6153 		result = kOSReturnSuccess;
6154 		/* Send the kext's personalities to the IOCatalog. This is an explicit load. */
6155 		result = newKext->sendPersonalitiesToCatalog(true, NULL);
6156 	}
6157 
6158 finish:
6159 	IORecursiveLockUnlock(sKextLock);
6160 
6161 	return result;
6162 }
6163 
6164 /*********************************************************************
6165 *********************************************************************/
6166 /* static */
6167 void
dropMatchingReferences(OSSet * kexts)6168 OSKext::dropMatchingReferences(
6169 	OSSet * kexts)
6170 {
6171 	IORecursiveLockLock(sKextLock);
6172 	kexts->iterateObjects(^bool (OSObject * obj) {
6173 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
6174 		if (!thisKext) {
6175 		        return false;
6176 		}
6177 		thisKext->matchingRefCount--;
6178 		return false;
6179 	});
6180 	IORecursiveLockUnlock(sKextLock);
6181 }
6182 
6183 /*********************************************************************
6184 *********************************************************************/
6185 /* static */
6186 void
recordIdentifierRequest(OSString * kextIdentifier)6187 OSKext::recordIdentifierRequest(
6188 	OSString * kextIdentifier)
6189 {
6190 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
6191 	bool             fail                 = false;
6192 
6193 	if (!sAllKextLoadIdentifiers || !kextIdentifier) {
6194 		goto finish;
6195 	}
6196 
6197 	kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
6198 	if (!kextIdentifierSymbol) {
6199 		// xxx - this is really a basic alloc failure
6200 		fail = true;
6201 		goto finish;
6202 	}
6203 
6204 	IORecursiveLockLock(sKextLock);
6205 	if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
6206 		if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
6207 			fail = true;
6208 		} else {
6209 			// xxx - need to find a way to associate this whole func w/the kext
6210 			OSKextLog(/* kext */ NULL,
6211 			    // xxx - check level
6212 			    kOSKextLogStepLevel |
6213 			    kOSKextLogArchiveFlag,
6214 			    "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
6215 			    kextIdentifier->getCStringNoCopy());
6216 		}
6217 	}
6218 	IORecursiveLockUnlock(sKextLock);
6219 
6220 finish:
6221 
6222 	if (fail) {
6223 		OSKextLog(/* kext */ NULL,
6224 		    kOSKextLogErrorLevel |
6225 		    kOSKextLogArchiveFlag,
6226 		    "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
6227 		    kextIdentifier->getCStringNoCopy());
6228 	}
6229 	return;
6230 }
6231 
6232 /*********************************************************************
6233 *********************************************************************/
6234 OSReturn
load(OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)6235 OSKext::load(
6236 	OSKextExcludeLevel   startOpt,
6237 	OSKextExcludeLevel   startMatchingOpt,
6238 	OSArray            * personalityNames)
6239 {
6240 	OSReturn             result                       = kOSReturnError;
6241 	OSKextExcludeLevel   dependenciesStartOpt         = startOpt;
6242 	OSKextExcludeLevel   dependenciesStartMatchingOpt = startMatchingOpt;
6243 	unsigned int         i, count;
6244 	Boolean              alreadyLoaded                = false;
6245 	OSKext             * lastLoadedKext               = NULL;        // do not release
6246 
6247 	if (isInExcludeList()) {
6248 		OSKextLog(this,
6249 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
6250 		    kOSKextLogLoadFlag,
6251 		    "Kext %s is in exclude list, not loadable",
6252 		    getIdentifierCString());
6253 
6254 		result = kOSKextReturnNotLoadable;
6255 		goto finish;
6256 	}
6257 	if (!isLoadable()) {
6258 		OSKextLog(this,
6259 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
6260 		    kOSKextLogLoadFlag,
6261 		    "Kext %s is not loadable",
6262 		    getIdentifierCString());
6263 
6264 		result = kOSKextReturnNotLoadable;
6265 		goto finish;
6266 	}
6267 
6268 	if (isLoaded()) {
6269 		alreadyLoaded = true;
6270 		result = kOSReturnSuccess;
6271 
6272 		OSKextLog(this,
6273 		    kOSKextLogDebugLevel |
6274 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6275 		    "Kext %s is already loaded.",
6276 		    getIdentifierCString());
6277 		goto loaded;
6278 	}
6279 
6280 #if CONFIG_MACF
6281 	/*
6282 	 * On kxld and on embedded, only call into the MAC hook when on a
6283 	 * user thread, for access control over userspace kextloads.
6284 	 *
6285 	 * On non-kxld systems, additionally check the MAC hook for kexts in
6286 	 * the Pageable and Aux KCs, regardless of whether we are on a user
6287 	 * thread or not. This means on Apple silicon devices that the MAC
6288 	 * hook will only be useful to block 3rd party kexts loaded via
6289 	 * matching, and any kexts loaded from userspace kextloads.
6290 	 *
6291 	 * Note that this should _not_ be called on kexts loaded from the
6292 	 * kernel bootstrap thread as the kernel proc's cred struct is not
6293 	 * yet initialized! This won't happen on macOS because all the kexts
6294 	 * in the BootKC are self-contained and their kc_type = KCKindPrimary.
6295 	 */
6296 	if (current_task() != kernel_task
6297 #if XNU_TARGET_OS_OSX && !CONFIG_KXLD
6298 	    || (kc_type != KCKindPrimary && kc_type != KCKindUnknown)
6299 #endif
6300 	    ) {
6301 		int                 macCheckResult      = 0;
6302 		kauth_cred_t        cred                = NULL;
6303 
6304 		cred = kauth_cred_get_with_ref();
6305 		macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
6306 		kauth_cred_unref(&cred);
6307 
6308 		if (macCheckResult != 0) {
6309 			result = kOSReturnError;
6310 			OSKextLog(this,
6311 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6312 			    "Failed to load kext %s (MAC policy error 0x%x).",
6313 			    getIdentifierCString(), macCheckResult);
6314 			goto finish;
6315 		}
6316 	}
6317 #endif /* CONFIG_MACF */
6318 
6319 	if (!sLoadEnabled) {
6320 		OSKextLog(this,
6321 		    kOSKextLogErrorLevel |
6322 		    kOSKextLogLoadFlag,
6323 		    "Kext loading is disabled (attempt to load kext %s).",
6324 		    getIdentifierCString());
6325 		result = kOSKextReturnDisabled;
6326 		goto finish;
6327 	}
6328 
6329 	/* If we've pushed the next available load tag to the invalid value,
6330 	 * we can't load any more kexts.
6331 	 */
6332 	if (sNextLoadTag == kOSKextInvalidLoadTag) {
6333 		OSKextLog(this,
6334 		    kOSKextLogErrorLevel |
6335 		    kOSKextLogLoadFlag,
6336 		    "Can't load kext %s - no more load tags to assign.",
6337 		    getIdentifierCString());
6338 		result = kOSKextReturnNoResources;
6339 		goto finish;
6340 	}
6341 
6342 	/* This is a bit of a hack, because we shouldn't be handling
6343 	 * personalities within the load function.
6344 	 */
6345 	if (!declaresExecutable()) {
6346 		/* There is a special case where a non-executable kext can be loaded: the
6347 		 * AppleKextExcludeList.  Detect that special kext by bundle identifier and
6348 		 * load its metadata into the global data structures, if appropriate
6349 		 */
6350 		if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
6351 			boolean_t updated = updateExcludeList(infoDict.get());
6352 			if (updated) {
6353 				OSKextLog(this,
6354 				    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
6355 				    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
6356 			}
6357 		}
6358 
6359 		if (isDriverKit()) {
6360 			if (loadTag == 0) {
6361 				sLoadedDriverKitKexts->setObject(this);
6362 				loadTag = sNextLoadTag++;
6363 			}
6364 		}
6365 		result = kOSReturnSuccess;
6366 		goto loaded;
6367 	}
6368 
6369 	/* Are we in safe boot?
6370 	 */
6371 	if (sSafeBoot && !isLoadableInSafeBoot()) {
6372 		OSKextLog(this,
6373 		    kOSKextLogErrorLevel |
6374 		    kOSKextLogLoadFlag,
6375 		    "Can't load kext %s - not loadable during safe boot.",
6376 		    getIdentifierCString());
6377 		result = kOSKextReturnBootLevel;
6378 		goto finish;
6379 	}
6380 
6381 	OSKextLog(this,
6382 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
6383 	    "Loading kext %s.",
6384 	    getIdentifierCString());
6385 
6386 #if !VM_MAPPED_KEXTS
6387 	if (isPrelinked() == false) {
6388 		OSKextLog(this,
6389 		    kOSKextLogErrorLevel |
6390 		    kOSKextLogLoadFlag,
6391 		    "Can't load kext %s - not in a kext collection.",
6392 		    getIdentifierCString());
6393 		result = kOSKextReturnDisabled;
6394 		goto finish;
6395 	}
6396 #endif /* defined(__x86_64__) */
6397 
6398 #if CONFIG_KXLD
6399 	if (!sKxldContext) {
6400 		kern_return_t kxldResult;
6401 		kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
6402 		    &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
6403 		    /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
6404 		if (kxldResult) {
6405 			OSKextLog(this,
6406 			    kOSKextLogErrorLevel |
6407 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6408 			    "Can't load kext %s - failed to create link context.",
6409 			    getIdentifierCString());
6410 			result = kOSKextReturnNoMemory;
6411 			goto finish;
6412 		}
6413 	}
6414 #endif // CONFIG_KXLD
6415 
6416 	/* We only need to resolve dependencies once for the whole graph, but
6417 	 * resolveDependencies will just return if there's no work to do, so it's
6418 	 * safe to call it more than once.
6419 	 */
6420 	if (!resolveDependencies()) {
6421 		// xxx - check resolveDependencies() for log msg
6422 		OSKextLog(this,
6423 		    kOSKextLogErrorLevel |
6424 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6425 		    "Can't load kext %s - failed to resolve library dependencies.",
6426 		    getIdentifierCString());
6427 		result = kOSKextReturnDependencies;
6428 		goto finish;
6429 	}
6430 
6431 	/* If we are excluding just the kext being loaded now (and not its
6432 	 * dependencies), drop the exclusion level to none so dependencies
6433 	 * start and/or add their personalities.
6434 	 */
6435 	if (dependenciesStartOpt == kOSKextExcludeKext) {
6436 		dependenciesStartOpt = kOSKextExcludeNone;
6437 	}
6438 
6439 	if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
6440 		dependenciesStartMatchingOpt = kOSKextExcludeNone;
6441 	}
6442 
6443 	/* Load the dependencies, recursively.
6444 	 */
6445 	count = getNumDependencies();
6446 	for (i = 0; i < count; i++) {
6447 		OSKext * dependency = OSDynamicCast(OSKext,
6448 		    dependencies->getObject(i));
6449 		if (dependency == NULL) {
6450 			OSKextLog(this,
6451 			    kOSKextLogErrorLevel |
6452 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6453 			    "Internal error loading kext %s; dependency disappeared.",
6454 			    getIdentifierCString());
6455 			result = kOSKextReturnInternalError;
6456 			goto finish;
6457 		}
6458 
6459 		/* Dependencies must be started accorting to the opt,
6460 		 * but not given the personality names of the main kext.
6461 		 */
6462 		result = dependency->load(dependenciesStartOpt,
6463 		    dependenciesStartMatchingOpt,
6464 		    /* personalityNames */ NULL);
6465 		if (result != KERN_SUCCESS) {
6466 			OSKextLog(this,
6467 			    kOSKextLogErrorLevel |
6468 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6469 			    "Dependency %s of kext %s failed to load.",
6470 			    dependency->getIdentifierCString(),
6471 			    getIdentifierCString());
6472 
6473 			OSKext::removeKext(dependency,
6474 			    /* terminateService/removePersonalities */ true);
6475 			result = kOSKextReturnDependencyLoadError;
6476 
6477 			goto finish;
6478 		}
6479 	}
6480 
6481 	result = loadExecutable();
6482 	if (result != KERN_SUCCESS) {
6483 		goto finish;
6484 	}
6485 
6486 	pendingPgoHead.next = &pendingPgoHead;
6487 	pendingPgoHead.prev = &pendingPgoHead;
6488 
6489 	// The kernel PRNG is not initialized when the first kext is
6490 	// loaded, so use early random
6491 	uuid_generate_early_random(instance_uuid);
6492 	account = IOMallocType(OSKextAccount);
6493 
6494 	account->loadTag = kmod_info->id;
6495 	account->site.refcount = 0;
6496 	account->site.flags = VM_TAG_KMOD;
6497 
6498 #if DEVELOPMENT || DEBUG
6499 	/* Setup the task reference group. */
6500 	(void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name),
6501 	    "task_%s", getIdentifierCString());
6502 	account->task_refgrp.grp_name = account->task_refgrp_name;
6503 	account->task_refgrp.grp_parent = &task_external_refgrp;
6504 	os_ref_log_init(&account->task_refgrp);
6505 #endif /* DEVELOPMENT || DEBUG */
6506 
6507 	account->kext = this;
6508 	if (gIOSurfaceIdentifier == bundleID) {
6509 		vm_tag_alloc(&account->site);
6510 		gIOSurfaceTag = account->site.tag;
6511 	}
6512 
6513 	flags.loaded = true;
6514 
6515 	/* Add the kext to the list of loaded kexts and update the kmod_info
6516 	 * struct to point to that of the last loaded kext (which is the way
6517 	 * it's always been done, though I'd rather do them in order now).
6518 	 */
6519 	lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
6520 	sLoadedKexts->setObject(this);
6521 
6522 	/* Keep the kernel itself out of the kmod list.
6523 	 */
6524 	if (lastLoadedKext->isKernel()) {
6525 		lastLoadedKext = NULL;
6526 	}
6527 
6528 	if (lastLoadedKext) {
6529 		kmod_info->next = lastLoadedKext->kmod_info;
6530 	}
6531 
6532 	notifyKextLoadObservers(this, kmod_info);
6533 
6534 	/* Make the global kmod list point at the just-loaded kext. Note that the
6535 	 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
6536 	 * although we do report it in kextstat these days by using the newer
6537 	 * OSArray of loaded kexts, which does contain it.
6538 	 *
6539 	 * (The OSKext object representing the kernel doesn't even have a kmod_info
6540 	 * struct, though I suppose we could stick a pointer to it from the
6541 	 * static struct in OSRuntime.cpp.)
6542 	 */
6543 	kmod = kmod_info;
6544 
6545 	/* Save the list of loaded kexts in case we panic.
6546 	 */
6547 	OSKext::saveLoadedKextPanicList();
6548 
6549 	if (isExecutable()) {
6550 		OSKext::updateLoadedKextSummaries();
6551 		savePanicString(/* isLoading */ true);
6552 
6553 #if CONFIG_DTRACE
6554 		registerWithDTrace();
6555 #else
6556 		jettisonLinkeditSegment();
6557 #endif /* CONFIG_DTRACE */
6558 
6559 #if !VM_MAPPED_KEXTS
6560 		/* If there is a page (or more) worth of padding after the end
6561 		 * of the last data section but before the end of the data segment
6562 		 * then free it in the same manner the LinkeditSegment is freed
6563 		 */
6564 		jettisonDATASegmentPadding();
6565 #endif
6566 	}
6567 
6568 loaded:
6569 	if (isExecutable() && !flags.started) {
6570 		if (startOpt == kOSKextExcludeNone) {
6571 			result = start();
6572 			if (result != kOSReturnSuccess) {
6573 				OSKextLog(this,
6574 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6575 				    "Kext %s start failed (result 0x%x).",
6576 				    getIdentifierCString(), result);
6577 				result = kOSKextReturnStartStopError;
6578 			}
6579 		}
6580 	}
6581 
6582 	/* If not excluding matching, send the personalities to the kernel.
6583 	 * This never affects the result of the load operation.
6584 	 * This is a bit of a hack, because we shouldn't be handling
6585 	 * personalities within the load function.
6586 	 */
6587 	if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
6588 		result = sendPersonalitiesToCatalog(true, personalityNames);
6589 	}
6590 
6591 finish:
6592 
6593 	if (result != kOSReturnSuccess) {
6594 		OSKextLog(this,
6595 		    kOSKextLogErrorLevel |
6596 		    kOSKextLogLoadFlag,
6597 		    "Kext %s failed to load (0x%x).",
6598 		    getIdentifierCString(), (int)result);
6599 	} else if (!alreadyLoaded) {
6600 		OSKextLog(this,
6601 		    kOSKextLogProgressLevel |
6602 		    kOSKextLogLoadFlag,
6603 		    "Kext %s loaded.",
6604 		    getIdentifierCString());
6605 
6606 		queueKextNotification(kKextRequestPredicateLoadNotification,
6607 		    OSDynamicCast(OSString, bundleID.get()));
6608 	}
6609 	return result;
6610 }
6611 
6612 #if CONFIG_KXLD
6613 /*********************************************************************
6614 *
6615 *********************************************************************/
6616 static char *
strdup(const char * string)6617 strdup(const char * string)
6618 {
6619 	char * result = NULL;
6620 	size_t size;
6621 
6622 	if (!string) {
6623 		goto finish;
6624 	}
6625 
6626 	size = 1 + strlen(string);
6627 	result = (char *)kalloc_data_tag(size, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
6628 	if (!result) {
6629 		goto finish;
6630 	}
6631 
6632 	memcpy(result, string, size);
6633 
6634 finish:
6635 	return result;
6636 }
6637 #endif // CONFIG_KXLD
6638 
6639 /*********************************************************************
6640 *
6641 *********************************************************************/
6642 
6643 kernel_section_t *
lookupSection(const char * segname,const char * secname)6644 OSKext::lookupSection(const char *segname, const char *secname)
6645 {
6646 	kernel_section_t         * found_section = NULL;
6647 	kernel_mach_header_t     * mh            = NULL;
6648 	kernel_segment_command_t * seg           = NULL;
6649 	kernel_section_t         * sec           = NULL;
6650 
6651 	if (!linkedExecutable) {
6652 		return NULL;
6653 	}
6654 
6655 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6656 
6657 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6658 		if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) {
6659 			continue;
6660 		}
6661 
6662 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6663 			if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) {
6664 				found_section = sec;
6665 				goto out;
6666 			}
6667 		}
6668 	}
6669 
6670 out:
6671 	return found_section;
6672 }
6673 
6674 /*********************************************************************
6675 *
6676 *********************************************************************/
6677 
6678 OSReturn
slidePrelinkedExecutable(bool doCoalescedSlides)6679 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides)
6680 {
6681 	OSReturn                       result           = kOSKextReturnBadData;
6682 	kernel_mach_header_t         * mh               = NULL;
6683 	kernel_segment_command_t     * seg              = NULL;
6684 	kernel_segment_command_t     * linkeditSeg      = NULL;
6685 	kernel_section_t             * sec              = NULL;
6686 	char                         * linkeditBase     = NULL;
6687 	bool                           haveLinkeditBase = false;
6688 	char                         * relocBase        = NULL;
6689 	bool                           haveRelocBase    = false;
6690 	struct dysymtab_command      * dysymtab         = NULL;
6691 	struct linkedit_data_command * segmentSplitInfo = NULL;
6692 	struct symtab_command        * symtab           = NULL;
6693 	kernel_nlist_t               * sym              = NULL;
6694 	struct relocation_info       * reloc            = NULL;
6695 	uint32_t                       i                = 0;
6696 	int                            reloc_size;
6697 	vm_offset_t                    new_kextsize;
6698 	kc_format                    format             = KCFormatUnknown;
6699 
6700 	if (linkedExecutable == NULL || flags.builtin) {
6701 		result = kOSReturnSuccess;
6702 		goto finish;
6703 	}
6704 
6705 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6706 	if (kernel_mach_header_is_in_fileset(mh)) {
6707 		// kexts in filesets are slid as part of collection sliding
6708 		result = kOSReturnSuccess;
6709 		goto finish;
6710 	}
6711 
6712 	segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
6713 
6714 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6715 		if (!seg->vmaddr) {
6716 			continue;
6717 		}
6718 
6719 		seg->vmaddr = ml_static_slide(seg->vmaddr);
6720 
6721 #if KASLR_KEXT_DEBUG
6722 		IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
6723 		    seg->segname,
6724 		    (unsigned long)ml_static_unslide(seg->vmaddr),
6725 		    (unsigned long)seg->vmaddr);
6726 #endif
6727 
6728 		if (!haveRelocBase) {
6729 			relocBase = (char *) seg->vmaddr;
6730 			haveRelocBase = true;
6731 		}
6732 		if (!strcmp(seg->segname, "__LINKEDIT")) {
6733 			linkeditBase = (char *) seg->vmaddr - seg->fileoff;
6734 			haveLinkeditBase = true;
6735 			linkeditSeg = seg;
6736 		}
6737 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6738 			sec->addr = ml_static_slide(sec->addr);
6739 
6740 #if KASLR_KEXT_DEBUG
6741 			IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
6742 			    sec->sectname,
6743 			    (unsigned long)ml_static_unslide(sec->addr),
6744 			    (unsigned long)sec->addr);
6745 #endif
6746 		}
6747 	}
6748 
6749 	dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
6750 
6751 	symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
6752 
6753 	if (symtab != NULL && doCoalescedSlides == false) {
6754 		/* Some pseudo-kexts have symbol tables without segments.
6755 		 * Ignore them. */
6756 		if (symtab->nsyms > 0 && haveLinkeditBase) {
6757 			sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
6758 			for (i = 0; i < symtab->nsyms; i++) {
6759 				if (sym[i].n_type & N_STAB) {
6760 					continue;
6761 				}
6762 				sym[i].n_value = ml_static_slide(sym[i].n_value);
6763 
6764 #if KASLR_KEXT_DEBUG
6765 #define MAX_SYMS_TO_LOG 5
6766 				if (i < MAX_SYMS_TO_LOG) {
6767 					IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
6768 					    (unsigned long)ml_static_unslide(sym[i].n_value),
6769 					    (unsigned long)sym[i].n_value);
6770 				}
6771 #endif
6772 			}
6773 		}
6774 	}
6775 
6776 	if (dysymtab != NULL && doCoalescedSlides == false) {
6777 		if (dysymtab->nextrel > 0) {
6778 			OSKextLog(this,
6779 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6780 			    kOSKextLogLinkFlag,
6781 			    "Sliding kext %s: External relocations found.",
6782 			    getIdentifierCString());
6783 			goto finish;
6784 		}
6785 
6786 		if (dysymtab->nlocrel > 0) {
6787 			if (!haveLinkeditBase) {
6788 				OSKextLog(this,
6789 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6790 				    kOSKextLogLinkFlag,
6791 				    "Sliding kext %s: No linkedit segment.",
6792 				    getIdentifierCString());
6793 				goto finish;
6794 			}
6795 
6796 			if (!haveRelocBase) {
6797 				OSKextLog(this,
6798 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6799 				    kOSKextLogLinkFlag,
6800 #if __x86_64__
6801 				    "Sliding kext %s: No writable segments.",
6802 #else
6803 				    "Sliding kext %s: No segments.",
6804 #endif
6805 				    getIdentifierCString());
6806 				goto finish;
6807 			}
6808 
6809 			reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
6810 			reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
6811 
6812 			for (i = 0; i < dysymtab->nlocrel; i++) {
6813 				if (reloc[i].r_extern != 0
6814 				    || reloc[i].r_type != 0
6815 				    || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
6816 				    ) {
6817 					OSKextLog(this,
6818 					    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6819 					    kOSKextLogLinkFlag,
6820 					    "Sliding kext %s: Unexpected relocation found.",
6821 					    getIdentifierCString());
6822 					goto finish;
6823 				}
6824 				if (reloc[i].r_pcrel != 0) {
6825 					continue;
6826 				}
6827 				uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
6828 				*relocAddr = ml_static_slide(*relocAddr);
6829 
6830 #if KASLR_KEXT_DEBUG
6831 #define MAX_DYSYMS_TO_LOG 5
6832 				if (i < MAX_DYSYMS_TO_LOG) {
6833 					IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
6834 					    (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
6835 					    (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
6836 				}
6837 #endif
6838 			}
6839 
6840 			/* We should free these relocations, not just delete the reference to them.
6841 			 * <rdar://problem/10535549> Free relocations from PIE kexts.
6842 			 *
6843 			 * For now, we do not free LINKEDIT for kexts with split segments.
6844 			 */
6845 			new_kextsize = round_page(kmod_info->size - reloc_size);
6846 			if (new_kextsize > UINT_MAX) {
6847 				OSKextLog(this,
6848 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
6849 				    kOSKextLogLinkFlag,
6850 				    "Kext %s: new kext size is too large.",
6851 				    getIdentifierCString());
6852 				goto finish;
6853 			}
6854 			if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
6855 				vm_offset_t     endofkext = kmod_info->address + kmod_info->size;
6856 				vm_offset_t     new_endofkext = kmod_info->address + new_kextsize;
6857 				vm_offset_t     endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
6858 				size_t          bytes_remaining = endofkext - endofrelocInfo;
6859 				OSSharedPtr<OSData>        new_osdata;
6860 
6861 				/* fix up symbol offsets if they are after the dsymtab local relocs */
6862 				if (symtab) {
6863 					if (dysymtab->locreloff < symtab->symoff) {
6864 						symtab->symoff -= reloc_size;
6865 					}
6866 					if (dysymtab->locreloff < symtab->stroff) {
6867 						symtab->stroff -= reloc_size;
6868 					}
6869 				}
6870 				if (dysymtab->locreloff < dysymtab->extreloff) {
6871 					dysymtab->extreloff -= reloc_size;
6872 				}
6873 
6874 				/* move data behind reloc info down to new offset */
6875 				if (endofrelocInfo < endofkext) {
6876 					memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
6877 				}
6878 
6879 				/* Create a new OSData for the smaller kext object and reflect
6880 				 * new linkedit segment size.
6881 				 */
6882 				linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
6883 				linkeditSeg->filesize = linkeditSeg->vmsize;
6884 
6885 				new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize);
6886 				if (new_osdata) {
6887 					/* Fix up kmod info and linkedExecutable.
6888 					 */
6889 					kmod_info->size = new_kextsize;
6890 					/*
6891 					 * Fileset KCs are mapped as a whole by iBoot.
6892 					 * Individual kext executables should not be unmapped
6893 					 * by xnu.
6894 					 * Doing so may result in panics like rdar://85419651
6895 					 */
6896 					if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
6897 						new_osdata->setDeallocFunction(NULL);
6898 					} else { // Not from a Fileset KC
6899 #if VM_MAPPED_KEXTS
6900 						new_osdata->setDeallocFunction(osdata_kext_free);
6901 #else
6902 						new_osdata->setDeallocFunction(osdata_phys_free);
6903 #endif
6904 					}
6905 					linkedExecutable->setDeallocFunction(NULL);
6906 					linkedExecutable = os::move(new_osdata);
6907 
6908 #if VM_MAPPED_KEXTS
6909 					kext_free(new_endofkext, (endofkext - new_endofkext));
6910 #else
6911 					ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
6912 #endif
6913 				}
6914 			}
6915 			dysymtab->nlocrel = 0;
6916 			dysymtab->locreloff = 0;
6917 		}
6918 	}
6919 
6920 	result = kOSReturnSuccess;
6921 finish:
6922 	return result;
6923 }
6924 
6925 /*********************************************************************
6926 * called only by load()
6927 *********************************************************************/
6928 OSReturn
loadExecutable()6929 OSKext::loadExecutable()
6930 {
6931 	OSReturn              result             = kOSReturnError;
6932 	OSSharedPtr<OSArray>  linkDependencies;
6933 	uint32_t              num_kmod_refs      = 0;
6934 	OSData              * theExecutable      = NULL;        // do not release
6935 	OSString            * versString         = NULL;        // do not release
6936 	const char          * versCString        = NULL;        // do not free
6937 	const char          * string             = NULL;        // do not free
6938 
6939 #if CONFIG_KXLD
6940 	unsigned int          i;
6941 	uint32_t              numDirectDependencies   = 0;
6942 	kern_return_t         kxldResult;
6943 	KXLDDependency     *  kxlddeps           = NULL;        // must kfree
6944 	uint32_t              num_kxlddeps       = 0;
6945 	struct mach_header ** kxldHeaderPtr      = NULL;        // do not free
6946 	struct mach_header  * kxld_header        = NULL;        // xxx - need to free here?
6947 #endif // CONFIG_KXLD
6948 
6949 	/* We need the version string for a variety of bits below.
6950 	 */
6951 	versString = OSDynamicCast(OSString,
6952 	    getPropertyForHostArch(kCFBundleVersionKey));
6953 	if (!versString) {
6954 		goto finish;
6955 	}
6956 	versCString = versString->getCStringNoCopy();
6957 
6958 	if (isKernelComponent()) {
6959 		if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
6960 			if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
6961 				OSKextLog(this,
6962 				    kOSKextLogErrorLevel |
6963 				    kOSKextLogLoadFlag,
6964 				    "Kernel component %s has incorrect version %s; "
6965 				    "expected %s.",
6966 				    getIdentifierCString(),
6967 				    versCString, KERNEL6_VERSION);
6968 				result = kOSKextReturnInternalError;
6969 				goto finish;
6970 			} else if (strcmp(versCString, osrelease)) {
6971 				OSKextLog(this,
6972 				    kOSKextLogErrorLevel |
6973 				    kOSKextLogLoadFlag,
6974 				    "Kernel component %s has incorrect version %s; "
6975 				    "expected %s.",
6976 				    getIdentifierCString(),
6977 				    versCString, osrelease);
6978 				result = kOSKextReturnInternalError;
6979 				goto finish;
6980 			}
6981 		}
6982 	}
6983 
6984 #if defined(__x86_64__) || defined(__i386__)
6985 	if (flags.resetSegmentsFromVnode) {
6986 		/* Fixup the chains and slide the mach headers */
6987 		kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address;
6988 
6989 		if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) {
6990 			result = kOSKextReturnValidation;
6991 			goto finish;
6992 		}
6993 	}
6994 #endif //(__x86_64__) || defined(__i386__)
6995 
6996 	if (isPrelinked()) {
6997 		goto register_kmod;
6998 	}
6999 
7000 	/* <rdar://problem/21444003> all callers must be entitled */
7001 	if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) {
7002 		OSKextLog(this,
7003 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7004 		    "Not entitled to link kext '%s'",
7005 		    getIdentifierCString());
7006 		result = kOSKextReturnNotPrivileged;
7007 		goto finish;
7008 	}
7009 
7010 	theExecutable = getExecutable();
7011 	if (!theExecutable) {
7012 		if (declaresExecutable()) {
7013 			OSKextLog(this,
7014 			    kOSKextLogErrorLevel |
7015 			    kOSKextLogLoadFlag,
7016 			    "Can't load kext %s - executable is missing.",
7017 			    getIdentifierCString());
7018 			result = kOSKextReturnValidation;
7019 			goto finish;
7020 		}
7021 		goto register_kmod;
7022 	}
7023 
7024 	if (isInterface()) {
7025 		OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable);
7026 		if (executableCopy) {
7027 			setLinkedExecutable(executableCopy.get());
7028 		}
7029 		goto register_kmod;
7030 	}
7031 
7032 #if CONFIG_KXLD
7033 	numDirectDependencies = getNumDependencies();
7034 
7035 	if (flags.hasBleedthrough) {
7036 		linkDependencies = dependencies;
7037 	} else {
7038 		linkDependencies = OSArray::withArray(dependencies.get());
7039 		if (!linkDependencies) {
7040 			OSKextLog(this,
7041 			    kOSKextLogErrorLevel |
7042 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7043 			    "Can't allocate link dependencies to load kext %s.",
7044 			    getIdentifierCString());
7045 			goto finish;
7046 		}
7047 
7048 		for (i = 0; i < numDirectDependencies; ++i) {
7049 			OSKext * dependencyKext = OSDynamicCast(OSKext,
7050 			    dependencies->getObject(i));
7051 			dependencyKext->addBleedthroughDependencies(linkDependencies.get());
7052 		}
7053 	}
7054 
7055 	num_kxlddeps = linkDependencies->getCount();
7056 	if (!num_kxlddeps) {
7057 		OSKextLog(this,
7058 		    kOSKextLogErrorLevel |
7059 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
7060 		    "Can't load kext %s - it has no library dependencies.",
7061 		    getIdentifierCString());
7062 		goto finish;
7063 	}
7064 
7065 	kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
7066 	if (!kxlddeps) {
7067 		OSKextLog(this,
7068 		    kOSKextLogErrorLevel |
7069 		    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7070 		    "Can't allocate link context to load kext %s.",
7071 		    getIdentifierCString());
7072 		goto finish;
7073 	}
7074 	bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
7075 
7076 	for (i = 0; i < num_kxlddeps; ++i) {
7077 		OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
7078 
7079 		if (dependency->isInterface()) {
7080 			OSKext *interfaceTargetKext = NULL;        //do not release
7081 			OSData * interfaceTarget = NULL;        //do not release
7082 
7083 			if (dependency->isKernelComponent()) {
7084 				interfaceTargetKext = sKernelKext;
7085 				interfaceTarget = sKernelKext->linkedExecutable.get();
7086 			} else {
7087 				interfaceTargetKext = OSDynamicCast(OSKext,
7088 				    dependency->dependencies->getObject(0));
7089 
7090 				interfaceTarget = interfaceTargetKext->linkedExecutable.get();
7091 			}
7092 
7093 			if (!interfaceTarget) {
7094 				// panic?
7095 				goto finish;
7096 			}
7097 
7098 			/* The names set here aren't actually logged yet <rdar://problem/7941514>,
7099 			 * it will be useful to have them in the debugger.
7100 			 * strdup() failing isn't critical right here so we don't check that.
7101 			 */
7102 			kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
7103 			kxlddeps[i].kext_size = interfaceTarget->getLength();
7104 			kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
7105 
7106 			if (dependency->linkedExecutable != NULL) {
7107 				kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
7108 				kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
7109 			} else {
7110 				kxlddeps[i].interface = (u_char *) NULL;
7111 				kxlddeps[i].interface_size = 0;
7112 			}
7113 			kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
7114 		} else {
7115 			kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
7116 			kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
7117 			kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
7118 		}
7119 
7120 		kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
7121 	}
7122 
7123 	kxldHeaderPtr = &kxld_header;
7124 
7125 #if DEBUG
7126 	OSKextLog(this,
7127 	    kOSKextLogExplicitLevel |
7128 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7129 	    "Kext %s - calling kxld_link_file:\n"
7130 	    "    kxld_context: %p\n"
7131 	    "    executable: %p    executable_length: %d\n"
7132 	    "    user_data: %p\n"
7133 	    "    kxld_dependencies: %p    num_dependencies: %d\n"
7134 	    "    kxld_header_ptr: %p    kmod_info_ptr: %p\n",
7135 	    getIdentifierCString(), sKxldContext,
7136 	    theExecutable->getBytesNoCopy(), theExecutable->getLength(),
7137 	    this, kxlddeps, num_kxlddeps,
7138 	    kxldHeaderPtr, &kmod_info);
7139 #endif
7140 
7141 	/* After this call, the linkedExecutable instance variable
7142 	 * should exist.
7143 	 */
7144 	kxldResult = kxld_link_file(sKxldContext,
7145 	    (u_char *)theExecutable->getBytesNoCopy(),
7146 	    theExecutable->getLength(),
7147 	    getIdentifierCString(), this, kxlddeps, num_kxlddeps,
7148 	    (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
7149 
7150 	if (kxldResult != KERN_SUCCESS) {
7151 		// xxx - add kxldResult here?
7152 		OSKextLog(this,
7153 		    kOSKextLogErrorLevel |
7154 		    kOSKextLogLoadFlag,
7155 		    "Can't load kext %s - link failed.",
7156 		    getIdentifierCString());
7157 		result = kOSKextReturnLinkError;
7158 		goto finish;
7159 	}
7160 
7161 	/* We've written data & instructions into kernel memory, so flush the data
7162 	 * cache and invalidate the instruction cache.
7163 	 * I/D caches are coherent on x86
7164 	 */
7165 #if !defined(__i386__) && !defined(__x86_64__)
7166 	flush_dcache(kmod_info->address, kmod_info->size, false);
7167 	invalidate_icache(kmod_info->address, kmod_info->size, false);
7168 #endif
7169 
7170 #else // !CONFIG_KXLD
7171 	OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7172 	    "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString());
7173 	result = kOSKextReturnLinkError;
7174 	goto finish;
7175 #endif // CONFIG_KXLD
7176 
7177 register_kmod:
7178 
7179 	if (isInterface()) {
7180 		/* Whip up a fake kmod_info entry for the interface kext.
7181 		 */
7182 		kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
7183 		if (!kmod_info) {
7184 			result = KERN_MEMORY_ERROR;
7185 			goto finish;
7186 		}
7187 
7188 		/* A pseudokext has almost nothing in its kmod_info struct.
7189 		 */
7190 		kmod_info->info_version = KMOD_INFO_VERSION;
7191 
7192 		/* An interface kext doesn't have a linkedExecutable, so save a
7193 		 * copy of the UUID out of the original executable via copyUUID()
7194 		 * while we still have the original executable.
7195 		 */
7196 		interfaceUUID = copyUUID();
7197 	}
7198 
7199 	kmod_info->id = loadTag = sNextLoadTag++;
7200 	kmod_info->reference_count = 0;         // KMOD_DECL... sets it to -1 (invalid).
7201 
7202 	/* Stamp the bundle ID and version from the OSKext over anything
7203 	 * resident inside the kmod_info.
7204 	 */
7205 	string = getIdentifierCString();
7206 	strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
7207 
7208 	string = versCString;
7209 	strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
7210 
7211 	/* Add the dependencies' kmod_info structs as kmod_references.
7212 	 */
7213 	num_kmod_refs = getNumDependencies();
7214 	if (num_kmod_refs) {
7215 		kmod_info->reference_list = kalloc_type_tag(kmod_reference_t,
7216 		    num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT);
7217 		if (!kmod_info->reference_list) {
7218 			result = KERN_MEMORY_ERROR;
7219 			goto finish;
7220 		}
7221 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
7222 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
7223 			OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
7224 			ref->info = refKext->kmod_info;
7225 			ref->info->reference_count++;
7226 
7227 			if (refIndex + 1 < num_kmod_refs) {
7228 				ref->next = kmod_info->reference_list + refIndex + 1;
7229 			}
7230 		}
7231 	}
7232 
7233 	if (kmod_info->hdr_size > UINT32_MAX) {
7234 		OSKextLog(this,
7235 		    kOSKextLogErrorLevel |
7236 		    kOSKextLogLoadFlag,
7237 #if __LP64__
7238 		    "Kext %s header size is too large (%lu > UINT32_MAX).",
7239 #else
7240 		    "Kext %s header size is too large (%u > UINT32_MAX).",
7241 #endif
7242 		    kmod_info->name,
7243 		    kmod_info->hdr_size);
7244 		result = KERN_FAILURE;
7245 		goto finish;
7246 	}
7247 
7248 	if (kmod_info->size > UINT32_MAX) {
7249 		OSKextLog(this,
7250 		    kOSKextLogErrorLevel |
7251 		    kOSKextLogLoadFlag,
7252 #if __LP64__
7253 		    "Kext %s size is too large (%lu > UINT32_MAX).",
7254 #else
7255 		    "Kext %s size is too large (%u > UINT32_MAX).",
7256 #endif
7257 		    kmod_info->name,
7258 		    kmod_info->size);
7259 		result = KERN_FAILURE;
7260 		goto finish;
7261 	}
7262 
7263 	if (!isInterface() && linkedExecutable) {
7264 		OSKextLog(this,
7265 		    kOSKextLogProgressLevel |
7266 		    kOSKextLogLoadFlag,
7267 		    "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
7268 		    kmod_info->name,
7269 		    (unsigned)kmod_info->size / PAGE_SIZE,
7270 		    (unsigned long)ml_static_unslide(kmod_info->address),
7271 		    (unsigned)kmod_info->id);
7272 	}
7273 
7274 	/* VM protections and wiring for the Aux KC are done at collection loading time */
7275 	if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) {
7276 		/* if prelinked and primary KC, VM protections are already set */
7277 		result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true);
7278 		if (result != KERN_SUCCESS) {
7279 			goto finish;
7280 		}
7281 	}
7282 
7283 #if KASAN
7284 	if (linkedExecutable) {
7285 		kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
7286 		    linkedExecutable->getLength(), getIdentifierCString());
7287 	}
7288 #else
7289 	if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
7290 		OSKextLog(this,
7291 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7292 		    "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
7293 		    getIdentifierCString()
7294 		    );
7295 		result = KERN_FAILURE;
7296 		goto finish;
7297 	}
7298 #endif
7299 
7300 	result = kOSReturnSuccess;
7301 
7302 finish:
7303 
7304 #if CONFIG_KXLD
7305 	/* Clear up locally allocated dependency info.
7306 	 */
7307 	for (i = 0; i < num_kxlddeps; ++i) {
7308 		size_t size;
7309 
7310 		if (kxlddeps[i].kext_name) {
7311 			size = 1 + strlen(kxlddeps[i].kext_name);
7312 			kfree_data(kxlddeps[i].kext_name, size);
7313 		}
7314 		if (kxlddeps[i].interface_name) {
7315 			size = 1 + strlen(kxlddeps[i].interface_name);
7316 			kfree_data(kxlddeps[i].interface_name, size);
7317 		}
7318 	}
7319 	if (kxlddeps) {
7320 		kfree_type(KXLDDependency, num_kxlddeps, kxlddeps);
7321 	}
7322 #endif // CONFIG_KXLD
7323 
7324 	/* We no longer need the unrelocated executable (which the linker
7325 	 * has altered anyhow).
7326 	 */
7327 	setExecutable(NULL);
7328 
7329 	if (result != kOSReturnSuccess) {
7330 		OSKextLog(this,
7331 		    kOSKextLogErrorLevel |
7332 		    kOSKextLogLoadFlag,
7333 		    "Failed to load executable for kext %s.",
7334 		    getIdentifierCString());
7335 
7336 		if (kmod_info && kmod_info->reference_list) {
7337 			kfree_type(kmod_reference_t, num_kmod_refs,
7338 			    kmod_info->reference_list);
7339 		}
7340 		if (isInterface()) {
7341 			kfree_type(kmod_info_t, kmod_info);
7342 			kmod_info = NULL;
7343 		}
7344 		if (kc_type == KCKindUnknown) {
7345 			kmod_info = NULL;
7346 			if (linkedExecutable) {
7347 				linkedExecutable.reset();
7348 			}
7349 		}
7350 	}
7351 
7352 	return result;
7353 }
7354 
7355 /* static */
7356 void
jettisonFileSetLinkeditSegment(kernel_mach_header_t * mh)7357 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh)
7358 {
7359 	kernel_segment_command_t *linkeditseg = NULL;
7360 
7361 	linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT);
7362 	if (linkeditseg == NULL) {
7363 		panic("FileSet booted with no Linkedit segment");
7364 	}
7365 
7366 #if VM_MAPPED_KEXTS
7367 	/* BootKC on x86_64 is not vm mapped */
7368 	ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize);
7369 
7370 	OSKextLog(/* kext */ NULL,
7371 	    kOSKextLogProgressLevel |
7372 	    kOSKextLogGeneralFlag,
7373 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
7374 	    linkeditseg->vmaddr, linkeditseg->vmsize);
7375 #else
7376 	/* BootKC on arm64 is not vm mapped, but is slid */
7377 	vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase));
7378 
7379 	ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize);
7380 
7381 	OSKextLog(/* kext */ NULL,
7382 	    kOSKextLogProgressLevel |
7383 	    kOSKextLogGeneralFlag,
7384 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
7385 	    (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize);
7386 #endif /* VM_MAPPED_KEXTS */
7387 }
7388 
7389 /*********************************************************************
7390 * The linkedit segment is used by the kext linker for dependency
7391 * resolution, and by dtrace for probe initialization. We can free it
7392 * for non-library kexts, since no kexts depend on non-library kexts
7393 * by definition, once dtrace has been initialized.
7394 *********************************************************************/
7395 void
jettisonLinkeditSegment(void)7396 OSKext::jettisonLinkeditSegment(void)
7397 {
7398 	kernel_mach_header_t     * machhdr = (kernel_mach_header_t *)kmod_info->address;
7399 	kernel_segment_command_t * linkedit = NULL;
7400 	vm_offset_t                start;
7401 	vm_size_t                  linkeditsize, kextsize;
7402 	OSSharedPtr<OSData>        data;
7403 	kc_format                format    = KCFormatUnknown;
7404 
7405 	if (isInFileset()) {
7406 		return;
7407 	}
7408 
7409 #if NO_KEXTD
7410 	/* We can free symbol tables for all embedded kexts because we don't
7411 	 * support runtime kext linking.
7412 	 */
7413 	if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
7414 #else
7415 	if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
7416 #endif
7417 		goto finish;
7418 	}
7419 
7420 	/* Find the linkedit segment.  If it's not the last segment, then freeing
7421 	 * it will fragment the kext into multiple VM regions, which OSKext is not
7422 	 * designed to handle, so we'll have to skip it.
7423 	 */
7424 	linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
7425 	if (!linkedit) {
7426 		goto finish;
7427 	}
7428 
7429 	if (round_page(kmod_info->address + kmod_info->size) !=
7430 	    round_page(linkedit->vmaddr + linkedit->vmsize)) {
7431 		goto finish;
7432 	}
7433 
7434 	/* Create a new OSData for the smaller kext object.
7435 	 */
7436 	linkeditsize = round_page(linkedit->vmsize);
7437 	kextsize = kmod_info->size - linkeditsize;
7438 	start = linkedit->vmaddr;
7439 
7440 	if (kextsize > UINT_MAX) {
7441 		goto finish;
7442 	}
7443 	data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize);
7444 	if (!data) {
7445 		goto finish;
7446 	}
7447 
7448 	/* Fix the kmod info and linkedExecutable.
7449 	 */
7450 	kmod_info->size = kextsize;
7451 
7452 	/*
7453 	 * Fileset KCs are mapped as a whole by iBoot.
7454 	 * Individual kext executables should not be unmapped by xnu
7455 	 * Doing so may result in panics like rdar://85419651
7456 	 */
7457 	if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
7458 		data->setDeallocFunction(NULL);
7459 	} else { // Not from a Fileset KC
7460 #if VM_MAPPED_KEXTS
7461 		data->setDeallocFunction(osdata_kext_free);
7462 #else
7463 		data->setDeallocFunction(osdata_phys_free);
7464 #endif
7465 	}
7466 	linkedExecutable->setDeallocFunction(NULL);
7467 	linkedExecutable = os::move(data);
7468 	flags.jettisonLinkeditSeg = 1;
7469 
7470 	/* Free the linkedit segment.
7471 	 */
7472 #if VM_MAPPED_KEXTS
7473 	kext_free(start, linkeditsize);
7474 #else
7475 	ml_static_mfree(start, linkeditsize);
7476 #endif
7477 
7478 finish:
7479 	return;
7480 }
7481 
7482 /*********************************************************************
7483 * If there are whole pages that are unused betweem the last section
7484 * of the DATA segment and the end of the DATA segment then we can free
7485 * them
7486 *********************************************************************/
7487 void
7488 OSKext::jettisonDATASegmentPadding(void)
7489 {
7490 	kernel_mach_header_t * mh;
7491 	kernel_segment_command_t * dataSeg;
7492 	kernel_section_t * sec, * lastSec;
7493 	vm_offset_t dataSegEnd, lastSecEnd;
7494 	vm_size_t padSize;
7495 
7496 	if (flags.builtin) {
7497 		return;
7498 	}
7499 	mh = (kernel_mach_header_t *)kmod_info->address;
7500 
7501 	if (isInFileset()) {
7502 		return;
7503 	}
7504 
7505 	dataSeg = getsegbynamefromheader(mh, SEG_DATA);
7506 	if (dataSeg == NULL) {
7507 		return;
7508 	}
7509 
7510 	lastSec = NULL;
7511 	sec = firstsect(dataSeg);
7512 	while (sec != NULL) {
7513 		lastSec = sec;
7514 		sec = nextsect(dataSeg, sec);
7515 	}
7516 
7517 	if (lastSec == NULL) {
7518 		return;
7519 	}
7520 
7521 	if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
7522 	    (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
7523 		return;
7524 	}
7525 
7526 	dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
7527 	lastSecEnd = round_page(lastSec->addr + lastSec->size);
7528 
7529 	if (dataSegEnd <= lastSecEnd) {
7530 		return;
7531 	}
7532 
7533 	padSize = dataSegEnd - lastSecEnd;
7534 
7535 	if (padSize >= PAGE_SIZE) {
7536 #if VM_MAPPED_KEXTS
7537 		kext_free(lastSecEnd, padSize);
7538 #else
7539 		ml_static_mfree(lastSecEnd, padSize);
7540 #endif
7541 	}
7542 }
7543 
7544 /*********************************************************************
7545 *********************************************************************/
7546 void
7547 OSKext::setLinkedExecutable(OSData * anExecutable)
7548 {
7549 	if (linkedExecutable) {
7550 		panic("Attempt to set linked executable on kext "
7551 		    "that already has one (%s).\n",
7552 		    getIdentifierCString());
7553 	}
7554 	linkedExecutable.reset(anExecutable, OSRetain);
7555 	return;
7556 }
7557 
7558 #if CONFIG_DTRACE
7559 /*********************************************************************
7560 * Go through all loaded kexts and tell them to register with dtrace.
7561 * The instance method only registers if necessary.
7562 *********************************************************************/
7563 /* static */
7564 void
7565 OSKext::registerKextsWithDTrace(void)
7566 {
7567 	uint32_t count = sLoadedKexts->getCount();
7568 	uint32_t i;
7569 
7570 	IORecursiveLockLock(sKextLock);
7571 
7572 	for (i = 0; i < count; i++) {
7573 		OSKext   * thisKext     = NULL;        // do not release
7574 
7575 		thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
7576 		if (!thisKext || !thisKext->isExecutable()) {
7577 			continue;
7578 		}
7579 
7580 		thisKext->registerWithDTrace();
7581 	}
7582 
7583 	IORecursiveLockUnlock(sKextLock);
7584 
7585 	return;
7586 }
7587 
7588 extern "C" {
7589 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
7590 extern int (*dtrace_modunload)(struct kmod_info *);
7591 };
7592 
7593 /*********************************************************************
7594 *********************************************************************/
7595 void
7596 OSKext::registerWithDTrace(void)
7597 {
7598 	/* Register kext with dtrace. A dtrace_modload failure should not
7599 	 * prevent a kext from loading, so we ignore the return code.
7600 	 */
7601 	if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
7602 		uint32_t modflag = 0;
7603 		OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
7604 
7605 		if (!sKeepSymbols && kc_type == KCKindPrimary) {
7606 			if (forceInit == kOSBooleanTrue) {
7607 				OSKextLog(this,
7608 				    kOSKextLogBasicLevel |
7609 				    kOSKextLogGeneralFlag,
7610 				    "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s",
7611 				    getIdentifierCString());
7612 				forceInit = kOSBooleanFalse;
7613 			}
7614 			/* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */
7615 			modflag |= KMOD_DTRACE_NO_KERNEL_SYMS;
7616 		}
7617 
7618 		if (forceInit == kOSBooleanTrue) {
7619 			modflag |= KMOD_DTRACE_FORCE_INIT;
7620 		}
7621 		if (flags.builtin) {
7622 			modflag |= KMOD_DTRACE_STATIC_KEXT;
7623 		}
7624 
7625 		(void)(*dtrace_modload)(kmod_info, modflag);
7626 		flags.dtraceInitialized = true;
7627 		jettisonLinkeditSegment();
7628 	}
7629 	return;
7630 }
7631 /*********************************************************************
7632 *********************************************************************/
7633 void
7634 OSKext::unregisterWithDTrace(void)
7635 {
7636 	/* Unregister kext with dtrace. A dtrace_modunload failure should not
7637 	 * prevent a kext from loading, so we ignore the return code.
7638 	 */
7639 	if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
7640 		(void)(*dtrace_modunload)(kmod_info);
7641 		flags.dtraceInitialized = false;
7642 	}
7643 	return;
7644 }
7645 #endif /* CONFIG_DTRACE */
7646 
7647 
7648 /*********************************************************************
7649 * called only by loadExecutable()
7650 *********************************************************************/
7651 #if !VM_MAPPED_KEXTS
7652 #if defined(__arm__) || defined(__arm64__)
7653 static inline kern_return_t
7654 OSKext_protect(
7655 	kernel_mach_header_t *kext_mh,
7656 	vm_map_t   map,
7657 	vm_map_offset_t    start,
7658 	vm_map_offset_t    end,
7659 	vm_prot_t  new_prot,
7660 	boolean_t  set_max,
7661 	kc_kind_t  kc_type)
7662 {
7663 #pragma unused(kext_mh,map,kc_type)
7664 	assert(map == kernel_map);         // we can handle KEXTs arising from the PRELINK segment and no others
7665 	assert(start <= end);
7666 	if (start >= end) {
7667 		return KERN_SUCCESS;         // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
7668 	} else if (set_max) {
7669 		return KERN_SUCCESS;         // Punt set_max, as there's no mechanism to record that state
7670 	} else {
7671 		return ml_static_protect(start, end - start, new_prot);
7672 	}
7673 }
7674 
7675 static inline kern_return_t
7676 OSKext_wire(
7677 	kernel_mach_header_t *kext_mh,
7678 	vm_map_t   map,
7679 	vm_map_offset_t    start,
7680 	vm_map_offset_t    end,
7681 	vm_prot_t  access_type,
7682 	boolean_t       user_wire,
7683 	kc_kind_t       kc_type)
7684 {
7685 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type)
7686 	return KERN_SUCCESS;         // No-op as PRELINK kexts are cemented into physical memory at boot
7687 }
7688 #else
7689 #error Unrecognized architecture
7690 #endif
7691 #else
7692 static inline kern_return_t
7693 OSKext_protect(
7694 	kernel_mach_header_t *kext_mh,
7695 	vm_map_t   map,
7696 	vm_map_offset_t    start,
7697 	vm_map_offset_t    end,
7698 	vm_prot_t  new_prot,
7699 	boolean_t  set_max,
7700 	kc_kind_t  kc_type)
7701 {
7702 	if (start == end) {         // 10538581
7703 		return KERN_SUCCESS;
7704 	}
7705 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7706 		/*
7707 		 * XXX: This will probably need to be different for AuxKC and
7708 		 * pageableKC!
7709 		 */
7710 		return ml_static_protect(start, end - start, new_prot);
7711 	}
7712 	return vm_map_protect(map, start, end, new_prot, set_max);
7713 }
7714 
7715 static inline kern_return_t
7716 OSKext_wire(
7717 	kernel_mach_header_t *kext_mh,
7718 	vm_map_t   map,
7719 	vm_map_offset_t    start,
7720 	vm_map_offset_t    end,
7721 	vm_prot_t  access_type,
7722 	boolean_t       user_wire,
7723 	kc_kind_t       kc_type)
7724 {
7725 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7726 		/* TODO: we may need to hook this for the pageableKC */
7727 		return KERN_SUCCESS;
7728 	}
7729 	return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
7730 }
7731 #endif
7732 
7733 OSReturn
7734 OSKext::setVMAttributes(bool protect, bool wire)
7735 {
7736 	vm_map_t                    kext_map        = NULL;
7737 	kernel_segment_command_t  * seg             = NULL;
7738 	vm_map_offset_t             start_protect   = 0;
7739 	vm_map_offset_t             start_wire      = 0;
7740 	vm_map_offset_t             end_protect     = 0;
7741 	vm_map_offset_t             end_wire        = 0;
7742 	OSReturn                    result          = kOSReturnError;
7743 
7744 	if (isInterface() || !declaresExecutable() || flags.builtin) {
7745 		result = kOSReturnSuccess;
7746 		goto finish;
7747 	}
7748 
7749 	/* Get the kext's vm map */
7750 	kext_map = kext_get_vm_map(kmod_info);
7751 	if (!kext_map) {
7752 		result = KERN_MEMORY_ERROR;
7753 		goto finish;
7754 	}
7755 
7756 #if !VM_MAPPED_KEXTS
7757 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
7758 		/* This is a split kext in a prelinked kernelcache; we'll let the
7759 		 * platform code take care of protecting it.  It is already wired.
7760 		 */
7761 		/* TODO: Should this still allow protections for the first segment
7762 		 * to go through, in the event that we have a mix of split and
7763 		 * unsplit kexts?
7764 		 */
7765 		result = KERN_SUCCESS;
7766 		goto finish;
7767 	}
7768 
7769 	if (isInFileset() && kc_type != KCKindPageable) {
7770 		// kexts in filesets have protections setup as part of collection loading
7771 		result = KERN_SUCCESS;
7772 		goto finish;
7773 	}
7774 #endif
7775 
7776 	/* Protect the headers as read-only; they do not need to be wired */
7777 	result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7778 	    kext_map, kmod_info->address,
7779 	    kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type)
7780 	    : KERN_SUCCESS;
7781 	if (result != KERN_SUCCESS) {
7782 		goto finish;
7783 	}
7784 
7785 	/* Set the VM protections and wire down each of the segments */
7786 	seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7787 	while (seg) {
7788 #if __arm__
7789 		/* We build all ARM kexts, so we can ensure they are aligned */
7790 		assert((seg->vmaddr & PAGE_MASK) == 0);
7791 		assert((seg->vmsize & PAGE_MASK) == 0);
7792 #endif
7793 
7794 		/*
7795 		 * For the non page aligned segments, the range calculation for protection
7796 		 * and wiring differ as follows:
7797 		 *
7798 		 * Protection: The non page aligned data at the start or at the end of the
7799 		 * segment is excluded from the protection. This exclusion is needed to make
7800 		 * sure OSKext_protect is not called twice on same page, if the page is shared
7801 		 * between two segments.
7802 		 *
7803 		 * Wiring: The non page aligned data at the start or at the end of the
7804 		 * segment is included in the wiring range, this inclusion is needed to make sure
7805 		 * all the data of the segment is wired.
7806 		 */
7807 		start_protect = round_page(seg->vmaddr);
7808 		end_protect = trunc_page(seg->vmaddr + seg->vmsize);
7809 
7810 		start_wire = trunc_page(seg->vmaddr);
7811 		end_wire = round_page(seg->vmaddr + seg->vmsize);
7812 
7813 		/*
7814 		 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared
7815 		 * across kexts and data from kexts is not page aligned
7816 		 */
7817 		if (protect && (end_protect > start_protect) &&
7818 		    ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 &&
7819 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) ||
7820 		    (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) {
7821 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7822 			    kext_map, start_protect, end_protect, seg->maxprot, TRUE, kc_type);
7823 			if (result != KERN_SUCCESS) {
7824 				OSKextLog(this,
7825 				    kOSKextLogErrorLevel |
7826 				    kOSKextLogLoadFlag,
7827 				    "Kext %s failed to set maximum VM protections "
7828 				    "for segment %s - 0x%x.",
7829 				    getIdentifierCString(), seg->segname, (int)result);
7830 				goto finish;
7831 			}
7832 
7833 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
7834 			    kext_map, start_protect, end_protect, seg->initprot, FALSE, kc_type);
7835 			if (result != KERN_SUCCESS) {
7836 				OSKextLog(this,
7837 				    kOSKextLogErrorLevel |
7838 				    kOSKextLogLoadFlag,
7839 				    "Kext %s failed to set initial VM protections "
7840 				    "for segment %s - 0x%x.",
7841 				    getIdentifierCString(), seg->segname, (int)result);
7842 				goto finish;
7843 			}
7844 		}
7845 
7846 		if (segmentShouldBeWired(seg) && wire) {
7847 			result = OSKext_wire((kernel_mach_header_t *)kmod_info->address,
7848 			    kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type);
7849 			if (result != KERN_SUCCESS) {
7850 				goto finish;
7851 			}
7852 		}
7853 
7854 		seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
7855 	}
7856 
7857 finish:
7858 	return result;
7859 }
7860 
7861 /*********************************************************************
7862 *********************************************************************/
7863 boolean_t
7864 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
7865 {
7866 	return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) &&
7867 	       strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)));
7868 }
7869 
7870 /*********************************************************************
7871 *********************************************************************/
7872 OSReturn
7873 OSKext::validateKextMapping(bool startFlag)
7874 {
7875 	OSReturn                              result      = kOSReturnError;
7876 	const char                          * whichOp = startFlag ? "start" : "stop";
7877 	kern_return_t                         kern_result = 0;
7878 	vm_map_t                              kext_map    = NULL;
7879 	kernel_segment_command_t            * seg         = NULL;
7880 	mach_vm_address_t                     address     = 0;
7881 	mach_vm_size_t                        size        = 0;
7882 	uint32_t                              depth       = 0;
7883 	uint64_t                              kext_segbase = 0;
7884 	uint64_t                              kext_segsize = 0;
7885 	mach_msg_type_number_t                count;
7886 	vm_region_submap_short_info_data_64_t info;
7887 	uintptr_t                             kext_slide = PE_get_kc_slide(kc_type);
7888 
7889 	if (flags.builtin) {
7890 		return kOSReturnSuccess;
7891 	}
7892 
7893 	count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
7894 	bzero(&info, sizeof(info));
7895 
7896 	// xxx - do we need a distinct OSReturn value for these or is "bad data"
7897 	// xxx - sufficient?
7898 
7899 	/* Verify that the kmod_info and start/stop pointers are non-NULL.
7900 	 */
7901 	if (!kmod_info) {
7902 		OSKextLog(this,
7903 		    kOSKextLogErrorLevel |
7904 		    kOSKextLogLoadFlag,
7905 		    "Kext %s - NULL kmod_info pointer.",
7906 		    getIdentifierCString());
7907 		result = kOSKextReturnBadData;
7908 		goto finish;
7909 	}
7910 
7911 	if (startFlag) {
7912 		address = (mach_vm_address_t)kmod_info->start;
7913 	} else {
7914 		address = (mach_vm_address_t)kmod_info->stop;
7915 	}
7916 
7917 	if (!address) {
7918 		OSKextLog(this,
7919 		    kOSKextLogErrorLevel |
7920 		    kOSKextLogLoadFlag,
7921 		    "Kext %s - NULL module %s pointer.",
7922 		    getIdentifierCString(), whichOp);
7923 		result = kOSKextReturnBadData;
7924 		goto finish;
7925 	}
7926 
7927 	kext_map = kext_get_vm_map(kmod_info);
7928 	depth = (kernel_map == kext_map) ? 1 : 2;
7929 	if (isInFileset()) {
7930 #if defined(HAS_APPLE_PAC)
7931 		address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0);
7932 #endif /* defined(HAS_APPLE_PAC) */
7933 	}
7934 
7935 	/* Verify that the start/stop function lies within the kext's address range.
7936 	 */
7937 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) ||
7938 	    isInFileset()) {
7939 		/* This will likely be how we deal with split kexts; walk the segments to
7940 		 * check that the function lies inside one of the segments of this kext.
7941 		 */
7942 		for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
7943 		    seg != NULL;
7944 		    seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
7945 			if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
7946 				kext_segbase = seg->vmaddr;
7947 				kext_segsize = seg->vmsize;
7948 				break;
7949 			}
7950 		}
7951 
7952 		if (!seg) {
7953 			OSKextLog(this,
7954 			    kOSKextLogErrorLevel |
7955 			    kOSKextLogLoadFlag,
7956 			    "Kext %s module %s pointer is outside of kext range "
7957 			    "(%s %p - kext starts at %p).",
7958 			    getIdentifierCString(),
7959 			    whichOp,
7960 			    whichOp,
7961 			    (void *)(((uintptr_t)address) - kext_slide),
7962 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide));
7963 			result = kOSKextReturnBadData;
7964 			goto finish;
7965 		}
7966 
7967 		seg = NULL;
7968 	} else {
7969 		if (address < kmod_info->address + kmod_info->hdr_size ||
7970 		    kmod_info->address + kmod_info->size <= address) {
7971 			OSKextLog(this,
7972 			    kOSKextLogErrorLevel |
7973 			    kOSKextLogLoadFlag,
7974 			    "Kext %s module %s pointer is outside of kext range "
7975 			    "(%s %p - kext at %p-%p).",
7976 			    getIdentifierCString(),
7977 			    whichOp,
7978 			    whichOp,
7979 			    (void *)(((uintptr_t)address) - kext_slide),
7980 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide),
7981 			    (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size));
7982 			result = kOSKextReturnBadData;
7983 			goto finish;
7984 		}
7985 	}
7986 
7987 	/* Only do these checks before calling the start function;
7988 	 * If anything goes wrong with the mapping while the kext is running,
7989 	 * we'll likely have panicked well before any attempt to stop the kext.
7990 	 */
7991 	if (startFlag) {
7992 		if (!isInFileset() || kc_type != KCKindPrimary) {
7993 			/*
7994 			 * Verify that the start/stop function is executable.
7995 			 */
7996 			kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
7997 			    (vm_region_recurse_info_t)&info, &count);
7998 			if (kern_result != KERN_SUCCESS) {
7999 				OSKextLog(this,
8000 				    kOSKextLogErrorLevel |
8001 				    kOSKextLogLoadFlag,
8002 				    "Kext %s - bad %s pointer %p.",
8003 				    getIdentifierCString(),
8004 				    whichOp, (void *)ml_static_unslide(address));
8005 				result = kOSKextReturnBadData;
8006 				goto finish;
8007 			}
8008 		} else {
8009 			/*
8010 			 * Since kexts loaded from the primary KC are held in memory
8011 			 * allocated by efiboot, we cannot use mach_vm_region_recurse() to
8012 			 * discover that memory's protection flags.  Instead, we need to
8013 			 * get that information from the kernel pmap itself.  Above, we
8014 			 * (potentially) saved the size of the segment in which the address
8015 			 * in question was located.  If we have a non-zero size, verify
8016 			 * that all pages in the (address, address + kext_segsize) range
8017 			 * are marked executable.  If we somehow did not record the size
8018 			 * (or the base) just verify the single page that includes the address.
8019 			 */
8020 			if (kext_segbase == 0 || kext_segsize == 0) {
8021 				kext_segbase = address & ~(uint64_t)PAGE_MASK;
8022 				kext_segsize = PAGE_SIZE;
8023 			}
8024 		}
8025 
8026 #if VM_MAPPED_KEXTS
8027 		if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) ||
8028 		    ((isInFileset() && kc_type == KCKindPrimary) &&
8029 		    ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) {
8030 			OSKextLog(this,
8031 			    kOSKextLogErrorLevel |
8032 			    kOSKextLogLoadFlag,
8033 			    "Kext %s - memory region containing module %s function "
8034 			    "is not executable.",
8035 			    getIdentifierCString(), whichOp);
8036 			result = kOSKextReturnBadData;
8037 			goto finish;
8038 		}
8039 #endif
8040 
8041 		/* Verify that the kext's segments are backed by physical memory.
8042 		 */
8043 		seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8044 		while (seg) {
8045 			if (!verifySegmentMapping(seg)) {
8046 				result = kOSKextReturnBadData;
8047 				goto finish;
8048 			}
8049 
8050 			seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8051 		}
8052 	}
8053 
8054 	result = kOSReturnSuccess;
8055 finish:
8056 	return result;
8057 }
8058 
8059 /*********************************************************************
8060 *********************************************************************/
8061 boolean_t
8062 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
8063 {
8064 	mach_vm_address_t address = 0;
8065 
8066 	if (seg->vmsize > UINT32_MAX) {
8067 		return false;
8068 	}
8069 
8070 	if (!segmentShouldBeWired(seg)) {
8071 		return true;
8072 	}
8073 
8074 	for (address = seg->vmaddr;
8075 	    address < round_page(seg->vmaddr + seg->vmsize);
8076 	    address += PAGE_SIZE) {
8077 		if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
8078 			OSKextLog(this,
8079 			    kOSKextLogErrorLevel |
8080 			    kOSKextLogLoadFlag,
8081 			    "Kext %s - page %p is not backed by physical memory.",
8082 			    getIdentifierCString(),
8083 			    (void *)address);
8084 			return false;
8085 		}
8086 	}
8087 
8088 	return true;
8089 }
8090 
8091 /*********************************************************************
8092 *********************************************************************/
8093 static void
8094 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
8095 {
8096 	uint64_t                            stamp = 0;
8097 	firehose_tracepoint_id_u            trace_id;
8098 	struct firehose_trace_uuid_info_s   uuid_info_s;
8099 	firehose_trace_uuid_info_t          uuid_info = &uuid_info_s;
8100 	size_t                              uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
8101 	OSSharedPtr<OSData>                 uuid_data;
8102 
8103 	stamp = firehose_tracepoint_time(firehose_activity_flags_default);
8104 	trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
8105 
8106 	uuid_data = aKext->copyTextUUID();
8107 	if (uuid_data) {
8108 		memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
8109 	}
8110 
8111 	uuid_info->ftui_size    = size;
8112 	if (aKext->isDriverKit()) {
8113 		uuid_info->ftui_address = address;
8114 	} else {
8115 		uuid_info->ftui_address = ml_static_unslide(address);
8116 	}
8117 	firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len);
8118 	return;
8119 }
8120 
8121 void
8122 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext)
8123 {
8124 	OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load);
8125 }
8126 
8127 /*********************************************************************
8128 *********************************************************************/
8129 OSReturn
8130 OSKext::start(bool startDependenciesFlag)
8131 {
8132 	OSReturn                            result = kOSReturnError;
8133 	kern_return_t                       (* startfunc)(kmod_info_t *, void *);
8134 	unsigned int                        i, count;
8135 	void                              * kmodStartData = NULL;
8136 
8137 	if (isStarted() || isInterface() || isKernelComponent()) {
8138 		result = kOSReturnSuccess;
8139 		goto finish;
8140 	}
8141 
8142 	if (!isLoaded()) {
8143 		OSKextLog(this,
8144 		    kOSKextLogErrorLevel |
8145 		    kOSKextLogLoadFlag,
8146 		    "Attempt to start nonloaded kext %s.",
8147 		    getIdentifierCString());
8148 		result = kOSKextReturnInvalidArgument;
8149 		goto finish;
8150 	}
8151 
8152 	if (!sLoadEnabled) {
8153 		OSKextLog(this,
8154 		    kOSKextLogErrorLevel |
8155 		    kOSKextLogLoadFlag,
8156 		    "Kext loading is disabled (attempt to start kext %s).",
8157 		    getIdentifierCString());
8158 		result = kOSKextReturnDisabled;
8159 		goto finish;
8160 	}
8161 
8162 	result = validateKextMapping(/* start? */ true);
8163 	if (result != kOSReturnSuccess) {
8164 		goto finish;
8165 	}
8166 
8167 	startfunc = kmod_info->start;
8168 
8169 	count = getNumDependencies();
8170 	for (i = 0; i < count; i++) {
8171 		OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
8172 		if (dependency == NULL) {
8173 			OSKextLog(this,
8174 			    kOSKextLogErrorLevel |
8175 			    kOSKextLogLoadFlag,
8176 			    "Kext %s start - internal error, dependency disappeared.",
8177 			    getIdentifierCString());
8178 			goto finish;
8179 		}
8180 		if (!dependency->isStarted()) {
8181 			if (startDependenciesFlag) {
8182 				OSReturn dependencyResult =
8183 				    dependency->start(startDependenciesFlag);
8184 				if (dependencyResult != KERN_SUCCESS) {
8185 					OSKextLog(this,
8186 					    kOSKextLogErrorLevel |
8187 					    kOSKextLogLoadFlag,
8188 					    "Kext %s start - dependency %s failed to start (error 0x%x).",
8189 					    getIdentifierCString(),
8190 					    dependency->getIdentifierCString(),
8191 					    dependencyResult);
8192 					goto finish;
8193 				}
8194 			} else {
8195 				OSKextLog(this,
8196 				    kOSKextLogErrorLevel |
8197 				    kOSKextLogLoadFlag,
8198 				    "Not starting %s - dependency %s not started yet.",
8199 				    getIdentifierCString(),
8200 				    dependency->getIdentifierCString());
8201 				result = kOSKextReturnStartStopError;         // xxx - make new return?
8202 				goto finish;
8203 			}
8204 		}
8205 	}
8206 
8207 	OSKextLog(this,
8208 	    kOSKextLogDetailLevel |
8209 	    kOSKextLogLoadFlag,
8210 	    "Kext %s calling module start function.",
8211 	    getIdentifierCString());
8212 
8213 	flags.starting = 1;
8214 
8215 	// Drop a log message so logd can grab the needed information to decode this kext
8216 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
8217 	result = OSRuntimeInitializeCPP(this);
8218 	if (result == KERN_SUCCESS) {
8219 		result = startfunc(kmod_info, kmodStartData);
8220 	}
8221 
8222 	flags.starting = 0;
8223 
8224 	/* On success overlap the setting of started/starting. On failure just
8225 	 * clear starting.
8226 	 */
8227 	if (result == KERN_SUCCESS) {
8228 		flags.started = 1;
8229 
8230 		// xxx - log start error from kernel?
8231 		OSKextLog(this,
8232 		    kOSKextLogProgressLevel |
8233 		    kOSKextLogLoadFlag,
8234 		    "Kext %s is now started.",
8235 		    getIdentifierCString());
8236 	} else {
8237 		invokeOrCancelRequestCallbacks(
8238 			/* result not actually used */ kOSKextReturnStartStopError,
8239 			/* invokeFlag */ false);
8240 		OSKextLog(this,
8241 		    kOSKextLogWarningLevel |
8242 		    kOSKextLogLoadFlag,
8243 		    "Kext %s did not start (return code 0x%x).",
8244 		    getIdentifierCString(), result);
8245 	}
8246 
8247 finish:
8248 	return result;
8249 }
8250 
8251 /*********************************************************************
8252 *********************************************************************/
8253 /* static */
8254 bool
8255 OSKext::canUnloadKextWithIdentifier(
8256 	OSString * kextIdentifier,
8257 	bool       checkClassesFlag)
8258 {
8259 	bool     result = false;
8260 	OSKext * aKext  = NULL;        // do not release
8261 
8262 	IORecursiveLockLock(sKextLock);
8263 
8264 	aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
8265 
8266 	if (!aKext) {
8267 		goto finish;         // can't unload what's not loaded
8268 	}
8269 
8270 	if (aKext->isLoaded()) {
8271 		if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
8272 			goto finish;
8273 		}
8274 		if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
8275 			goto finish;
8276 		}
8277 	}
8278 
8279 	result = true;
8280 
8281 finish:
8282 	IORecursiveLockUnlock(sKextLock);
8283 	return result;
8284 }
8285 
8286 /*********************************************************************
8287 *********************************************************************/
8288 OSReturn
8289 OSKext::stop(void)
8290 {
8291 	OSReturn result = kOSReturnError;
8292 	kern_return_t (*stopfunc)(kmod_info_t *, void *);
8293 
8294 	if (!isStarted() || isInterface()) {
8295 		result = kOSReturnSuccess;
8296 		goto finish;
8297 	}
8298 
8299 	if (!isLoaded()) {
8300 		OSKextLog(this,
8301 		    kOSKextLogErrorLevel |
8302 		    kOSKextLogLoadFlag,
8303 		    "Attempt to stop nonloaded kext %s.",
8304 		    getIdentifierCString());
8305 		result = kOSKextReturnInvalidArgument;
8306 		goto finish;
8307 	}
8308 
8309 	/* Refuse to stop if we have clients or instances. It is up to
8310 	 * the caller to make sure those aren't true.
8311 	 */
8312 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8313 		OSKextLog(this,
8314 		    kOSKextLogErrorLevel |
8315 		    kOSKextLogLoadFlag,
8316 		    "Kext %s - C++ instances; can't stop.",
8317 		    getIdentifierCString());
8318 		result = kOSKextReturnInUse;
8319 		goto finish;
8320 	}
8321 
8322 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8323 		OSKextLog(this,
8324 		    kOSKextLogErrorLevel |
8325 		    kOSKextLogLoadFlag,
8326 		    "Kext %s - has references (linkage or tracking object); "
8327 		    "can't stop.",
8328 		    getIdentifierCString());
8329 		result = kOSKextReturnInUse;
8330 		goto finish;
8331 	}
8332 
8333 	/* Note: If validateKextMapping fails on the stop & unload path,
8334 	 * we are in serious trouble and a kernel panic is likely whether
8335 	 * we stop & unload the kext or not.
8336 	 */
8337 	result = validateKextMapping(/* start? */ false);
8338 	if (result != kOSReturnSuccess) {
8339 		goto finish;
8340 	}
8341 
8342 	stopfunc = kmod_info->stop;
8343 	if (stopfunc) {
8344 		OSKextLog(this,
8345 		    kOSKextLogDetailLevel |
8346 		    kOSKextLogLoadFlag,
8347 		    "Kext %s calling module stop function.",
8348 		    getIdentifierCString());
8349 
8350 		flags.stopping = 1;
8351 
8352 		result = stopfunc(kmod_info, /* userData */ NULL);
8353 		if (result == KERN_SUCCESS) {
8354 			result = OSRuntimeFinalizeCPP(this);
8355 		}
8356 
8357 		flags.stopping = 0;
8358 
8359 		if (result == KERN_SUCCESS) {
8360 			flags.started = 0;
8361 
8362 			OSKextLog(this,
8363 			    kOSKextLogDetailLevel |
8364 			    kOSKextLogLoadFlag,
8365 			    "Kext %s is now stopped and ready to unload.",
8366 			    getIdentifierCString());
8367 		} else {
8368 			OSKextLog(this,
8369 			    kOSKextLogErrorLevel |
8370 			    kOSKextLogLoadFlag,
8371 			    "Kext %s did not stop (return code 0x%x).",
8372 			    getIdentifierCString(), result);
8373 			result = kOSKextReturnStartStopError;
8374 		}
8375 	}
8376 
8377 finish:
8378 	// Drop a log message so logd can update this kext's metadata
8379 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
8380 	return result;
8381 }
8382 
8383 /*********************************************************************
8384 *********************************************************************/
8385 OSReturn
8386 OSKext::unload(void)
8387 {
8388 	OSReturn        result = kOSReturnError;
8389 	unsigned int    index;
8390 	uint32_t        num_kmod_refs = 0;
8391 	OSKextAccount * freeAccount;
8392 	bool            in_fileset = false;
8393 
8394 	if (!sUnloadEnabled) {
8395 		OSKextLog(this,
8396 		    kOSKextLogErrorLevel |
8397 		    kOSKextLogLoadFlag,
8398 		    "Kext unloading is disabled (%s).",
8399 		    this->getIdentifierCString());
8400 
8401 		result = kOSKextReturnDisabled;
8402 		goto finish;
8403 	}
8404 
8405 	// cache this result so we don't need to access the kmod_info after
8406 	// it's been potentially free'd
8407 	in_fileset = isInFileset();
8408 
8409 	/* Refuse to unload if we have clients or instances. It is up to
8410 	 * the caller to make sure those aren't true.
8411 	 */
8412 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8413 		// xxx - Don't log under errors? this is more of an info thing
8414 		OSKextLog(this,
8415 		    kOSKextLogErrorLevel |
8416 		    kOSKextLogKextBookkeepingFlag,
8417 		    "Can't unload kext %s; outstanding references %d (linkage or tracking object).",
8418 		    getIdentifierCString(), getRetainCount());
8419 		result = kOSKextReturnInUse;
8420 		goto finish;
8421 	}
8422 
8423 	if (isDriverKit()) {
8424 		index = sLoadedDriverKitKexts->getNextIndexOfObject(this, 0);
8425 		if (index != (unsigned int)-1) {
8426 			sLoadedDriverKitKexts->removeObject(index);
8427 			OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
8428 			loadTag = 0;
8429 		}
8430 	}
8431 
8432 	if (!isLoaded()) {
8433 		result = kOSReturnSuccess;
8434 		goto finish;
8435 	}
8436 
8437 	if (isKernelComponent()) {
8438 		result = kOSKextReturnInvalidArgument;
8439 		goto finish;
8440 	}
8441 
8442 	if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) {
8443 		OSKextLog(this,
8444 		    kOSKextLogErrorLevel |
8445 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8446 		    "Can't unload kext %s; classes have instances:",
8447 		    getIdentifierCString());
8448 		reportOSMetaClassInstances(kOSKextLogErrorLevel |
8449 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
8450 		result = kOSKextReturnInUse;
8451 		goto finish;
8452 	}
8453 
8454 	/* Note that the kext is unloading before running any code that
8455 	 * might be in the kext (request callbacks, module stop function).
8456 	 * We will deny certain requests made against a kext in the process
8457 	 * of unloading.
8458 	 */
8459 	flags.unloading = 1;
8460 
8461 	/* Update the string describing the last kext to unload in case we panic.
8462 	 */
8463 	savePanicString(/* isLoading */ false);
8464 
8465 	if (isStarted()) {
8466 		result = stop();
8467 		if (result != KERN_SUCCESS) {
8468 			OSKextLog(this,
8469 			    kOSKextLogErrorLevel |
8470 			    kOSKextLogLoadFlag,
8471 			    "Kext %s can't unload - module stop returned 0x%x.",
8472 			    getIdentifierCString(), (unsigned)result);
8473 			result = kOSKextReturnStartStopError;
8474 			goto finish;
8475 		}
8476 	}
8477 
8478 	OSKextLog(this,
8479 	    kOSKextLogProgressLevel |
8480 	    kOSKextLogLoadFlag,
8481 	    "Kext %s unloading.",
8482 	    getIdentifierCString());
8483 
8484 	{
8485 		struct list_head *p;
8486 		struct list_head *prev;
8487 		struct list_head *next;
8488 		for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
8489 			OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
8490 			s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
8491 			prev = p->prev;
8492 			next = p->next;
8493 			prev->next = next;
8494 			next->prev = prev;
8495 			p->prev = p;
8496 			p->next = p;
8497 			IORecursiveLockWakeup(sKextLock, s, false);
8498 		}
8499 	}
8500 
8501 
8502 	/* Even if we don't call the stop function, we want to be sure we
8503 	 * have no OSMetaClass references before unloading the kext executable
8504 	 * from memory. OSMetaClasses may have pointers into the kext executable
8505 	 * and that would cause a panic on OSKext::free() when metaClasses is freed.
8506 	 */
8507 	if (metaClasses) {
8508 		metaClasses->flushCollection();
8509 	}
8510 	(void) OSRuntimeFinalizeCPP(this);
8511 
8512 	/* Remove the kext from the list of loaded kexts, patch the gap
8513 	 * in the kmod_info_t linked list, and reset "kmod" to point to the
8514 	 * last loaded kext that isn't the fake kernel kext (sKernelKext).
8515 	 */
8516 	index = sLoadedKexts->getNextIndexOfObject(this, 0);
8517 	if (index != (unsigned int)-1) {
8518 		sLoadedKexts->removeObject(index);
8519 
8520 		OSKext * nextKext = OSDynamicCast(OSKext,
8521 		    sLoadedKexts->getObject(index));
8522 
8523 		if (nextKext) {
8524 			if (index > 0) {
8525 				OSKext * gapKext = OSDynamicCast(OSKext,
8526 				    sLoadedKexts->getObject(index - 1));
8527 
8528 				nextKext->kmod_info->next = gapKext->kmod_info;
8529 			} else {         /* index == 0 */
8530 				nextKext->kmod_info->next = NULL;
8531 			}
8532 		}
8533 
8534 		OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
8535 		if (lastKext && !lastKext->isKernel()) {
8536 			kmod = lastKext->kmod_info;
8537 		} else {
8538 			kmod = NULL;         // clear the global kmod variable
8539 		}
8540 	}
8541 
8542 	/* Clear out the kmod references that we're keeping for compatibility
8543 	 * with current panic backtrace code & kgmacros.
8544 	 * xxx - will want to update those bits sometime and remove this.
8545 	 */
8546 	num_kmod_refs = getNumDependencies();
8547 	if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
8548 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
8549 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
8550 			ref->info->reference_count--;
8551 		}
8552 		kfree_type(kmod_reference_t, num_kmod_refs,
8553 		    kmod_info->reference_list);
8554 	}
8555 
8556 #if CONFIG_DTRACE
8557 	unregisterWithDTrace();
8558 #endif /* CONFIG_DTRACE */
8559 
8560 	notifyKextUnloadObservers(this);
8561 
8562 	freeAccount = NULL;
8563 	lck_ticket_lock(sKextAccountsLock, LCK_GRP_NULL);
8564 	account->kext = NULL;
8565 	if (account->site.tag) {
8566 		account->site.flags |= VM_TAG_UNLOAD;
8567 	} else {
8568 		freeAccount = account;
8569 	}
8570 
8571 #if DEVELOPMENT || DEBUG
8572 	assertf(account->task_refgrp.grp_count == 0,
8573 	    "unloading a kext with active task references");
8574 #endif /* DEVELOPMENT || DEBUG */
8575 
8576 	lck_ticket_unlock(sKextAccountsLock);
8577 	if (freeAccount) {
8578 		IOFreeType(freeAccount, OSKextAccount);
8579 	}
8580 
8581 	/* Unwire and free the linked executable.
8582 	 */
8583 	if (linkedExecutable) {
8584 #if KASAN
8585 		kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
8586 #endif
8587 
8588 #if VM_MAPPED_KEXTS
8589 		if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) {
8590 			kernel_segment_command_t *seg = NULL;
8591 			vm_map_t kext_map = kext_get_vm_map(kmod_info);
8592 
8593 			if (!kext_map) {
8594 				OSKextLog(this,
8595 				    kOSKextLogErrorLevel |
8596 				    kOSKextLogLoadFlag,
8597 				    "Failed to free kext %s; couldn't find the kext map.",
8598 				    getIdentifierCString());
8599 				result = kOSKextReturnInternalError;
8600 				goto finish;
8601 			}
8602 
8603 			OSKextLog(this,
8604 			    kOSKextLogProgressLevel |
8605 			    kOSKextLogLoadFlag,
8606 			    "Kext %s unwiring and unmapping linked executable.",
8607 			    getIdentifierCString());
8608 
8609 			seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8610 			while (seg) {
8611 				if (segmentShouldBeWired(seg)) {
8612 					vm_map_offset_t start_wire = trunc_page(seg->vmaddr);
8613 					vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize);
8614 
8615 					result = vm_map_unwire(kext_map, start_wire,
8616 					    end_wire, FALSE);
8617 					if (result != KERN_SUCCESS) {
8618 						OSKextLog(this,
8619 						    kOSKextLogErrorLevel |
8620 						    kOSKextLogLoadFlag,
8621 						    "Failed to unwire kext %s.",
8622 						    getIdentifierCString());
8623 						result = kOSKextReturnInternalError;
8624 						goto finish;
8625 					}
8626 				}
8627 
8628 				seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8629 			}
8630 #if defined(__x86_64__) || defined(__i386__)
8631 			if (in_fileset && flags.resetSegmentsFromVnode) {
8632 				IORecursiveLockLock(sKextLock);
8633 				resetKCFileSetSegments();
8634 				IORecursiveLockUnlock(sKextLock);
8635 			}
8636 #endif // (__x86_64__) || defined(__i386__)
8637 		}
8638 #endif /* VM_MAPPED_KEXTS */
8639 		if (flags.resetSegmentsFromImmutableCopy) {
8640 			result = resetMutableSegments();
8641 			if (result != kOSReturnSuccess) {
8642 				OSKextLog(this,
8643 				    kOSKextLogErrorLevel |
8644 				    kOSKextLogLoadFlag,
8645 				    "Failed to reset kext %s.",
8646 				    getIdentifierCString());
8647 				result = kOSKextReturnInternalError;
8648 				goto finish;
8649 			}
8650 		}
8651 		if (kc_type == KCKindUnknown) {
8652 			linkedExecutable.reset();
8653 		}
8654 	}
8655 
8656 	/* An interface kext has a fake kmod_info that was allocated,
8657 	 * so we have to free it.
8658 	 */
8659 	if (isInterface()) {
8660 		kfree_type(kmod_info_t, kmod_info);
8661 		kmod_info = NULL;
8662 	}
8663 
8664 	if (!in_fileset) {
8665 		kmod_info = NULL;
8666 	}
8667 
8668 	flags.loaded = false;
8669 	flushDependencies();
8670 
8671 	/* save a copy of the bundle ID for us to check when deciding to
8672 	 * rebuild the kernel cache file.  If a kext was already in the kernel
8673 	 * cache and unloaded then later loaded we do not need to rebuild the
8674 	 * kernel cache.  9055303
8675 	 */
8676 	if (isPrelinked()) {
8677 		if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) {
8678 			IORecursiveLockLock(sKextLock);
8679 			if (sUnloadedPrelinkedKexts) {
8680 				sUnloadedPrelinkedKexts->setObject(bundleID.get());
8681 			}
8682 			IORecursiveLockUnlock(sKextLock);
8683 		}
8684 	}
8685 
8686 	OSKextLog(this,
8687 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8688 	    "Kext %s unloaded.", getIdentifierCString());
8689 
8690 	queueKextNotification(kKextRequestPredicateUnloadNotification,
8691 	    OSDynamicCast(OSString, bundleID.get()));
8692 
8693 finish:
8694 	OSKext::saveLoadedKextPanicList();
8695 	OSKext::updateLoadedKextSummaries();
8696 
8697 	flags.unloading = 0;
8698 	return result;
8699 }
8700 
8701 /*********************************************************************
8702 * Assumes sKextLock is held.
8703 *********************************************************************/
8704 /* static */
8705 OSReturn
8706 OSKext::queueKextNotification(
8707 	const char * notificationName,
8708 	OSString   * kextIdentifier)
8709 {
8710 	OSReturn          result               = kOSReturnError;
8711 	OSSharedPtr<OSDictionary>    loadRequest;
8712 
8713 	if (!kextIdentifier) {
8714 		result = kOSKextReturnInvalidArgument;
8715 		goto finish;
8716 	}
8717 
8718 	/* Create a new request unless one is already sitting
8719 	 * in sKernelRequests for this bundle identifier
8720 	 */
8721 	result = _OSKextCreateRequest(notificationName, loadRequest);
8722 	if (result != kOSReturnSuccess) {
8723 		goto finish;
8724 	}
8725 	if (!_OSKextSetRequestArgument(loadRequest.get(),
8726 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
8727 		result = kOSKextReturnNoMemory;
8728 		goto finish;
8729 	}
8730 	if (!sKernelRequests->setObject(loadRequest.get())) {
8731 		result = kOSKextReturnNoMemory;
8732 		goto finish;
8733 	}
8734 
8735 	/* We might want to only queue the notification if the IOKit daemon is active,
8736 	 * but that wouldn't work for embedded. Note that we don't care if
8737 	 * the ping immediately succeeds here so don't do anything with the
8738 	 * result of this call.
8739 	 */
8740 	OSKext::pingIOKitDaemon();
8741 
8742 	result = kOSReturnSuccess;
8743 
8744 finish:
8745 	return result;
8746 }
8747 
8748 
8749 #if CONFIG_KXLD
8750 /*********************************************************************
8751 *********************************************************************/
8752 static void
8753 _OSKextConsiderDestroyingLinkContext(
8754 	__unused thread_call_param_t p0,
8755 	__unused thread_call_param_t p1)
8756 {
8757 	/* Take multiple locks in the correct order.
8758 	 */
8759 	IORecursiveLockLock(sKextLock);
8760 	IORecursiveLockLock(sKextInnerLock);
8761 
8762 	/* The first time we destroy the kxldContext is in the first
8763 	 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
8764 	 * before calling this function. Thereafter any call to this function
8765 	 * will actually destroy the context.
8766 	 */
8767 	if (sConsiderUnloadsCalled && sKxldContext) {
8768 		kxld_destroy_context(sKxldContext);
8769 		sKxldContext = NULL;
8770 	}
8771 
8772 	/* Free the thread_call that was allocated to execute this function.
8773 	 */
8774 	if (sDestroyLinkContextThread) {
8775 		if (!thread_call_free(sDestroyLinkContextThread)) {
8776 			OSKextLog(/* kext */ NULL,
8777 			    kOSKextLogErrorLevel |
8778 			    kOSKextLogGeneralFlag,
8779 			    "thread_call_free() failed for kext link context.");
8780 		}
8781 		sDestroyLinkContextThread = NULL;
8782 	}
8783 
8784 	IORecursiveLockUnlock(sKextInnerLock);
8785 	IORecursiveLockUnlock(sKextLock);
8786 
8787 	return;
8788 }
8789 
8790 /*********************************************************************
8791 * Destroying the kxldContext requires checking variables under both
8792 * sKextInnerLock and sKextLock, so we do it on a separate thread
8793 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
8794 * call relationship.
8795 *
8796 * This function must be invoked with sKextInnerLock held.
8797 * Do not call any function that takes sKextLock here!
8798 *********************************************************************/
8799 /* static */
8800 void
8801 OSKext::considerDestroyingLinkContext(void)
8802 {
8803 	IORecursiveLockLock(sKextInnerLock);
8804 
8805 	/* If we have already queued a thread to destroy the link context,
8806 	 * don't bother resetting; that thread will take care of it.
8807 	 */
8808 	if (sDestroyLinkContextThread) {
8809 		goto finish;
8810 	}
8811 
8812 	/* The function to be invoked in the thread will deallocate
8813 	 * this thread_call, so don't share it around.
8814 	 */
8815 	sDestroyLinkContextThread = thread_call_allocate(
8816 		&_OSKextConsiderDestroyingLinkContext, NULL);
8817 	if (!sDestroyLinkContextThread) {
8818 		OSKextLog(/* kext */ NULL,
8819 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
8820 		    "Can't create thread to destroy kext link context.");
8821 		goto finish;
8822 	}
8823 
8824 	thread_call_enter(sDestroyLinkContextThread);
8825 
8826 finish:
8827 	IORecursiveLockUnlock(sKextInnerLock);
8828 	return;
8829 }
8830 
8831 #else // !CONFIG_KXLD
8832 
8833 /* static */
8834 void
8835 OSKext::considerDestroyingLinkContext(void)
8836 {
8837 	return;
8838 }
8839 
8840 #endif // CONFIG_KXLD
8841 
8842 #if PRAGMA_MARK
8843 #pragma mark Autounload
8844 #endif
8845 /*********************************************************************
8846 * This is a static method because the kext will be deallocated if it
8847 * does unload!
8848 *********************************************************************/
8849 /* static */
8850 OSReturn
8851 OSKext::autounloadKext(OSKext * aKext)
8852 {
8853 	OSReturn result = kOSKextReturnInUse;
8854 
8855 #if NO_KEXTD
8856 	/*
8857 	 * Do not unload prelinked kexts on platforms that do not have an
8858 	 * IOKit daemon as there is no way to reload the kext or restart
8859 	 * matching.
8860 	 */
8861 	if (aKext->isPrelinked()) {
8862 		goto finish;
8863 	}
8864 #endif /* defined(__x86_64__) */
8865 
8866 	/* Check for external references to this kext (usu. dependents),
8867 	 * instances of defined classes (or classes derived from them),
8868 	 * outstanding requests.
8869 	 */
8870 	if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
8871 	    !aKext->flags.autounloadEnabled ||
8872 	    aKext->isKernelComponent()) {
8873 		goto finish;
8874 	}
8875 
8876 	/* Skip a delay-autounload kext, once.
8877 	 */
8878 	if (aKext->flags.delayAutounload) {
8879 		OSKextLog(aKext,
8880 		    kOSKextLogProgressLevel |
8881 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8882 		    "Kext %s has delayed autounload set; skipping and clearing flag.",
8883 		    aKext->getIdentifierCString());
8884 		aKext->flags.delayAutounload = 0;
8885 		goto finish;
8886 	}
8887 
8888 	if (aKext->hasOSMetaClassInstances() ||
8889 	    aKext->countRequestCallbacks()) {
8890 		goto finish;
8891 	}
8892 
8893 	result = OSKext::removeKext(aKext);
8894 
8895 finish:
8896 	return result;
8897 }
8898 
8899 /*********************************************************************
8900 *********************************************************************/
8901 void
8902 _OSKextConsiderUnloads(
8903 	__unused thread_call_param_t p0,
8904 	__unused thread_call_param_t p1)
8905 {
8906 	bool         didUnload = false;
8907 	unsigned int count, i;
8908 
8909 	/* Take multiple locks in the correct order
8910 	 * (note also sKextSummaries lock further down).
8911 	 */
8912 	IORecursiveLockLock(sKextLock);
8913 	IORecursiveLockLock(sKextInnerLock);
8914 
8915 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
8916 
8917 	/* If the system is powering down, don't try to unload anything.
8918 	 */
8919 	if (sSystemSleep) {
8920 		goto finish;
8921 	}
8922 
8923 	OSKextLog(/* kext */ NULL,
8924 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8925 	    "Checking for unused kexts to autounload.");
8926 
8927 	/*****
8928 	 * Remove any request callbacks marked as stale,
8929 	 * and mark as stale any currently in flight.
8930 	 */
8931 	count = sRequestCallbackRecords->getCount();
8932 	if (count) {
8933 		i = count - 1;
8934 		do {
8935 			OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
8936 			    sRequestCallbackRecords->getObject(i));
8937 			if (callbackRecord) {
8938 				OSBoolean * stale = OSDynamicCast(OSBoolean,
8939 				    callbackRecord->getObject(kKextRequestStaleKey));
8940 
8941 				if (stale == kOSBooleanTrue) {
8942 					OSKext::invokeRequestCallback(callbackRecord,
8943 					    kOSKextReturnTimeout);
8944 				} else {
8945 					callbackRecord->setObject(kKextRequestStaleKey,
8946 					    kOSBooleanTrue);
8947 				}
8948 			}
8949 		} while (i--);
8950 	}
8951 
8952 	/*****
8953 	 * Make multiple passes through the array of loaded kexts until
8954 	 * we don't unload any. This handles unwinding of dependency
8955 	 * chains. We have to go *backwards* through the array because
8956 	 * kexts are removed from it when unloaded, and we cannot make
8957 	 * a copy or we'll mess up the retain counts we rely on to
8958 	 * check whether a kext will unload. If only we could have
8959 	 * nonretaining collections like CF has....
8960 	 */
8961 	do {
8962 		didUnload = false;
8963 
8964 		count = sLoadedKexts->getCount();
8965 		if (count) {
8966 			i = count - 1;
8967 			do {
8968 				OSKext * thisKext = OSDynamicCast(OSKext,
8969 				    sLoadedKexts->getObject(i));
8970 				didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
8971 			} while (i--);
8972 		}
8973 	} while (didUnload);
8974 
8975 finish:
8976 	sConsiderUnloadsPending = false;
8977 	sConsiderUnloadsExecuted = true;
8978 
8979 	(void) OSKext::considerRebuildOfPrelinkedKernel();
8980 
8981 	IORecursiveLockUnlock(sKextInnerLock);
8982 	IORecursiveLockUnlock(sKextLock);
8983 
8984 	return;
8985 }
8986 
8987 /*********************************************************************
8988 * Do not call any function that takes sKextLock here!
8989 *********************************************************************/
8990 void
8991 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
8992 {
8993 	AbsoluteTime when;
8994 
8995 	IORecursiveLockLock(sKextInnerLock);
8996 
8997 	if (!sUnloadCallout) {
8998 		sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL);
8999 	}
9000 
9001 	/* we only reset delay value for unloading if we already have something
9002 	 * pending.  rescheduleOnlyFlag should not start the count down.
9003 	 */
9004 	if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
9005 		goto finish;
9006 	}
9007 
9008 	thread_call_cancel(sUnloadCallout);
9009 	if (OSKext::getAutounloadEnabled() && !sSystemSleep
9010 #if !NO_KEXTD
9011 	    && sIOKitDaemonActive
9012 #endif
9013 	    ) {
9014 		clock_interval_to_deadline(sConsiderUnloadDelay,
9015 		    1000 * 1000 * 1000, &when);
9016 
9017 		OSKextLog(/* kext */ NULL,
9018 		    kOSKextLogProgressLevel |
9019 		    kOSKextLogLoadFlag,
9020 		    "%scheduling %sscan for unused kexts in %lu seconds.",
9021 		    sConsiderUnloadsPending ? "Res" : "S",
9022 		    sConsiderUnloadsCalled ? "" : "initial ",
9023 		    (unsigned long)sConsiderUnloadDelay);
9024 
9025 		sConsiderUnloadsPending = true;
9026 		thread_call_enter_delayed(sUnloadCallout, when);
9027 	}
9028 
9029 finish:
9030 	/* The kxld context should be reused throughout boot.  We mark the end of
9031 	 * period as the first time considerUnloads() is called, and we destroy
9032 	 * the first kxld context in that function.  Afterwards, it will be
9033 	 * destroyed in flushNonloadedKexts.
9034 	 */
9035 	if (!sConsiderUnloadsCalled) {
9036 		sConsiderUnloadsCalled = true;
9037 		OSKext::considerDestroyingLinkContext();
9038 	}
9039 
9040 	IORecursiveLockUnlock(sKextInnerLock);
9041 	return;
9042 }
9043 
9044 /*********************************************************************
9045 * Do not call any function that takes sKextLock here!
9046 *********************************************************************/
9047 extern "C" {
9048 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
9049 IOReturn
9050 OSKextSystemSleepOrWake(UInt32 messageType)
9051 {
9052 	IORecursiveLockLock(sKextInnerLock);
9053 
9054 	/* If the system is going to sleep, cancel the reaper thread timer,
9055 	 * and note that we're in a sleep state in case it just fired but hasn't
9056 	 * taken the lock yet. If we are coming back from sleep, just
9057 	 * clear the sleep flag; IOService's normal operation will cause
9058 	 * unloads to be considered soon enough.
9059 	 */
9060 	if (messageType == kIOMessageSystemWillSleep) {
9061 		if (sUnloadCallout) {
9062 			thread_call_cancel(sUnloadCallout);
9063 		}
9064 		sSystemSleep = true;
9065 		AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
9066 	} else if (messageType == kIOMessageSystemHasPoweredOn) {
9067 		sSystemSleep = false;
9068 		clock_get_uptime(&sLastWakeTime);
9069 	}
9070 	IORecursiveLockUnlock(sKextInnerLock);
9071 
9072 	return kIOReturnSuccess;
9073 }
9074 };
9075 
9076 
9077 #if PRAGMA_MARK
9078 #pragma mark Prelinked Kernel
9079 #endif
9080 
9081 #ifdef CONFIG_KXLD
9082 /*********************************************************************
9083 * Do not access sConsiderUnloads... variables other than
9084 * sConsiderUnloadsExecuted in this function. They are guarded by a
9085 * different lock.
9086 *********************************************************************/
9087 /* static */
9088 void
9089 OSKext::considerRebuildOfPrelinkedKernel(void)
9090 {
9091 	static bool     requestedPrelink        = false;
9092 	OSReturn        checkResult             = kOSReturnError;
9093 	OSSharedPtr<OSDictionary>         prelinkRequest;
9094 	OSSharedPtr<OSCollectionIterator> kextIterator;
9095 	const OSSymbol * thisID                 = NULL;        // do not release
9096 	bool            doRebuild               = false;
9097 	AbsoluteTime    my_abstime;
9098 	UInt64          my_ns;
9099 	SInt32          delta_secs;
9100 
9101 	/* Only one auto rebuild per boot and only on boot from prelinked kernel */
9102 	if (requestedPrelink || !sPrelinkBoot) {
9103 		return;
9104 	}
9105 
9106 	/* no direct return from this point */
9107 	IORecursiveLockLock(sKextLock);
9108 
9109 	/* We need to wait for the IOKit daemon to get up and running with unloads already done
9110 	 * and any new startup kexts loaded.
9111 	 */
9112 	if (!sConsiderUnloadsExecuted ||
9113 	    !sDeferredLoadSucceeded) {
9114 		goto finish;
9115 	}
9116 
9117 	/* we really only care about boot / system start up related kexts so bail
9118 	 * if we're here after REBUILD_MAX_TIME.
9119 	 */
9120 	if (!_OSKextInPrelinkRebuildWindow()) {
9121 		OSKextLog(/* kext */ NULL,
9122 		    kOSKextLogArchiveFlag,
9123 		    "%s prebuild rebuild has expired",
9124 		    __FUNCTION__);
9125 		requestedPrelink = true;
9126 		goto finish;
9127 	}
9128 
9129 	/* we do not want to trigger a rebuild if we get here too close to waking
9130 	 * up.  (see radar 10233768)
9131 	 */
9132 	IORecursiveLockLock(sKextInnerLock);
9133 
9134 	clock_get_uptime(&my_abstime);
9135 	delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
9136 	if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
9137 		SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
9138 		absolutetime_to_nanoseconds(my_abstime, &my_ns);
9139 		delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
9140 	}
9141 	IORecursiveLockUnlock(sKextInnerLock);
9142 
9143 	if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
9144 		/* too close to time of last wake from sleep */
9145 		goto finish;
9146 	}
9147 	requestedPrelink = true;
9148 
9149 	/* Now it's time to see if we have a reason to rebuild.  We may have done
9150 	 * some loads and unloads but the kernel cache didn't actually change.
9151 	 * We will rebuild if any kext is not marked prelinked AND is not in our
9152 	 * list of prelinked kexts that got unloaded.  (see radar 9055303)
9153 	 */
9154 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
9155 	if (!kextIterator) {
9156 		goto finish;
9157 	}
9158 
9159 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
9160 		OSKext *    thisKext;        // do not release
9161 
9162 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
9163 		if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
9164 			continue;
9165 		}
9166 
9167 		if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) {
9168 			continue;
9169 		}
9170 		/* kext is loaded and was not in current kernel cache so let's rebuild
9171 		 */
9172 		doRebuild = true;
9173 		OSKextLog(/* kext */ NULL,
9174 		    kOSKextLogArchiveFlag,
9175 		    "considerRebuildOfPrelinkedKernel %s triggered rebuild",
9176 		    thisKext->bundleID->getCStringNoCopy());
9177 		break;
9178 	}
9179 	sUnloadedPrelinkedKexts->flushCollection();
9180 
9181 	if (!doRebuild) {
9182 		goto finish;
9183 	}
9184 
9185 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
9186 	    prelinkRequest);
9187 	if (checkResult != kOSReturnSuccess) {
9188 		goto finish;
9189 	}
9190 
9191 	if (!sKernelRequests->setObject(prelinkRequest.get())) {
9192 		goto finish;
9193 	}
9194 
9195 	OSKext::pingIOKitDaemon();
9196 
9197 finish:
9198 	IORecursiveLockUnlock(sKextLock);
9199 
9200 	return;
9201 }
9202 
9203 #else /* !CONFIG_KXLD */
9204 
9205 void
9206 OSKext::considerRebuildOfPrelinkedKernel(void)
9207 {
9208 	/* in a non-dynamic kext loading world, there is never a reason to rebuild */
9209 	return;
9210 }
9211 
9212 #endif /* CONFIG_KXLD */
9213 
9214 #if PRAGMA_MARK
9215 #pragma mark Dependencies
9216 #endif
9217 /*********************************************************************
9218 *********************************************************************/
9219 bool
9220 OSKext::resolveDependencies(
9221 	OSArray * loopStack)
9222 {
9223 	bool                   result                   = false;
9224 	OSSharedPtr<OSArray>   localLoopStack;
9225 	bool                   addedToLoopStack         = false;
9226 	OSDictionary         * libraries                = NULL;        // do not release
9227 	OSSharedPtr<OSCollectionIterator> libraryIterator;
9228 	OSString             * libraryID                = NULL;        // do not release
9229 	OSKext               * libraryKext              = NULL;        // do not release
9230 	bool                   hasRawKernelDependency   = false;
9231 	bool                   hasKernelDependency      = false;
9232 	bool                   hasKPIDependency         = false;
9233 	bool                   hasPrivateKPIDependency  = false;
9234 	unsigned int           count;
9235 
9236 #if CONFIG_KXLD
9237 	OSString             * infoString               = NULL;        // do not release
9238 	OSString             * readableString           = NULL;        // do not release
9239 #endif // CONFIG_KXLD
9240 
9241 	/* A kernel component will automatically have this flag set,
9242 	 * and a loaded kext should also have it set (as should all its
9243 	 * loaded dependencies).
9244 	 */
9245 	if (flags.hasAllDependencies) {
9246 		result = true;
9247 		goto finish;
9248 	}
9249 
9250 	/* Check for loops in the dependency graph.
9251 	 */
9252 	if (loopStack) {
9253 		if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
9254 			OSKextLog(this,
9255 			    kOSKextLogErrorLevel |
9256 			    kOSKextLogDependenciesFlag,
9257 			    "Kext %s has a dependency loop; can't resolve dependencies.",
9258 			    getIdentifierCString());
9259 			goto finish;
9260 		}
9261 	} else {
9262 		OSKextLog(this,
9263 		    kOSKextLogStepLevel |
9264 		    kOSKextLogDependenciesFlag,
9265 		    "Kext %s resolving dependencies.",
9266 		    getIdentifierCString());
9267 
9268 		localLoopStack = OSArray::withCapacity(6);         // any small capacity will do
9269 		if (!localLoopStack) {
9270 			OSKextLog(this,
9271 			    kOSKextLogErrorLevel |
9272 			    kOSKextLogDependenciesFlag,
9273 			    "Kext %s can't create bookkeeping stack to resolve dependencies.",
9274 			    getIdentifierCString());
9275 			goto finish;
9276 		}
9277 		loopStack = localLoopStack.get();
9278 	}
9279 	if (!loopStack->setObject(this)) {
9280 		OSKextLog(this,
9281 		    kOSKextLogErrorLevel |
9282 		    kOSKextLogDependenciesFlag,
9283 		    "Kext %s - internal error resolving dependencies.",
9284 		    getIdentifierCString());
9285 		goto finish;
9286 	}
9287 	addedToLoopStack = true;
9288 
9289 	/* Purge any existing kexts in the dependency list and start over.
9290 	 */
9291 	flushDependencies();
9292 	if (dependencies) {
9293 		OSKextLog(this,
9294 		    kOSKextLogErrorLevel |
9295 		    kOSKextLogDependenciesFlag,
9296 		    "Kext %s - internal error resolving dependencies.",
9297 		    getIdentifierCString());
9298 	}
9299 
9300 	libraries = OSDynamicCast(OSDictionary,
9301 	    getPropertyForHostArch(kOSBundleLibrariesKey));
9302 	if (libraries == NULL || libraries->getCount() == 0) {
9303 		OSKextLog(this,
9304 		    kOSKextLogErrorLevel |
9305 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9306 		    "Kext %s - can't resolve dependencies; %s missing/invalid type.",
9307 		    getIdentifierCString(), kOSBundleLibrariesKey);
9308 		goto finish;
9309 	}
9310 
9311 	/* Make a new array to hold the dependencies (flush freed the old one).
9312 	 */
9313 	dependencies = OSArray::withCapacity(libraries->getCount());
9314 	if (!dependencies) {
9315 		OSKextLog(this,
9316 		    kOSKextLogErrorLevel |
9317 		    kOSKextLogDependenciesFlag,
9318 		    "Kext %s - can't allocate dependencies array.",
9319 		    getIdentifierCString());
9320 		goto finish;
9321 	}
9322 
9323 	// xxx - compat: We used to add an implicit dependency on kernel 6.0
9324 	// xxx - compat: if none were declared.
9325 
9326 	libraryIterator = OSCollectionIterator::withCollection(libraries);
9327 	if (!libraryIterator) {
9328 		OSKextLog(this,
9329 		    kOSKextLogErrorLevel |
9330 		    kOSKextLogDependenciesFlag,
9331 		    "Kext %s - can't allocate dependencies iterator.",
9332 		    getIdentifierCString());
9333 		goto finish;
9334 	}
9335 
9336 	while ((libraryID = OSDynamicCast(OSString,
9337 	    libraryIterator->getNextObject()))) {
9338 		const char * library_id = libraryID->getCStringNoCopy();
9339 
9340 		OSString * libraryVersion = OSDynamicCast(OSString,
9341 		    libraries->getObject(libraryID));
9342 		if (libraryVersion == NULL) {
9343 			OSKextLog(this,
9344 			    kOSKextLogErrorLevel |
9345 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9346 			    "Kext %s - illegal type in OSBundleLibraries.",
9347 			    getIdentifierCString());
9348 			goto finish;
9349 		}
9350 
9351 		OSKextVersion libraryVers =
9352 		    OSKextParseVersionString(libraryVersion->getCStringNoCopy());
9353 		if (libraryVers == -1) {
9354 			OSKextLog(this,
9355 			    kOSKextLogErrorLevel |
9356 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9357 			    "Kext %s - invalid library version %s.",
9358 			    getIdentifierCString(),
9359 			    libraryVersion->getCStringNoCopy());
9360 			goto finish;
9361 		}
9362 
9363 		libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
9364 		if (libraryKext == NULL) {
9365 			OSKextLog(this,
9366 			    kOSKextLogErrorLevel |
9367 			    kOSKextLogDependenciesFlag,
9368 			    "Kext %s - library kext %s not found.",
9369 			    getIdentifierCString(), library_id);
9370 			goto finish;
9371 		}
9372 
9373 		if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
9374 			OSKextLog(this,
9375 			    kOSKextLogErrorLevel |
9376 			    kOSKextLogDependenciesFlag,
9377 			    "Kext %s - library kext %s not compatible "
9378 			    "with requested version %s.",
9379 			    getIdentifierCString(), library_id,
9380 			    libraryVersion->getCStringNoCopy());
9381 			goto finish;
9382 		}
9383 
9384 		/* If a nonprelinked library somehow got into the mix for a
9385 		 * prelinked kext, at any point in the chain, we must fail
9386 		 * because the prelinked relocs for the library will be all wrong.
9387 		 */
9388 		if (this->isPrelinked() &&
9389 		    libraryKext->declaresExecutable() &&
9390 		    !libraryKext->isPrelinked()) {
9391 			OSKextLog(this,
9392 			    kOSKextLogErrorLevel |
9393 			    kOSKextLogDependenciesFlag,
9394 			    "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
9395 			    getIdentifierCString(), library_id,
9396 			    libraryVersion->getCStringNoCopy());
9397 			goto finish;
9398 		}
9399 
9400 		if (!libraryKext->resolveDependencies(loopStack)) {
9401 			goto finish;
9402 		}
9403 
9404 		/* Add the library directly only if it has an executable to link.
9405 		 * Otherwise it's just used to collect other dependencies, so put
9406 		 * *its* dependencies on the list for this kext.
9407 		 */
9408 		// xxx - We are losing info here; would like to make fake entries or
9409 		// xxx - keep these in the dependency graph for loaded kexts.
9410 		// xxx - I really want to make kernel components not a special case!
9411 		if (libraryKext->declaresExecutable() ||
9412 		    libraryKext->isInterface()) {
9413 			if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
9414 				dependencies->setObject(libraryKext);
9415 
9416 				OSKextLog(this,
9417 				    kOSKextLogDetailLevel |
9418 				    kOSKextLogDependenciesFlag,
9419 				    "Kext %s added dependency %s.",
9420 				    getIdentifierCString(),
9421 				    libraryKext->getIdentifierCString());
9422 			}
9423 		} else {
9424 			int       numLibDependencies  = libraryKext->getNumDependencies();
9425 			OSArray * libraryDependencies = libraryKext->getDependencies();
9426 			int       index;
9427 
9428 			if (numLibDependencies) {
9429 				// xxx - this msg level should be 1 lower than the per-kext one
9430 				OSKextLog(this,
9431 				    kOSKextLogDetailLevel |
9432 				    kOSKextLogDependenciesFlag,
9433 				    "Kext %s pulling %d dependencies from codeless library %s.",
9434 				    getIdentifierCString(),
9435 				    numLibDependencies,
9436 				    libraryKext->getIdentifierCString());
9437 			}
9438 			for (index = 0; index < numLibDependencies; index++) {
9439 				OSKext * thisLibDependency = OSDynamicCast(OSKext,
9440 				    libraryDependencies->getObject(index));
9441 				if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
9442 					dependencies->setObject(thisLibDependency);
9443 					OSKextLog(this,
9444 					    kOSKextLogDetailLevel |
9445 					    kOSKextLogDependenciesFlag,
9446 					    "Kext %s added dependency %s from codeless library %s.",
9447 					    getIdentifierCString(),
9448 					    thisLibDependency->getIdentifierCString(),
9449 					    libraryKext->getIdentifierCString());
9450 				}
9451 			}
9452 		}
9453 
9454 		if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
9455 		    0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
9456 			hasRawKernelDependency = true;
9457 		} else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
9458 			hasKernelDependency = true;
9459 		} else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
9460 			hasKPIDependency = true;
9461 			if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
9462 				hasPrivateKPIDependency = true;
9463 			}
9464 		}
9465 	}
9466 
9467 	if (hasRawKernelDependency) {
9468 		OSKextLog(this,
9469 		    kOSKextLogErrorLevel |
9470 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9471 		    "Error - kext %s declares a dependency on %s, which is not permitted.",
9472 		    getIdentifierCString(), KERNEL_LIB);
9473 		goto finish;
9474 	}
9475 #if __LP64__
9476 	if (hasKernelDependency) {
9477 		OSKextLog(this,
9478 		    kOSKextLogErrorLevel |
9479 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9480 		    "Error - kext %s declares %s dependencies. "
9481 		    "Only %s* dependencies are supported for 64-bit kexts.",
9482 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
9483 		goto finish;
9484 	}
9485 	if (!hasKPIDependency) {
9486 		OSKextLog(this,
9487 		    kOSKextLogWarningLevel |
9488 		    kOSKextLogDependenciesFlag,
9489 		    "Warning - kext %s declares no %s* dependencies. "
9490 		    "If it uses any KPIs, the link may fail with undefined symbols.",
9491 		    getIdentifierCString(), KPI_LIB_PREFIX);
9492 	}
9493 #else /* __LP64__ */
9494 	// xxx - will change to flatly disallow "kernel" dependencies at some point
9495 	// xxx - is it invalid to do both "com.apple.kernel" and any
9496 	// xxx - "com.apple.kernel.*"?
9497 
9498 	if (hasKernelDependency && hasKPIDependency) {
9499 		OSKextLog(this,
9500 		    kOSKextLogWarningLevel |
9501 		    kOSKextLogDependenciesFlag,
9502 		    "Warning - kext %s has immediate dependencies on both "
9503 		    "%s* and %s* components; use only one style.",
9504 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
9505 	}
9506 
9507 	if (!hasKernelDependency && !hasKPIDependency) {
9508 		// xxx - do we want to use validation flag for these too?
9509 		OSKextLog(this,
9510 		    kOSKextLogWarningLevel |
9511 		    kOSKextLogDependenciesFlag,
9512 		    "Warning - %s declares no kernel dependencies; using %s.",
9513 		    getIdentifierCString(), KERNEL6_LIB);
9514 		OSKext * kernelKext = OSDynamicCast(OSKext,
9515 		    sKextsByID->getObject(KERNEL6_LIB));
9516 		if (kernelKext) {
9517 			dependencies->setObject(kernelKext);
9518 		} else {
9519 			OSKextLog(this,
9520 			    kOSKextLogErrorLevel |
9521 			    kOSKextLogDependenciesFlag,
9522 			    "Error - Library %s not found for %s.",
9523 			    KERNEL6_LIB, getIdentifierCString());
9524 		}
9525 	}
9526 
9527 	/* If the kext doesn't have a raw kernel or KPI dependency, then add all of
9528 	 * its indirect dependencies to simulate old-style linking.  XXX - Should
9529 	 * check for duplicates.
9530 	 */
9531 	if (!hasKPIDependency) {
9532 		unsigned int i;
9533 
9534 		flags.hasBleedthrough = true;
9535 
9536 		count = getNumDependencies();
9537 
9538 		/* We add to the dependencies array in this loop, but do not iterate
9539 		 * past its original count.
9540 		 */
9541 		for (i = 0; i < count; i++) {
9542 			OSKext * dependencyKext = OSDynamicCast(OSKext,
9543 			    dependencies->getObject(i));
9544 			dependencyKext->addBleedthroughDependencies(dependencies.get());
9545 		}
9546 	}
9547 #endif /* __LP64__ */
9548 
9549 #if CONFIG_KXLD
9550 	/*
9551 	 * If we're not dynamically linking kexts, then we don't need to check
9552 	 * copyright strings. The linker in user space has already done this.
9553 	 */
9554 	if (hasPrivateKPIDependency) {
9555 		bool hasApplePrefix = false;
9556 		bool infoCopyrightIsValid = false;
9557 		bool readableCopyrightIsValid = false;
9558 
9559 		hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
9560 		    APPLE_KEXT_PREFIX);
9561 
9562 		infoString = OSDynamicCast(OSString,
9563 		    getPropertyForHostArch("CFBundleGetInfoString"));
9564 		if (infoString) {
9565 			infoCopyrightIsValid =
9566 			    kxld_validate_copyright_string(infoString->getCStringNoCopy());
9567 		}
9568 
9569 		readableString = OSDynamicCast(OSString,
9570 		    getPropertyForHostArch("NSHumanReadableCopyright"));
9571 		if (readableString) {
9572 			readableCopyrightIsValid =
9573 			    kxld_validate_copyright_string(readableString->getCStringNoCopy());
9574 		}
9575 
9576 		if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
9577 			OSKextLog(this,
9578 			    kOSKextLogErrorLevel |
9579 			    kOSKextLogDependenciesFlag,
9580 			    "Error - kext %s declares a dependency on %s. "
9581 			    "Only Apple kexts may declare a dependency on %s.",
9582 			    getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
9583 			goto finish;
9584 		}
9585 	}
9586 #endif // CONFIG_KXLD
9587 
9588 	result = true;
9589 	flags.hasAllDependencies = 1;
9590 
9591 finish:
9592 
9593 	if (addedToLoopStack) {
9594 		count = loopStack->getCount();
9595 		if (count > 0 && (this == loopStack->getObject(count - 1))) {
9596 			loopStack->removeObject(count - 1);
9597 		} else {
9598 			OSKextLog(this,
9599 			    kOSKextLogErrorLevel |
9600 			    kOSKextLogDependenciesFlag,
9601 			    "Kext %s - internal error resolving dependencies.",
9602 			    getIdentifierCString());
9603 		}
9604 	}
9605 
9606 	if (result && localLoopStack) {
9607 		OSKextLog(this,
9608 		    kOSKextLogStepLevel |
9609 		    kOSKextLogDependenciesFlag,
9610 		    "Kext %s successfully resolved dependencies.",
9611 		    getIdentifierCString());
9612 	}
9613 
9614 	return result;
9615 }
9616 
9617 /*********************************************************************
9618 *********************************************************************/
9619 bool
9620 OSKext::addBleedthroughDependencies(OSArray * anArray)
9621 {
9622 	bool result = false;
9623 	unsigned int dependencyIndex, dependencyCount;
9624 
9625 	dependencyCount = getNumDependencies();
9626 
9627 	for (dependencyIndex = 0;
9628 	    dependencyIndex < dependencyCount;
9629 	    dependencyIndex++) {
9630 		OSKext * dependency = OSDynamicCast(OSKext,
9631 		    dependencies->getObject(dependencyIndex));
9632 		if (!dependency) {
9633 			OSKextLog(this,
9634 			    kOSKextLogErrorLevel |
9635 			    kOSKextLogDependenciesFlag,
9636 			    "Kext %s - internal error propagating compatibility dependencies.",
9637 			    getIdentifierCString());
9638 			goto finish;
9639 		}
9640 		if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
9641 			anArray->setObject(dependency);
9642 		}
9643 		dependency->addBleedthroughDependencies(anArray);
9644 	}
9645 
9646 	result = true;
9647 
9648 finish:
9649 	return result;
9650 }
9651 
9652 /*********************************************************************
9653 *********************************************************************/
9654 bool
9655 OSKext::flushDependencies(bool forceFlag)
9656 {
9657 	bool result = false;
9658 
9659 	/* Only clear the dependencies if the kext isn't loaded;
9660 	 * we need the info for loaded kexts to track references.
9661 	 */
9662 	if (!isLoaded() || forceFlag) {
9663 		if (dependencies) {
9664 			// xxx - check level
9665 			OSKextLog(this,
9666 			    kOSKextLogProgressLevel |
9667 			    kOSKextLogDependenciesFlag,
9668 			    "Kext %s flushing dependencies.",
9669 			    getIdentifierCString());
9670 			dependencies.reset();
9671 		}
9672 		if (!isKernelComponent()) {
9673 			flags.hasAllDependencies = 0;
9674 		}
9675 		result = true;
9676 	}
9677 
9678 	return result;
9679 }
9680 
9681 /*********************************************************************
9682 *********************************************************************/
9683 uint32_t
9684 OSKext::getNumDependencies(void)
9685 {
9686 	if (!dependencies) {
9687 		return 0;
9688 	}
9689 	return dependencies->getCount();
9690 }
9691 
9692 /*********************************************************************
9693 *********************************************************************/
9694 OSArray *
9695 OSKext::getDependencies(void)
9696 {
9697 	return dependencies.get();
9698 }
9699 
9700 bool
9701 OSKext::hasDependency(const OSSymbol * depID)
9702 {
9703 	bool result __block;
9704 
9705 	if (depID == getIdentifier()) {
9706 		return true;
9707 	}
9708 	if (!dependencies) {
9709 		return false;
9710 	}
9711 	result = false;
9712 	dependencies->iterateObjects(^bool (OSObject * obj) {
9713 		OSKext * kext;
9714 		kext = OSDynamicCast(OSKext, obj);
9715 		if (!kext) {
9716 		        return false;
9717 		}
9718 		result = (depID == kext->getIdentifier());
9719 		return result;
9720 	});
9721 	return result;
9722 }
9723 
9724 #if PRAGMA_MARK
9725 #pragma mark OSMetaClass Support
9726 #endif
9727 /*********************************************************************
9728 *********************************************************************/
9729 OSReturn
9730 OSKext::addClass(
9731 	OSMetaClass * aClass,
9732 	uint32_t      numClasses)
9733 {
9734 	OSReturn result = kOSMetaClassNoInsKModSet;
9735 
9736 	if (!metaClasses) {
9737 		metaClasses = OSSet::withCapacity(numClasses);
9738 		if (!metaClasses) {
9739 			goto finish;
9740 		}
9741 	}
9742 
9743 	if (metaClasses->containsObject(aClass)) {
9744 		OSKextLog(this,
9745 		    kOSKextLogWarningLevel |
9746 		    kOSKextLogLoadFlag,
9747 		    "Notice - kext %s has already registered class %s.",
9748 		    getIdentifierCString(),
9749 		    aClass->getClassName());
9750 		result = kOSReturnSuccess;
9751 		goto finish;
9752 	}
9753 
9754 	if (!metaClasses->setObject(aClass)) {
9755 		goto finish;
9756 	} else {
9757 		OSKextLog(this,
9758 		    kOSKextLogDetailLevel |
9759 		    kOSKextLogLoadFlag,
9760 		    "Kext %s registered class %s.",
9761 		    getIdentifierCString(),
9762 		    aClass->getClassName());
9763 	}
9764 
9765 	if (!flags.autounloadEnabled) {
9766 		const OSMetaClass * metaScan  = NULL;        // do not release
9767 
9768 		for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
9769 			if (metaScan == OSTypeID(IOService)) {
9770 				OSKextLog(this,
9771 				    kOSKextLogProgressLevel |
9772 				    kOSKextLogLoadFlag,
9773 				    "Kext %s has IOService subclass %s; enabling autounload.",
9774 				    getIdentifierCString(),
9775 				    aClass->getClassName());
9776 
9777 				flags.autounloadEnabled = (0 == flags.unloadUnsupported);
9778 				break;
9779 			}
9780 		}
9781 	}
9782 
9783 	notifyAddClassObservers(this, aClass, flags);
9784 
9785 	result = kOSReturnSuccess;
9786 
9787 finish:
9788 	if (result != kOSReturnSuccess) {
9789 		OSKextLog(this,
9790 		    kOSKextLogErrorLevel |
9791 		    kOSKextLogLoadFlag,
9792 		    "Kext %s failed to register class %s.",
9793 		    getIdentifierCString(),
9794 		    aClass->getClassName());
9795 	}
9796 
9797 	return result;
9798 }
9799 
9800 /*********************************************************************
9801 *********************************************************************/
9802 OSReturn
9803 OSKext::removeClass(
9804 	OSMetaClass * aClass)
9805 {
9806 	OSReturn result = kOSMetaClassNoKModSet;
9807 
9808 	if (!metaClasses) {
9809 		goto finish;
9810 	}
9811 
9812 	if (!metaClasses->containsObject(aClass)) {
9813 		OSKextLog(this,
9814 		    kOSKextLogWarningLevel |
9815 		    kOSKextLogLoadFlag,
9816 		    "Notice - kext %s asked to unregister unknown class %s.",
9817 		    getIdentifierCString(),
9818 		    aClass->getClassName());
9819 		result = kOSReturnSuccess;
9820 		goto finish;
9821 	}
9822 
9823 	OSKextLog(this,
9824 	    kOSKextLogDetailLevel |
9825 	    kOSKextLogLoadFlag,
9826 	    "Kext %s unregistering class %s.",
9827 	    getIdentifierCString(),
9828 	    aClass->getClassName());
9829 
9830 	metaClasses->removeObject(aClass);
9831 
9832 	notifyRemoveClassObservers(this, aClass, flags);
9833 
9834 	result = kOSReturnSuccess;
9835 
9836 finish:
9837 	if (result != kOSReturnSuccess) {
9838 		OSKextLog(this,
9839 		    kOSKextLogErrorLevel |
9840 		    kOSKextLogLoadFlag,
9841 		    "Failed to unregister kext %s class %s.",
9842 		    getIdentifierCString(),
9843 		    aClass->getClassName());
9844 	}
9845 	return result;
9846 }
9847 
9848 /*********************************************************************
9849 *********************************************************************/
9850 OSSet *
9851 OSKext::getMetaClasses(void)
9852 {
9853 	return metaClasses.get();
9854 }
9855 
9856 /*********************************************************************
9857 *********************************************************************/
9858 bool
9859 OSKext::hasOSMetaClassInstances(void)
9860 {
9861 	bool                   result        = false;
9862 	OSSharedPtr<OSCollectionIterator> classIterator;
9863 	OSMetaClass          * checkClass    = NULL;        // do not release
9864 
9865 	if (!metaClasses) {
9866 		goto finish;
9867 	}
9868 
9869 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9870 	if (!classIterator) {
9871 		// xxx - log alloc failure?
9872 		goto finish;
9873 	}
9874 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9875 		if (checkClass->getInstanceCount()) {
9876 			result = true;
9877 			goto finish;
9878 		}
9879 	}
9880 
9881 finish:
9882 	return result;
9883 }
9884 
9885 /*********************************************************************
9886 *********************************************************************/
9887 /* static */
9888 void
9889 OSKext::reportOSMetaClassInstances(
9890 	const char     * kextIdentifier,
9891 	OSKextLogSpec    msgLogSpec)
9892 {
9893 	OSSharedPtr<OSKext> theKext;
9894 
9895 	theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
9896 	if (!theKext) {
9897 		goto finish;
9898 	}
9899 
9900 	theKext->reportOSMetaClassInstances(msgLogSpec);
9901 finish:
9902 	return;
9903 }
9904 
9905 /*********************************************************************
9906 *********************************************************************/
9907 void
9908 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
9909 {
9910 	OSSharedPtr<OSCollectionIterator> classIterator;
9911 	OSMetaClass          * checkClass    = NULL;        // do not release
9912 
9913 	if (!metaClasses) {
9914 		goto finish;
9915 	}
9916 
9917 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
9918 	if (!classIterator) {
9919 		goto finish;
9920 	}
9921 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
9922 		if (checkClass->getInstanceCount()) {
9923 			OSKextLog(this,
9924 			    msgLogSpec,
9925 			    "    Kext %s class %s has %d instance%s.",
9926 			    getIdentifierCString(),
9927 			    checkClass->getClassName(),
9928 			    checkClass->getInstanceCount(),
9929 			    checkClass->getInstanceCount() == 1 ? "" : "s");
9930 		}
9931 	}
9932 
9933 finish:
9934 	return;
9935 }
9936 
9937 #if PRAGMA_MARK
9938 #pragma mark User-Space Requests
9939 #endif
9940 
9941 static kern_return_t
9942 patchDextLaunchRequests(task_t calling_task, OSArray *requests)
9943 {
9944 	OSReturn result = kOSReturnSuccess;
9945 	for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) {
9946 		OSDictionary * request = NULL;         //do not release
9947 		IOUserServerCheckInToken * token = NULL;         //do not release
9948 		OSString * requestPredicate = NULL;         //do not release
9949 		OSSharedPtr<OSNumber> portNameNumber;
9950 		mach_port_name_t portName = 0;
9951 		request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex));
9952 		if (!request) {
9953 			OSKextLog(/* kext */ NULL,
9954 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9955 			    "Elements of request should be of type OSDictionary");
9956 			result = kOSKextReturnInternalError;
9957 			goto finish;
9958 		}
9959 		requestPredicate = _OSKextGetRequestPredicate(request);
9960 		if (!requestPredicate) {
9961 			OSKextLog(/* kext */ NULL,
9962 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9963 			    "Failed to get request predicate");
9964 			result = kOSKextReturnInternalError;
9965 			goto finish;
9966 		}
9967 		// is this a dext launch?
9968 		if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) {
9969 			token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken));
9970 			if (!token) {
9971 				OSKextLog(/* kext */ NULL,
9972 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9973 				    "Could not find a IOUserServerCheckInToken in daemon launch request.");
9974 				result = kOSKextReturnInternalError;
9975 				goto finish;
9976 			}
9977 			portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT);
9978 			if (portName == 0 || portName == MACH_PORT_DEAD) {
9979 				OSKextLog(/* kext */ NULL,
9980 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9981 				    "Could not create send right for object.");
9982 				result = kOSKextReturnInternalError;
9983 				goto finish;
9984 			}
9985 			// Store the mach port name as a OSNumber
9986 			portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName));
9987 			if (!portNameNumber) {
9988 				OSKextLog(/* kext */ NULL,
9989 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9990 				    "Could not create OSNumber object.");
9991 				result = kOSKextReturnNoMemory;
9992 				goto finish;
9993 			}
9994 			if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) {
9995 				OSKextLog(/* kext */ NULL,
9996 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
9997 				    "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken);
9998 				result = kOSKextReturnNoMemory;
9999 				goto finish;
10000 			}
10001 		}
10002 finish:
10003 		if (result != kOSReturnSuccess) {
10004 			break;
10005 		}
10006 	}
10007 	return result;
10008 }
10009 
10010 bool
10011 OSKext::iokitDaemonActive()
10012 {
10013 	bool result;
10014 	IORecursiveLockLock(sKextLock);
10015 	result = sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot;
10016 	IORecursiveLockUnlock(sKextLock);
10017 	return result;
10018 }
10019 
10020 /*********************************************************************
10021 * XXX - this function is a big ugly mess
10022 *********************************************************************/
10023 /* static */
10024 OSReturn
10025 OSKext::handleRequest(
10026 	host_priv_t     hostPriv,
10027 	OSKextLogSpec   clientLogFilter,
10028 	char          * requestBuffer,
10029 	uint32_t        requestLength,
10030 	char         ** responseOut,
10031 	uint32_t      * responseLengthOut,
10032 	char         ** logInfoOut,
10033 	uint32_t      * logInfoLengthOut)
10034 {
10035 	OSReturn       result             = kOSReturnError;
10036 	kern_return_t  kmem_result        = KERN_FAILURE;
10037 
10038 	char         * response           = NULL;        // returned by reference
10039 	uint32_t       responseLength     = 0;
10040 
10041 	bool           taskCanManageAllKCs   = false;
10042 	bool           taskOnlyManagesBootKC = false;
10043 
10044 	OSSharedPtr<OSObject>     parsedXML;
10045 	OSDictionary            * requestDict    = NULL;        // do not release
10046 	OSSharedPtr<OSString>     errorString;
10047 
10048 	OSSharedPtr<OSObject>     responseObject;
10049 
10050 	OSSharedPtr<OSSerialize>  serializer;
10051 
10052 	OSSharedPtr<OSArray>      logInfoArray;
10053 
10054 	OSString     * predicate          = NULL;        // do not release
10055 	OSString     * kextIdentifier     = NULL;        // do not release
10056 	OSArray      * kextIdentifiers    = NULL;        // do not release
10057 	OSKext       * theKext            = NULL;        // do not release
10058 	OSBoolean    * boolArg            = NULL;        // do not release
10059 
10060 
10061 	IORecursiveLockLock(sKextLock);
10062 
10063 	if (responseOut) {
10064 		*responseOut = NULL;
10065 		*responseLengthOut = 0;
10066 	}
10067 	if (logInfoOut) {
10068 		*logInfoOut = NULL;
10069 		*logInfoLengthOut = 0;
10070 	}
10071 
10072 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
10073 
10074 	/* XML must be nul-terminated.
10075 	 */
10076 	if (requestBuffer[requestLength - 1] != '\0') {
10077 		OSKextLog(/* kext */ NULL,
10078 		    kOSKextLogErrorLevel |
10079 		    kOSKextLogIPCFlag,
10080 		    "Invalid request from user space (not nul-terminated).");
10081 		result = kOSKextReturnBadData;
10082 		goto finish;
10083 	}
10084 	parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString);
10085 	if (parsedXML) {
10086 		requestDict = OSDynamicCast(OSDictionary, parsedXML.get());
10087 	}
10088 	if (!requestDict) {
10089 		const char * errorCString = "(unknown error)";
10090 
10091 		if (errorString && errorString->getCStringNoCopy()) {
10092 			errorCString = errorString->getCStringNoCopy();
10093 		} else if (parsedXML) {
10094 			errorCString = "not a dictionary";
10095 		}
10096 		OSKextLog(/* kext */ NULL,
10097 		    kOSKextLogErrorLevel |
10098 		    kOSKextLogIPCFlag,
10099 		    "Error unserializing request from user space: %s.",
10100 		    errorCString);
10101 		result = kOSKextReturnSerialization;
10102 		goto finish;
10103 	}
10104 
10105 	predicate = _OSKextGetRequestPredicate(requestDict);
10106 	if (!predicate) {
10107 		OSKextLog(/* kext */ NULL,
10108 		    kOSKextLogErrorLevel |
10109 		    kOSKextLogIPCFlag,
10110 		    "Recieved kext request from user space with no predicate.");
10111 		result = kOSKextReturnInvalidArgument;
10112 		goto finish;
10113 	}
10114 	OSKextLog(/* kext */ NULL,
10115 	    kOSKextLogDebugLevel |
10116 	    kOSKextLogIPCFlag,
10117 	    "Received '%s' request from user space.",
10118 	    predicate->getCStringNoCopy());
10119 
10120 	/*
10121 	 * All management of file sets requires an entitlement
10122 	 */
10123 	result = kOSKextReturnNotPrivileged;
10124 	if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
10125 	    predicate->isEqualTo(kKextRequestPredicateStart) ||
10126 	    predicate->isEqualTo(kKextRequestPredicateStop) ||
10127 	    predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
10128 	    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
10129 	    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
10130 	    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
10131 	    predicate->isEqualTo(kKextRequestPredicateLoadFromKC) ||
10132 	    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
10133 	    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
10134 	    predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
10135 		if (!iokitDaemonAvailable()) {
10136 			panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable");
10137 		}
10138 		if (hostPriv == HOST_PRIV_NULL) {
10139 			OSKextLog(/* kext */ NULL,
10140 			    kOSKextLogErrorLevel |
10141 			    kOSKextLogIPCFlag,
10142 			    "Access Failure - must be root user.");
10143 			goto finish;
10144 		}
10145 		taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE;
10146 		taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE;
10147 
10148 		if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) {
10149 			OSKextLog(/* kext */ NULL,
10150 			    kOSKextLogErrorLevel |
10151 			    kOSKextLogIPCFlag,
10152 			    "Access Failure - client not entitled to manage file sets.");
10153 			goto finish;
10154 		}
10155 
10156 		/*
10157 		 * The OnlyBootKC entitlement restricts the
10158 		 * collection-management entitlement to only managing kexts in
10159 		 * the BootKC. All other predicates that alter global state or
10160 		 * add new KCs are disallowed.
10161 		 */
10162 		if (taskOnlyManagesBootKC &&
10163 		    (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
10164 		    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
10165 		    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
10166 		    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
10167 		    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
10168 		    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
10169 		    predicate->isEqualTo(kKextRequestPredicateDaemonReady))) {
10170 			OSKextLog(/* kext */ NULL,
10171 			    kOSKextLogErrorLevel |
10172 			    kOSKextLogIPCFlag,
10173 			    "Access Failure - client not entitled to manage non-primary KCs");
10174 			goto finish;
10175 		}
10176 
10177 		/*
10178 		 * If we get here, then the process either has the full KC
10179 		 * management entitlement, or it has the BootKC-only
10180 		 * entitlement and the request is about the BootKC.
10181 		 */
10182 	}
10183 
10184 	/* Get common args in anticipation of use.
10185 	 */
10186 	kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
10187 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
10188 	kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
10189 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
10190 	if (kextIdentifier) {
10191 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
10192 	}
10193 	boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
10194 		    requestDict, kKextRequestArgumentValueKey));
10195 
10196 	if (taskOnlyManagesBootKC &&
10197 	    theKext &&
10198 	    theKext->isInFileset() &&
10199 	    theKext->kc_type != KCKindPrimary) {
10200 		OSKextLog(/* kext */ NULL,
10201 		    kOSKextLogErrorLevel |
10202 		    kOSKextLogIPCFlag,
10203 		    "Access Failure - client not entitled to manage kext in non-primary KC");
10204 		result = kOSKextReturnNotPrivileged;
10205 		goto finish;
10206 	}
10207 	result = kOSKextReturnInvalidArgument;
10208 
10209 	if (predicate->isEqualTo(kKextRequestPredicateStart)) {
10210 		if (!kextIdentifier) {
10211 			OSKextLog(/* kext */ NULL,
10212 			    kOSKextLogErrorLevel |
10213 			    kOSKextLogIPCFlag,
10214 			    "Invalid arguments to kext start request.");
10215 		} else if (!theKext) {
10216 			OSKextLog(/* kext */ NULL,
10217 			    kOSKextLogErrorLevel |
10218 			    kOSKextLogIPCFlag,
10219 			    "Kext %s not found for start request.",
10220 			    kextIdentifier->getCStringNoCopy());
10221 			result = kOSKextReturnNotFound;
10222 		} else {
10223 			result = theKext->start();
10224 		}
10225 	} else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
10226 		if (!kextIdentifier) {
10227 			OSKextLog(/* kext */ NULL,
10228 			    kOSKextLogErrorLevel |
10229 			    kOSKextLogIPCFlag,
10230 			    "Invalid arguments to kext stop request.");
10231 		} else if (!theKext) {
10232 			OSKextLog(/* kext */ NULL,
10233 			    kOSKextLogErrorLevel |
10234 			    kOSKextLogIPCFlag,
10235 			    "Kext %s not found for stop request.",
10236 			    kextIdentifier->getCStringNoCopy());
10237 			result = kOSKextReturnNotFound;
10238 		} else {
10239 			result = theKext->stop();
10240 		}
10241 	} else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) {
10242 		result = OSKext::setMissingAuxKCBundles(requestDict);
10243 	} else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) {
10244 		if (!kextIdentifier) {
10245 			OSKextLog(/* kext */ NULL,
10246 			    kOSKextLogErrorLevel |
10247 			    kOSKextLogIPCFlag,
10248 			    "Invalid arguments to AuxKC Bundle Available request.");
10249 		} else {
10250 			result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict);
10251 		}
10252 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) {
10253 		if (!kextIdentifier) {
10254 			OSKextLog(/* kext */ NULL,
10255 			    kOSKextLogErrorLevel |
10256 			    kOSKextLogIPCFlag,
10257 			    "Invalid arguments to kext load from KC request.");
10258 		} else if (!theKext) {
10259 			OSKextLog(/* kext */ NULL,
10260 			    kOSKextLogErrorLevel |
10261 			    kOSKextLogIPCFlag,
10262 			    "Kext %s not found for load from KC request.",
10263 			    kextIdentifier->getCStringNoCopy());
10264 			result = kOSKextReturnNotFound;
10265 		} else if (!theKext->isInFileset()) {
10266 			OSKextLog(/* kext */ NULL,
10267 			    kOSKextLogErrorLevel |
10268 			    kOSKextLogIPCFlag,
10269 			    "Kext %s does not exist in a KC: refusing to load.",
10270 			    kextIdentifier->getCStringNoCopy());
10271 			result = kOSKextReturnNotLoadable;
10272 		} else {
10273 			result = OSKext::loadKextFromKC(theKext, requestDict);
10274 		}
10275 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) {
10276 		if (!kextIdentifier) {
10277 			OSKextLog(/* kext */ NULL,
10278 			    kOSKextLogErrorLevel |
10279 			    kOSKextLogIPCFlag,
10280 			    "Invalid arguments to codeless kext load interface (missing identifier).");
10281 		} else {
10282 			result = OSKext::loadCodelessKext(kextIdentifier, requestDict);
10283 		}
10284 	} else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
10285 		if (!kextIdentifier) {
10286 			OSKextLog(/* kext */ NULL,
10287 			    kOSKextLogErrorLevel |
10288 			    kOSKextLogIPCFlag,
10289 			    "Invalid arguments to kext unload request.");
10290 		} else if (!theKext) {
10291 			OSKextLog(/* kext */ NULL,
10292 			    kOSKextLogErrorLevel |
10293 			    kOSKextLogIPCFlag,
10294 			    "Kext %s not found for unload request.",
10295 			    kextIdentifier->getCStringNoCopy());
10296 			result = kOSKextReturnNotFound;
10297 		} else {
10298 			if (theKext->isDriverKit()) {
10299 				result = OSKext::removeDext(theKext);
10300 			} else {
10301 				OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
10302 				    _OSKextGetRequestArgument(requestDict,
10303 				    kKextRequestArgumentTerminateIOServicesKey));
10304 				result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
10305 			}
10306 		}
10307 	} else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
10308 		result = OSKext::dispatchResource(requestDict);
10309 	} else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
10310 		OSNumber     *lookupNum   = NULL;
10311 		lookupNum = OSDynamicCast(OSNumber,
10312 		    _OSKextGetRequestArgument(requestDict,
10313 		    kKextRequestArgumentLookupAddressKey));
10314 
10315 		responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
10316 		if (responseObject) {
10317 			result = kOSReturnSuccess;
10318 		} else {
10319 			goto finish;
10320 		}
10321 	} else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
10322 	    predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) ||
10323 	    predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection) ||
10324 	    predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
10325 		OSBoolean    * delayAutounloadBool = NULL;
10326 		OSObject     * infoKeysRaw         = NULL;
10327 		OSArray      * infoKeys            = NULL;
10328 		uint32_t       infoKeysCount       = 0;
10329 
10330 		delayAutounloadBool = OSDynamicCast(OSBoolean,
10331 		    _OSKextGetRequestArgument(requestDict,
10332 		    kKextRequestArgumentDelayAutounloadKey));
10333 
10334 		/* If asked to delay autounload, reset the timer if it's currently set.
10335 		 * (That is, don't schedule an unload if one isn't already pending.
10336 		 */
10337 		if (delayAutounloadBool == kOSBooleanTrue) {
10338 			OSKext::considerUnloads(/* rescheduleOnly? */ true);
10339 		}
10340 
10341 		infoKeysRaw = _OSKextGetRequestArgument(requestDict,
10342 		    kKextRequestArgumentInfoKeysKey);
10343 		infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
10344 		if (infoKeysRaw && !infoKeys) {
10345 			OSKextLog(/* kext */ NULL,
10346 			    kOSKextLogErrorLevel |
10347 			    kOSKextLogIPCFlag,
10348 			    "Invalid arguments to kext info request.");
10349 			goto finish;
10350 		}
10351 
10352 		if (infoKeys) {
10353 			infoKeysCount = infoKeys->getCount();
10354 			for (uint32_t i = 0; i < infoKeysCount; i++) {
10355 				if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
10356 					OSKextLog(/* kext */ NULL,
10357 					    kOSKextLogErrorLevel |
10358 					    kOSKextLogIPCFlag,
10359 					    "Invalid arguments to kext info request.");
10360 					goto finish;
10361 				}
10362 			}
10363 		}
10364 
10365 		if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
10366 			responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
10367 		} else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
10368 			responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
10369 		} else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
10370 			responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys);
10371 		} else if (predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
10372 			responseObject = OSKext::copyDextsInfo(kextIdentifiers, infoKeys);
10373 		}
10374 
10375 		if (!responseObject) {
10376 			result = kOSKextReturnInternalError;
10377 		} else {
10378 			OSKextLog(/* kext */ NULL,
10379 			    kOSKextLogDebugLevel |
10380 			    kOSKextLogIPCFlag,
10381 			    "Returning loaded kext info.");
10382 			result = kOSReturnSuccess;
10383 		}
10384 	} else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
10385 		/* Hand the current sKernelRequests array to the caller
10386 		 * (who must release it), and make a new one.
10387 		 */
10388 		responseObject = os::move(sKernelRequests);
10389 		sKernelRequests = OSArray::withCapacity(0);
10390 		sPostedKextLoadIdentifiers->flushCollection();
10391 		OSKextLog(/* kext */ NULL,
10392 		    kOSKextLogDebugLevel |
10393 		    kOSKextLogIPCFlag,
10394 		    "Returning kernel requests.");
10395 		result = kOSReturnSuccess;
10396 	} else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
10397 		/* Return the set of all requested bundle identifiers */
10398 		responseObject = sAllKextLoadIdentifiers;
10399 		OSKextLog(/* kext */ NULL,
10400 		    kOSKextLogDebugLevel |
10401 		    kOSKextLogIPCFlag,
10402 		    "Returning load requests.");
10403 		result = kOSReturnSuccess;
10404 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) {
10405 		printf("KextLog: Loading FileSet KC(s)\n");
10406 		result = OSKext::loadFileSetKexts(requestDict);
10407 	} else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
10408 		bool active = iokitDaemonActive();
10409 		printf("KextLog: " kIOKitDaemonName " is %s\n", active ? "active" : "not active");
10410 		if (sOSKextWasResetAfterUserspaceReboot) {
10411 			printf("KextLog: was reset after userspace reboot\n");
10412 		}
10413 		result = active ? kOSReturnSuccess : kIOReturnNotReady;
10414 	} else {
10415 		OSKextLog(/* kext */ NULL,
10416 		    kOSKextLogDebugLevel |
10417 		    kOSKextLogIPCFlag,
10418 		    "Received '%s' invalid request from user space.",
10419 		    predicate->getCStringNoCopy());
10420 		goto finish;
10421 	}
10422 
10423 	/**********
10424 	 * Now we have handle the request, or not. Gather up the response & logging
10425 	 * info to ship to user space.
10426 	 *********/
10427 
10428 	/* Note: Nothing in OSKext is supposed to retain requestDict,
10429 	 * but you never know....
10430 	 */
10431 	if (requestDict->getRetainCount() > 1) {
10432 		OSKextLog(/* kext */ NULL,
10433 		    kOSKextLogWarningLevel |
10434 		    kOSKextLogIPCFlag,
10435 		    "Request from user space still retained by a kext; "
10436 		    "probable memory leak.");
10437 	}
10438 
10439 	if (responseOut && responseObject) {
10440 		serializer = OSSerialize::withCapacity(0);
10441 		if (!serializer) {
10442 			result = kOSKextReturnNoMemory;
10443 			goto finish;
10444 		}
10445 		/*
10446 		 * Before serializing the kernel requests, patch the dext launch requests so
10447 		 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the
10448 		 * IOUserServerCheckInToken kernel object.
10449 		 */
10450 		if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
10451 			OSArray * requests = OSDynamicCast(OSArray, responseObject.get());
10452 			task_t calling_task = current_task();
10453 			if (!requests) {
10454 				OSKextLog(/* kext */ NULL,
10455 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10456 				    "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests);
10457 				result = kOSKextReturnInternalError;
10458 				goto finish;
10459 			}
10460 			result = patchDextLaunchRequests(calling_task, requests);
10461 			if (result != kOSReturnSuccess) {
10462 				OSKextLog(/* kext */ NULL,
10463 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10464 				    "Failed to patch dext launch requests.");
10465 				goto finish;
10466 			}
10467 		}
10468 
10469 		if (!responseObject->serialize(serializer.get())) {
10470 			OSKextLog(/* kext */ NULL,
10471 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10472 			    "Failed to serialize response to request from user space.");
10473 			result = kOSKextReturnSerialization;
10474 			goto finish;
10475 		}
10476 
10477 		response = (char *)serializer->text();
10478 		responseLength = serializer->getLength();
10479 	}
10480 
10481 	if (responseOut && response) {
10482 		char * buffer;
10483 
10484 		/* This kmem_alloc sets the return value of the function.
10485 		 */
10486 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
10487 		    round_page(responseLength), KMA_DATA, VM_KERN_MEMORY_OSKEXT);
10488 		if (kmem_result != KERN_SUCCESS) {
10489 			OSKextLog(/* kext */ NULL,
10490 			    kOSKextLogErrorLevel |
10491 			    kOSKextLogIPCFlag,
10492 			    "Failed to copy response to request from user space.");
10493 			result = kmem_result;
10494 			goto finish;
10495 		} else {
10496 			/* 11981737 - clear uninitialized data in last page */
10497 			bzero((void *)(buffer + responseLength),
10498 			    (round_page(responseLength) - responseLength));
10499 			memcpy(buffer, response, responseLength);
10500 			*responseOut = buffer;
10501 			*responseLengthOut = responseLength;
10502 		}
10503 	}
10504 
10505 finish:
10506 
10507 	/* Gather up the collected log messages for user space. Any messages
10508 	 * messages past this call will not make it up as log messages but
10509 	 * will be in the system log. Note that we ignore the return of the
10510 	 * serialize; it has no bearing on the operation at hand even if we
10511 	 * fail to get the log messages.
10512 	 */
10513 	logInfoArray = OSKext::clearUserSpaceLogFilter();
10514 
10515 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
10516 		(void)OSKext::serializeLogInfo(logInfoArray.get(),
10517 		    logInfoOut, logInfoLengthOut);
10518 	}
10519 
10520 	IORecursiveLockUnlock(sKextLock);
10521 
10522 	return result;
10523 }
10524 
10525 #if PRAGMA_MARK
10526 #pragma mark Linked Kext Collection Support
10527 #endif
10528 
10529 static int
10530 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount)
10531 {
10532 	for (int i = 0; i < segCount; i++) {
10533 		vm_offset_t segStart = segAddrs[i];
10534 		vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i];
10535 
10536 		if (theAddr >= segStart && theAddr < segEnd) {
10537 			return i;
10538 		}
10539 	}
10540 	return -1;
10541 }
10542 
10543 static void
10544 __slideOldKaslrOffsets(kernel_mach_header_t *mh,
10545     kernel_segment_command_t *kextTextSeg,
10546     OSData *kaslrOffsets)
10547 {
10548 	static const char *plk_segNames[] = {
10549 		"__TEXT",
10550 		"__TEXT_EXEC",
10551 		"__DATA",
10552 		"__DATA_CONST",
10553 		"__LINKEDIT",
10554 		"__PRELINK_TEXT",
10555 		"__PLK_TEXT_EXEC",
10556 		"__PRELINK_DATA",
10557 		"__PLK_DATA_CONST",
10558 		"__PLK_LLVM_COV",
10559 		"__PLK_LINKEDIT",
10560 		"__PRELINK_INFO"
10561 	};
10562 	static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0]));
10563 
10564 	unsigned long plk_segSizes[num_plk_seg];
10565 	vm_offset_t   plk_segAddrs[num_plk_seg];
10566 
10567 	for (size_t i = 0; i < num_plk_seg; i++) {
10568 		plk_segSizes[i] = 0;
10569 		plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]);
10570 	}
10571 
10572 	uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr;
10573 
10574 	int slidKextAddrCount = 0;
10575 	int badSlideAddr = 0;
10576 	int badSlideTarget = 0;
10577 
10578 	struct kaslrPackedOffsets {
10579 		uint32_t    count;          /* number of offsets */
10580 		uint32_t    offsetsArray[];        /* offsets to slide */
10581 	};
10582 	const struct kaslrPackedOffsets *myOffsets = NULL;
10583 	myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy();
10584 
10585 	for (uint32_t j = 0; j < myOffsets->count; j++) {
10586 		uint64_t   slideOffset = (uint64_t)myOffsets->offsetsArray[j];
10587 		vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset);
10588 		int        slideAddrSegIndex = -1;
10589 		int        addrToSlideSegIndex = -1;
10590 
10591 		slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
10592 		if (slideAddrSegIndex >= 0) {
10593 			addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
10594 			if (addrToSlideSegIndex < 0) {
10595 				badSlideTarget++;
10596 				continue;
10597 			}
10598 		} else {
10599 			badSlideAddr++;
10600 			continue;
10601 		}
10602 
10603 		slidKextAddrCount++;
10604 		*slideAddr = ml_static_slide(*slideAddr);
10605 	}         // for ...
10606 }
10607 
10608 
10609 
10610 /********************************************************************
10611 * addKextsFromKextCollection
10612 *
10613 * Input: MachO header of kext collection. The MachO is assumed to
10614 *        have a section named 'info_seg_name,info_sect_name' that
10615 *        contains a serialized XML info dictionary. This dictionary
10616 *        contains a UUID, possibly a set of relocations (for older
10617 *        kxld-built binaries), and an array of kext personalities.
10618 *
10619 ********************************************************************/
10620 bool
10621 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10622     OSDictionary *infoDict, const char *text_seg_name,
10623     OSData **kcUUID, kc_kind_t type)
10624 {
10625 	bool result = false;
10626 
10627 	OSArray *kextArray     = NULL;        // do not release
10628 	OSData *infoDictKCUUID = NULL;         // do not release
10629 	OSData *kaslrOffsets   = NULL;        // do not release
10630 
10631 	IORegistryEntry *registryRoot = NULL;         // do not release
10632 	OSSharedPtr<OSNumber> kcKextCount;
10633 
10634 	/* extract the KC UUID from the dictionary */
10635 	infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
10636 	if (infoDictKCUUID) {
10637 		if (infoDictKCUUID->getLength() != sizeof(uuid_t)) {
10638 			panic("kcUUID length is %d, expected %lu",
10639 			    infoDictKCUUID->getLength(), sizeof(uuid_t));
10640 		}
10641 	}
10642 
10643 	/* locate the array of kext dictionaries */
10644 	kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey));
10645 	if (!kextArray) {
10646 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10647 		    "The given KC has no kext info dictionaries");
10648 		goto finish;
10649 	}
10650 
10651 	/*
10652 	 * old-style KASLR offsets may be present in the info dictionary. If
10653 	 * we find them, use them and eventually slide them.
10654 	 */
10655 	kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey));
10656 
10657 	/*
10658 	 * Before processing any kexts, locate the special kext bundle which
10659 	 * contains a list of kexts that we are to prevent from loading.
10660 	 */
10661 	createExcludeListFromPrelinkInfo(kextArray);
10662 
10663 	/*
10664 	 * Create OSKext objects for each kext we find in the array of kext
10665 	 * info plist dictionaries.
10666 	 */
10667 	for (int i = 0; i < (int)kextArray->getCount(); ++i) {
10668 		OSDictionary *kextDict = NULL;
10669 		kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i));
10670 		if (!kextDict) {
10671 			OSKextLog(/* kext */ NULL,
10672 			    kOSKextLogErrorLevel |
10673 			    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10674 			    "Kext info dictionary for kext #%d isn't a dictionary?", i);
10675 			continue;
10676 		}
10677 
10678 		/*
10679 		 * Create the kext for the entry, then release it, because the
10680 		 * kext system keeps a reference around until the kext is
10681 		 * explicitly removed.  Any creation/registration failures are
10682 		 * already logged for us.
10683 		 */
10684 		withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type);
10685 	}
10686 
10687 	/*
10688 	 * slide old-style kxld relocations
10689 	 * NOTE: this is still used on embedded KCs built with kcgen
10690 	 * TODO: Remove this once we use the new kext linker everywhere!
10691 	 */
10692 	if (kaslrOffsets && vm_kernel_slide > 0) {
10693 		kernel_segment_command_t *text_segment = NULL;
10694 		text_segment = getsegbynamefromheader(mh, text_seg_name);
10695 		if (!text_segment) {
10696 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10697 			    "Can't find a TEXT segment named '%s' in macho header", text_seg_name);
10698 			goto finish;
10699 		}
10700 
10701 		__slideOldKaslrOffsets(mh, text_segment, kaslrOffsets);
10702 		/* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */
10703 		setAllVMAttributes();
10704 	}
10705 
10706 	/* Store the number of prelinked kexts in the registry so we can tell
10707 	 * when the system has been started from a prelinked kernel.
10708 	 */
10709 	registryRoot = IORegistryEntry::getRegistryRoot();
10710 	assert(registryRoot);
10711 
10712 	kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t));
10713 	assert(kcKextCount);
10714 	if (kcKextCount) {
10715 		OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey);
10716 		OSNumber *num;
10717 		num = OSDynamicCast(OSNumber, prop.get());
10718 		if (num) {
10719 			kcKextCount->addValue(num->unsigned64BitValue());
10720 		}
10721 		registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get());
10722 	}
10723 
10724 	OSKextLog(/* kext */ NULL,
10725 	    kOSKextLogProgressLevel |
10726 	    kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
10727 	    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10728 	    "%u prelinked kexts", infoDict->getCount());
10729 
10730 
10731 	if (kcUUID && infoDictKCUUID) {
10732 		*kcUUID = OSData::withData(infoDictKCUUID).detach();
10733 	}
10734 
10735 	result = true;
10736 
10737 finish:
10738 	return result;
10739 }
10740 
10741 bool
10742 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10743     OSDictionary *infoDict, const char *text_seg_name,
10744     OSSharedPtr<OSData> &kcUUID, kc_kind_t type)
10745 {
10746 	OSData  *result = NULL;
10747 	bool success = addKextsFromKextCollection(mh,
10748 	    infoDict,
10749 	    text_seg_name,
10750 	    &result,
10751 	    type);
10752 	if (success) {
10753 		kcUUID.reset(result, OSNoRetain);
10754 	}
10755 	return success;
10756 }
10757 
10758 static OSSharedPtr<OSObject> deferredAuxKCXML;
10759 bool
10760 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh,
10761     OSSharedPtr<OSObject> &parsedXML, kc_kind_t type)
10762 {
10763 	if (type != KCKindAuxiliary) {
10764 		return false;
10765 	}
10766 
10767 	kernel_mach_header_t *_mh;
10768 	_mh = (kernel_mach_header_t*)PE_get_kc_header(type);
10769 	if (!_mh || _mh != mh) {
10770 		return false;
10771 	}
10772 
10773 	if (deferredAuxKCXML) {
10774 		/* only allow this to be called once */
10775 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10776 		    "An Aux KC has already been registered for deferred processing.");
10777 		return false;
10778 	}
10779 
10780 	OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
10781 	if (!infoDict) {
10782 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10783 		    "The Aux KC has info dictionary");
10784 		return false;
10785 	}
10786 
10787 	OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
10788 	if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) {
10789 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10790 		    "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey);
10791 		return false;
10792 	}
10793 
10794 	/*
10795 	 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid
10796 	 * sysctl can return the UUID to user space which will check this
10797 	 * value for errors.
10798 	 */
10799 	memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(),
10800 	    kcUUID->getLength());
10801 	uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
10802 	auxkc_uuid_valid = TRUE;
10803 
10804 	deferredAuxKCXML = parsedXML;
10805 
10806 	return true;
10807 }
10808 
10809 OSSharedPtr<OSObject>
10810 OSKext::consumeDeferredKextCollection(kc_kind_t type)
10811 {
10812 	if (type != KCKindAuxiliary || !deferredAuxKCXML) {
10813 		return NULL;
10814 	}
10815 
10816 	return os::move(deferredAuxKCXML);
10817 }
10818 
10819 #if PRAGMA_MARK
10820 #pragma mark Profile-Guided-Optimization Support
10821 #endif
10822 
10823 // #include <InstrProfiling.h>
10824 extern "C" {
10825 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin,
10826     const char *DataEnd,
10827     const char *CountersBegin,
10828     const char *CountersEnd,
10829     const char *NamesBegin,
10830     const char *NamesEnd);
10831 int __llvm_profile_write_buffer_internal(char *Buffer,
10832     const char *DataBegin,
10833     const char *DataEnd,
10834     const char *CountersBegin,
10835     const char *CountersEnd,
10836     const char *NamesBegin,
10837     const char *NamesEnd);
10838 }
10839 
10840 
10841 static
10842 void
10843 OSKextPgoMetadataPut(char *pBuffer,
10844     size_t *position,
10845     size_t bufferSize,
10846     uint32_t *num_pairs,
10847     const char *key,
10848     const char *value)
10849 {
10850 	size_t strlen_key = strlen(key);
10851 	size_t strlen_value = strlen(value);
10852 	size_t len = strlen(key) + 1 + strlen(value) + 1;
10853 	char *pos = pBuffer + *position;
10854 	*position += len;
10855 	if (pBuffer && bufferSize && *position <= bufferSize) {
10856 		memcpy(pos, key, strlen_key); pos += strlen_key;
10857 		*(pos++) = '=';
10858 		memcpy(pos, value, strlen_value); pos += strlen_value;
10859 		*(pos++) = 0;
10860 		if (num_pairs) {
10861 			(*num_pairs)++;
10862 		}
10863 	}
10864 }
10865 
10866 
10867 static
10868 void
10869 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
10870 {
10871 	*position += strlen(key) + 1 + value_max + 1;
10872 }
10873 
10874 
10875 static
10876 void
10877 OSKextPgoMetadataPutAll(OSKext *kext,
10878     uuid_t instance_uuid,
10879     char *pBuffer,
10880     size_t *position,
10881     size_t bufferSize,
10882     uint32_t *num_pairs)
10883 {
10884 	_static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
10885 	//log_10 2^16 ≈ 4.82
10886 	const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
10887 	const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
10888 
10889 	if (!pBuffer) {
10890 		OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
10891 		OSKextPgoMetadataPutMax(position, "UUID", 36);
10892 		OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
10893 	} else {
10894 		uuid_string_t instance_uuid_string;
10895 		uuid_unparse(instance_uuid, instance_uuid_string);
10896 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10897 		    "INSTANCE", instance_uuid_string);
10898 
10899 		OSSharedPtr<OSData> uuid_data;
10900 		uuid_t uuid;
10901 		uuid_string_t uuid_string;
10902 		uuid_data = kext->copyUUID();
10903 		if (uuid_data) {
10904 			memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
10905 			uuid_unparse(uuid, uuid_string);
10906 			OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10907 			    "UUID", uuid_string);
10908 		}
10909 
10910 		clock_sec_t secs;
10911 		clock_usec_t usecs;
10912 		clock_get_calendar_microtime(&secs, &usecs);
10913 		assert(usecs < 1000000);
10914 		char timestamp[max_timestamp_string_size + 1];
10915 		_static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
10916 		snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
10917 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10918 		    "TIMESTAMP", timestamp);
10919 	}
10920 
10921 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10922 	    "NAME", kext->getIdentifierCString());
10923 
10924 	char versionCString[kOSKextVersionMaxLength];
10925 	OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
10926 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
10927 	    "VERSION", versionCString);
10928 }
10929 
10930 static
10931 size_t
10932 OSKextPgoMetadataSize(OSKext *kext)
10933 {
10934 	size_t position = 0;
10935 	uuid_t fakeuuid = {};
10936 	OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
10937 	return position;
10938 }
10939 
10940 int
10941 OSKextGrabPgoDataLocked(OSKext *kext,
10942     bool metadata,
10943     uuid_t instance_uuid,
10944     uint64_t *pSize,
10945     char *pBuffer,
10946     uint64_t bufferSize)
10947 {
10948 	int err = 0;
10949 
10950 	kernel_section_t *sect_prf_data = NULL;
10951 	kernel_section_t *sect_prf_name = NULL;
10952 	kernel_section_t *sect_prf_cnts = NULL;
10953 	uint64_t size;
10954 	size_t metadata_size = 0;
10955 	size_t offset_to_pairs = 0;
10956 
10957 	sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
10958 	sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
10959 	if (!sect_prf_name) {
10960 		// kextcache sometimes truncates the section name to 15 chars
10961 		// <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache
10962 		sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
10963 	}
10964 	sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
10965 
10966 	if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
10967 		err = ENOTSUP;
10968 		goto out;
10969 	}
10970 
10971 	size = __llvm_profile_get_size_for_buffer_internal(
10972 		(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
10973 		(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
10974 		(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
10975 
10976 	if (metadata) {
10977 		metadata_size = OSKextPgoMetadataSize(kext);
10978 		size += metadata_size;
10979 		size += sizeof(pgo_metadata_footer);
10980 	}
10981 
10982 
10983 	if (pSize) {
10984 		*pSize = size;
10985 	}
10986 
10987 	if (pBuffer && bufferSize) {
10988 		if (bufferSize < size) {
10989 			err = ERANGE;
10990 			goto out;
10991 		}
10992 
10993 		err = __llvm_profile_write_buffer_internal(
10994 			pBuffer,
10995 			(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
10996 			(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
10997 			(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
10998 
10999 		if (err) {
11000 			err = EIO;
11001 			goto out;
11002 		}
11003 
11004 		if (metadata) {
11005 			offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size;
11006 			if (offset_to_pairs > UINT32_MAX) {
11007 				err = E2BIG;
11008 				goto out;
11009 			}
11010 
11011 			char *end_of_buffer = pBuffer + size;
11012 			struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
11013 			char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
11014 
11015 			size_t metadata_position = 0;
11016 			uint32_t num_pairs = 0;
11017 			OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
11018 			while (metadata_position < metadata_size) {
11019 				metadata_buffer[metadata_position++] = 0;
11020 			}
11021 
11022 			struct pgo_metadata_footer footer;
11023 			footer.magic = htonl(0x6d657461);
11024 			footer.number_of_pairs = htonl( num_pairs );
11025 			footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs );
11026 			memcpy(footerp, &footer, sizeof(footer));
11027 		}
11028 	}
11029 
11030 out:
11031 	return err;
11032 }
11033 
11034 
11035 int
11036 OSKextGrabPgoData(uuid_t uuid,
11037     uint64_t *pSize,
11038     char *pBuffer,
11039     uint64_t bufferSize,
11040     int wait_for_unload,
11041     int metadata)
11042 {
11043 	int err = 0;
11044 	OSSharedPtr<OSKext> kext;
11045 
11046 
11047 	IORecursiveLockLock(sKextLock);
11048 
11049 	kext = OSKext::lookupKextWithUUID(uuid);
11050 	if (!kext) {
11051 		err = ENOENT;
11052 		goto out;
11053 	}
11054 
11055 	if (wait_for_unload) {
11056 		OSKextGrabPgoStruct s;
11057 
11058 		s.metadata = metadata;
11059 		s.pSize = pSize;
11060 		s.pBuffer = pBuffer;
11061 		s.bufferSize = bufferSize;
11062 		s.err = EINTR;
11063 
11064 		struct list_head *prev = &kext->pendingPgoHead;
11065 		struct list_head *next = kext->pendingPgoHead.next;
11066 
11067 		s.list_head.prev = prev;
11068 		s.list_head.next = next;
11069 
11070 		prev->next = &s.list_head;
11071 		next->prev = &s.list_head;
11072 
11073 		kext.reset();
11074 
11075 		IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
11076 
11077 		prev = s.list_head.prev;
11078 		next = s.list_head.next;
11079 
11080 		prev->next = next;
11081 		next->prev = prev;
11082 
11083 		err = s.err;
11084 	} else {
11085 		err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
11086 	}
11087 
11088 out:
11089 
11090 	IORecursiveLockUnlock(sKextLock);
11091 
11092 	return err;
11093 }
11094 
11095 void
11096 OSKextResetPgoCountersLock()
11097 {
11098 	IORecursiveLockLock(sKextLock);
11099 }
11100 
11101 void
11102 OSKextResetPgoCountersUnlock()
11103 {
11104 	IORecursiveLockUnlock(sKextLock);
11105 }
11106 
11107 
11108 extern unsigned int not_in_kdp;
11109 
11110 void
11111 OSKextResetPgoCounters()
11112 {
11113 	assert(!not_in_kdp);
11114 	uint32_t count = sLoadedKexts->getCount();
11115 	for (uint32_t i = 0; i < count; i++) {
11116 		OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
11117 		kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
11118 		if (!sect_prf_cnts) {
11119 			continue;
11120 		}
11121 		memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
11122 	}
11123 }
11124 
11125 OSSharedPtr<OSDictionary>
11126 OSKext::copyLoadedKextInfoByUUID(
11127 	OSArray * kextIdentifiers,
11128 	OSArray * infoKeys)
11129 {
11130 	OSSharedPtr<OSDictionary> result;
11131 	OSSharedPtr<OSDictionary> kextInfo;
11132 	uint32_t       max_count, i, j;
11133 	uint32_t       idCount = 0;
11134 	uint32_t       idIndex = 0;
11135 	IORecursiveLockLock(sKextLock);
11136 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
11137 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
11138 
11139 #if CONFIG_MACF
11140 	/* Is the calling process allowed to query kext info? */
11141 	if (current_task() != kernel_task) {
11142 		int                 macCheckResult      = 0;
11143 		kauth_cred_t        cred                = NULL;
11144 
11145 		cred = kauth_cred_get_with_ref();
11146 		macCheckResult = mac_kext_check_query(cred);
11147 		kauth_cred_unref(&cred);
11148 
11149 		if (macCheckResult != 0) {
11150 			OSKextLog(/* kext */ NULL,
11151 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11152 			    "Failed to query kext info (MAC policy error 0x%x).",
11153 			    macCheckResult);
11154 			goto finish;
11155 		}
11156 	}
11157 #endif
11158 
11159 	/* Empty list of UUIDs is equivalent to no list (get all).
11160 	 */
11161 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11162 		kextIdentifiers = NULL;
11163 	} else if (kextIdentifiers) {
11164 		idCount = kextIdentifiers->getCount();
11165 	}
11166 
11167 	/* Same for keys.
11168 	 */
11169 	if (infoKeys && !infoKeys->getCount()) {
11170 		infoKeys = NULL;
11171 	}
11172 
11173 	max_count = count[0] + count[1];
11174 	result = OSDictionary::withCapacity(max_count);
11175 	if (!result) {
11176 		goto finish;
11177 	}
11178 
11179 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
11180 		for (i = 0; i < count[j]; i++) {
11181 			OSKext       *thisKext     = NULL;        // do not release
11182 			Boolean       includeThis  = true;
11183 			uuid_t        thisKextUUID;
11184 			uuid_t        thisKextTextUUID;
11185 			OSSharedPtr<OSData> uuid_data;
11186 			uuid_string_t uuid_key;
11187 
11188 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
11189 			if (!thisKext) {
11190 				continue;
11191 			}
11192 
11193 			uuid_data = thisKext->copyUUID();
11194 			if (!uuid_data) {
11195 				continue;
11196 			}
11197 
11198 			memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
11199 
11200 			uuid_unparse(thisKextUUID, uuid_key);
11201 
11202 			uuid_data = thisKext->copyTextUUID();
11203 			if (!uuid_data) {
11204 				continue;
11205 			}
11206 			memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
11207 
11208 			/* Skip current kext if we have a list of UUIDs and
11209 			 * it isn't in the list.
11210 			 */
11211 			if (kextIdentifiers) {
11212 				includeThis = false;
11213 
11214 				for (idIndex = 0; idIndex < idCount; idIndex++) {
11215 					const OSString* wantedUUID = OSDynamicCast(OSString,
11216 					    kextIdentifiers->getObject(idIndex));
11217 
11218 					uuid_t uuid;
11219 					uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
11220 
11221 					if ((0 == uuid_compare(uuid, thisKextUUID))
11222 					    || (0 == uuid_compare(uuid, thisKextTextUUID))) {
11223 						includeThis = true;
11224 						/* Only need to find the first kext if multiple match,
11225 						 * ie. asking for the kernel uuid does not need to find
11226 						 * interface kexts or builtin static kexts.
11227 						 */
11228 						kextIdentifiers->removeObject(idIndex);
11229 						uuid_unparse(uuid, uuid_key);
11230 						break;
11231 					}
11232 				}
11233 			}
11234 
11235 			if (!includeThis) {
11236 				continue;
11237 			}
11238 
11239 			kextInfo = thisKext->copyInfo(infoKeys);
11240 			if (kextInfo) {
11241 				result->setObject(uuid_key, kextInfo.get());
11242 			}
11243 
11244 			if (kextIdentifiers && !kextIdentifiers->getCount()) {
11245 				goto finish;
11246 			}
11247 		}
11248 	}
11249 
11250 finish:
11251 	IORecursiveLockUnlock(sKextLock);
11252 
11253 	return result;
11254 }
11255 
11256 /*********************************************************************
11257 *********************************************************************/
11258 /* static */
11259 OSSharedPtr<OSDictionary>
11260 OSKext::copyKextCollectionInfo(
11261 	OSDictionary *requestDict,
11262 	OSArray  *infoKeys)
11263 {
11264 	OSSharedPtr<OSDictionary> result;
11265 	OSString *collectionType = NULL;
11266 	OSObject *rawLoadedState = NULL;
11267 	OSString *loadedState    = NULL;
11268 
11269 	kc_kind_t kc_request_kind = KCKindUnknown;
11270 	bool onlyLoaded = false;
11271 	bool onlyUnloaded = false;
11272 
11273 #if CONFIG_MACF
11274 	/* Is the calling process allowed to query kext info? */
11275 	if (current_task() != kernel_task) {
11276 		int                 macCheckResult      = 0;
11277 		kauth_cred_t        cred                = NULL;
11278 
11279 		cred = kauth_cred_get_with_ref();
11280 		macCheckResult = mac_kext_check_query(cred);
11281 		kauth_cred_unref(&cred);
11282 
11283 		if (macCheckResult != 0) {
11284 			OSKextLog(/* kext */ NULL,
11285 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11286 			    "Failed to query kext info (MAC policy error 0x%x).",
11287 			    macCheckResult);
11288 			goto finish;
11289 		}
11290 	}
11291 #endif
11292 
11293 	if (infoKeys && !infoKeys->getCount()) {
11294 		infoKeys = NULL;
11295 	}
11296 
11297 	collectionType = OSDynamicCast(OSString,
11298 	    _OSKextGetRequestArgument(requestDict,
11299 	    kKextRequestArgumentCollectionTypeKey));
11300 	if (!collectionType) {
11301 		OSKextLog(/* kext */ NULL,
11302 		    kOSKextLogErrorLevel |
11303 		    kOSKextLogIPCFlag,
11304 		    "Invalid '%s' argument to kext collection info request.",
11305 		    kKextRequestArgumentCollectionTypeKey);
11306 		goto finish;
11307 	}
11308 	if (collectionType->isEqualTo(kKCTypePrimary)) {
11309 		kc_request_kind = KCKindPrimary;
11310 	} else if (collectionType->isEqualTo(kKCTypeSystem)) {
11311 		kc_request_kind = KCKindPageable;
11312 	} else if (collectionType->isEqualTo(kKCTypeAuxiliary)) {
11313 		kc_request_kind = KCKindAuxiliary;
11314 	} else if (collectionType->isEqualTo(kKCTypeCodeless)) {
11315 		kc_request_kind = KCKindNone;
11316 	} else if (!collectionType->isEqualTo(kKCTypeAny)) {
11317 		OSKextLog(/* kext */ NULL,
11318 		    kOSKextLogErrorLevel |
11319 		    kOSKextLogIPCFlag,
11320 		    "Invalid '%s' argument value '%s' to kext collection info request.",
11321 		    kKextRequestArgumentCollectionTypeKey,
11322 		    collectionType->getCStringNoCopy());
11323 		goto finish;
11324 	}
11325 
11326 	rawLoadedState = _OSKextGetRequestArgument(requestDict,
11327 	    kKextRequestArgumentLoadedStateKey);
11328 	if (rawLoadedState) {
11329 		loadedState = OSDynamicCast(OSString, rawLoadedState);
11330 		if (!loadedState) {
11331 			OSKextLog(/* kext */ NULL,
11332 			    kOSKextLogErrorLevel |
11333 			    kOSKextLogIPCFlag,
11334 			    "Invalid '%s' argument to kext collection info request.",
11335 			    kKextRequestArgumentLoadedStateKey);
11336 			goto finish;
11337 		}
11338 	}
11339 	if (loadedState) {
11340 		if (loadedState->isEqualTo("Loaded")) {
11341 			onlyLoaded = true;
11342 		} else if (loadedState->isEqualTo("Unloaded")) {
11343 			onlyUnloaded = true;
11344 		} else if (!loadedState->isEqualTo("Any")) {
11345 			OSKextLog(/* kext */ NULL,
11346 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11347 			    "Invalid '%s' argument value '%s' for '%s' collection info",
11348 			    kKextRequestArgumentLoadedStateKey,
11349 			    loadedState->getCStringNoCopy(),
11350 			    collectionType->getCStringNoCopy());
11351 			goto finish;
11352 		}
11353 	}
11354 
11355 	result = OSDictionary::withCapacity(sKextsByID->getCount());
11356 	if (!result) {
11357 		goto finish;
11358 	}
11359 
11360 	IORecursiveLockLock(sKextLock);
11361 	{         // start block scope
11362 		sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11363 		{
11364 			OSKext       *thisKext    = NULL;  // do not release
11365 			OSSharedPtr<OSDictionary> kextInfo;
11366 
11367 			(void)thisKextID;
11368 
11369 			thisKext = OSDynamicCast(OSKext, obj);
11370 			if (!thisKext) {
11371 			        return false;
11372 			}
11373 
11374 			/*
11375 			 * skip the kext if it came from the wrong collection type
11376 			 * (and the caller requested a specific type)
11377 			 */
11378 			if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) {
11379 			        return false;
11380 			}
11381 
11382 			/*
11383 			 * respect the caller's desire to find only loaded or
11384 			 * unloaded kexts
11385 			 */
11386 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11387 			        return false;
11388 			}
11389 			if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11390 			        return false;
11391 			}
11392 
11393 			kextInfo = thisKext->copyInfo(infoKeys);
11394 			if (kextInfo) {
11395 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
11396 			}
11397 			return false;
11398 		});
11399 	} // end block scope
11400 	IORecursiveLockUnlock(sKextLock);
11401 
11402 finish:
11403 	return result;
11404 }
11405 
11406 /* static */
11407 OSSharedPtr<OSArray>
11408 OSKext::copyDextsInfo(
11409 	OSArray *kextIdentifiers,
11410 	OSArray *infoKeys)
11411 {
11412 	OSSharedPtr<OSArray> result = NULL;
11413 	uint32_t idCount = 0;
11414 	bool getActive = false;
11415 	bool getLoaded = false;
11416 	bool getUnloaded = false;
11417 	bool getPendingUpgrade = false;
11418 	unsigned int avgDextCount = 0;
11419 
11420 #if CONFIG_MACF
11421 	/* Is the calling process allowed to query dext info? */
11422 	if (current_task() != kernel_task) {
11423 		int                 macCheckResult      = 0;
11424 		kauth_cred_t        cred                = NULL;
11425 
11426 		cred = kauth_cred_get_with_ref();
11427 		macCheckResult = mac_kext_check_query(cred);
11428 		kauth_cred_unref(&cred);
11429 
11430 		if (macCheckResult != 0) {
11431 			OSKextLog(/* kext */ NULL,
11432 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11433 			    "Failed to query kext info (MAC policy error 0x%x).",
11434 			    macCheckResult);
11435 			goto finish;
11436 		}
11437 	}
11438 #endif
11439 	/*
11440 	 * No infoKeys means return everything we
11441 	 * know about the dexts.
11442 	 */
11443 	if (infoKeys && !infoKeys->getCount()) {
11444 		infoKeys = NULL;
11445 	}
11446 
11447 	/*
11448 	 * Empty list of bundle ids is equivalent to
11449 	 * no list (get all).
11450 	 */
11451 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11452 		kextIdentifiers = NULL;
11453 	} else if (kextIdentifiers) {
11454 		idCount = kextIdentifiers->getCount();
11455 	}
11456 
11457 	/*
11458 	 * Caller can specify which state of dexts to query.
11459 	 */
11460 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveKey)) {
11461 		getActive = true;
11462 	}
11463 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveLoadedKey)) {
11464 		getLoaded = true;
11465 	}
11466 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveUnloadedKey)) {
11467 		getUnloaded = true;
11468 	}
11469 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStatePendingUpgradeKey)) {
11470 		getPendingUpgrade = true;
11471 	}
11472 
11473 	/*
11474 	 * By default we are going to return all active and pendingUpgrade dexts
11475 	 * only.
11476 	 */
11477 	if (!(getActive || getLoaded || getUnloaded || getPendingUpgrade)) {
11478 		getActive = true;
11479 		getPendingUpgrade = true;
11480 	}
11481 
11482 	/*
11483 	 * We return a dictionary of dexts
11484 	 * for every group requested.
11485 	 */
11486 	avgDextCount = sLoadedDriverKitKexts->getCount() + sDriverKitToUpgradeByID->getCount();
11487 	result = OSArray::withCapacity(avgDextCount);
11488 	if (!result) {
11489 		goto finish;
11490 	}
11491 
11492 	IORecursiveLockLock(sKextLock);
11493 	{ // start block scope
11494 		if (getActive || getLoaded || getUnloaded) {
11495 			sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11496 			{
11497 				OSKext *thisKext = NULL;  // do not release
11498 				OSSharedPtr<OSDictionary> kextInfo;
11499 				Boolean includeThis = true;
11500 				(void)thisKextID;
11501 
11502 				thisKext = OSDynamicCast(OSKext, obj);
11503 				if (!thisKext || !thisKext->isDriverKit()) {
11504 				        return false;
11505 				}
11506 
11507 				/*
11508 				 * Skip current dext if we have a list of bundle IDs and
11509 				 * it isn't in the list.
11510 				 */
11511 				if (kextIdentifiers) {
11512 				        includeThis = false;
11513 
11514 				        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11515 				                const OSString * thisRequestID = OSDynamicCast(OSString,
11516 				                kextIdentifiers->getObject(idIndex));
11517 				                if (thisKextID->isEqualTo(thisRequestID)) {
11518 				                        includeThis = true;
11519 				                        break;
11520 						}
11521 					}
11522 				}
11523 
11524 				if (!includeThis) {
11525 				        return false;
11526 				}
11527 
11528 				OSSharedPtr<OSString> state;
11529 				if (sLoadedDriverKitKexts->getNextIndexOfObject(thisKext, 0) == -1U) {
11530 				        if (!(getActive || getUnloaded)) {
11531 				                return false;
11532 					}
11533 				        state = OSString::withCString(kOSBundleDextStateActiveUnloadedKey);
11534 				} else {
11535 				        if (!(getActive || getLoaded)) {
11536 				                return false;
11537 					}
11538 				        state = OSString::withCString(kOSBundleDextStateActiveLoadedKey);
11539 				}
11540 
11541 				kextInfo = thisKext->copyInfo(infoKeys);
11542 				if (kextInfo) {
11543 				        kextInfo->setObject(kOSBundleDextStateKey, state.get());
11544 				        result->setObject(kextInfo.get());
11545 				}
11546 
11547 				return false;
11548 			});
11549 		}
11550 
11551 		if (getPendingUpgrade) {
11552 			sDriverKitToUpgradeByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11553 			{
11554 				OSKext *thisKext = NULL;  // do not release
11555 				OSSharedPtr<OSDictionary> kextInfo;
11556 				Boolean includeThis = true;
11557 				(void)thisKextID;
11558 
11559 				thisKext = OSDynamicCast(OSKext, obj);
11560 				if (!thisKext) {
11561 				        return false;
11562 				}
11563 				__assert_only bool isDext = thisKext->isDriverKit();
11564 				assert(isDext == true);
11565 
11566 				/*
11567 				 * Skip current dext if we have a list of bundle IDs and
11568 				 * it isn't in the list.
11569 				 */
11570 				if (kextIdentifiers) {
11571 				        includeThis = false;
11572 
11573 				        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11574 				                const OSString * thisRequestID = OSDynamicCast(OSString,
11575 				                kextIdentifiers->getObject(idIndex));
11576 				                if (thisKextID->isEqualTo(thisRequestID)) {
11577 				                        includeThis = true;
11578 				                        break;
11579 						}
11580 					}
11581 				}
11582 
11583 				if (!includeThis) {
11584 				        return false;
11585 				}
11586 
11587 				kextInfo = thisKext->copyInfo(infoKeys);
11588 				if (kextInfo) {
11589 				        OSSharedPtr<OSString> state = OSString::withCString(kOSBundleDextStatePendingUpgradeKey);
11590 				        kextInfo->setObject(kOSBundleDextStateKey, state.get());
11591 				        result->setObject(kextInfo.get());
11592 				}
11593 				return false;
11594 			});
11595 		}
11596 	} // end block scope
11597 	IORecursiveLockUnlock(sKextLock);
11598 finish:
11599 	return result;
11600 }
11601 
11602 /*********************************************************************
11603 *********************************************************************/
11604 /* static */
11605 OSSharedPtr<OSDictionary>
11606 OSKext::copyLoadedKextInfo(
11607 	OSArray * kextIdentifiers,
11608 	OSArray * infoKeys)
11609 {
11610 	OSSharedPtr<OSDictionary> result;
11611 	uint32_t       idCount = 0;
11612 	bool           onlyLoaded;
11613 
11614 	IORecursiveLockLock(sKextLock);
11615 
11616 #if CONFIG_MACF
11617 	/* Is the calling process allowed to query kext info? */
11618 	if (current_task() != kernel_task) {
11619 		int                 macCheckResult      = 0;
11620 		kauth_cred_t        cred                = NULL;
11621 
11622 		cred = kauth_cred_get_with_ref();
11623 		macCheckResult = mac_kext_check_query(cred);
11624 		kauth_cred_unref(&cred);
11625 
11626 		if (macCheckResult != 0) {
11627 			OSKextLog(/* kext */ NULL,
11628 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11629 			    "Failed to query kext info (MAC policy error 0x%x).",
11630 			    macCheckResult);
11631 			goto finish;
11632 		}
11633 	}
11634 #endif
11635 
11636 	/* Empty list of bundle ids is equivalent to no list (get all).
11637 	 */
11638 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11639 		kextIdentifiers = NULL;
11640 	} else if (kextIdentifiers) {
11641 		idCount = kextIdentifiers->getCount();
11642 	}
11643 
11644 	/* Same for keys.
11645 	 */
11646 	if (infoKeys && !infoKeys->getCount()) {
11647 		infoKeys = NULL;
11648 	}
11649 
11650 	onlyLoaded =  (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
11651 
11652 	result = OSDictionary::withCapacity(128);
11653 	if (!result) {
11654 		goto finish;
11655 	}
11656 
11657 #if 0
11658 	OSKextLog(/* kext */ NULL,
11659 	    kOSKextLogErrorLevel |
11660 	    kOSKextLogGeneralFlag,
11661 	    "kaslr: vm_kernel_slide 0x%lx \n",
11662 	    vm_kernel_slide);
11663 	OSKextLog(/* kext */ NULL,
11664 	    kOSKextLogErrorLevel |
11665 	    kOSKextLogGeneralFlag,
11666 	    "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
11667 	    vm_kernel_stext, vm_kernel_etext);
11668 	OSKextLog(/* kext */ NULL,
11669 	    kOSKextLogErrorLevel |
11670 	    kOSKextLogGeneralFlag,
11671 	    "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
11672 	    vm_kernel_base, vm_kernel_top);
11673 	OSKextLog(/* kext */ NULL,
11674 	    kOSKextLogErrorLevel |
11675 	    kOSKextLogGeneralFlag,
11676 	    "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
11677 	    vm_kext_base, vm_kext_top);
11678 	OSKextLog(/* kext */ NULL,
11679 	    kOSKextLogErrorLevel |
11680 	    kOSKextLogGeneralFlag,
11681 	    "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
11682 	    vm_prelink_stext, vm_prelink_etext);
11683 	OSKextLog(/* kext */ NULL,
11684 	    kOSKextLogErrorLevel |
11685 	    kOSKextLogGeneralFlag,
11686 	    "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
11687 	    vm_prelink_sinfo, vm_prelink_einfo);
11688 	OSKextLog(/* kext */ NULL,
11689 	    kOSKextLogErrorLevel |
11690 	    kOSKextLogGeneralFlag,
11691 	    "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
11692 	    vm_slinkedit, vm_elinkedit);
11693 #endif
11694 	{         // start block scope
11695 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
11696 		{
11697 			OSKext       * thisKext     = NULL;        // do not release
11698 			Boolean        includeThis  = true;
11699 			OSSharedPtr<OSDictionary> kextInfo;
11700 
11701 			thisKext = OSDynamicCast(OSKext, obj);
11702 			if (!thisKext) {
11703 			        return false;
11704 			}
11705 
11706 			/* Skip current kext if not yet started and caller didn't request all.
11707 			 */
11708 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11709 			        return false;
11710 			}
11711 
11712 			/* Skip current kext if we have a list of bundle IDs and
11713 			 * it isn't in the list.
11714 			 */
11715 			if (kextIdentifiers) {
11716 			        includeThis = false;
11717 
11718 			        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11719 			                const OSString * thisRequestID = OSDynamicCast(OSString,
11720 			                kextIdentifiers->getObject(idIndex));
11721 			                if (thisKextID->isEqualTo(thisRequestID)) {
11722 			                        includeThis = true;
11723 			                        break;
11724 					}
11725 				}
11726 			}
11727 
11728 			if (!includeThis) {
11729 			        return false;
11730 			}
11731 
11732 			kextInfo = thisKext->copyInfo(infoKeys);
11733 			if (kextInfo) {
11734 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
11735 			}
11736 			return false;
11737 		});
11738 	}         // end block scope
11739 
11740 finish:
11741 	IORecursiveLockUnlock(sKextLock);
11742 
11743 	return result;
11744 }
11745 
11746 /*********************************************************************
11747 * Any info that needs to do allocations must goto finish on alloc
11748 * failure. Info that is just a lookup should just not set the object
11749 * if the info does not exist.
11750 *********************************************************************/
11751 #define _OSKextLoadInfoDictCapacity   (12)
11752 
11753 OSSharedPtr<OSDictionary>
11754 OSKext::copyInfo(OSArray * infoKeys)
11755 {
11756 	OSSharedPtr<OSDictionary>  result;
11757 	bool                       success                     = false;
11758 	OSSharedPtr<OSData>        headerData;
11759 	OSSharedPtr<OSData>        logData;
11760 	OSSharedPtr<OSNumber>      cpuTypeNumber;
11761 	OSSharedPtr<OSNumber>      cpuSubtypeNumber;
11762 	OSString                 * versionString               = NULL;        // do not release
11763 	OSString                 * bundleType                  = NULL;        // do not release
11764 	uint32_t                   executablePathCStringSize   = 0;
11765 	char                     * executablePathCString       = NULL;        // must kfree
11766 	OSSharedPtr<OSString>      executablePathString;
11767 	OSSharedPtr<OSData>        uuid;
11768 	OSSharedPtr<OSArray>       dependencyLoadTags;
11769 	OSSharedPtr<OSCollectionIterator>      metaClassIterator;
11770 	OSSharedPtr<OSArray>       metaClassInfo;
11771 	OSSharedPtr<OSDictionary>  metaClassDict;
11772 	OSMetaClass              * thisMetaClass               = NULL;        // do not release
11773 	OSSharedPtr<OSString>      metaClassName;
11774 	OSSharedPtr<OSString>      superclassName;
11775 	kc_format_t                kcformat;
11776 	uint32_t                   count, i;
11777 
11778 	result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
11779 	if (!result) {
11780 		goto finish;
11781 	}
11782 
11783 
11784 	/* Empty keys means no keys, but NULL is quicker to check.
11785 	 */
11786 	if (infoKeys && !infoKeys->getCount()) {
11787 		infoKeys = NULL;
11788 	}
11789 
11790 	if (!PE_get_primary_kc_format(&kcformat)) {
11791 		goto finish;
11792 	}
11793 
11794 	/* Headers, CPU type, and CPU subtype.
11795 	 */
11796 	if (!infoKeys ||
11797 	    _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
11798 	    _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
11799 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
11800 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
11801 		if (linkedExecutable && !isInterface()) {
11802 			kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
11803 			    linkedExecutable->getBytesNoCopy();
11804 
11805 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX
11806 			// do not return macho header info on shipping embedded - 19095897
11807 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
11808 				kernel_mach_header_t *  temp_kext_mach_hdr;
11809 				struct load_command *   lcp;
11810 
11811 				headerData = OSData::withBytes(kext_mach_hdr,
11812 				    (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
11813 				if (!headerData) {
11814 					goto finish;
11815 				}
11816 
11817 				// unslide any vmaddrs we return to userspace - 10726716
11818 				temp_kext_mach_hdr = (kernel_mach_header_t *)
11819 				    headerData->getBytesNoCopy();
11820 				if (temp_kext_mach_hdr == NULL) {
11821 					goto finish;
11822 				}
11823 
11824 				lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
11825 				for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) {
11826 					if (lcp->cmd == LC_SEGMENT_KERNEL) {
11827 						kernel_segment_command_t *  segp;
11828 						kernel_section_t *          secp;
11829 
11830 						segp = (kernel_segment_command_t *) lcp;
11831 						// 10543468 - if we jettisoned __LINKEDIT clear size info
11832 						if (flags.jettisonLinkeditSeg) {
11833 							if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
11834 								segp->vmsize = 0;
11835 								segp->fileoff = 0;
11836 								segp->filesize = 0;
11837 							}
11838 						}
11839 
11840 #if __arm__ || __arm64__
11841 						// iBoot disregards zero-size segments, just set their addresses to gVirtBase
11842 						// and unslide them to avoid vm assertion failures / kernel logging breakage.
11843 						if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) {
11844 							segp->vmaddr = gVirtBase;
11845 							for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
11846 								secp->size = 0; // paranoia :)
11847 								secp->addr = gVirtBase;
11848 							}
11849 						}
11850 #endif
11851 
11852 #if 0
11853 						OSKextLog(/* kext */ NULL,
11854 						    kOSKextLogErrorLevel |
11855 						    kOSKextLogGeneralFlag,
11856 						    "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
11857 						    __FUNCTION__, segp->segname, segp->vmaddr,
11858 						    VM_KERNEL_UNSLIDE(segp->vmaddr),
11859 						    segp->vmsize, segp->nsects);
11860 						if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
11861 						    (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
11862 						    (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
11863 						    (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
11864 						    (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
11865 							OSKextLog(/* kext */ NULL,
11866 							    kOSKextLogErrorLevel |
11867 							    kOSKextLogGeneralFlag,
11868 							    "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
11869 							    __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
11870 						}
11871 #endif
11872 						segp->vmaddr = ml_static_unslide(segp->vmaddr);
11873 
11874 						for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
11875 							secp->addr = ml_static_unslide(secp->addr);
11876 						}
11877 					}
11878 					lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
11879 				}
11880 				result->setObject(kOSBundleMachOHeadersKey, headerData.get());
11881 			}
11882 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX
11883 
11884 			if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
11885 				osLogDataHeaderRef *header;
11886 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
11887 
11888 				void *os_log_data               = NULL;
11889 				void *cstring_data              = NULL;
11890 				void *asan_cstring_data         = NULL;
11891 				unsigned long os_log_size       = 0;
11892 				unsigned long cstring_size      = 0;
11893 				unsigned long asan_cstring_size = 0;
11894 				uint32_t os_log_offset          = 0;
11895 				uint32_t cstring_offset         = 0;
11896 				uint32_t asan_cstring_offset    = 0;
11897 				bool res;
11898 
11899 				os_log_data         = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
11900 				os_log_offset       = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr;
11901 				cstring_data        = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
11902 				cstring_offset      = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr;
11903 				asan_cstring_data   = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size);
11904 				asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr;
11905 
11906 				header             = (osLogDataHeaderRef *) headerBytes;
11907 				header->version    = OS_LOG_HDR_VERSION;
11908 				header->sect_count = NUM_OS_LOG_SECTIONS;
11909 				header->sections[OS_LOG_SECT_IDX].sect_offset       = os_log_offset;
11910 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) os_log_size;
11911 				header->sections[CSTRING_SECT_IDX].sect_offset      = cstring_offset;
11912 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) cstring_size;
11913 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset;
11914 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) asan_cstring_size;
11915 
11916 
11917 				logData = OSData::withValue(*header);
11918 				if (!logData) {
11919 					goto finish;
11920 				}
11921 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
11922 				if (!res) {
11923 					goto finish;
11924 				}
11925 				if (os_log_data) {
11926 					res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
11927 					if (!res) {
11928 						goto finish;
11929 					}
11930 				}
11931 				if (cstring_data) {
11932 					res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
11933 					if (!res) {
11934 						goto finish;
11935 					}
11936 				}
11937 				if (asan_cstring_data) {
11938 					res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size);
11939 					if (!res) {
11940 						goto finish;
11941 					}
11942 				}
11943 				result->setObject(kOSBundleLogStringsKey, logData.get());
11944 			}
11945 
11946 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
11947 				cpuTypeNumber = OSNumber::withNumber(
11948 					(uint64_t) kext_mach_hdr->cputype,
11949 					8 * sizeof(kext_mach_hdr->cputype));
11950 				if (!cpuTypeNumber) {
11951 					goto finish;
11952 				}
11953 				result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get());
11954 			}
11955 
11956 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
11957 				cpuSubtypeNumber = OSNumber::withNumber(
11958 					(uint64_t) kext_mach_hdr->cpusubtype,
11959 					8 * sizeof(kext_mach_hdr->cpusubtype));
11960 				if (!cpuSubtypeNumber) {
11961 					goto finish;
11962 				}
11963 				result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get());
11964 			}
11965 		} else {
11966 			if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
11967 				osLogDataHeaderRef *header;
11968 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
11969 				bool res;
11970 
11971 				header             = (osLogDataHeaderRef *) headerBytes;
11972 				header->version    = OS_LOG_HDR_VERSION;
11973 				header->sect_count = NUM_OS_LOG_SECTIONS;
11974 				header->sections[OS_LOG_SECT_IDX].sect_offset       = 0;
11975 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) 0;
11976 				header->sections[CSTRING_SECT_IDX].sect_offset      = 0;
11977 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) 0;
11978 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0;
11979 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) 0;
11980 
11981 				logData = OSData::withValue(*header);
11982 				if (!logData) {
11983 					goto finish;
11984 				}
11985 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
11986 				if (!res) {
11987 					goto finish;
11988 				}
11989 				result->setObject(kOSBundleLogStringsKey, logData.get());
11990 			}
11991 		}
11992 	}
11993 
11994 	/* CFBundleIdentifier. We set this regardless because it's just stupid not to.
11995 	 */
11996 	result->setObject(kCFBundleIdentifierKey, bundleID.get());
11997 
11998 	/* kOSBundleDextUniqueIdentifierKey if present.
11999 	 */
12000 	if (isDriverKit() && dextUniqueID != NULL) {
12001 		result->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID.get());
12002 	}
12003 
12004 	/* CFBundlePackageType
12005 	 */
12006 	bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL;
12007 	if (bundleType) {
12008 		result->setObject(kCFBundlePackageTypeKey, bundleType);
12009 	}
12010 
12011 	/* CFBundleVersion.
12012 	 */
12013 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
12014 		versionString = OSDynamicCast(OSString,
12015 		    getPropertyForHostArch(kCFBundleVersionKey));
12016 		if (versionString) {
12017 			result->setObject(kCFBundleVersionKey, versionString);
12018 		}
12019 	}
12020 
12021 	/* OSBundleCompatibleVersion.
12022 	 */
12023 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
12024 		versionString = OSDynamicCast(OSString,
12025 		    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
12026 		if (versionString) {
12027 			result->setObject(kOSBundleCompatibleVersionKey, versionString);
12028 		}
12029 	}
12030 
12031 	/* Path.
12032 	 */
12033 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
12034 		if (path) {
12035 			result->setObject(kOSBundlePathKey, path.get());
12036 		}
12037 	}
12038 
12039 
12040 	/* OSBundleExecutablePath.
12041 	 */
12042 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
12043 		if (path && executableRelPath) {
12044 			uint32_t pathLength = path->getLength();         // gets incremented below
12045 
12046 			// +1 for slash, +1 for \0
12047 			executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
12048 
12049 			executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
12050 			    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);         // +1 for \0
12051 			if (!executablePathCString) {
12052 				goto finish;
12053 			}
12054 			strlcpy(executablePathCString, path->getCStringNoCopy(),
12055 			    executablePathCStringSize);
12056 			executablePathCString[pathLength++] = '/';
12057 			executablePathCString[pathLength++] = '\0';
12058 			strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
12059 			    executablePathCStringSize);
12060 
12061 			executablePathString = OSString::withCString(executablePathCString);
12062 
12063 			if (!executablePathString) {
12064 				goto finish;
12065 			}
12066 
12067 			result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
12068 		} else if (flags.builtin) {
12069 			result->setObject(kOSBundleExecutablePathKey, bundleID.get());
12070 		} else if (isDriverKit()) {
12071 			if (path) {
12072 				// +1 for slash, +1 for \0
12073 				uint32_t pathLength = path->getLength();
12074 				executablePathCStringSize = pathLength + 2;
12075 
12076 				executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
12077 				    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
12078 				if (!executablePathCString) {
12079 					goto finish;
12080 				}
12081 				strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize);
12082 				executablePathCString[pathLength++] = '/';
12083 				executablePathCString[pathLength++] = '\0';
12084 
12085 				executablePathString = OSString::withCString(executablePathCString);
12086 
12087 				if (!executablePathString) {
12088 					goto finish;
12089 				}
12090 
12091 				result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
12092 			}
12093 		}
12094 	}
12095 
12096 	/* UUID, if the kext has one.
12097 	 */
12098 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
12099 		uuid = copyUUID();
12100 		if (uuid) {
12101 			result->setObject(kOSBundleUUIDKey, uuid.get());
12102 		}
12103 	}
12104 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
12105 		uuid = copyTextUUID();
12106 		if (uuid) {
12107 			result->setObject(kOSBundleTextUUIDKey, uuid.get());
12108 		}
12109 	}
12110 
12111 	/*
12112 	 * Info.plist digest
12113 	 */
12114 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) {
12115 		OSData *digest;
12116 		digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL;
12117 		if (digest) {
12118 			result->setObject(kOSKextInfoPlistDigestKey, digest);
12119 		}
12120 	}
12121 
12122 	/*
12123 	 * Collection type
12124 	 */
12125 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) {
12126 		result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString()));
12127 	}
12128 
12129 	/*
12130 	 * Collection availability
12131 	 */
12132 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) {
12133 		result->setObject(kOSKextAuxKCAvailabilityKey,
12134 		    isLoadable() ? kOSBooleanTrue : kOSBooleanFalse);
12135 	}
12136 
12137 	/*
12138 	 * Allows user load
12139 	 */
12140 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) {
12141 		OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey));
12142 		if (allowUserLoad) {
12143 			result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad);
12144 		}
12145 	}
12146 
12147 	/*
12148 	 * Bundle Dependencies (OSBundleLibraries)
12149 	 */
12150 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) {
12151 		OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey));
12152 		if (libraries) {
12153 			result->setObject(kOSBundleLibrariesKey, libraries);
12154 		}
12155 	}
12156 
12157 	/*****
12158 	 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
12159 	 */
12160 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
12161 		result->setObject(kOSKernelResourceKey,
12162 		    isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
12163 	}
12164 
12165 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
12166 		result->setObject(kOSBundleIsInterfaceKey,
12167 		    isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
12168 	}
12169 
12170 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
12171 		result->setObject(kOSBundlePrelinkedKey,
12172 		    isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
12173 	}
12174 
12175 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
12176 		result->setObject(kOSBundleStartedKey,
12177 		    isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
12178 	}
12179 
12180 	/* LoadTag (Index).
12181 	 */
12182 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
12183 		OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
12184 		    /* numBits */ 8 * sizeof(loadTag));
12185 		if (!scratchNumber) {
12186 			goto finish;
12187 		}
12188 		result->setObject(kOSBundleLoadTagKey, scratchNumber.get());
12189 	}
12190 
12191 	/* LoadAddress, LoadSize.
12192 	 */
12193 	if (!infoKeys ||
12194 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
12195 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
12196 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
12197 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
12198 	    _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
12199 		bool is_dext = isDriverKit();
12200 		if (isInterface() || flags.builtin || linkedExecutable || is_dext) {
12201 			/* These go to userspace via serialization, so we don't want any doubts
12202 			 * about their size.
12203 			 */
12204 			uint64_t    loadAddress     = 0;
12205 			uint32_t    loadSize        = 0;
12206 			uint32_t    wiredSize       = 0;
12207 			uint64_t    execLoadAddress = 0;
12208 			uint32_t    execLoadSize    = 0;
12209 
12210 			/* Interfaces always report 0 load address & size.
12211 			 * Just the way they roll.
12212 			 *
12213 			 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
12214 			 * xxx - shouldn't have one!
12215 			 */
12216 
12217 			if (flags.builtin || linkedExecutable) {
12218 				kernel_mach_header_t     *mh  = NULL;
12219 				kernel_segment_command_t *seg = NULL;
12220 
12221 				if (flags.builtin) {
12222 					loadAddress = kmod_info->address;
12223 					loadSize    = (uint32_t)kmod_info->size;
12224 				} else {
12225 					loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
12226 					loadSize = linkedExecutable->getLength();
12227 				}
12228 				mh = (kernel_mach_header_t *)loadAddress;
12229 				loadAddress = ml_static_unslide(loadAddress);
12230 
12231 				/* Walk through the kext, looking for the first executable
12232 				 * segment in case we were asked for its size/address.
12233 				 */
12234 				for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
12235 					if (seg->initprot & VM_PROT_EXECUTE) {
12236 						execLoadAddress = ml_static_unslide(seg->vmaddr);
12237 						execLoadSize = (uint32_t)seg->vmsize;
12238 						break;
12239 					}
12240 				}
12241 
12242 				/* If we have a kmod_info struct, calculated the wired size
12243 				 * from that. Otherwise it's the full load size.
12244 				 */
12245 				if (kmod_info) {
12246 					wiredSize = loadSize - (uint32_t)kmod_info->hdr_size;
12247 				} else {
12248 					wiredSize = loadSize;
12249 				}
12250 			} else if (is_dext) {
12251 				/*
12252 				 * DriverKit userspace executables do not have a kernel linkedExecutable,
12253 				 * so we "fake" their address range with the LoadTag.
12254 				 */
12255 				if (loadTag) {
12256 					loadAddress = execLoadAddress = loadTag;
12257 					loadSize = execLoadSize = 1;
12258 				}
12259 			}
12260 
12261 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
12262 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12263 					(unsigned long long)(loadAddress),
12264 					/* numBits */ 8 * sizeof(loadAddress));
12265 				if (!scratchNumber) {
12266 					goto finish;
12267 				}
12268 				result->setObject(kOSBundleLoadAddressKey, scratchNumber.get());
12269 			}
12270 			if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) {
12271 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
12272 				    && loadAddress && loadSize) {
12273 					void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary);
12274 					if (!baseAddress) {
12275 						goto finish;
12276 					}
12277 
12278 					OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12279 						(unsigned long long)ml_static_unslide((vm_offset_t)baseAddress),
12280 						/* numBits */ 8 * sizeof(loadAddress));
12281 					if (!scratchNumber) {
12282 						goto finish;
12283 					}
12284 					result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get());
12285 				}
12286 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
12287 				    && (this == sKernelKext) && gBuiltinKmodsCount) {
12288 					result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
12289 				}
12290 			}
12291 
12292 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
12293 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12294 					(unsigned long long)(execLoadAddress),
12295 					/* numBits */ 8 * sizeof(execLoadAddress));
12296 				if (!scratchNumber) {
12297 					goto finish;
12298 				}
12299 				result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get());
12300 			}
12301 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
12302 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12303 					(unsigned long long)(loadSize),
12304 					/* numBits */ 8 * sizeof(loadSize));
12305 				if (!scratchNumber) {
12306 					goto finish;
12307 				}
12308 				result->setObject(kOSBundleLoadSizeKey, scratchNumber.get());
12309 			}
12310 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
12311 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12312 					(unsigned long long)(execLoadSize),
12313 					/* numBits */ 8 * sizeof(execLoadSize));
12314 				if (!scratchNumber) {
12315 					goto finish;
12316 				}
12317 				result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get());
12318 			}
12319 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
12320 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12321 					(unsigned long long)(wiredSize),
12322 					/* numBits */ 8 * sizeof(wiredSize));
12323 				if (!scratchNumber) {
12324 					goto finish;
12325 				}
12326 				result->setObject(kOSBundleWiredSizeKey, scratchNumber.get());
12327 			}
12328 		}
12329 	}
12330 
12331 	/* OSBundleDependencies. In descending order for
12332 	 * easy compatibility with kextstat(8).
12333 	 */
12334 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
12335 		if ((count = getNumDependencies())) {
12336 			dependencyLoadTags = OSArray::withCapacity(count);
12337 			result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get());
12338 
12339 			i = count - 1;
12340 			do {
12341 				OSKext * dependency = OSDynamicCast(OSKext,
12342 				    dependencies->getObject(i));
12343 
12344 				if (!dependency) {
12345 					continue;
12346 				}
12347 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12348 					(unsigned long long)dependency->getLoadTag(),
12349 					/* numBits*/ 8 * sizeof(loadTag));
12350 				if (!scratchNumber) {
12351 					goto finish;
12352 				}
12353 				dependencyLoadTags->setObject(scratchNumber.get());
12354 			} while (i--);
12355 		}
12356 	}
12357 
12358 	/* OSBundleMetaClasses.
12359 	 */
12360 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
12361 		if (metaClasses && metaClasses->getCount()) {
12362 			metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get());
12363 			metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
12364 			if (!metaClassIterator || !metaClassInfo) {
12365 				goto finish;
12366 			}
12367 			result->setObject(kOSBundleClassesKey, metaClassInfo.get());
12368 
12369 			while ((thisMetaClass = OSDynamicCast(OSMetaClass,
12370 			    metaClassIterator->getNextObject()))) {
12371 				metaClassDict = OSDictionary::withCapacity(3);
12372 				if (!metaClassDict) {
12373 					goto finish;
12374 				}
12375 
12376 				metaClassName = OSString::withCString(thisMetaClass->getClassName());
12377 				if (thisMetaClass->getSuperClass()) {
12378 					superclassName = OSString::withCString(
12379 						thisMetaClass->getSuperClass()->getClassName());
12380 				}
12381 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
12382 				    8 * sizeof(unsigned int));
12383 
12384 				/* Bail if any of the essentials is missing. The root class lacks a superclass,
12385 				 * of course.
12386 				 */
12387 				if (!metaClassDict || !metaClassName || !scratchNumber) {
12388 					goto finish;
12389 				}
12390 
12391 				metaClassInfo->setObject(metaClassDict.get());
12392 				metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get());
12393 				if (superclassName) {
12394 					metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get());
12395 				}
12396 				metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get());
12397 			}
12398 		}
12399 	}
12400 
12401 	/* OSBundleRetainCount.
12402 	 */
12403 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
12404 		{
12405 			int kextRetainCount = getRetainCount() - 1;
12406 			if (isLoaded()) {
12407 				kextRetainCount--;
12408 			}
12409 			OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12410 				(int)kextRetainCount,
12411 				/* numBits*/ 8 * sizeof(int));
12412 			if (scratchNumber) {
12413 				result->setObject(kOSBundleRetainCountKey, scratchNumber.get());
12414 			}
12415 		}
12416 	}
12417 
12418 	success = true;
12419 
12420 finish:
12421 	if (executablePathCString) {
12422 		kfree_data(executablePathCString, executablePathCStringSize);
12423 	}
12424 	if (!success) {
12425 		result.reset();
12426 	}
12427 	return result;
12428 }
12429 
12430 /*********************************************************************
12431 *********************************************************************/
12432 /* static */
12433 bool
12434 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
12435 {
12436 	bool ok;
12437 	OSSharedPtr<OSKext> kext;
12438 
12439 	IORecursiveLockLock(sKextLock);
12440 	kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain);
12441 	IORecursiveLockUnlock(sKextLock);
12442 
12443 	if (!kext || !kext->path || !kext->userExecutableRelPath) {
12444 		return false;
12445 	}
12446 	snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
12447 	    kext->path->getCStringNoCopy(),
12448 	    kext->userExecutableRelPath->getCStringNoCopy());
12449 	ok = true;
12450 
12451 	return ok;
12452 }
12453 
12454 /*********************************************************************
12455 *********************************************************************/
12456 /* static */
12457 OSReturn
12458 OSKext::requestResource(
12459 	const char                    * kextIdentifierCString,
12460 	const char                    * resourceNameCString,
12461 	OSKextRequestResourceCallback   callback,
12462 	void                          * context,
12463 	OSKextRequestTag              * requestTagOut)
12464 {
12465 	OSReturn                        result = kOSReturnError;
12466 	OSSharedPtr<OSKext>             callbackKext;        // looked up
12467 
12468 	OSKextRequestTag   requestTag      = -1;
12469 	OSSharedPtr<OSNumber>           requestTagNum;
12470 	OSSharedPtr<OSDictionary>       requestDict;
12471 	OSSharedPtr<OSString>           kextIdentifier;
12472 	OSSharedPtr<OSString>           resourceName;
12473 
12474 	OSSharedPtr<OSDictionary>       callbackRecord;
12475 	OSSharedPtr<OSValueObject<OSKextRequestResourceCallback> > callbackWrapper;
12476 
12477 	OSSharedPtr<OSValueObject<void *> > contextWrapper;
12478 
12479 	IORecursiveLockLock(sKextLock);
12480 
12481 	if (requestTagOut) {
12482 		*requestTagOut = kOSKextRequestTagInvalid;
12483 	}
12484 
12485 	/* If requests to user space are disabled, don't go any further */
12486 	if (!sKernelRequestsEnabled) {
12487 		OSKextLog(/* kext */ NULL,
12488 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12489 		    "Can't request resource %s for %s - requests to user space are disabled.",
12490 		    resourceNameCString,
12491 		    kextIdentifierCString);
12492 		result = kOSKextReturnDisabled;
12493 		goto finish;
12494 	}
12495 
12496 	if (!kextIdentifierCString || !resourceNameCString || !callback) {
12497 		result = kOSKextReturnInvalidArgument;
12498 		goto finish;
12499 	}
12500 
12501 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
12502 	if (!callbackKext) {
12503 		OSKextLog(/* kext */ NULL,
12504 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12505 		    "Resource request has bad callback address.");
12506 		result = kOSKextReturnInvalidArgument;
12507 		goto finish;
12508 	}
12509 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
12510 		OSKextLog(/* kext */ NULL,
12511 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12512 		    "Resource request callback is in a kext that is not started.");
12513 		result = kOSKextReturnInvalidArgument;
12514 		goto finish;
12515 	}
12516 
12517 	/* Do not allow any new requests to be made on a kext that is unloading.
12518 	 */
12519 	if (callbackKext->flags.stopping) {
12520 		result = kOSKextReturnStopping;
12521 		goto finish;
12522 	}
12523 
12524 	/* If we're wrapped the next available request tag around to the negative
12525 	 * numbers, we can't service any more requests.
12526 	 */
12527 	if (sNextRequestTag == kOSKextRequestTagInvalid) {
12528 		OSKextLog(/* kext */ NULL,
12529 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12530 		    "No more request tags available; restart required.");
12531 		result = kOSKextReturnNoResources;
12532 		goto finish;
12533 	}
12534 	requestTag = sNextRequestTag++;
12535 
12536 	result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
12537 	    requestDict);
12538 	if (result != kOSReturnSuccess) {
12539 		goto finish;
12540 	}
12541 
12542 	kextIdentifier = OSString::withCString(kextIdentifierCString);
12543 	resourceName   = OSString::withCString(resourceNameCString);
12544 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
12545 	    8 * sizeof(requestTag));
12546 	if (!kextIdentifier ||
12547 	    !resourceName ||
12548 	    !requestTagNum ||
12549 	    !_OSKextSetRequestArgument(requestDict.get(),
12550 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) ||
12551 	    !_OSKextSetRequestArgument(requestDict.get(),
12552 	    kKextRequestArgumentNameKey, resourceName.get()) ||
12553 	    !_OSKextSetRequestArgument(requestDict.get(),
12554 	    kKextRequestArgumentRequestTagKey, requestTagNum.get())) {
12555 		result = kOSKextReturnNoMemory;
12556 		goto finish;
12557 	}
12558 
12559 	callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection());
12560 	if (!callbackRecord) {
12561 		result = kOSKextReturnNoMemory;
12562 		goto finish;
12563 	}
12564 	// we validate callback address at call time
12565 	callbackWrapper = OSValueObjectWithValue(callback);
12566 	if (context) {
12567 		contextWrapper = OSValueObjectWithValue(context);
12568 	}
12569 	if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
12570 	    kKextRequestArgumentCallbackKey, callbackWrapper.get())) {
12571 		result = kOSKextReturnNoMemory;
12572 		goto finish;
12573 	}
12574 
12575 	if (context) {
12576 		if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
12577 		    kKextRequestArgumentContextKey, contextWrapper.get())) {
12578 			result = kOSKextReturnNoMemory;
12579 			goto finish;
12580 		}
12581 	}
12582 
12583 	/* Only post the requests after all the other potential failure points
12584 	 * have been passed.
12585 	 */
12586 	if (!sKernelRequests->setObject(requestDict.get()) ||
12587 	    !sRequestCallbackRecords->setObject(callbackRecord.get())) {
12588 		result = kOSKextReturnNoMemory;
12589 		goto finish;
12590 	}
12591 
12592 	OSKext::pingIOKitDaemon();
12593 
12594 	result = kOSReturnSuccess;
12595 	if (requestTagOut) {
12596 		*requestTagOut = requestTag;
12597 	}
12598 
12599 finish:
12600 
12601 	/* If we didn't succeed, yank the request & callback
12602 	 * from their holding arrays.
12603 	 */
12604 	if (result != kOSReturnSuccess) {
12605 		unsigned int index;
12606 
12607 		index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0);
12608 		if (index != (unsigned int)-1) {
12609 			sKernelRequests->removeObject(index);
12610 		}
12611 		index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0);
12612 		if (index != (unsigned int)-1) {
12613 			sRequestCallbackRecords->removeObject(index);
12614 		}
12615 	}
12616 
12617 	OSKext::considerUnloads(/* rescheduleOnly? */ true);
12618 
12619 	IORecursiveLockUnlock(sKextLock);
12620 
12621 	return result;
12622 }
12623 
12624 OSReturn
12625 OSKext::requestDaemonLaunch(
12626 	OSString *kextIdentifier,
12627 	OSString *serverName,
12628 	OSNumber *serverTag,
12629 	OSBoolean *reslide,
12630 	IOUserServerCheckInToken * checkInToken,
12631 	OSData *serverDUI)
12632 {
12633 	OSReturn       result        = kOSReturnError;
12634 	OSSharedPtr<OSDictionary> requestDict;
12635 	unsigned int size = 0;
12636 	const char *dextUniqueIDCString = NULL;
12637 
12638 	if (!kextIdentifier || !serverName || !serverTag || !checkInToken) {
12639 		return kOSKextReturnInvalidArgument;
12640 	}
12641 
12642 	if (serverDUI != NULL) {
12643 		dextUniqueIDCString = getDextUniqueIDCString(serverDUI, &size);
12644 	}
12645 
12646 	IORecursiveLockLock(sKextLock);
12647 
12648 	OSKextLog(/* kext */ NULL,
12649 	    kOSKextLogDebugLevel |
12650 	    kOSKextLogGeneralFlag,
12651 	    "Requesting daemon launch for %s %s with serverName %s and tag %llu%s",
12652 	    kextIdentifier->getCStringNoCopy(),
12653 	    (dextUniqueIDCString != NULL)?dextUniqueIDCString:"",
12654 	    serverName->getCStringNoCopy(),
12655 	    serverTag->unsigned64BitValue(),
12656 	    reslide == kOSBooleanTrue ? " with reslid shared cache" : ""
12657 	    );
12658 
12659 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict);
12660 	if (result != kOSReturnSuccess) {
12661 		goto finish;
12662 	}
12663 
12664 	if (!_OSKextSetRequestArgument(requestDict.get(),
12665 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
12666 	    !_OSKextSetRequestArgument(requestDict.get(),
12667 	    kKextRequestArgumentDriverExtensionServerName, serverName) ||
12668 	    !_OSKextSetRequestArgument(requestDict.get(),
12669 	    kKextRequestArgumentDriverExtensionServerTag, serverTag) ||
12670 	    !_OSKextSetRequestArgument(requestDict.get(),
12671 	    kKextRequestArgumentDriverExtensionReslideSharedCache, reslide) ||
12672 	    !_OSKextSetRequestArgument(requestDict.get(),
12673 	    kKextRequestArgumentCheckInToken, checkInToken)) {
12674 		result = kOSKextReturnNoMemory;
12675 		goto finish;
12676 	}
12677 
12678 	if (serverDUI) {
12679 		if (!_OSKextSetRequestArgument(requestDict.get(),
12680 		    kOSBundleDextUniqueIdentifierKey, serverDUI)) {
12681 			result = kOSKextReturnNoMemory;
12682 			goto finish;
12683 		}
12684 	}
12685 
12686 	/* Only post the requests after all the other potential failure points
12687 	 * have been passed.
12688 	 */
12689 	if (!sKernelRequests->setObject(requestDict.get())) {
12690 		result = kOSKextReturnNoMemory;
12691 		goto finish;
12692 	}
12693 	OSKext::pingIOKitDaemon();
12694 
12695 	result = kOSReturnSuccess;
12696 finish:
12697 	IORecursiveLockUnlock(sKextLock);
12698 	if (dextUniqueIDCString) {
12699 		kfree_data(dextUniqueIDCString, size);
12700 	}
12701 	return result;
12702 }
12703 
12704 OSReturn
12705 OSKext::notifyDextUpgrade(
12706 	OSString *kextIdentifier,
12707 	OSData *dextUniqueIdentifier)
12708 {
12709 	OSReturn result = kOSReturnError;
12710 	OSSharedPtr<OSDictionary> requestDict;
12711 	unsigned int size = 0;
12712 	const char *dextUniqueIDCString = getDextUniqueIDCString(dextUniqueIdentifier, &size);
12713 	assert(dextUniqueIDCString != NULL);
12714 
12715 	IORecursiveLockLock(sKextLock);
12716 
12717 	OSKextLog(NULL,
12718 	    kOSKextLogDebugLevel |
12719 	    kOSKextLogGeneralFlag,
12720 	    "Notifying of dext upgrade for %s with UniqueID %s",
12721 	    kextIdentifier->getCStringNoCopy(), dextUniqueIDCString);
12722 
12723 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonUpgradeNotification, requestDict);
12724 	if (result != kOSReturnSuccess) {
12725 		goto finish;
12726 	}
12727 
12728 	if (!_OSKextSetRequestArgument(requestDict.get(),
12729 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
12730 	    !_OSKextSetRequestArgument(requestDict.get(),
12731 	    kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) {
12732 		result = kOSKextReturnNoMemory;
12733 		goto finish;
12734 	}
12735 
12736 	/* Only post the requests after all the other potential failure points
12737 	 * have been passed.
12738 	 */
12739 	if (!sKernelRequests->setObject(requestDict.get())) {
12740 		result = kOSKextReturnNoMemory;
12741 		goto finish;
12742 	}
12743 	OSKext::pingIOKitDaemon();
12744 
12745 	result = kOSReturnSuccess;
12746 finish:
12747 	IORecursiveLockUnlock(sKextLock);
12748 
12749 	if (dextUniqueIDCString != NULL) {
12750 		kfree_data(dextUniqueIDCString, size);
12751 	}
12752 	return result;
12753 }
12754 
12755 /*********************************************************************
12756 * Assumes sKextLock is held.
12757 *********************************************************************/
12758 /* static */
12759 OSReturn
12760 OSKext::dequeueCallbackForRequestTag(
12761 	OSKextRequestTag    requestTag,
12762 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
12763 {
12764 	OSDictionary * callbackRecordOutRaw = NULL;
12765 	OSReturn result;
12766 
12767 	result = dequeueCallbackForRequestTag(requestTag,
12768 	    &callbackRecordOutRaw);
12769 
12770 	if (kOSReturnSuccess == result) {
12771 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
12772 	}
12773 
12774 	return result;
12775 }
12776 OSReturn
12777 OSKext::dequeueCallbackForRequestTag(
12778 	OSKextRequestTag    requestTag,
12779 	OSDictionary     ** callbackRecordOut)
12780 {
12781 	OSReturn   result = kOSReturnError;
12782 	OSSharedPtr<OSNumber> requestTagNum;
12783 
12784 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
12785 	    8 * sizeof(requestTag));
12786 	if (!requestTagNum) {
12787 		goto finish;
12788 	}
12789 
12790 	result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(),
12791 	    callbackRecordOut);
12792 
12793 finish:
12794 	return result;
12795 }
12796 
12797 /*********************************************************************
12798 * Assumes sKextLock is held.
12799 *********************************************************************/
12800 /* static */
12801 OSReturn
12802 OSKext::dequeueCallbackForRequestTag(
12803 	OSNumber     *    requestTagNum,
12804 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
12805 {
12806 	OSDictionary * callbackRecordOutRaw = NULL;
12807 	OSReturn result;
12808 
12809 	result = dequeueCallbackForRequestTag(requestTagNum,
12810 	    &callbackRecordOutRaw);
12811 
12812 	if (kOSReturnSuccess == result) {
12813 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
12814 	}
12815 
12816 	return result;
12817 }
12818 OSReturn
12819 OSKext::dequeueCallbackForRequestTag(
12820 	OSNumber     *    requestTagNum,
12821 	OSDictionary ** callbackRecordOut)
12822 {
12823 	OSReturn        result          = kOSKextReturnInvalidArgument;
12824 	OSDictionary  * callbackRecord  = NULL;        // retain if matched!
12825 	OSNumber      * callbackTagNum  = NULL;        // do not release
12826 	unsigned int    count, i;
12827 
12828 	result = kOSReturnError;
12829 	count = sRequestCallbackRecords->getCount();
12830 	for (i = 0; i < count; i++) {
12831 		callbackRecord = OSDynamicCast(OSDictionary,
12832 		    sRequestCallbackRecords->getObject(i));
12833 		if (!callbackRecord) {
12834 			goto finish;
12835 		}
12836 
12837 		/* If we don't find a tag, we basically have a leak here. Maybe
12838 		 * we should just remove it.
12839 		 */
12840 		callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
12841 			    callbackRecord, kKextRequestArgumentRequestTagKey));
12842 		if (!callbackTagNum) {
12843 			goto finish;
12844 		}
12845 
12846 		/* We could be even more paranoid and check that all the incoming
12847 		 * args match what's in the callback record.
12848 		 */
12849 		if (callbackTagNum->isEqualTo(requestTagNum)) {
12850 			if (callbackRecordOut) {
12851 				*callbackRecordOut = callbackRecord;
12852 				callbackRecord->retain();
12853 			}
12854 			sRequestCallbackRecords->removeObject(i);
12855 			result = kOSReturnSuccess;
12856 			goto finish;
12857 		}
12858 	}
12859 	result = kOSKextReturnNotFound;
12860 
12861 finish:
12862 	return result;
12863 }
12864 
12865 
12866 /*********************************************************************
12867 * Busy timeout triage
12868 *********************************************************************/
12869 /* static */
12870 bool
12871 OSKext::pendingIOKitDaemonRequests(void)
12872 {
12873 	return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
12874 }
12875 
12876 /*********************************************************************
12877 * Acquires and releases sKextLock
12878 *
12879 * This function is designed to be called by kernelmanagerd and driverkitd
12880 * and it gathers all codeless kext and dext personalities, and then attempts
12881 * to map a System (pageable) KC and an Auxiliary (aux) KC.
12882 *
12883 * The pageable and aux KC can be loaded only once at boot time.
12884 * Even if the pageable or aux KC fail to load - this function will
12885 * not allow a new pageable or aux KC to be installed by subsequent calls.
12886 * This is done to avoid security issues where userspace has been compromised
12887 * or the pageable kc has been tampered with and the attacker
12888 * attempts to re-load a malicious variant.
12889 * However dexts can be dynamically loaded, so this function can be used
12890 * to request the installation of a new set of dexts even after boot time.
12891 *
12892 *
12893 *
12894 * Return: if a KC fails to load the return value will contain:
12895 *         kOSKextReturnKCLoadFailure. If the pageable KC fails,
12896 *         the return value will contain kOSKextReturnKCLoadFailureSystemKC.
12897 *         Similarly, if the aux kc load fails, the return value will
12898 *         contain kOSKextReturnKCLoadFailureAuxKC. The two values
12899 *         compose with each other and with kOSKextReturnKCLoadFailure.
12900 *********************************************************************/
12901 /* static */
12902 OSReturn
12903 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused)
12904 {
12905 	static bool daemon_ready = false;
12906 
12907 	OSReturn ret = kOSKextReturnInvalidArgument;
12908 	OSReturn kcerr = 0;
12909 	bool start_matching = false;
12910 
12911 	bool allow_fileset_load = !daemon_ready;
12912 #if !(defined(__x86_64__) || defined(__i386__))
12913 	/* never allow KCs full of kexts on non-x86 machines */
12914 	allow_fileset_load = false;
12915 #endif
12916 
12917 	/*
12918 	 * Change with 70582300
12919 	 */
12920 #if 0 || !defined(VM_MAPPED_KEXTS)
12921 	/*
12922 	 * On platforms that don't support the SystemKC or a file-backed
12923 	 * AuxKC, the kext receipt for 3rd party kexts loaded by the booter
12924 	 * needs to be queried before we load any codeless kexts or release
12925 	 * any 3rd party kexts to run. On platforms that support a file-backed
12926 	 * AuxKC, this process is done via the kext audit mechanism.
12927 	 */
12928 
12929 	printf("KextLog: waiting for kext receipt to be queried.\n");
12930 	while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) {
12931 		IOSleep(30);
12932 	}
12933 #endif /* !VM_MAPPED_KEXTS */
12934 
12935 	/*
12936 	 * Get the args from the request. Right now we need the file
12937 	 * name for the pageable and the aux kext collection file sets.
12938 	 */
12939 	OSDictionary * requestArgs                = NULL;        // do not release
12940 	OSString     * pageable_filepath          = NULL;        // do not release
12941 	OSString     * aux_filepath               = NULL;        // do not release
12942 	OSArray      * codeless_kexts             = NULL;        // do not release
12943 
12944 	kernel_mach_header_t *akc_mh              = NULL;
12945 
12946 	requestArgs = OSDynamicCast(OSDictionary,
12947 	    requestDict->getObject(kKextRequestArgumentsKey));
12948 
12949 	if (requestArgs == NULL) {
12950 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12951 		    "KextLog: No arguments in plist for loading fileset kext\n");
12952 		printf("KextLog: No arguments in plist for loading fileset kext\n");
12953 		return ret;
12954 	}
12955 
12956 	ret = kOSKextReturnDisabled;
12957 
12958 	IORecursiveLockLock(sKextLock);
12959 
12960 	if (!sLoadEnabled) {
12961 		OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12962 		    "KextLog: Kext loading is disabled (attempt to load KCs).");
12963 		IORecursiveLockUnlock(sKextLock);
12964 		return ret;
12965 	}
12966 
12967 	pageable_filepath = OSDynamicCast(OSString,
12968 	    requestArgs->getObject(kKextRequestArgumentPageableKCFilename));
12969 
12970 	if (allow_fileset_load && pageable_filepath != NULL) {
12971 		printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy());
12972 
12973 		ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable);
12974 		if (ret) {
12975 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
12976 			    "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
12977 
12978 			printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
12979 			ret = kOSKextReturnKCLoadFailure;
12980 			kcerr |= kOSKextReturnKCLoadFailureSystemKC;
12981 			goto try_auxkc;
12982 		}
12983 		/*
12984 		 * Even if the AuxKC fails to load, we still want to send
12985 		 * the System KC personalities to the catalog for matching
12986 		 */
12987 		start_matching = true;
12988 	} else if (pageable_filepath != NULL) {
12989 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
12990 		    "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy());
12991 		ret = kOSKextReturnUnsupported;
12992 	}
12993 
12994 try_auxkc:
12995 	akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
12996 	if (akc_mh) {
12997 		/*
12998 		 * If we try to load a deferred AuxKC, then don't ever attempt
12999 		 * a filesystem map of a file
13000 		 */
13001 		allow_fileset_load = false;
13002 
13003 		/*
13004 		 * This function is only called once per boot, so we haven't
13005 		 * yet loaded an AuxKC. If we have registered the AuxKC mach
13006 		 * header, that means that the kext collection has been placed
13007 		 * in memory for us by the booter, and is waiting for us to
13008 		 * process it.  Grab the deferred XML plist of info
13009 		 * dictionaries and add all the kexts.
13010 		 */
13011 		OSSharedPtr<OSObject>  parsedXML;
13012 		OSSharedPtr<OSData>    loaded_kcUUID;
13013 		OSDictionary          *infoDict;
13014 		parsedXML = consumeDeferredKextCollection(KCKindAuxiliary);
13015 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
13016 #if !defined(VM_MAPPED_KEXTS)
13017 		/*
13018 		 * On platforms where we don't dynamically wire-down / page-in
13019 		 * kext memory, we need to maintain the invariant that if the
13020 		 * AuxKC in memory does not contain a kext receipt, then we
13021 		 * should not load any of the kexts.
13022 		 */
13023 		size_t receipt_sz = 0;
13024 		if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) {
13025 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13026 			    "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt");
13027 			ret = kOSKextReturnKCLoadFailure;
13028 			goto try_codeless;
13029 		}
13030 #endif
13031 		if (infoDict) {
13032 			bool added;
13033 			printf("KextLog: Adding kexts from in-memory AuxKC\n");
13034 			added = OSKext::addKextsFromKextCollection(akc_mh, infoDict,
13035 			    kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary);
13036 			if (!loaded_kcUUID) {
13037 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13038 				    "KextLog: WARNING: did not find UUID in deferred Aux KC!");
13039 			} else if (!added) {
13040 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13041 				    "KextLog: WARNING: Failed to load AuxKC from memory.");
13042 			}
13043 			/* only return success if the pageable load (above) was successful */
13044 			if (ret != kOSKextReturnKCLoadFailure) {
13045 				ret = kOSReturnSuccess;
13046 			}
13047 			/* the registration of the AuxKC parsed out the KC's UUID already */
13048 		} else {
13049 			if (daemon_ready) {
13050 				/*
13051 				 * Complain, but don't return an error if this isn't the first time the
13052 				 * IOKit daemon is checking in. If the daemon ever restarts, we will
13053 				 * hit this case because we've already consumed the deferred personalities.
13054 				 * We return success here so that a call to this function from a restarted
13055 				 * daemon with no codeless kexts will succeed.
13056 				 */
13057 				OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13058 				    "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart");
13059 				if (ret != kOSKextReturnKCLoadFailure) {
13060 					ret = kOSReturnSuccess;
13061 				}
13062 			} else {
13063 				/* this is a real error case */
13064 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13065 				    "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary");
13066 				printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n");
13067 				ret = kOSKextReturnKCLoadFailure;
13068 				kcerr |= kOSKextReturnKCLoadFailureAuxKC;
13069 			}
13070 		}
13071 	}
13072 
13073 	aux_filepath = OSDynamicCast(OSString,
13074 	    requestArgs->getObject(kKextRequestArgumentAuxKCFilename));
13075 	if (allow_fileset_load && aux_filepath != NULL) {
13076 		printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy());
13077 
13078 		ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary);
13079 		if (ret) {
13080 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13081 			    "KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
13082 
13083 			printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
13084 			ret = kOSKextReturnKCLoadFailure;
13085 			kcerr |= kOSKextReturnKCLoadFailureAuxKC;
13086 			goto try_codeless;
13087 		}
13088 		start_matching = true;
13089 	} else if (aux_filepath != NULL) {
13090 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13091 		    "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy());
13092 		if (ret != kOSKextReturnKCLoadFailure) {
13093 			ret = kOSKextReturnUnsupported;
13094 		}
13095 	}
13096 
13097 try_codeless:
13098 	/*
13099 	 * Load codeless kexts last so that there is no possibilty of a
13100 	 * codeless kext bundle ID preventing a kext in the system KC from
13101 	 * loading
13102 	 */
13103 	codeless_kexts = OSDynamicCast(OSArray,
13104 	    requestArgs->getObject(kKextRequestArgumentCodelessPersonalities));
13105 	if (codeless_kexts != NULL) {
13106 		uint32_t count = codeless_kexts->getCount();
13107 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13108 		    "KextLog: loading %d codeless kexts/dexts", count);
13109 		for (uint32_t i = 0; i < count; i++) {
13110 			OSDictionary *infoDict;
13111 			infoDict = OSDynamicCast(OSDictionary,
13112 			    codeless_kexts->getObject(i));
13113 			if (!infoDict) {
13114 				continue;
13115 			}
13116 			// instantiate a new kext, and don't hold a reference
13117 			// (the kext subsystem will hold one implicitly)
13118 			OSKext::withCodelessInfo(infoDict, NULL);
13119 		}
13120 		/* ignore errors that are not KC load failures */
13121 		if (ret != kOSKextReturnKCLoadFailure) {
13122 			ret = kOSReturnSuccess;
13123 		}
13124 		start_matching = true;
13125 	}
13126 
13127 	/* send personalities to the IOCatalog once */
13128 	if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) {
13129 		OSKext::sendAllKextPersonalitiesToCatalog(true);
13130 		/*
13131 		 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark
13132 		 * things as active and start all the delayed matching: the
13133 		 * dext and codeless kext personalities should have all been
13134 		 * delivered via this one call.
13135 		 */
13136 		if (!daemon_ready) {
13137 			OSKext::setIOKitDaemonActive();
13138 			OSKext::setDeferredLoadSucceeded(TRUE);
13139 			IOService::iokitDaemonLaunched();
13140 		}
13141 		if (sOSKextWasResetAfterUserspaceReboot) {
13142 			sOSKextWasResetAfterUserspaceReboot = false;
13143 			OSKext::setIOKitDaemonActive();
13144 			IOService::startDeferredMatches();
13145 		}
13146 	}
13147 
13148 	if (ret == kOSKextReturnKCLoadFailure) {
13149 		ret |= kcerr;
13150 	}
13151 
13152 	/*
13153 	 * Only allow this function to attempt to load the pageable and
13154 	 * aux KCs once per boot.
13155 	 */
13156 	daemon_ready = true;
13157 
13158 	IORecursiveLockUnlock(sKextLock);
13159 
13160 	return ret;
13161 }
13162 
13163 OSReturn
13164 OSKext::resetMutableSegments(void)
13165 {
13166 	kernel_segment_command_t *seg = NULL;
13167 	kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
13168 	u_int index = 0;
13169 	OSKextSavedMutableSegment *savedSegment = NULL;
13170 	uintptr_t kext_slide = PE_get_kc_slide(kc_type);
13171 	OSReturn err;
13172 
13173 	if (!savedMutableSegments) {
13174 		OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
13175 		    "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString());
13176 		err = kOSKextReturnInternalError;
13177 		goto finish;
13178 	}
13179 
13180 	for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) {
13181 		if (!segmentIsMutable(seg)) {
13182 			continue;
13183 		}
13184 		uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
13185 		uint64_t vmsize = seg->vmsize;
13186 		err = kOSKextReturnInternalError;
13187 		for (index = 0; index < savedMutableSegments->getCount(); index++) {
13188 			savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index));
13189 			assert(savedSegment);
13190 			if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) {
13191 				OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
13192 				    "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13193 				err = savedSegment->restoreContents(seg);
13194 				if (err != kOSReturnSuccess) {
13195 					panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13196 				}
13197 			}
13198 		}
13199 		if (err != kOSReturnSuccess) {
13200 			panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13201 		}
13202 	}
13203 	err = kOSReturnSuccess;
13204 finish:
13205 	return err;
13206 }
13207 
13208 
13209 /*********************************************************************
13210 * Assumes sKextLock is held.
13211 *********************************************************************/
13212 /* static */
13213 OSReturn
13214 OSKext::loadKCFileSet(
13215 	const char *filepath,
13216 	kc_kind_t   type)
13217 {
13218 #if VM_MAPPED_KEXTS
13219 	/* we only need to load filesets on systems that support VM_MAPPED kexts */
13220 	OSReturn err;
13221 	struct vnode *vp = NULL;
13222 	void *fileset_control;
13223 	off_t fsize;
13224 	bool pageable = (type == KCKindPageable);
13225 
13226 	if ((pageable && pageableKCloaded) ||
13227 	    (!pageable && auxKCloaded)) {
13228 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13229 		    "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux"));
13230 
13231 		return kOSKextReturnInvalidArgument;
13232 	}
13233 
13234 	/* Do not allow AuxKC to load if Pageable KC is not loaded */
13235 	if (!pageable && !pageableKCloaded) {
13236 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13237 		    "Trying to load the Aux KC without loading the Pageable KC");
13238 		return kOSKextReturnInvalidArgument;
13239 	}
13240 
13241 	fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize);
13242 
13243 	if (fileset_control == NULL) {
13244 		printf("Could not get memory control object for file %s", filepath);
13245 
13246 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13247 		    "Could not get memory control object for file %s", filepath);
13248 		return kOSKextReturnInvalidArgument;
13249 	}
13250 	if (vp == NULL) {
13251 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13252 		    "Could not find vnode for file %s", filepath);
13253 		return kOSKextReturnInvalidArgument;
13254 	}
13255 
13256 	kernel_mach_header_t *mh = NULL;
13257 	uintptr_t slide = 0;
13258 
13259 #if CONFIG_CSR
13260 	/*
13261 	 * When SIP is enabled, the KC we map must be SIP-protected
13262 	 */
13263 	if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) {
13264 		struct vnode_attr va;
13265 		int error;
13266 		VATTR_INIT(&va);
13267 		VATTR_WANTED(&va, va_flags);
13268 		error = vnode_getattr(vp, &va, vfs_context_current());
13269 		if (error) {
13270 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13271 			    "vnode_getattr(%s) failed (error=%d)", filepath, error);
13272 			err = kOSKextReturnInternalError;
13273 			goto finish;
13274 		}
13275 		if (!(va.va_flags & SF_RESTRICTED)) {
13276 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13277 			    "Path to KC '%s' is not SIP-protected", filepath);
13278 			err = kOSKextReturnInvalidArgument;
13279 			goto finish;
13280 		}
13281 	}
13282 #endif
13283 
13284 	err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL);
13285 	if (err) {
13286 		printf("KextLog: mapKCFileSet returned %d\n", err);
13287 
13288 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13289 		    "mapKCFileSet returned %d\n", err);
13290 
13291 		err = kOSKextReturnInvalidArgument;
13292 	}
13293 
13294 #if CONFIG_CSR
13295 finish:
13296 #endif
13297 	/* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */
13298 	assert(vp != NULL);
13299 	if (err == kOSReturnSuccess) {
13300 		PE_set_kc_vp(type, vp);
13301 		if (pageable) {
13302 			pageableKCloaded = true;
13303 		} else {
13304 			auxKCloaded = true;
13305 		}
13306 	} else {
13307 		vnode_put(vp);
13308 	}
13309 
13310 	return err;
13311 #else
13312 	(void)filepath;
13313 	(void)type;
13314 	return kOSKextReturnUnsupported;
13315 #endif // VM_MAPPED_KEXTS
13316 }
13317 
13318 #if defined(__x86_64__) || defined(__i386__)
13319 /*********************************************************************
13320 * Assumes sKextLock is held.
13321 *********************************************************************/
13322 /* static */
13323 OSReturn
13324 OSKext::mapKCFileSet(
13325 	void                 *control,
13326 	vm_size_t            fsize,
13327 	kernel_mach_header_t **mhp,
13328 	off_t                file_offset,
13329 	uintptr_t            *slidep,
13330 	bool                 pageable,
13331 	void                 *map_entry_list)
13332 {
13333 	bool fileset_load = false;
13334 	kern_return_t ret;
13335 	OSReturn err;
13336 	kernel_section_t *infoPlistSection = NULL;
13337 	OSDictionary *infoDict = NULL;
13338 
13339 	OSSharedPtr<OSObject> parsedXML;
13340 	OSSharedPtr<OSString> errorString;
13341 	OSSharedPtr<OSData> loaded_kcUUID;
13342 
13343 	/* Check if initial load for file set */
13344 	if (*mhp == NULL) {
13345 		fileset_load = true;
13346 
13347 		/* Get a page aligned address from kext map to map the file */
13348 		vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize);
13349 		if (pagealigned_addr == 0) {
13350 			return kOSKextReturnNoMemory;
13351 		}
13352 
13353 		*mhp = (kernel_mach_header_t *)pagealigned_addr;
13354 
13355 		/* Allocate memory for bailout mechanism */
13356 		map_entry_list = allocate_kcfileset_map_entry_list();
13357 		if (map_entry_list == NULL) {
13358 			return kOSKextReturnNoMemory;
13359 		}
13360 	}
13361 
13362 	uintptr_t *slideptr = fileset_load ? slidep : NULL;
13363 	err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list);
13364 	/* mhp and slideptr are updated by mapKCTextSegment */
13365 	if (err) {
13366 		if (fileset_load) {
13367 			deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13368 		}
13369 		return err;
13370 	}
13371 
13372 	/* Initialize the kc header globals */
13373 	if (fileset_load) {
13374 		if (pageable) {
13375 			PE_set_kc_header(KCKindPageable, *mhp, *slidep);
13376 		} else {
13377 			PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep);
13378 		}
13379 	}
13380 
13381 	/* Iterate through all the segments and map necessary segments */
13382 	struct load_command *lcp = (struct load_command *) (*mhp + 1);
13383 	for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) {
13384 		vm_map_offset_t start;
13385 		kernel_mach_header_t *k_mh = NULL;
13386 		kernel_segment_command_t * seg = NULL;
13387 		struct fileset_entry_command *fse = NULL;
13388 
13389 		if (lcp->cmd == LC_SEGMENT_KERNEL) {
13390 			seg = (kernel_segment_command_t *)lcp;
13391 			start = ((uintptr_t)(seg->vmaddr)) + *slidep;
13392 		} else if (lcp->cmd == LC_FILESET_ENTRY) {
13393 			fse = (struct fileset_entry_command *)lcp;
13394 			k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep);
13395 
13396 			/* Map the segments of the mach-o binary */
13397 			err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list);
13398 			if (err) {
13399 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13400 				return kOSKextReturnInvalidArgument;
13401 			}
13402 			continue;
13403 		} else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) {
13404 			/* Check if the Aux KC is built pageable style */
13405 			if (!pageable && !fileset_load && !auxKCloaded) {
13406 				resetAuxKCSegmentOnUnload = true;
13407 			}
13408 			continue;
13409 		} else {
13410 			continue;
13411 		}
13412 
13413 		if (fileset_load) {
13414 			if (seg->vmsize == 0) {
13415 				continue;
13416 			}
13417 
13418 			/* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */
13419 			if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 &&
13420 			    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 &&
13421 			    strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 &&
13422 			    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) {
13423 				continue;
13424 			}
13425 		} else {
13426 			if (seg->vmsize == 0) {
13427 				continue;
13428 			}
13429 
13430 			/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
13431 			if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
13432 			    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
13433 			    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
13434 				continue;
13435 			}
13436 		}
13437 
13438 		ret = vm_map_kcfileset_segment(
13439 			&start, seg->vmsize,
13440 			(memory_object_control_t)control, seg->fileoff, seg->maxprot);
13441 
13442 		if (ret != KERN_SUCCESS) {
13443 			if (fileset_load) {
13444 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13445 			}
13446 			return kOSKextReturnInvalidArgument;
13447 		}
13448 		add_kcfileset_map_entry(map_entry_list, start, seg->vmsize);
13449 	}
13450 
13451 	/* Return if regular mach-o */
13452 	if (!fileset_load) {
13453 		return 0;
13454 	}
13455 
13456 	/*
13457 	 * Fixup for the Pageable KC and the Aux KC is done by
13458 	 * i386_slide_kext_collection_mh_addrs, but it differs in
13459 	 * following ways:
13460 	 *
13461 	 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands.
13462 	 * The fixup of kext segments and kext load commands are done at kext
13463 	 * load time by calling i386_slide_individual_kext.
13464 	 *
13465 	 * AuxKC old style: Fixup all the segments and all the load commands.
13466 	 *
13467 	 * AuxKC pageable style: Same as the Pageable KC.
13468 	 */
13469 	bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false));
13470 	ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header);
13471 	if (ret != KERN_SUCCESS) {
13472 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13473 		return kOSKextReturnInvalidArgument;
13474 	}
13475 
13476 	/* Get the prelink info dictionary */
13477 	infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection);
13478 	parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
13479 	if (parsedXML) {
13480 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
13481 	}
13482 
13483 	if (!infoDict) {
13484 		const char *errorCString = "(unknown error)";
13485 
13486 		if (errorString && errorString->getCStringNoCopy()) {
13487 			errorCString = errorString->getCStringNoCopy();
13488 		} else if (parsedXML) {
13489 			errorCString = "not a dictionary";
13490 		}
13491 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13492 		    "Error unserializing kext info plist section: %s.", errorCString);
13493 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13494 		return kOSKextReturnInvalidArgument;
13495 	}
13496 
13497 	/* Validate that the Kext Collection is prelinked to the loaded KC */
13498 	err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary);
13499 	if (err) {
13500 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13501 		return kOSKextReturnInvalidArgument;
13502 	}
13503 
13504 	/* Set Protection of Segments */
13505 	OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary);
13506 
13507 	OSKext::addKextsFromKextCollection(*mhp,
13508 	    infoDict, kPrelinkTextSegment,
13509 	    loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary);
13510 
13511 	/* Copy in the KC UUID */
13512 	if (!loaded_kcUUID) {
13513 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13514 		    "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux");
13515 	} else if (pageable) {
13516 		pageablekc_uuid_valid = TRUE;
13517 		memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
13518 		uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string);
13519 	} else {
13520 		auxkc_uuid_valid = TRUE;
13521 		memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
13522 		uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
13523 	}
13524 
13525 	deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable);
13526 
13527 	return 0;
13528 }
13529 
13530 /*********************************************************************
13531 * Assumes sKextLock is held.
13532 *********************************************************************/
13533 /* static */
13534 OSReturn
13535 OSKext::mapKCTextSegment(
13536 	void                 *control,
13537 	kernel_mach_header_t **mhp,
13538 	off_t                file_offset,
13539 	uintptr_t            *slidep,
13540 	void                 *map_entry_list)
13541 {
13542 	kern_return_t ret;
13543 	vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t),
13544 	    PAGE_MASK);
13545 	vm_map_offset_t load_command_map_size = 0;
13546 	kernel_mach_header_t *base_mh = *mhp;
13547 
13548 	/* Map the mach header at start of fileset for now (vmaddr = 0) */
13549 	ret = vm_map_kcfileset_segment(
13550 		(vm_map_offset_t *)&base_mh, mach_header_map_size,
13551 		(memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE));
13552 
13553 	if (ret != KERN_SUCCESS) {
13554 		printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret);
13555 
13556 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13557 		    "Failed to map mach header of kc fileset with error %d", ret);
13558 		return kOSKextReturnInvalidArgument;
13559 	}
13560 
13561 	if (slidep) {
13562 		/* Verify that it's an MH_FILESET */
13563 		if (base_mh->filetype != MH_FILESET) {
13564 			printf("Kext Log: mapKCTextSegment mach header filetype"
13565 			    " is not an MH_FILESET, it is %x", base_mh->filetype);
13566 
13567 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13568 			    "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype);
13569 
13570 			/* Unmap the mach header */
13571 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13572 			return kOSKextReturnInvalidArgument;
13573 		}
13574 	}
13575 
13576 	/* Map the remaining pages of load commands */
13577 	if (base_mh->sizeofcmds > mach_header_map_size) {
13578 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
13579 		load_command_map_size = base_mh->sizeofcmds - mach_header_map_size;
13580 
13581 		/* Map the load commands */
13582 		ret = vm_map_kcfileset_segment(
13583 			&load_command_addr, load_command_map_size,
13584 			(memory_object_control_t)control, file_offset + mach_header_map_size,
13585 			(VM_PROT_READ | VM_PROT_WRITE));
13586 
13587 		if (ret != KERN_SUCCESS) {
13588 			printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret);
13589 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13590 			    "Failed to map load commands of kc fileset with error %d", ret);
13591 
13592 			/* Unmap the mach header */
13593 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13594 			return kOSKextReturnInvalidArgument;
13595 		}
13596 	}
13597 
13598 	kernel_segment_command_t *text_seg;
13599 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT);
13600 
13601 	/* Calculate the slide and vm addr of mach header */
13602 	if (slidep) {
13603 		*mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr);
13604 		*slidep = ((uintptr_t)*mhp) - text_seg->vmaddr;
13605 	}
13606 
13607 	/* Cache the text segment size and file offset before unmapping */
13608 	vm_map_offset_t text_segment_size = text_seg->vmsize;
13609 	vm_object_offset_t text_segment_fileoff = text_seg->fileoff;
13610 	vm_prot_t text_maxprot = text_seg->maxprot;
13611 
13612 	/* Unmap the first page and loadcommands and map the text segment */
13613 	ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13614 	assert(ret == KERN_SUCCESS);
13615 
13616 	if (load_command_map_size) {
13617 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
13618 		ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size);
13619 		assert(ret == KERN_SUCCESS);
13620 	}
13621 
13622 	/* Map the text segment at actual vm addr specified in fileset */
13623 	ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size,
13624 	    (memory_object_control_t)control, text_segment_fileoff, text_maxprot);
13625 	if (ret != KERN_SUCCESS) {
13626 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13627 		    "Failed to map Text segment of kc fileset with error %d", ret);
13628 		return kOSKextReturnInvalidArgument;
13629 	}
13630 
13631 	add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size);
13632 	return 0;
13633 }
13634 
13635 /*********************************************************************
13636 * Assumes sKextLock is held.
13637 *********************************************************************/
13638 /* static */
13639 OSReturn
13640 OSKext::protectKCFileSet(
13641 	kernel_mach_header_t *mh,
13642 	kc_kind_t            type)
13643 {
13644 	vm_map_t                    kext_map        = g_kext_map;
13645 	kernel_segment_command_t  * seg             = NULL;
13646 	vm_map_offset_t             start           = 0;
13647 	vm_map_offset_t             end             = 0;
13648 	OSReturn                    ret             = 0;
13649 
13650 	/* Set VM permissions */
13651 	seg = firstsegfromheader((kernel_mach_header_t *)mh);
13652 	while (seg) {
13653 		start = round_page(seg->vmaddr);
13654 		end = trunc_page(seg->vmaddr + seg->vmsize);
13655 
13656 		/*
13657 		 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS
13658 		 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT
13659 		 * for the Aux KC as well.
13660 		 */
13661 		if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 ||
13662 		    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 ||
13663 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 ||
13664 		    (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload &&
13665 		    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) {
13666 			ret = OSKext_protect((kernel_mach_header_t *)mh,
13667 			    kext_map, start, end, seg->maxprot, TRUE, type);
13668 			if (ret != KERN_SUCCESS) {
13669 				printf("OSKext protect failed with error %d", ret);
13670 				return kOSKextReturnInvalidArgument;
13671 			}
13672 
13673 			ret = OSKext_protect((kernel_mach_header_t *)mh,
13674 			    kext_map, start, end, seg->initprot, FALSE, type);
13675 			if (ret != KERN_SUCCESS) {
13676 				printf("OSKext protect failed with error %d", ret);
13677 				return kOSKextReturnInvalidArgument;
13678 			}
13679 
13680 			ret = OSKext_wire((kernel_mach_header_t *)mh,
13681 			    kext_map, start, end, seg->initprot, FALSE, type);
13682 			if (ret != KERN_SUCCESS) {
13683 				printf("OSKext wire failed with error %d", ret);
13684 				return kOSKextReturnInvalidArgument;
13685 			}
13686 		}
13687 
13688 		seg = nextsegfromheader((kernel_mach_header_t *) mh, seg);
13689 	}
13690 
13691 	return 0;
13692 }
13693 
13694 /*********************************************************************
13695 * Assumes sKextLock is held.
13696 *********************************************************************/
13697 /* static */
13698 void
13699 OSKext::freeKCFileSetcontrol(void)
13700 {
13701 	PE_reset_all_kc_vp();
13702 }
13703 
13704 /*********************************************************************
13705 * Assumes sKextLock is held.
13706 *
13707 * resetKCFileSetSegments: Kext start function expects data segment to
13708 * be pristine on every load, unmap the dirty segments on unload and
13709 * remap them from FileSet on disk. Remap all segments of kext since
13710 * fixups are done per kext and not per segment.
13711 *********************************************************************/
13712 OSReturn
13713 OSKext::resetKCFileSetSegments(void)
13714 {
13715 	kernel_segment_command_t *seg = NULL;
13716 	kernel_segment_command_t *text_seg;
13717 	uint32_t text_fileoff;
13718 	kernel_mach_header_t *k_mh = NULL;
13719 	uintptr_t slide;
13720 	struct vnode *vp = NULL;
13721 	void *fileset_control = NULL;
13722 	bool pageable = (kc_type == KCKindPageable);
13723 	OSReturn err;
13724 	kern_return_t kr;
13725 
13726 	/* Check the vnode reference is still available */
13727 	vp = (struct vnode *)PE_get_kc_vp(kc_type);
13728 	if (vp == NULL) {
13729 		OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
13730 		    "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString());
13731 		return kOSKextReturnInternalError;
13732 	}
13733 
13734 	fileset_control = ubc_getobject(vp, 0);
13735 	assert(fileset_control != NULL);
13736 
13737 	OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
13738 	    "Kext %s resetting all segments", getIdentifierCString());
13739 
13740 	k_mh = (kernel_mach_header_t *)kmod_info->address;
13741 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT);
13742 	text_fileoff = text_seg->fileoff;
13743 	slide = PE_get_kc_slide(kc_type);
13744 
13745 	seg = firstsegfromheader((kernel_mach_header_t *)k_mh);
13746 	while (seg) {
13747 		if (seg->vmsize == 0) {
13748 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
13749 			continue;
13750 		}
13751 
13752 		/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
13753 		if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
13754 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
13755 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
13756 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
13757 			continue;
13758 		}
13759 
13760 		kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize);
13761 		assert(kr == KERN_SUCCESS);
13762 		seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
13763 	}
13764 
13765 	/* Unmap the text segment */
13766 	kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize);
13767 	assert(kr == KERN_SUCCESS);
13768 
13769 	/* Map all the segments of the kext */
13770 	err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL);
13771 	if (err) {
13772 		panic("Could not reset segments of a mapped kext, error %x", err);
13773 	}
13774 
13775 	/* Update address in kmod_info, since it has been reset */
13776 	if (kmod_info->address) {
13777 		kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide);
13778 	}
13779 
13780 	return 0;
13781 }
13782 
13783 /*********************************************************************
13784 * Mechanism to track all segment mapping while mapping KC fileset.
13785 *********************************************************************/
13786 
13787 struct kcfileset_map_entry {
13788 	vm_map_offset_t me_start;
13789 	vm_map_offset_t me_size;
13790 };
13791 
13792 struct kcfileset_map_entry_list {
13793 	int                        kme_list_count;
13794 	int                        kme_list_index;
13795 	struct kcfileset_map_entry kme_list[];
13796 };
13797 
13798 #define KCFILESET_MAP_ENTRY_MAX (16380)
13799 
13800 static void *
13801 allocate_kcfileset_map_entry_list(void)
13802 {
13803 	struct kcfileset_map_entry_list *entry_list;
13804 
13805 	entry_list = kalloc_type(struct kcfileset_map_entry_list,
13806 	    struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO);
13807 
13808 	entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX;
13809 	entry_list->kme_list_index = 0;
13810 	return entry_list;
13811 }
13812 
13813 static void
13814 add_kcfileset_map_entry(
13815 	void            *map_entry_list,
13816 	vm_map_offset_t start,
13817 	vm_map_offset_t size)
13818 {
13819 	if (map_entry_list == NULL) {
13820 		return;
13821 	}
13822 
13823 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
13824 
13825 	if (entry_list->kme_list_index >= entry_list->kme_list_count) {
13826 		panic("Ran out of map kc fileset list");
13827 	}
13828 
13829 	entry_list->kme_list[entry_list->kme_list_index].me_start = start;
13830 	entry_list->kme_list[entry_list->kme_list_index].me_size = size;
13831 
13832 	entry_list->kme_list_index++;
13833 }
13834 
13835 static void
13836 deallocate_kcfileset_map_entry_list_and_unmap_entries(
13837 	void      *map_entry_list,
13838 	boolean_t unmap_entries,
13839 	bool      pageable)
13840 {
13841 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
13842 
13843 	if (unmap_entries) {
13844 		for (int i = 0; i < entry_list->kme_list_index; i++) {
13845 			kern_return_t ret;
13846 			ret = vm_unmap_kcfileset_segment(
13847 				&(entry_list->kme_list[i].me_start),
13848 				entry_list->kme_list[i].me_size);
13849 			assert(ret == KERN_SUCCESS);
13850 		}
13851 
13852 		PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary);
13853 	}
13854 
13855 	kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry,
13856 	    KCFILESET_MAP_ENTRY_MAX, entry_list);
13857 }
13858 
13859 /*********************************************************************
13860 * Mechanism to map kext segment.
13861 *********************************************************************/
13862 
13863 kern_return_t
13864 vm_map_kcfileset_segment(
13865 	vm_map_offset_t    *start,
13866 	vm_map_offset_t    size,
13867 	void               *control,
13868 	vm_object_offset_t fileoffset,
13869 	vm_prot_t          max_prot)
13870 {
13871 	vm_map_kernel_flags_t vmk_flags = VM_MAP_KERNEL_FLAGS_NONE;
13872 	vmk_flags.vmkf_no_copy_on_read = 1;
13873 	vmk_flags.vmkf_cs_enforcement = 0;
13874 	vmk_flags.vmkf_cs_enforcement_override = 1;
13875 	kern_return_t ret;
13876 
13877 	/* Add Write to max prot to allow fixups */
13878 	max_prot = max_prot | VM_PROT_WRITE;
13879 
13880 	/*
13881 	 * Map the segments from file as COPY mappings to
13882 	 * make sure changes on disk to the file does not affect
13883 	 * mapped segments.
13884 	 */
13885 	ret = vm_map_enter_mem_object_control(
13886 		g_kext_map,
13887 		start,
13888 		size,
13889 		(mach_vm_offset_t)0,
13890 		VM_FLAGS_FIXED,
13891 		vmk_flags,
13892 		VM_KERN_MEMORY_OSKEXT,
13893 		(memory_object_control_t)control,
13894 		fileoffset,
13895 		TRUE,         /* copy */
13896 		(VM_PROT_READ | VM_PROT_WRITE), max_prot,
13897 		VM_INHERIT_NONE);
13898 
13899 	return ret;
13900 }
13901 
13902 kern_return_t
13903 vm_unmap_kcfileset_segment(
13904 	vm_map_offset_t    *start,
13905 	vm_map_offset_t    size)
13906 {
13907 	return mach_vm_deallocate(g_kext_map, *start, size);
13908 }
13909 
13910 #endif //(__x86_64__) || defined(__i386__)
13911 
13912 /*********************************************************************
13913 * Assumes sKextLock is held.
13914 *********************************************************************/
13915 /* static */
13916 OSReturn
13917 OSKext::validateKCFileSetUUID(
13918 	OSDictionary         *infoDict,
13919 	kc_kind_t            type)
13920 {
13921 	OSReturn ret           = kOSReturnSuccess;
13922 
13923 	if (!kernelcache_uuid_valid) {
13924 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13925 		    "validateKCFileSetUUID Boot KC UUID was not set at boot.");
13926 		ret = kOSKextReturnInvalidArgument;
13927 		goto finish;
13928 	}
13929 	ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey);
13930 	if (ret != 0) {
13931 		goto finish;
13932 	}
13933 
13934 #if defined(__x86_64__) || defined(__i386__)
13935 	/* Check if the Aux KC is prelinked to correct Pageable KC */
13936 	if (type == KCKindAuxiliary) {
13937 		if (!pageablekc_uuid_valid) {
13938 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13939 			    "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC.");
13940 			ret = kOSKextReturnInvalidArgument;
13941 			goto finish;
13942 		}
13943 		ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey);
13944 		if (ret != 0) {
13945 			goto finish;
13946 		}
13947 	}
13948 #endif //(__x86_64__) || defined(__i386__)
13949 
13950 	printf("KextLog: Collection UUID matches with loaded KCs.\n");
13951 finish:
13952 	return ret;
13953 }
13954 
13955 /*********************************************************************
13956 * Assumes sKextLock is held.
13957 *********************************************************************/
13958 /* static */
13959 OSReturn
13960 OSKext::validateKCUUIDfromPrelinkInfo(
13961 	uuid_t               *loaded_kcuuid,
13962 	kc_kind_t             type,
13963 	OSDictionary         *infoDict,
13964 	const char           *uuid_key)
13965 {
13966 	/* extract the UUID from the dictionary */
13967 	OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key));
13968 	if (!prelinkinfoKCUUID) {
13969 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13970 		    "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key);
13971 		return kOSKextReturnInvalidArgument;
13972 	}
13973 
13974 	if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) {
13975 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13976 		    "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength());
13977 		return kOSKextReturnInvalidArgument;
13978 	}
13979 
13980 	if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(),
13981 	    prelinkinfoKCUUID->getLength())) {
13982 		OSData       *info_dict_uuid;
13983 		uuid_string_t info_dict_uuid_str = {};
13984 		uuid_string_t expected_uuid_str = {};
13985 		uuid_string_t given_uuid_str = {};
13986 		uuid_t        given_uuid;
13987 
13988 		/* extract the KC UUID from the dictionary */
13989 		info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
13990 		if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) {
13991 			uuid_t tmp_uuid;
13992 			memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid));
13993 			uuid_unparse(tmp_uuid, info_dict_uuid_str);
13994 		}
13995 
13996 		uuid_unparse(*loaded_kcuuid, expected_uuid_str);
13997 		memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid));
13998 		uuid_unparse(given_uuid, given_uuid_str);
13999 
14000 		printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
14001 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
14002 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14003 		    "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
14004 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
14005 		if (type == KCKindPageable && sPanicOnKCMismatch) {
14006 			panic("System KC UUID %s linked against %s, but %s is loaded",
14007 			    info_dict_uuid_str, given_uuid_str, expected_uuid_str);
14008 		}
14009 		return kOSKextReturnInvalidArgument;
14010 	}
14011 
14012 	return 0;
14013 }
14014 
14015 /*********************************************************************
14016 * Assumes sKextLock is held.
14017 *********************************************************************/
14018 /* static */
14019 OSReturn
14020 OSKext::dispatchResource(OSDictionary * requestDict)
14021 {
14022 	OSReturn                        result          = kOSReturnError;
14023 	OSSharedPtr<OSDictionary>       callbackRecord;
14024 	OSNumber                      * requestTag      = NULL;        // do not release
14025 	OSNumber                      * requestResult   = NULL;        // do not release
14026 	OSData                        * dataObj         = NULL;        // do not release
14027 	uint32_t                        dataLength      = 0;
14028 	const void                    * dataPtr         = NULL;        // do not free
14029 	OSValueObject<OSKextRequestResourceCallback> * callbackWrapper = nullptr; // do not release
14030 	OSKextRequestResourceCallback   callback        = NULL;
14031 	OSValueObject<void *>         * contextWrapper  = nullptr;     // do not release
14032 	void                          * context         = NULL;        // do not free
14033 	OSSharedPtr<OSKext>             callbackKext;
14034 
14035 	/* Get the args from the request. Right now we need the tag
14036 	 * to look up the callback record, and the result for invoking the callback.
14037 	 */
14038 	requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
14039 	    kKextRequestArgumentRequestTagKey));
14040 	requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
14041 	    kKextRequestArgumentResultKey));
14042 	if (!requestTag || !requestResult) {
14043 		result = kOSKextReturnInvalidArgument;
14044 		goto finish;
14045 	}
14046 
14047 	/* Look for a callback record matching this request's tag.
14048 	 */
14049 	result = dequeueCallbackForRequestTag(requestTag, callbackRecord);
14050 	if (result != kOSReturnSuccess) {
14051 		goto finish;
14052 	}
14053 
14054 	/*****
14055 	 * Get the context pointer of the callback record (if there is one).
14056 	 */
14057 	contextWrapper = OSDynamicCast(OSValueObject<void *>, _OSKextGetRequestArgument(
14058 		    callbackRecord.get(), kKextRequestArgumentContextKey));
14059 	context = _OSKextExtractPointer(contextWrapper);
14060 	if (contextWrapper && !context) {
14061 		goto finish;
14062 	}
14063 
14064 	callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14065 	    _OSKextGetRequestArgument(callbackRecord.get(),
14066 	    kKextRequestArgumentCallbackKey));
14067 	callback = _OSKextExtractCallbackPointer(callbackWrapper);
14068 	if (!callback) {
14069 		goto finish;
14070 	}
14071 
14072 	/* Check for a data obj. We might not have one and that's ok, that means
14073 	 * we didn't find the requested resource, and we still have to tell the
14074 	 * caller that via the callback.
14075 	 */
14076 	dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
14077 	    kKextRequestArgumentValueKey));
14078 	if (dataObj) {
14079 		dataPtr = dataObj->getBytesNoCopy();
14080 		dataLength = dataObj->getLength();
14081 	}
14082 
14083 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
14084 	if (!callbackKext) {
14085 		OSKextLog(/* kext */ NULL,
14086 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
14087 		    "Can't invoke callback for resource request; ");
14088 		goto finish;
14089 	}
14090 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
14091 		OSKextLog(/* kext */ NULL,
14092 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
14093 		    "Can't invoke kext resource callback; ");
14094 		goto finish;
14095 	}
14096 
14097 	(void)callback(requestTag->unsigned32BitValue(),
14098 	    (OSReturn)requestResult->unsigned32BitValue(),
14099 	    dataPtr, dataLength, context);
14100 
14101 	result = kOSReturnSuccess;
14102 
14103 finish:
14104 	return result;
14105 }
14106 
14107 /*********************************************************************
14108 * Assumes sKextLock is held.
14109 *********************************************************************/
14110 /* static */
14111 OSReturn
14112 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict)
14113 {
14114 	OSSharedPtr<OSDictionary> missingIDs;
14115 	OSArray *bundleIDList     = NULL; // do not release
14116 
14117 	bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
14118 		    requestDict, kKextRequestArgumentMissingBundleIDs));
14119 	if (!bundleIDList) {
14120 		return kOSKextReturnInvalidArgument;
14121 	}
14122 
14123 	missingIDs = OSDictionary::withCapacity(bundleIDList->getCount());
14124 	if (!missingIDs) {
14125 		return kOSKextReturnNoMemory;
14126 	}
14127 
14128 	uint32_t count, i;
14129 	count = bundleIDList->getCount();
14130 	for (i = 0; i < count; i++) {
14131 		OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i));
14132 		if (thisID) {
14133 			missingIDs->setObject(thisID, kOSBooleanFalse);
14134 		}
14135 	}
14136 
14137 	sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain);
14138 
14139 	return kOSReturnSuccess;
14140 }
14141 
14142 /*********************************************************************
14143 * Assumes sKextLock is held.
14144 *********************************************************************/
14145 /* static */
14146 OSReturn
14147 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict)
14148 {
14149 	bool loadable = true;
14150 	if (!kextIdentifier) {
14151 		return kOSKextReturnInvalidArgument;
14152 	}
14153 
14154 	if (requestDict) {
14155 		OSBoolean *loadableArg;
14156 		loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
14157 			    requestDict, kKextRequestArgumentBundleAvailability));
14158 		/* If we find the "Bundle Available" arg, and it's false, then
14159 		 * mark the bundle ID as _not_ loadable
14160 		 */
14161 		if (loadableArg && !loadableArg->getValue()) {
14162 			loadable = false;
14163 		}
14164 	}
14165 
14166 	if (!sNonLoadableKextsByID) {
14167 		sNonLoadableKextsByID = OSDictionary::withCapacity(1);
14168 	}
14169 
14170 	sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable));
14171 
14172 	OSKextLog(/* kext */ NULL,
14173 	    kOSKextLogBasicLevel | kOSKextLogIPCFlag,
14174 	    "KextLog: AuxKC bundle %s marked as %s",
14175 	    kextIdentifier->getCStringNoCopy(),
14176 	    (loadable ? "loadable" : "NOT loadable"));
14177 
14178 	return kOSReturnSuccess;
14179 }
14180 
14181 /*********************************************************************
14182 *********************************************************************/
14183 /* static */
14184 void
14185 OSKext::invokeRequestCallback(
14186 	OSDictionary * callbackRecord,
14187 	OSReturn       callbackResult)
14188 {
14189 	OSString * predicate  = _OSKextGetRequestPredicate(callbackRecord);
14190 	OSSharedPtr<OSNumber> resultNum;
14191 
14192 	if (!predicate) {
14193 		goto finish;
14194 	}
14195 
14196 	resultNum  = OSNumber::withNumber((long long unsigned int)callbackResult,
14197 	    8 * sizeof(callbackResult));
14198 	if (!resultNum) {
14199 		goto finish;
14200 	}
14201 
14202 	/* Insert the result into the callback record and dispatch it as if it
14203 	 * were the reply coming down from user space.
14204 	 */
14205 	_OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
14206 	    resultNum.get());
14207 
14208 	if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
14209 		/* This removes the pending callback record.
14210 		 */
14211 		OSKext::dispatchResource(callbackRecord);
14212 	}
14213 
14214 finish:
14215 	return;
14216 }
14217 
14218 /*********************************************************************
14219 * Assumes sKextLock is held.
14220 *********************************************************************/
14221 /* static */
14222 OSReturn
14223 OSKext::cancelRequest(
14224 	OSKextRequestTag    requestTag,
14225 	void             ** contextOut)
14226 {
14227 	OSReturn       result         = kOSKextReturnNoMemory;
14228 	OSSharedPtr<OSDictionary> callbackRecord;
14229 	OSValueObject<void *> * contextWrapper = nullptr; // do not release
14230 
14231 	IORecursiveLockLock(sKextLock);
14232 	result = OSKext::dequeueCallbackForRequestTag(requestTag,
14233 	    callbackRecord);
14234 	IORecursiveLockUnlock(sKextLock);
14235 
14236 	if (result == kOSReturnSuccess && contextOut) {
14237 		contextWrapper = OSDynamicCast(OSValueObject<void *>,
14238 		    _OSKextGetRequestArgument(callbackRecord.get(),
14239 		    kKextRequestArgumentContextKey));
14240 		*contextOut = _OSKextExtractPointer(contextWrapper);
14241 	}
14242 
14243 	return result;
14244 }
14245 
14246 /*********************************************************************
14247 * Assumes sKextLock is held.
14248 *********************************************************************/
14249 void
14250 OSKext::invokeOrCancelRequestCallbacks(
14251 	OSReturn callbackResult,
14252 	bool     invokeFlag)
14253 {
14254 	unsigned int count, i;
14255 
14256 	count = sRequestCallbackRecords->getCount();
14257 	if (!count) {
14258 		goto finish;
14259 	}
14260 
14261 	i = count - 1;
14262 	do {
14263 		OSDictionary * request = OSDynamicCast(OSDictionary,
14264 		    sRequestCallbackRecords->getObject(i));
14265 
14266 		if (!request) {
14267 			continue;
14268 		}
14269 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14270 		    _OSKextGetRequestArgument(request,
14271 		    kKextRequestArgumentCallbackKey));
14272 
14273 		if (!callbackWrapper) {
14274 			sRequestCallbackRecords->removeObject(i);
14275 			continue;
14276 		}
14277 
14278 		vm_address_t callbackAddress = (vm_address_t)
14279 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
14280 
14281 		if ((kmod_info->address <= callbackAddress) &&
14282 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
14283 			if (invokeFlag) {
14284 				/* This removes the callback record.
14285 				 */
14286 				invokeRequestCallback(request, callbackResult);
14287 			} else {
14288 				sRequestCallbackRecords->removeObject(i);
14289 			}
14290 		}
14291 	} while (i--);
14292 
14293 finish:
14294 	return;
14295 }
14296 
14297 /*********************************************************************
14298 * Assumes sKextLock is held.
14299 *********************************************************************/
14300 uint32_t
14301 OSKext::countRequestCallbacks(void)
14302 {
14303 	uint32_t     result = 0;
14304 	unsigned int count, i;
14305 
14306 	count = sRequestCallbackRecords->getCount();
14307 	if (!count) {
14308 		goto finish;
14309 	}
14310 
14311 	i = count - 1;
14312 	do {
14313 		OSDictionary * request = OSDynamicCast(OSDictionary,
14314 		    sRequestCallbackRecords->getObject(i));
14315 
14316 		if (!request) {
14317 			continue;
14318 		}
14319 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14320 		    _OSKextGetRequestArgument(request,
14321 		    kKextRequestArgumentCallbackKey));
14322 
14323 		if (!callbackWrapper) {
14324 			continue;
14325 		}
14326 
14327 		vm_address_t callbackAddress = (vm_address_t)
14328 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
14329 
14330 		if ((kmod_info->address <= callbackAddress) &&
14331 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
14332 			result++;
14333 		}
14334 	} while (i--);
14335 
14336 finish:
14337 	return result;
14338 }
14339 
14340 /*********************************************************************
14341 *********************************************************************/
14342 static OSReturn
14343 _OSKextCreateRequest(
14344 	const char    * predicate,
14345 	OSSharedPtr<OSDictionary> & requestR)
14346 {
14347 	OSReturn result = kOSKextReturnNoMemory;
14348 	OSSharedPtr<OSDictionary> request;
14349 
14350 	request = OSDictionary::withCapacity(2);
14351 	if (!request) {
14352 		goto finish;
14353 	}
14354 	result = _OSDictionarySetCStringValue(request.get(),
14355 	    kKextRequestPredicateKey, predicate);
14356 	if (result != kOSReturnSuccess) {
14357 		goto finish;
14358 	}
14359 	result = kOSReturnSuccess;
14360 
14361 finish:
14362 	if (result == kOSReturnSuccess) {
14363 		requestR = os::move(request);
14364 	}
14365 
14366 	return result;
14367 }
14368 
14369 /*********************************************************************
14370 *********************************************************************/
14371 static OSString *
14372 _OSKextGetRequestPredicate(OSDictionary * requestDict)
14373 {
14374 	return OSDynamicCast(OSString,
14375 	           requestDict->getObject(kKextRequestPredicateKey));
14376 }
14377 
14378 /*********************************************************************
14379 *********************************************************************/
14380 static OSObject *
14381 _OSKextGetRequestArgument(
14382 	OSDictionary * requestDict,
14383 	const char   * argName)
14384 {
14385 	OSDictionary * args = OSDynamicCast(OSDictionary,
14386 	    requestDict->getObject(kKextRequestArgumentsKey));
14387 	if (args) {
14388 		return args->getObject(argName);
14389 	}
14390 	return NULL;
14391 }
14392 
14393 /*********************************************************************
14394 *********************************************************************/
14395 static bool
14396 _OSKextSetRequestArgument(
14397 	OSDictionary    * requestDict,
14398 	const char      * argName,
14399 	OSMetaClassBase * value)
14400 {
14401 	OSDictionary * args = OSDynamicCast(OSDictionary,
14402 	    requestDict->getObject(kKextRequestArgumentsKey));
14403 	OSSharedPtr<OSDictionary> newArgs;
14404 	if (!args) {
14405 		newArgs = OSDictionary::withCapacity(2);
14406 		args = newArgs.get();
14407 		if (!args) {
14408 			goto finish;
14409 		}
14410 		requestDict->setObject(kKextRequestArgumentsKey, args);
14411 	}
14412 	if (args) {
14413 		return args->setObject(argName, value);
14414 	}
14415 finish:
14416 	return false;
14417 }
14418 
14419 /*********************************************************************
14420 *********************************************************************/
14421 template <typename T>
14422 static T *
14423 _OSKextExtractPointer(OSValueObject<T *> * wrapper)
14424 {
14425 	if (!wrapper) {
14426 		return nullptr;
14427 	}
14428 	return wrapper->getRef();
14429 }
14430 
14431 /*********************************************************************
14432 *********************************************************************/
14433 static OSKextRequestResourceCallback
14434 _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper)
14435 {
14436 	if (!wrapper) {
14437 		return nullptr;
14438 	}
14439 	return wrapper->getRef();
14440 }
14441 
14442 
14443 /*********************************************************************
14444 *********************************************************************/
14445 static OSReturn
14446 _OSDictionarySetCStringValue(
14447 	OSDictionary * dict,
14448 	const char   * cKey,
14449 	const char   * cValue)
14450 {
14451 	OSReturn result = kOSKextReturnNoMemory;
14452 	OSSharedPtr<const OSSymbol> key;
14453 	OSSharedPtr<OSString> value;
14454 
14455 	key = OSSymbol::withCString(cKey);
14456 	value = OSString::withCString(cValue);
14457 	if (!key || !value) {
14458 		goto finish;
14459 	}
14460 	if (dict->setObject(key.get(), value.get())) {
14461 		result = kOSReturnSuccess;
14462 	}
14463 
14464 finish:
14465 	return result;
14466 }
14467 
14468 /*********************************************************************
14469 *********************************************************************/
14470 static bool
14471 _OSArrayContainsCString(
14472 	OSArray    * array,
14473 	const char * cString)
14474 {
14475 	bool             result = false;
14476 	OSSharedPtr<const OSSymbol> symbol;
14477 	uint32_t         count, i;
14478 
14479 	if (!array || !cString) {
14480 		goto finish;
14481 	}
14482 
14483 	symbol = OSSymbol::withCStringNoCopy(cString);
14484 	if (!symbol) {
14485 		goto finish;
14486 	}
14487 
14488 	count = array->getCount();
14489 	for (i = 0; i < count; i++) {
14490 		OSObject * thisObject = array->getObject(i);
14491 		if (symbol->isEqualTo(thisObject)) {
14492 			result = true;
14493 			goto finish;
14494 		}
14495 	}
14496 
14497 finish:
14498 	return result;
14499 }
14500 
14501 #if CONFIG_KXLD
14502 /*********************************************************************
14503 * We really only care about boot / system start up related kexts.
14504 * We return true if we're less than REBUILD_MAX_TIME since start up,
14505 * otherwise return false.
14506 *********************************************************************/
14507 bool
14508 _OSKextInPrelinkRebuildWindow(void)
14509 {
14510 	static bool     outside_the_window = false;
14511 	AbsoluteTime    my_abstime;
14512 	UInt64          my_ns;
14513 	SInt32          my_secs;
14514 
14515 	if (outside_the_window) {
14516 		return false;
14517 	}
14518 	clock_get_uptime(&my_abstime);
14519 	absolutetime_to_nanoseconds(my_abstime, &my_ns);
14520 	my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
14521 	if (my_secs > REBUILD_MAX_TIME) {
14522 		outside_the_window = true;
14523 		return false;
14524 	}
14525 	return true;
14526 }
14527 #endif /* CONFIG_KXLD */
14528 
14529 /*********************************************************************
14530 *********************************************************************/
14531 bool
14532 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
14533 {
14534 	int unLoadedCount, i;
14535 	bool result = false;
14536 
14537 	IORecursiveLockLock(sKextLock);
14538 
14539 	if (sUnloadedPrelinkedKexts == NULL) {
14540 		goto finish;
14541 	}
14542 	unLoadedCount = sUnloadedPrelinkedKexts->getCount();
14543 	if (unLoadedCount == 0) {
14544 		goto finish;
14545 	}
14546 
14547 	for (i = 0; i < unLoadedCount; i++) {
14548 		const OSSymbol *    myBundleID;        // do not release
14549 
14550 		myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
14551 		if (!myBundleID) {
14552 			continue;
14553 		}
14554 		if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
14555 			result = true;
14556 			break;
14557 		}
14558 	}
14559 finish:
14560 	IORecursiveLockUnlock(sKextLock);
14561 	return result;
14562 }
14563 
14564 #if PRAGMA_MARK
14565 #pragma mark Personalities (IOKit Drivers)
14566 #endif
14567 /*********************************************************************
14568 *********************************************************************/
14569 /* static */
14570 OSSharedPtr<OSArray>
14571 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
14572 {
14573 	OSSharedPtr<OSArray>              result;
14574 	OSSharedPtr<OSCollectionIterator> kextIterator;
14575 	OSSharedPtr<OSArray>              personalities;
14576 
14577 	OSString             * kextID                = NULL;        // do not release
14578 	OSKext               * theKext               = NULL;        // do not release
14579 
14580 	IORecursiveLockLock(sKextLock);
14581 
14582 	/* Let's conservatively guess that any given kext has around 3
14583 	 * personalities for now.
14584 	 */
14585 	result = OSArray::withCapacity(sKextsByID->getCount() * 3);
14586 	if (!result) {
14587 		goto finish;
14588 	}
14589 
14590 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
14591 	if (!kextIterator) {
14592 		goto finish;
14593 	}
14594 
14595 	while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
14596 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
14597 		if (theKext->flags.requireExplicitLoad) {
14598 			OSKextLog(theKext,
14599 			    kOSKextLogDebugLevel |
14600 			    kOSKextLogLoadFlag,
14601 			    "Kext %s requires an explicit kextload; "
14602 			    "omitting its personalities.",
14603 			    theKext->getIdentifierCString());
14604 		} else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
14605 			personalities = theKext->copyPersonalitiesArray();
14606 			if (!personalities) {
14607 				continue;
14608 			}
14609 			result->merge(personalities.get());
14610 		} else {
14611 			// xxx - check for better place to put this log msg
14612 			OSKextLog(theKext,
14613 			    kOSKextLogWarningLevel |
14614 			    kOSKextLogLoadFlag,
14615 			    "Kext %s is not loadable during safe boot; "
14616 			    "omitting its personalities.",
14617 			    theKext->getIdentifierCString());
14618 		}
14619 	}
14620 
14621 finish:
14622 	IORecursiveLockUnlock(sKextLock);
14623 
14624 	return result;
14625 }
14626 
14627 /*********************************************************************
14628 *********************************************************************/
14629 /* static */
14630 void
14631 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
14632 {
14633 	int numPersonalities = 0;
14634 
14635 	OSKextLog(/* kext */ NULL,
14636 	    kOSKextLogStepLevel |
14637 	    kOSKextLogLoadFlag,
14638 	    "Sending all eligible registered kexts' personalities "
14639 	    "to the IOCatalogue %s.",
14640 	    startMatching ? "and starting matching" : "but not starting matching");
14641 
14642 	OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities(
14643 		/* filterSafeBootFlag */ true);
14644 
14645 	if (personalities) {
14646 		gIOCatalogue->addDrivers(personalities.get(), startMatching);
14647 		numPersonalities = personalities->getCount();
14648 	}
14649 
14650 	OSKextLog(/* kext */ NULL,
14651 	    kOSKextLogStepLevel |
14652 	    kOSKextLogLoadFlag,
14653 	    "%d kext personalit%s sent to the IOCatalogue; %s.",
14654 	    numPersonalities, numPersonalities > 0 ? "ies" : "y",
14655 	    startMatching ? "matching started" : "matching not started");
14656 	return;
14657 }
14658 
14659 /*********************************************************************
14660 * Do not make a deep copy, just convert the IOKitPersonalities dict
14661 * to an array for sending to the IOCatalogue.
14662 *********************************************************************/
14663 OSSharedPtr<OSArray>
14664 OSKext::copyPersonalitiesArray(void)
14665 {
14666 	OSSharedPtr<OSArray>              result;
14667 	OSDictionary         * personalities               = NULL;        // do not release
14668 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
14669 
14670 	OSString             * personalityName             = NULL;        // do not release
14671 	OSString             * personalityBundleIdentifier = NULL;        // do not release
14672 
14673 	personalities = OSDynamicCast(OSDictionary,
14674 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
14675 	if (!personalities) {
14676 		goto finish;
14677 	}
14678 
14679 	result = OSArray::withCapacity(personalities->getCount());
14680 	if (!result) {
14681 		goto finish;
14682 	}
14683 
14684 	personalitiesIterator =
14685 	    OSCollectionIterator::withCollection(personalities);
14686 	if (!personalitiesIterator) {
14687 		goto finish;
14688 	}
14689 	while ((personalityName = OSDynamicCast(OSString,
14690 	    personalitiesIterator->getNextObject()))) {
14691 		OSDictionary * personality = OSDynamicCast(OSDictionary,
14692 		    personalities->getObject(personalityName));
14693 
14694 		if (personality) {
14695 			/******
14696 			 * If the personality doesn't have a CFBundleIdentifier, or if it
14697 			 * differs from the kext's, insert the kext's ID so we can find it.
14698 			 * The publisher ID is used to remove personalities from bundles
14699 			 * correctly.
14700 			 */
14701 			personalityBundleIdentifier = OSDynamicCast(OSString,
14702 			    personality->getObject(kCFBundleIdentifierKey));
14703 
14704 			if (!personalityBundleIdentifier) {
14705 				personality->setObject(kCFBundleIdentifierKey, bundleID.get());
14706 			} else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) {
14707 				personality->setObject(kIOPersonalityPublisherKey, bundleID.get());
14708 			}
14709 		}
14710 
14711 		result->setObject(personality);
14712 	}
14713 
14714 finish:
14715 	return result;
14716 }
14717 
14718 /*********************************************************************
14719 *   Might want to change this to a bool return?
14720 *********************************************************************/
14721 OSReturn
14722 OSKext::sendPersonalitiesToCatalog(
14723 	bool      startMatching,
14724 	OSArray * personalityNames)
14725 {
14726 	OSReturn       result              = kOSReturnSuccess;
14727 	OSSharedPtr<OSArray> personalitiesToSend;
14728 	OSDictionary * kextPersonalities   = NULL;        // do not release
14729 	int            count, i;
14730 
14731 	if (!sLoadEnabled) {
14732 		OSKextLog(this,
14733 		    kOSKextLogErrorLevel |
14734 		    kOSKextLogLoadFlag,
14735 		    "Kext loading is disabled (attempt to start matching for kext %s).",
14736 		    getIdentifierCString());
14737 		result = kOSKextReturnDisabled;
14738 		goto finish;
14739 	}
14740 
14741 	if (sSafeBoot && !isLoadableInSafeBoot()) {
14742 		OSKextLog(this,
14743 		    kOSKextLogErrorLevel |
14744 		    kOSKextLogLoadFlag,
14745 		    "Kext %s is not loadable during safe boot; "
14746 		    "not sending personalities to the IOCatalogue.",
14747 		    getIdentifierCString());
14748 		result = kOSKextReturnNotLoadable;
14749 		goto finish;
14750 	}
14751 
14752 	if (!personalityNames || !personalityNames->getCount()) {
14753 		personalitiesToSend = copyPersonalitiesArray();
14754 	} else {
14755 		kextPersonalities = OSDynamicCast(OSDictionary,
14756 		    getPropertyForHostArch(kIOKitPersonalitiesKey));
14757 		if (!kextPersonalities || !kextPersonalities->getCount()) {
14758 			// not an error
14759 			goto finish;
14760 		}
14761 		personalitiesToSend = OSArray::withCapacity(0);
14762 		if (!personalitiesToSend) {
14763 			result = kOSKextReturnNoMemory;
14764 			goto finish;
14765 		}
14766 		count = personalityNames->getCount();
14767 		for (i = 0; i < count; i++) {
14768 			OSString * name = OSDynamicCast(OSString,
14769 			    personalityNames->getObject(i));
14770 			if (!name) {
14771 				continue;
14772 			}
14773 			OSDictionary * personality = OSDynamicCast(OSDictionary,
14774 			    kextPersonalities->getObject(name));
14775 			if (personality) {
14776 				personalitiesToSend->setObject(personality);
14777 			}
14778 		}
14779 	}
14780 	if (personalitiesToSend) {
14781 		unsigned numPersonalities = personalitiesToSend->getCount();
14782 		OSKextLog(this,
14783 		    kOSKextLogStepLevel |
14784 		    kOSKextLogLoadFlag,
14785 		    "Kext %s sending %d personalit%s to the IOCatalogue%s.",
14786 		    getIdentifierCString(),
14787 		    numPersonalities,
14788 		    numPersonalities > 1 ? "ies" : "y",
14789 		    startMatching ? " and starting matching" : " but not starting matching");
14790 		gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching);
14791 	}
14792 finish:
14793 	return result;
14794 }
14795 
14796 /*********************************************************************
14797 * xxx - We should allow removing the kext's declared personalities,
14798 * xxx - even with other bundle identifiers.
14799 *********************************************************************/
14800 void
14801 OSKext::removePersonalitiesFromCatalog(void)
14802 {
14803 	OSSharedPtr<OSDictionary> personality;
14804 
14805 	personality = OSDictionary::withCapacity(1);
14806 	if (!personality) {
14807 		goto finish;
14808 	}
14809 	personality->setObject(kCFBundleIdentifierKey, getIdentifier());
14810 
14811 	OSKextLog(this,
14812 	    kOSKextLogStepLevel |
14813 	    kOSKextLogLoadFlag,
14814 	    "Kext %s removing all personalities naming it from the IOCatalogue.",
14815 	    getIdentifierCString());
14816 
14817 	/* Have the IOCatalog remove all personalities matching this kext's
14818 	 * bundle ID and trigger matching anew.
14819 	 */
14820 	gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true);
14821 
14822 finish:
14823 	return;
14824 }
14825 
14826 void
14827 OSKext::updatePersonalitiesInCatalog(OSArray *upgradedPersonalities)
14828 {
14829 	if (!upgradedPersonalities || upgradedPersonalities->getCount() == 0) {
14830 		return;
14831 	}
14832 
14833 	OSSharedPtr<OSDictionary> personalityToRemove = OSDictionary::withCapacity(1);
14834 	if (!personalityToRemove) {
14835 		return;
14836 	}
14837 
14838 	/*
14839 	 * Create a personality dictionary with just the bundleID.
14840 	 * We will remove any personality that has a matching bundleID,
14841 	 * irrespective of which other keys are present on the dictionary.
14842 	 */
14843 	personalityToRemove->setObject(kCFBundleIdentifierKey, getIdentifier());
14844 	gIOCatalogue->exchangeDrivers(personalityToRemove.get(), upgradedPersonalities, true);
14845 }
14846 
14847 #if PRAGMA_MARK
14848 #pragma mark Logging
14849 #endif
14850 /*********************************************************************
14851 * Do not call any function that takes sKextLock here!
14852 *********************************************************************/
14853 /* static */
14854 OSKextLogSpec
14855 OSKext::setUserSpaceLogFilter(
14856 	OSKextLogSpec   newUserLogFilter,
14857 	bool            captureFlag)
14858 {
14859 	OSKextLogSpec result;
14860 	bool          allocError = false;
14861 
14862 	/* Do not call any function that takes sKextLoggingLock during
14863 	 * this critical block. That means do logging after.
14864 	 */
14865 	IOLockLock(sKextLoggingLock);
14866 
14867 	result = sUserSpaceKextLogFilter;
14868 	sUserSpaceKextLogFilter = newUserLogFilter;
14869 
14870 	if (newUserLogFilter && captureFlag &&
14871 	    !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
14872 		// xxx - do some measurements for a good initial capacity?
14873 		sUserSpaceLogSpecArray = OSArray::withCapacity(0);
14874 		sUserSpaceLogMessageArray = OSArray::withCapacity(0);
14875 
14876 		if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
14877 			allocError = true;
14878 		}
14879 	}
14880 
14881 	IOLockUnlock(sKextLoggingLock);
14882 
14883 	/* If the config flag itself is changing, log the state change
14884 	 * going both ways, before setting up the user-space log arrays,
14885 	 * so that this is only logged in the kernel.
14886 	 */
14887 	if (result != newUserLogFilter) {
14888 		OSKextLog(/* kext */ NULL,
14889 		    kOSKextLogDebugLevel |
14890 		    kOSKextLogGeneralFlag,
14891 		    "User-space log flags changed from 0x%x to 0x%x.",
14892 		    result, newUserLogFilter);
14893 	}
14894 	if (allocError) {
14895 		OSKextLog(/* kext */ NULL,
14896 		    kOSKextLogErrorLevel |
14897 		    kOSKextLogGeneralFlag,
14898 		    "Failed to allocate user-space log message arrays.");
14899 	}
14900 
14901 	return result;
14902 }
14903 
14904 /*********************************************************************
14905 * Do not call any function that takes sKextLock here!
14906 *********************************************************************/
14907 /* static */
14908 OSSharedPtr<OSArray>
14909 OSKext::clearUserSpaceLogFilter(void)
14910 {
14911 	OSSharedPtr<OSArray>       result;
14912 	OSKextLogSpec   oldLogFilter;
14913 	OSKextLogSpec   newLogFilter = kOSKextLogSilentFilter;
14914 
14915 	/* Do not call any function that takes sKextLoggingLock during
14916 	 * this critical block. That means do logging after.
14917 	 */
14918 	IOLockLock(sKextLoggingLock);
14919 
14920 	result = OSArray::withCapacity(2);
14921 	if (result) {
14922 		result->setObject(sUserSpaceLogSpecArray.get());
14923 		result->setObject(sUserSpaceLogMessageArray.get());
14924 	}
14925 	sUserSpaceLogSpecArray.reset();
14926 	sUserSpaceLogMessageArray.reset();
14927 
14928 	oldLogFilter = sUserSpaceKextLogFilter;
14929 	sUserSpaceKextLogFilter = newLogFilter;
14930 
14931 	IOLockUnlock(sKextLoggingLock);
14932 
14933 	/* If the config flag itself is changing, log the state change
14934 	 * going both ways, after tearing down the user-space log
14935 	 * arrays, so this is only logged within the kernel.
14936 	 */
14937 	if (oldLogFilter != newLogFilter) {
14938 		OSKextLog(/* kext */ NULL,
14939 		    kOSKextLogDebugLevel |
14940 		    kOSKextLogGeneralFlag,
14941 		    "User-space log flags changed from 0x%x to 0x%x.",
14942 		    oldLogFilter, newLogFilter);
14943 	}
14944 
14945 	return result;
14946 }
14947 
14948 
14949 /*********************************************************************
14950 * Do not call any function that takes sKextLock here!
14951 *********************************************************************/
14952 /* static */
14953 OSKextLogSpec
14954 OSKext::getUserSpaceLogFilter(void)
14955 {
14956 	OSKextLogSpec result;
14957 
14958 	IOLockLock(sKextLoggingLock);
14959 	result = sUserSpaceKextLogFilter;
14960 	IOLockUnlock(sKextLoggingLock);
14961 
14962 	return result;
14963 }
14964 
14965 /*********************************************************************
14966 * This function is called by OSMetaClass during kernel C++ setup.
14967 * Be careful what you access here; assume only OSKext::initialize()
14968 * has been called.
14969 *
14970 * Do not call any function that takes sKextLock here!
14971 *********************************************************************/
14972 #define VTRESET   "\033[0m"
14973 
14974 #define VTBOLD    "\033[1m"
14975 #define VTUNDER   "\033[4m"
14976 
14977 #define VTRED     "\033[31m"
14978 #define VTGREEN   "\033[32m"
14979 #define VTYELLOW  "\033[33m"
14980 #define VTBLUE    "\033[34m"
14981 #define VTMAGENTA "\033[35m"
14982 #define VTCYAN    "\033[36m"
14983 
14984 inline const char *
14985 colorForFlags(OSKextLogSpec flags)
14986 {
14987 	OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
14988 
14989 	switch (logLevel) {
14990 	case kOSKextLogErrorLevel:
14991 		return VTRED VTBOLD;
14992 	case kOSKextLogWarningLevel:
14993 		return VTRED;
14994 	case kOSKextLogBasicLevel:
14995 		return VTYELLOW VTUNDER;
14996 	case kOSKextLogProgressLevel:
14997 		return VTYELLOW;
14998 	case kOSKextLogStepLevel:
14999 		return VTGREEN;
15000 	case kOSKextLogDetailLevel:
15001 		return VTCYAN;
15002 	case kOSKextLogDebugLevel:
15003 		return VTMAGENTA;
15004 	default:
15005 		return "";         // white
15006 	}
15007 }
15008 
15009 inline bool
15010 logSpecMatch(
15011 	OSKextLogSpec msgLogSpec,
15012 	OSKextLogSpec logFilter)
15013 {
15014 	OSKextLogSpec filterKextGlobal  = logFilter & kOSKextLogKextOrGlobalMask;
15015 	OSKextLogSpec filterLevel       = logFilter & kOSKextLogLevelMask;
15016 	OSKextLogSpec filterFlags       = logFilter & kOSKextLogFlagsMask;
15017 
15018 	OSKextLogSpec msgKextGlobal    = msgLogSpec & kOSKextLogKextOrGlobalMask;
15019 	OSKextLogSpec msgLevel         = msgLogSpec & kOSKextLogLevelMask;
15020 	OSKextLogSpec msgFlags         = msgLogSpec & kOSKextLogFlagsMask;
15021 
15022 	/* Explicit messages always get logged.
15023 	 */
15024 	if (msgLevel == kOSKextLogExplicitLevel) {
15025 		return true;
15026 	}
15027 
15028 	/* Warnings and errors are logged regardless of the flags.
15029 	 */
15030 	if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
15031 		return true;
15032 	}
15033 
15034 	/* A verbose message that isn't for a logging-enabled kext and isn't global
15035 	 * does *not* get logged.
15036 	 */
15037 	if (!msgKextGlobal && !filterKextGlobal) {
15038 		return false;
15039 	}
15040 
15041 	/* Warnings and errors are logged regardless of the flags.
15042 	 * All other messages must fit the flags and
15043 	 * have a level at or below the filter.
15044 	 *
15045 	 */
15046 	if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
15047 		return true;
15048 	}
15049 	return false;
15050 }
15051 
15052 extern "C" {
15053 void
15054 OSKextLog(
15055 	OSKext         * aKext,
15056 	OSKextLogSpec    msgLogSpec,
15057 	const char     * format, ...)
15058 {
15059 	va_list argList;
15060 
15061 	va_start(argList, format);
15062 	OSKextVLog(aKext, msgLogSpec, format, argList);
15063 	va_end(argList);
15064 }
15065 
15066 void
15067 OSKextVLog(
15068 	OSKext         * aKext,
15069 	OSKextLogSpec    msgLogSpec,
15070 	const char     * format,
15071 	va_list          srcArgList)
15072 {
15073 	extern int       disableConsoleOutput;
15074 
15075 	bool             logForKernel       = false;
15076 	bool             logForUser         = false;
15077 	va_list          argList;
15078 	char             stackBuffer[120];
15079 	uint32_t         length            = 0;
15080 	char           * allocBuffer       = NULL;        // must kfree
15081 	OSSharedPtr<OSNumber> logSpecNum;
15082 	OSSharedPtr<OSString> logString;
15083 	char           * buffer            = stackBuffer;        // do not free
15084 
15085 	IOLockLock(sKextLoggingLock);
15086 
15087 	/* Set the kext/global bit in the message spec if we have no
15088 	 * kext or if the kext requests logging.
15089 	 */
15090 	if (!aKext || aKext->flags.loggingEnabled) {
15091 		msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
15092 	}
15093 
15094 	logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
15095 	if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
15096 		logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
15097 	}
15098 
15099 	if (!(logForKernel || logForUser)) {
15100 		goto finish;
15101 	}
15102 
15103 	/* No goto from here until past va_end()!
15104 	 */
15105 	va_copy(argList, srcArgList);
15106 	length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
15107 	va_end(argList);
15108 
15109 	if (length + 1 >= sizeof(stackBuffer)) {
15110 		allocBuffer = (char *)kalloc_data_tag(length + 1,
15111 		    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
15112 		if (!allocBuffer) {
15113 			goto finish;
15114 		}
15115 
15116 		/* No goto from here until past va_end()!
15117 		 */
15118 		va_copy(argList, srcArgList);
15119 		vsnprintf(allocBuffer, length + 1, format, argList);
15120 		va_end(argList);
15121 
15122 		buffer = allocBuffer;
15123 	}
15124 
15125 	/* If user space wants the log message, queue it up.
15126 	 */
15127 	if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
15128 		logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
15129 		logString = OSString::withCString(buffer);
15130 		if (logSpecNum && logString) {
15131 			sUserSpaceLogSpecArray->setObject(logSpecNum.get());
15132 			sUserSpaceLogMessageArray->setObject(logString.get());
15133 		}
15134 	}
15135 
15136 	/* Always log messages from the kernel according to the kernel's
15137 	 * log flags.
15138 	 */
15139 	if (logForKernel) {
15140 		/* If we are in console mode and have a custom log filter,
15141 		 * colorize the log message.
15142 		 */
15143 		if (!disableConsoleOutput && sBootArgLogFilterFound) {
15144 			const char * color = "";         // do not free
15145 			color = colorForFlags(msgLogSpec);
15146 			printf("%s%s%s\n", colorForFlags(msgLogSpec),
15147 			    buffer, color[0] ? VTRESET : "");
15148 		} else {
15149 			printf("%s\n", buffer);
15150 		}
15151 	}
15152 
15153 finish:
15154 	IOLockUnlock(sKextLoggingLock);
15155 
15156 	if (allocBuffer) {
15157 		kfree_data(allocBuffer, length + 1);
15158 	}
15159 	return;
15160 }
15161 
15162 #if KASLR_IOREG_DEBUG
15163 
15164 #define IOLOG_INDENT( the_indention ) \
15165 { \
15166     int     i; \
15167     for ( i = 0; i < (the_indention); i++ ) { \
15168 	IOLog(" "); \
15169     } \
15170 }
15171 
15172 extern vm_offset_t       vm_kernel_stext;
15173 extern vm_offset_t       vm_kernel_etext;
15174 extern mach_vm_offset_t kext_alloc_base;
15175 extern mach_vm_offset_t kext_alloc_max;
15176 
15177 bool ScanForAddrInObject(OSObject * theObject,
15178     int indent );
15179 
15180 bool
15181 ScanForAddrInObject(OSObject * theObject,
15182     int indent)
15183 {
15184 	const OSMetaClass *     myTypeID;
15185 	OSSharedPtr<OSCollectionIterator>  myIter;
15186 	OSSymbol *              myKey;
15187 	OSObject *              myValue;
15188 	bool                    myResult = false;
15189 
15190 	if (theObject == NULL) {
15191 		IOLog("%s: theObject is NULL \n",
15192 		    __FUNCTION__);
15193 		return myResult;
15194 	}
15195 
15196 	myTypeID = OSTypeIDInst(theObject);
15197 
15198 	if (myTypeID == OSTypeID(OSDictionary)) {
15199 		OSDictionary *      myDictionary;
15200 
15201 		myDictionary = OSDynamicCast(OSDictionary, theObject);
15202 		myIter = OSCollectionIterator::withCollection( myDictionary );
15203 		if (myIter == NULL) {
15204 			return myResult;
15205 		}
15206 
15207 		// !! reset the iterator
15208 		myIter->reset();
15209 
15210 		while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
15211 			bool    myTempResult;
15212 
15213 			myValue = myDictionary->getObject(myKey);
15214 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
15215 			if (myTempResult) {
15216 				// if we ever get a true result return true
15217 				myResult = true;
15218 				IOLOG_INDENT(indent);
15219 				IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
15220 			}
15221 		}
15222 
15223 		// !! release the iterator
15224 		myIter.reset();
15225 	} else if (myTypeID == OSTypeID(OSArray)) {
15226 		OSArray *   myArray;
15227 
15228 		myArray = OSDynamicCast(OSArray, theObject);
15229 		myIter = OSCollectionIterator::withCollection(myArray);
15230 		if (myIter == NULL) {
15231 			return myResult;
15232 		}
15233 		// !! reset the iterator
15234 		myIter->reset();
15235 
15236 		while ((myValue = myIter->getNextObject())) {
15237 			bool        myTempResult;
15238 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
15239 			if (myTempResult) {
15240 				// if we ever get a true result return true
15241 				myResult = true;
15242 				IOLOG_INDENT(indent);
15243 				IOLog("OSArray: \n");
15244 			}
15245 		}
15246 		// !! release the iterator
15247 		myIter.reset();
15248 	} else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
15249 		// should we look for addresses in strings?
15250 	} else if (myTypeID == OSTypeID(OSData)) {
15251 		void * *        myPtrPtr;
15252 		unsigned int    myLen;
15253 		OSData *        myDataObj;
15254 
15255 		myDataObj =    OSDynamicCast(OSData, theObject);
15256 		myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
15257 		myLen = myDataObj->getLength();
15258 
15259 		if (myPtrPtr && myLen && myLen > 7) {
15260 			int     i;
15261 			int     myPtrCount = (myLen / sizeof(void *));
15262 
15263 			for (i = 0; i < myPtrCount; i++) {
15264 				UInt64 numberValue = (UInt64) * (myPtrPtr);
15265 
15266 				if (kext_alloc_max != 0 &&
15267 				    numberValue >= kext_alloc_base &&
15268 				    numberValue < kext_alloc_max) {
15269 					OSSharedPtr<OSKext> myKext;
15270 					// IOLog("found OSData %p in kext map %p to %p  \n",
15271 					//       *(myPtrPtr),
15272 					//       (void *) kext_alloc_base,
15273 					//       (void *) kext_alloc_max);
15274 
15275 					myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
15276 					if (myKext) {
15277 						IOLog("found addr %p from an OSData obj within kext \"%s\"  \n",
15278 						    *(myPtrPtr),
15279 						    myKext->getIdentifierCString());
15280 					}
15281 					myResult = true;
15282 				}
15283 				if (vm_kernel_etext != 0 &&
15284 				    numberValue >= vm_kernel_stext &&
15285 				    numberValue < vm_kernel_etext) {
15286 					IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n",
15287 					    *(myPtrPtr),
15288 					    (void *) vm_kernel_stext,
15289 					    (void *) vm_kernel_etext);
15290 					myResult = true;
15291 				}
15292 				myPtrPtr++;
15293 			}
15294 		}
15295 	} else if (myTypeID == OSTypeID(OSBoolean)) {
15296 		// do nothing here...
15297 	} else if (myTypeID == OSTypeID(OSNumber)) {
15298 		OSNumber * number = OSDynamicCast(OSNumber, theObject);
15299 
15300 		UInt64 numberValue = number->unsigned64BitValue();
15301 
15302 		if (kext_alloc_max != 0 &&
15303 		    numberValue >= kext_alloc_base &&
15304 		    numberValue < kext_alloc_max) {
15305 			OSSharedPtr<OSKext> myKext;
15306 			IOLog("found OSNumber in kext map %p to %p  \n",
15307 			    (void *) kext_alloc_base,
15308 			    (void *) kext_alloc_max);
15309 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
15310 
15311 			myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
15312 			if (myKext) {
15313 				IOLog("found in kext \"%s\"  \n",
15314 				    myKext->getIdentifierCString());
15315 			}
15316 
15317 			myResult = true;
15318 		}
15319 		if (vm_kernel_etext != 0 &&
15320 		    numberValue >= vm_kernel_stext &&
15321 		    numberValue < vm_kernel_etext) {
15322 			IOLog("found OSNumber in kernel text segment %p to %p  \n",
15323 			    (void *) vm_kernel_stext,
15324 			    (void *) vm_kernel_etext);
15325 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
15326 			myResult = true;
15327 		}
15328 	}
15329 #if 0
15330 	else {
15331 		const OSMetaClass* myMetaClass = NULL;
15332 
15333 		myMetaClass = theObject->getMetaClass();
15334 		if (myMetaClass) {
15335 			IOLog("class %s \n", myMetaClass->getClassName());
15336 		} else {
15337 			IOLog("Unknown object \n" );
15338 		}
15339 	}
15340 #endif
15341 
15342 	return myResult;
15343 }
15344 #endif // KASLR_KEXT_DEBUG
15345 };         /* extern "C" */
15346 
15347 #if PRAGMA_MARK
15348 #pragma mark Backtrace Dump & kmod_get_info() support
15349 #endif
15350 /*********************************************************************
15351 * This function must be safe to call in panic context.
15352 *********************************************************************/
15353 /* static */
15354 void
15355 OSKext::printKextsInBacktrace(
15356 	vm_offset_t  * addr __unused,
15357 	unsigned int   cnt __unused,
15358 	int         (* printf_func)(const char *fmt, ...) __unused,
15359 	uint32_t       flags __unused)
15360 {
15361 	addr64_t    summary_page = 0;
15362 	addr64_t    last_summary_page = 0;
15363 	bool        found_kmod = false;
15364 	u_int       i = 0;
15365 
15366 	if (kPrintKextsLock & flags) {
15367 		if (!sKextSummariesLock) {
15368 			return;
15369 		}
15370 		IOLockLock(sKextSummariesLock);
15371 	}
15372 
15373 	if (!gLoadedKextSummaries) {
15374 		(*printf_func)("         can't perform kext scan: no kext summary");
15375 		goto finish;
15376 	}
15377 
15378 	summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
15379 	last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
15380 	for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
15381 		if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
15382 			(*printf_func)("         can't perform kext scan: "
15383 			    "missing kext summary page %p", summary_page);
15384 			goto finish;
15385 		}
15386 	}
15387 
15388 	for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15389 		OSKextLoadedKextSummary * summary;
15390 
15391 		summary = gLoadedKextSummaries->summaries + i;
15392 		if (!summary->address) {
15393 			continue;
15394 		}
15395 
15396 		if (!summaryIsInBacktrace(summary, addr, cnt)) {
15397 			continue;
15398 		}
15399 
15400 		if (!found_kmod) {
15401 			if (!(kPrintKextsTerse & flags)) {
15402 				(*printf_func)("      Kernel Extensions in backtrace:\n");
15403 			}
15404 			found_kmod = true;
15405 		}
15406 
15407 		printSummary(summary, printf_func, flags);
15408 	}
15409 
15410 finish:
15411 	if (kPrintKextsLock & flags) {
15412 		IOLockUnlock(sKextSummariesLock);
15413 	}
15414 
15415 	return;
15416 }
15417 
15418 /*********************************************************************
15419 * This function must be safe to call in panic context.
15420 *********************************************************************/
15421 /* static */
15422 boolean_t
15423 OSKext::summaryIsInBacktrace(
15424 	OSKextLoadedKextSummary   * summary,
15425 	vm_offset_t               * addr,
15426 	unsigned int                cnt)
15427 {
15428 	u_int i = 0;
15429 
15430 	for (i = 0; i < cnt; i++) {
15431 		vm_offset_t kscan_addr = addr[i];
15432 #if  __has_feature(ptrauth_calls)
15433 		kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr);
15434 #endif /*  __has_feature(ptrauth_calls) */
15435 		if ((kscan_addr >= summary->text_exec_address) &&
15436 		    (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) {
15437 			return TRUE;
15438 		}
15439 	}
15440 
15441 	return FALSE;
15442 }
15443 
15444 /*
15445  * Get the kext summary object for the kext where 'addr' lies. Must be called with
15446  * sKextSummariesLock held.
15447  */
15448 OSKextLoadedKextSummary *
15449 OSKext::summaryForAddress(uintptr_t addr)
15450 {
15451 #if  __has_feature(ptrauth_calls)
15452 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
15453 #endif /*  __has_feature(ptrauth_calls) */
15454 	for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15455 		OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
15456 		if (!summary->address) {
15457 			continue;
15458 		}
15459 
15460 #if VM_MAPPED_KEXTS
15461 		/* On our platforms that use VM_MAPPED_KEXTS, we currently do not
15462 		 * support split kexts, but we also may unmap the kexts, which can
15463 		 * race with the above codepath (see OSKext::unload).  As such,
15464 		 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
15465 		 */
15466 		if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
15467 			return summary;
15468 		}
15469 #else
15470 		kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
15471 		kernel_segment_command_t *seg;
15472 
15473 		for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
15474 			if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
15475 				return summary;
15476 			}
15477 		}
15478 #endif
15479 	}
15480 
15481 	/* addr did not map to any kext */
15482 	return NULL;
15483 }
15484 
15485 /* static */
15486 void *
15487 OSKext::kextForAddress(const void *address)
15488 {
15489 	void                * image = NULL;
15490 	OSKextActiveAccount * active;
15491 	OSKext              * kext = NULL;
15492 	uint32_t              baseIdx;
15493 	uint32_t              lim;
15494 	uintptr_t             addr = (uintptr_t) address;
15495 	size_t                i;
15496 
15497 	if (!addr) {
15498 		return NULL;
15499 	}
15500 #if  __has_feature(ptrauth_calls)
15501 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
15502 #endif /*  __has_feature(ptrauth_calls) */
15503 
15504 	if (sKextAccountsCount) {
15505 		lck_ticket_lock(sKextAccountsLock, LCK_GRP_NULL);
15506 		// bsearch sKextAccounts list
15507 		for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15508 			active = &sKextAccounts[baseIdx + (lim >> 1)];
15509 			if ((addr >= active->address) && (addr < active->address_end)) {
15510 				kext = active->account->kext;
15511 				if (kext && kext->kmod_info) {
15512 					image = (void *) kext->kmod_info->address;
15513 				}
15514 				break;
15515 			} else if (addr > active->address) {
15516 				// move right
15517 				baseIdx += (lim >> 1) + 1;
15518 				lim--;
15519 			}
15520 			// else move left
15521 		}
15522 		lck_ticket_unlock(sKextAccountsLock);
15523 	}
15524 	if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) {
15525 		image = (void *) &_mh_execute_header;
15526 	}
15527 	if (!image && gLoadedKextSummaries) {
15528 		IOLockLock(sKextSummariesLock);
15529 		for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) {
15530 			OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
15531 			if (addr >= summary->address && addr < summary->address + summary->size) {
15532 				image = (void *)summary->address;
15533 			}
15534 		}
15535 		IOLockUnlock(sKextSummariesLock);
15536 	}
15537 
15538 	return image;
15539 }
15540 
15541 /*
15542  * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t *
15543  * Safe to call in panic context.
15544  */
15545 static OSKextLoadedKextSummary *
15546 findSummary(uint32_t tagID)
15547 {
15548 	OSKextLoadedKextSummary * summary;
15549 	for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15550 		summary = gLoadedKextSummaries->summaries + i;
15551 		if (summary->loadTag == tagID) {
15552 			return summary;
15553 		}
15554 	}
15555 	return NULL;
15556 }
15557 
15558 /*********************************************************************
15559 * This function must be safe to call in panic context.
15560 *********************************************************************/
15561 void
15562 OSKext::printSummary(
15563 	OSKextLoadedKextSummary * summary,
15564 	int                    (* printf_func)(const char *fmt, ...),
15565 	uint32_t                  flags)
15566 {
15567 	kmod_reference_t * kmod_ref = NULL;
15568 	uuid_string_t uuid;
15569 	char version[kOSKextVersionMaxLength];
15570 	uint64_t tmpAddr;
15571 	uint64_t tmpSize;
15572 	OSKextLoadedKextSummary *dependencySummary;
15573 
15574 	if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
15575 		strlcpy(version, "unknown version", sizeof(version));
15576 	}
15577 	(void) uuid_unparse(summary->uuid, uuid);
15578 
15579 #if defined(__arm__) || defined(__arm64__)
15580 	tmpAddr = summary->text_exec_address;
15581 	tmpSize = summary->text_exec_size;
15582 #else
15583 	tmpAddr = summary->address;
15584 	tmpSize = summary->size;
15585 #endif
15586 	if (kPrintKextsUnslide & flags) {
15587 		tmpAddr = ml_static_unslide(tmpAddr);
15588 	}
15589 	(*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
15590 	    (kPrintKextsTerse & flags) ? "" : "         ",
15591 	    summary->name, version, uuid,
15592 	    tmpAddr, tmpAddr + tmpSize - 1);
15593 
15594 	if (kPrintKextsTerse & flags) {
15595 		return;
15596 	}
15597 
15598 	/* print dependency info */
15599 	for (kmod_ref = (kmod_reference_t *) summary->reference_list;
15600 	    kmod_ref;
15601 	    kmod_ref = kmod_ref->next) {
15602 		kmod_info_t * rinfo;
15603 
15604 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
15605 			(*printf_func)("            kmod dependency scan stopped "
15606 			    "due to missing dependency page: %p\n",
15607 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
15608 			break;
15609 		}
15610 		rinfo = kmod_ref->info;
15611 
15612 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
15613 			(*printf_func)("            kmod dependency scan stopped "
15614 			    "due to missing kmod page: %p\n",
15615 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
15616 			break;
15617 		}
15618 
15619 		if (!rinfo->address) {
15620 			continue;         // skip fake entries for built-ins
15621 		}
15622 
15623 		dependencySummary = findSummary(rinfo->id);
15624 		uuid[0] = 0x00;
15625 		tmpAddr = rinfo->address;
15626 		tmpSize = rinfo->size;
15627 		if (dependencySummary) {
15628 			(void) uuid_unparse(dependencySummary->uuid, uuid);
15629 #if defined(__arm__) || defined(__arm64__)
15630 			tmpAddr = dependencySummary->text_exec_address;
15631 			tmpSize = dependencySummary->text_exec_size;
15632 #endif
15633 		}
15634 
15635 		if (kPrintKextsUnslide & flags) {
15636 			tmpAddr = ml_static_unslide(tmpAddr);
15637 		}
15638 		(*printf_func)("            dependency: %s(%s)[%s]@%p->%p\n",
15639 		    rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1);
15640 	}
15641 	return;
15642 }
15643 
15644 
15645 #if !defined(__arm__) && !defined(__arm64__)
15646 /*******************************************************************************
15647 * substitute() looks at an input string (a pointer within a larger buffer)
15648 * for a match to a substring, and on match it writes the marker & substitution
15649 * character to an output string, updating the scan (from) and
15650 * output (to) indexes as appropriate.
15651 *******************************************************************************/
15652 static int substitute(
15653 	const char * scan_string,
15654 	char       * string_out,
15655 	uint32_t   * to_index,
15656 	uint32_t   * from_index,
15657 	const char * substring,
15658 	char         marker,
15659 	char         substitution);
15660 
15661 /* string_out must be at least KMOD_MAX_NAME bytes.
15662  */
15663 static int
15664 substitute(
15665 	const char * scan_string,
15666 	char       * string_out,
15667 	uint32_t   * to_index,
15668 	uint32_t   * from_index,
15669 	const char * substring,
15670 	char         marker,
15671 	char         substitution)
15672 {
15673 	size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
15674 
15675 	/* On a substring match, append the marker (if there is one) and then
15676 	 * the substitution character, updating the output (to) index accordingly.
15677 	 * Then update the input (from) length by the length of the substring
15678 	 * that got replaced.
15679 	 */
15680 	if (!strncmp(scan_string, substring, substring_length)) {
15681 		if (marker) {
15682 			string_out[(*to_index)++] = marker;
15683 		}
15684 		string_out[(*to_index)++] = substitution;
15685 		(*from_index) += substring_length;
15686 		return 1;
15687 	}
15688 	return 0;
15689 }
15690 
15691 /*******************************************************************************
15692 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
15693 * KMOD_MAX_NAME characters and performs various substitutions of common
15694 * prefixes & substrings as defined by tables in kext_panic_report.h.
15695 *******************************************************************************/
15696 static void compactIdentifier(
15697 	const char * identifier,
15698 	char       * identifier_out,
15699 	char      ** identifier_out_end);
15700 
15701 static void
15702 compactIdentifier(
15703 	const char * identifier,
15704 	char       * identifier_out,
15705 	char      ** identifier_out_end)
15706 {
15707 	uint32_t       from_index, to_index;
15708 	uint32_t       scan_from_index = 0;
15709 	uint32_t       scan_to_index   = 0;
15710 	subs_entry_t * subs_entry    = NULL;
15711 	int            did_sub       = 0;
15712 
15713 	from_index = to_index = 0;
15714 	identifier_out[0] = '\0';
15715 
15716 	/* Replace certain identifier prefixes with shorter @+character sequences.
15717 	 * Check the return value of substitute() so we only replace the prefix.
15718 	 */
15719 	for (subs_entry = &kext_identifier_prefix_subs[0];
15720 	    subs_entry->substring && !did_sub;
15721 	    subs_entry++) {
15722 		did_sub = substitute(identifier, identifier_out,
15723 		    &scan_to_index, &scan_from_index,
15724 		    subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
15725 	}
15726 	did_sub = 0;
15727 
15728 	/* Now scan through the identifier looking for the common substrings
15729 	 * and replacing them with shorter !+character sequences via substitute().
15730 	 */
15731 	for (/* see above */;
15732 	    scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
15733 	    /* see loop */) {
15734 		const char   * scan_string = &identifier[scan_from_index];
15735 
15736 		did_sub = 0;
15737 
15738 		if (scan_from_index) {
15739 			for (subs_entry = &kext_identifier_substring_subs[0];
15740 			    subs_entry->substring && !did_sub;
15741 			    subs_entry++) {
15742 				did_sub = substitute(scan_string, identifier_out,
15743 				    &scan_to_index, &scan_from_index,
15744 				    subs_entry->substring, '!', subs_entry->substitute);
15745 			}
15746 		}
15747 
15748 		/* If we didn't substitute, copy the input character to the output.
15749 		 */
15750 		if (!did_sub) {
15751 			identifier_out[scan_to_index++] = identifier[scan_from_index++];
15752 		}
15753 	}
15754 
15755 	identifier_out[scan_to_index] = '\0';
15756 	if (identifier_out_end) {
15757 		*identifier_out_end = &identifier_out[scan_to_index];
15758 	}
15759 
15760 	return;
15761 }
15762 #endif /* !defined(__arm__) && !defined(__arm64__) */
15763 
15764 /*******************************************************************************
15765 * assemble_identifier_and_version() adds to a string buffer a compacted
15766 * bundle identifier followed by a version string.
15767 *******************************************************************************/
15768 
15769 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
15770  */
15771 static size_t assemble_identifier_and_version(
15772 	kmod_info_t * kmod_info,
15773 	char        * identPlusVers,
15774 	size_t        bufSize);
15775 
15776 static size_t
15777 assemble_identifier_and_version(
15778 	kmod_info_t * kmod_info,
15779 	char        * identPlusVers,
15780 	size_t        bufSize)
15781 {
15782 	size_t result = 0;
15783 
15784 #if defined(__arm__) || defined(__arm64__)
15785 	result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME);
15786 #else
15787 	compactIdentifier(kmod_info->name, identPlusVers, NULL);
15788 	result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
15789 #endif
15790 	identPlusVers[result++] = '\t';         // increment for real char
15791 	identPlusVers[result] = '\0';         // don't increment for nul char
15792 	result = strlcat(identPlusVers, kmod_info->version, bufSize);
15793 	if (result >= bufSize) {
15794 		identPlusVers[bufSize - 1] = '\0';
15795 		result = bufSize - 1;
15796 	}
15797 
15798 	return result;
15799 }
15800 
15801 /*******************************************************************************
15802 * Assumes sKextLock is held.
15803 *******************************************************************************/
15804 /* static */
15805 int
15806 OSKext::saveLoadedKextPanicListTyped(
15807 	const char * prefix,
15808 	int          invertFlag,
15809 	int          libsFlag,
15810 	char       * paniclist,
15811 	uint32_t     list_size)
15812 {
15813 	int             result = -1;
15814 	unsigned int    count, i;
15815 
15816 	count = sLoadedKexts->getCount();
15817 	if (!count) {
15818 		goto finish;
15819 	}
15820 
15821 	i = count - 1;
15822 	do {
15823 		OSObject    * rawKext = sLoadedKexts->getObject(i);
15824 		OSKext      * theKext = OSDynamicCast(OSKext, rawKext);
15825 		int           match;
15826 		size_t        identPlusVersLength;
15827 		size_t        tempLen;
15828 		char          identPlusVers[2 * KMOD_MAX_NAME];
15829 
15830 		if (!rawKext) {
15831 			printf("OSKext::saveLoadedKextPanicListTyped - "
15832 			    "NULL kext in loaded kext list; continuing\n");
15833 			continue;
15834 		}
15835 
15836 		if (!theKext) {
15837 			printf("OSKext::saveLoadedKextPanicListTyped - "
15838 			    "Kext type cast failed in loaded kext list; continuing\n");
15839 			continue;
15840 		}
15841 
15842 		/* Skip all built-in kexts.
15843 		 */
15844 		if (theKext->isKernelComponent()) {
15845 			continue;
15846 		}
15847 
15848 		kmod_info_t * kmod_info = theKext->kmod_info;
15849 
15850 		/* Filter for kmod name (bundle identifier).
15851 		 */
15852 		match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
15853 		if ((match && invertFlag) || (!match && !invertFlag)) {
15854 			continue;
15855 		}
15856 
15857 		/* Filter for libraries (kexts that have a compatible version).
15858 		 */
15859 		if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
15860 		    (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
15861 			continue;
15862 		}
15863 
15864 		if (!kmod_info ||
15865 		    !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
15866 			printf("kext scan stopped due to missing kmod_info page: %p\n",
15867 			    kmod_info);
15868 			goto finish;
15869 		}
15870 
15871 		identPlusVersLength = assemble_identifier_and_version(kmod_info,
15872 		    identPlusVers,
15873 		    sizeof(identPlusVers));
15874 		if (!identPlusVersLength) {
15875 			printf("error saving loaded kext info\n");
15876 			goto finish;
15877 		}
15878 
15879 		/* make sure everything fits and we null terminate.
15880 		 */
15881 		tempLen = strlcat(paniclist, identPlusVers, list_size);
15882 		if (tempLen >= list_size) {
15883 			// panic list is full, keep it and null terminate
15884 			paniclist[list_size - 1] = 0x00;
15885 			result = 0;
15886 			goto finish;
15887 		}
15888 		tempLen = strlcat(paniclist, "\n", list_size);
15889 		if (tempLen >= list_size) {
15890 			// panic list is full, keep it and null terminate
15891 			paniclist[list_size - 1] = 0x00;
15892 			result = 0;
15893 			goto finish;
15894 		}
15895 	} while (i--);
15896 
15897 	result = 0;
15898 finish:
15899 
15900 	return result;
15901 }
15902 
15903 /*********************************************************************
15904 *********************************************************************/
15905 /* static */
15906 void
15907 OSKext::saveLoadedKextPanicList(void)
15908 {
15909 	char     * newlist        = NULL;
15910 	uint32_t   newlist_size   = 0;
15911 
15912 	newlist_size = KEXT_PANICLIST_SIZE;
15913 	newlist = (char *)kalloc_data_tag(newlist_size,
15914 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
15915 
15916 	if (!newlist) {
15917 		OSKextLog(/* kext */ NULL,
15918 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
15919 		    "Couldn't allocate kext panic log buffer.");
15920 		goto finish;
15921 	}
15922 
15923 	newlist[0] = '\0';
15924 
15925 	// non-"com.apple." kexts
15926 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
15927 	    /* libs? */ -1, newlist, newlist_size) != 0) {
15928 		goto finish;
15929 	}
15930 	// "com.apple." nonlibrary kexts
15931 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
15932 	    /* libs? */ 0, newlist, newlist_size) != 0) {
15933 		goto finish;
15934 	}
15935 	// "com.apple." library kexts
15936 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
15937 	    /* libs? */ 1, newlist, newlist_size) != 0) {
15938 		goto finish;
15939 	}
15940 
15941 	if (loaded_kext_paniclist) {
15942 		kfree_data(loaded_kext_paniclist, loaded_kext_paniclist_size);
15943 	}
15944 	loaded_kext_paniclist = newlist;
15945 	newlist = NULL;
15946 	loaded_kext_paniclist_size = newlist_size;
15947 
15948 finish:
15949 	if (newlist) {
15950 		kfree_data(newlist, newlist_size);
15951 	}
15952 	return;
15953 }
15954 
15955 /*********************************************************************
15956 * Assumes sKextLock is held.
15957 *********************************************************************/
15958 void
15959 OSKext::savePanicString(bool isLoading)
15960 {
15961 	u_long len;
15962 
15963 	if (!kmod_info) {
15964 		return;         // do not goto finish here b/c of lock
15965 	}
15966 
15967 	len = assemble_identifier_and_version( kmod_info,
15968 	    (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
15969 	    (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
15970 	if (!len) {
15971 		printf("error saving unloaded kext info\n");
15972 		goto finish;
15973 	}
15974 
15975 	if (isLoading) {
15976 		last_loaded_strlen = len;
15977 		last_loaded_address = (void *)kmod_info->address;
15978 		last_loaded_size = kmod_info->size;
15979 		clock_get_uptime(&last_loaded_timestamp);
15980 	} else {
15981 		last_unloaded_strlen = len;
15982 		last_unloaded_address = (void *)kmod_info->address;
15983 		last_unloaded_size = kmod_info->size;
15984 		clock_get_uptime(&last_unloaded_timestamp);
15985 	}
15986 
15987 finish:
15988 	return;
15989 }
15990 
15991 /*********************************************************************
15992 *********************************************************************/
15993 /* static */
15994 void
15995 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
15996 {
15997 	if (last_loaded_strlen) {
15998 		printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n",
15999 		    AbsoluteTime_to_scalar(&last_loaded_timestamp),
16000 		    last_loaded_strlen, last_loaded_str_buf,
16001 		    last_loaded_address, last_loaded_size);
16002 	}
16003 
16004 	if (last_unloaded_strlen) {
16005 		printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n",
16006 		    AbsoluteTime_to_scalar(&last_unloaded_timestamp),
16007 		    last_unloaded_strlen, last_unloaded_str_buf,
16008 		    last_unloaded_address, last_unloaded_size);
16009 	}
16010 
16011 	printf_func("loaded kexts:\n");
16012 	if (loaded_kext_paniclist &&
16013 	    pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
16014 	    loaded_kext_paniclist[0]) {
16015 		printf_func("%.*s",
16016 		    strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
16017 		    loaded_kext_paniclist);
16018 	} else {
16019 		printf_func("(none)\n");
16020 	}
16021 	return;
16022 }
16023 
16024 /*********************************************************************
16025 * Assumes sKextLock is held.
16026 *********************************************************************/
16027 /* static */
16028 void
16029 OSKext::updateLoadedKextSummaries(void)
16030 {
16031 	kern_return_t result = KERN_FAILURE;
16032 	OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
16033 	OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
16034 	OSKext *aKext;
16035 	vm_map_offset_t start, end;
16036 	size_t summarySize = 0;
16037 	size_t size;
16038 	u_int count;
16039 	u_int maxKexts;
16040 	u_int i, j;
16041 	OSKextActiveAccount * accountingList;
16042 	OSKextActiveAccount * prevAccountingList;
16043 	uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
16044 
16045 	prevAccountingList = NULL;
16046 	prevAccountingListCount = 0;
16047 
16048 #if DEVELOPMENT || DEBUG
16049 	if (IORecursiveLockHaveLock(sKextLock) == false) {
16050 		panic("sKextLock must be held");
16051 	}
16052 #endif
16053 
16054 	IOLockLock(sKextSummariesLock);
16055 
16056 	count = sLoadedKexts->getCount();
16057 	for (i = 0, maxKexts = 0; i < count; ++i) {
16058 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16059 		maxKexts += (aKext && aKext->isExecutable());
16060 	}
16061 
16062 	if (!maxKexts) {
16063 		goto finish;
16064 	}
16065 	if (maxKexts < kOSKextTypicalLoadCount) {
16066 		maxKexts = kOSKextTypicalLoadCount;
16067 	}
16068 
16069 	/* Calculate the size needed for the new summary headers.
16070 	 */
16071 
16072 	size = sizeof(*gLoadedKextSummaries);
16073 	size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
16074 	size = round_page(size);
16075 
16076 	if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
16077 		if (gLoadedKextSummaries) {
16078 			kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
16079 			gLoadedKextSummaries = NULL;
16080 			gLoadedKextSummariesTimestamp = mach_absolute_time();
16081 			sLoadedKextSummariesAllocSize = 0;
16082 		}
16083 		result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size,
16084 		    KMA_DATA, VM_KERN_MEMORY_OSKEXT);
16085 		if (result != KERN_SUCCESS) {
16086 			goto finish;
16087 		}
16088 		summaryHeader = summaryHeaderAlloc;
16089 		summarySize = size;
16090 	} else {
16091 		summaryHeader = gLoadedKextSummaries;
16092 		summarySize = sLoadedKextSummariesAllocSize;
16093 
16094 		start = (vm_map_offset_t) summaryHeader;
16095 		end = start + summarySize;
16096 		result = vm_map_protect(kernel_map,
16097 		    start,
16098 		    end,
16099 		    VM_PROT_DEFAULT,
16100 		    FALSE);
16101 		if (result != KERN_SUCCESS) {
16102 			goto finish;
16103 		}
16104 	}
16105 
16106 	/* Populate the summary header.
16107 	 */
16108 
16109 	bzero(summaryHeader, summarySize);
16110 	summaryHeader->version = kOSKextLoadedKextSummaryVersion;
16111 	summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
16112 
16113 	/* Populate each kext summary.
16114 	 */
16115 
16116 	count = sLoadedKexts->getCount();
16117 	accountingListAlloc = 0;
16118 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
16119 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16120 		if (!aKext || !aKext->isExecutable()) {
16121 			continue;
16122 		}
16123 
16124 		aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
16125 		summaryHeader->numSummaries++;
16126 		accountingListAlloc++;
16127 	}
16128 
16129 	accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
16130 	accountingListCount = 0;
16131 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
16132 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16133 		if (!aKext || !aKext->isExecutable()) {
16134 			continue;
16135 		}
16136 
16137 		OSKextActiveAccount activeAccount;
16138 		aKext->updateActiveAccount(&activeAccount);
16139 		// order by address
16140 		for (idx = 0; idx < accountingListCount; idx++) {
16141 			if (activeAccount.address < accountingList[idx].address) {
16142 				break;
16143 			}
16144 		}
16145 		bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
16146 		accountingList[idx] = activeAccount;
16147 		accountingListCount++;
16148 	}
16149 	assert(accountingListCount == accountingListAlloc);
16150 	/* Write protect the buffer and move it into place.
16151 	 */
16152 
16153 	start = (vm_map_offset_t) summaryHeader;
16154 	end = start + summarySize;
16155 
16156 	result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
16157 	if (result != KERN_SUCCESS) {
16158 		goto finish;
16159 	}
16160 
16161 	gLoadedKextSummaries = summaryHeader;
16162 	gLoadedKextSummariesTimestamp = mach_absolute_time();
16163 	sLoadedKextSummariesAllocSize = summarySize;
16164 	summaryHeaderAlloc = NULL;
16165 
16166 	/* Call the magic breakpoint function through a static function pointer so
16167 	 * the compiler can't optimize the function away.
16168 	 */
16169 	if (sLoadedKextSummariesUpdated) {
16170 		(*sLoadedKextSummariesUpdated)();
16171 	}
16172 
16173 	lck_ticket_lock(sKextAccountsLock, LCK_GRP_NULL);
16174 	prevAccountingList      = sKextAccounts;
16175 	prevAccountingListCount = sKextAccountsCount;
16176 	sKextAccounts           = accountingList;
16177 	sKextAccountsCount      = accountingListCount;
16178 	lck_ticket_unlock(sKextAccountsLock);
16179 
16180 finish:
16181 	IOLockUnlock(sKextSummariesLock);
16182 
16183 	/* If we had to allocate a new buffer but failed to generate the summaries,
16184 	 * free that now.
16185 	 */
16186 	if (summaryHeaderAlloc) {
16187 		kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
16188 	}
16189 	if (prevAccountingList) {
16190 		IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
16191 	}
16192 
16193 	return;
16194 }
16195 
16196 /*********************************************************************
16197 *********************************************************************/
16198 void
16199 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
16200 {
16201 	OSSharedPtr<OSData> uuid;
16202 
16203 	strlcpy(summary->name, getIdentifierCString(),
16204 	    sizeof(summary->name));
16205 
16206 	uuid = copyUUID();
16207 	if (uuid) {
16208 		memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
16209 	}
16210 
16211 	if (flags.builtin) {
16212 //      this value will stop lldb from parsing the mach-o header
16213 //      summary->address = UINT64_MAX;
16214 //      summary->size = 0;
16215 		summary->address = kmod_info->address;
16216 		summary->size = kmod_info->size;
16217 	} else {
16218 		summary->address = kmod_info->address;
16219 		summary->size = kmod_info->size;
16220 	}
16221 	summary->version = getVersion();
16222 	summary->loadTag = kmod_info->id;
16223 	summary->flags = 0;
16224 	summary->reference_list = (uint64_t) kmod_info->reference_list;
16225 
16226 	summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size);
16227 	if (summary->text_exec_address == 0) {
16228 		// Fallback to __TEXT
16229 		summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size);
16230 	}
16231 	return;
16232 }
16233 
16234 /*********************************************************************
16235 *********************************************************************/
16236 
16237 void
16238 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
16239 {
16240 	kernel_mach_header_t     *hdr = NULL;
16241 	kernel_segment_command_t *seg = NULL;
16242 
16243 	bzero(accountp, sizeof(*accountp));
16244 
16245 	hdr = (kernel_mach_header_t *)kmod_info->address;
16246 	if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) {
16247 		/*
16248 		 * If this kext supports split segments (or is in a new
16249 		 * MH_FILESET kext collection), use the first
16250 		 * executable segment as the range for instructions
16251 		 * (and thus for backtracing.
16252 		 */
16253 		for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
16254 			if (seg->initprot & VM_PROT_EXECUTE) {
16255 				break;
16256 			}
16257 		}
16258 	}
16259 	if (seg) {
16260 		accountp->address = seg->vmaddr;
16261 		if (accountp->address) {
16262 			accountp->address_end = seg->vmaddr + seg->vmsize;
16263 		}
16264 	} else {
16265 		/* For non-split kexts and for kexts without executable
16266 		 * segments, just use the kmod_info range (as the kext
16267 		 * is either all in one range or should not show up in
16268 		 * instruction backtraces).
16269 		 */
16270 		accountp->address = kmod_info->address;
16271 		if (accountp->address) {
16272 			accountp->address_end = kmod_info->address + kmod_info->size;
16273 		}
16274 	}
16275 
16276 	accountp->account = this->account;
16277 }
16278 
16279 bool
16280 OSKext::isDriverKit(void)
16281 {
16282 	OSString *bundleType;
16283 
16284 	if (infoDict) {
16285 		bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey));
16286 		if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) {
16287 			return TRUE;
16288 		}
16289 	}
16290 	return FALSE;
16291 }
16292 
16293 bool
16294 OSKext::isInFileset(void)
16295 {
16296 	if (!kmod_info) {
16297 		goto check_prelinked;
16298 	}
16299 
16300 	if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) {
16301 		return true;
16302 	}
16303 
16304 check_prelinked:
16305 	if (isPrelinked()) {
16306 		/*
16307 		 * If we haven't setup kmod_info yet, but we know
16308 		 * we're loading a prelinked kext in an MH_FILESET KC,
16309 		 * then return true
16310 		 */
16311 		kc_format_t kc_format;
16312 		if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
16313 			return true;
16314 		}
16315 	}
16316 	return false;
16317 }
16318 
16319 OSSharedPtr<OSDextStatistics>
16320 OSKext::copyDextStatistics(void)
16321 {
16322 	return dextStatistics;
16323 }
16324 
16325 bool
16326 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg)
16327 {
16328 	kern_return_t result;
16329 	if (!super::init()) {
16330 		return false;
16331 	}
16332 	if (seg == nullptr) {
16333 		return false;
16334 	}
16335 	result = kmem_alloc(kernel_map, (vm_offset_t *)&data, seg->vmsize,
16336 	    KMA_PAGEABLE, VM_KERN_MEMORY_KEXT);
16337 	if (result != KERN_SUCCESS) {
16338 		return false;
16339 	}
16340 	memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize);
16341 	savedSegment = seg;
16342 	vmsize = seg->vmsize;
16343 	vmaddr = seg->vmaddr;
16344 	return true;
16345 }
16346 
16347 OSSharedPtr<OSKextSavedMutableSegment>
16348 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg)
16349 {
16350 	OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>();
16351 	if (me && !me->initWithSegment(seg)) {
16352 		return nullptr;
16353 	}
16354 	return me;
16355 }
16356 
16357 void
16358 OSKextSavedMutableSegment::free(void)
16359 {
16360 	if (data) {
16361 		kmem_free(kernel_map, (vm_offset_t)data, vmsize);
16362 	}
16363 }
16364 
16365 vm_offset_t
16366 OSKextSavedMutableSegment::getVMAddr() const
16367 {
16368 	return vmaddr;
16369 }
16370 
16371 vm_offset_t
16372 OSKextSavedMutableSegment::getVMSize() const
16373 {
16374 	return vmsize;
16375 }
16376 
16377 OSReturn
16378 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg)
16379 {
16380 	if (seg != savedSegment) {
16381 		return kOSKextReturnInvalidArgument;
16382 	}
16383 	if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) {
16384 		return kOSKextReturnInvalidArgument;
16385 	}
16386 	memcpy((void *)seg->vmaddr, data, vmsize);
16387 	return kOSReturnSuccess;
16388 }
16389 
16390 extern "C" kern_return_t
16391 OSKextSetReceiptQueried(void)
16392 {
16393 	OSKextLog(/* kext */ NULL,
16394 	    kOSKextLogStepLevel | kOSKextLogGeneralFlag,
16395 	    "Setting kext receipt as queried");
16396 
16397 	IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue);
16398 	return KERN_SUCCESS;
16399 }
16400 
16401 extern "C" const vm_allocation_site_t *
16402 OSKextGetAllocationSiteForCaller(uintptr_t address)
16403 {
16404 	OSKextActiveAccount *  active;
16405 	vm_allocation_site_t * site;
16406 	vm_allocation_site_t * releasesite;
16407 
16408 	uint32_t baseIdx;
16409 	uint32_t lim;
16410 #if  __has_feature(ptrauth_calls)
16411 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
16412 #endif /*  __has_feature(ptrauth_calls) */
16413 
16414 	lck_ticket_lock(sKextAccountsLock, LCK_GRP_NULL);
16415 	site = releasesite = NULL;
16416 
16417 	// bsearch sKextAccounts list
16418 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
16419 		active = &sKextAccounts[baseIdx + (lim >> 1)];
16420 		if ((address >= active->address) && (address < active->address_end)) {
16421 			site = &active->account->site;
16422 			if (!site->tag) {
16423 				vm_tag_alloc_locked(site, &releasesite);
16424 			}
16425 			break;
16426 		} else if (address > active->address) {
16427 			// move right
16428 			baseIdx += (lim >> 1) + 1;
16429 			lim--;
16430 		}
16431 		// else move left
16432 	}
16433 	lck_ticket_unlock(sKextAccountsLock);
16434 	if (releasesite) {
16435 		kern_allocation_name_release(releasesite);
16436 	}
16437 
16438 	return site;
16439 }
16440 
16441 #if DEVELOPMENT || DEBUG
16442 extern "C" void
16443 OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *))
16444 {
16445 	OSKextActiveAccount *  active;
16446 
16447 	uint32_t baseIdx;
16448 	uint32_t lim;
16449 #if  __has_feature(ptrauth_calls)
16450 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
16451 #endif /*  __has_feature(ptrauth_calls) */
16452 
16453 	lck_ticket_lock(sKextAccountsLock, LCK_GRP_NULL);
16454 
16455 	// bsearch sKextAccounts list
16456 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
16457 		active = &sKextAccounts[baseIdx + (lim >> 1)];
16458 		if ((address >= active->address) && (address < active->address_end)) {
16459 			cb(&active->account->task_refgrp);
16460 			break;
16461 		} else if (address > active->address) {
16462 			// move right
16463 			baseIdx += (lim >> 1) + 1;
16464 			lim--;
16465 		}
16466 		// else move left
16467 	}
16468 	lck_ticket_unlock(sKextAccountsLock);
16469 }
16470 #endif /* DEVELOPMENT || DEBUG */
16471 
16472 extern "C" uint32_t
16473 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
16474 {
16475 	OSKextAccount * account = (typeof(account))site;
16476 	const char    * kname;
16477 
16478 	if (name) {
16479 		if (account->kext) {
16480 			kname = account->kext->getIdentifierCString();
16481 		} else {
16482 			kname = "<>";
16483 		}
16484 		strlcpy(name, kname, namelen);
16485 	}
16486 
16487 	return account->loadTag;
16488 }
16489 
16490 extern "C" void
16491 OSKextFreeSite(vm_allocation_site_t * site)
16492 {
16493 	OSKextAccount * freeAccount = (typeof(freeAccount))site;
16494 	IOFreeType(freeAccount, OSKextAccount);
16495 }
16496 
16497 /*********************************************************************
16498 *********************************************************************/
16499 
16500 #if CONFIG_IMAGEBOOT
16501 int
16502 OSKextGetUUIDForName(const char *name, uuid_t uuid)
16503 {
16504 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name);
16505 	if (!kext) {
16506 		return 1;
16507 	}
16508 
16509 	OSSharedPtr<OSData> uuid_data = kext->copyUUID();
16510 	if (uuid_data) {
16511 		memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
16512 		return 0;
16513 	}
16514 
16515 	return 1;
16516 }
16517 #endif
16518 
16519 
16520 
16521 class OSDextCrash : public OSObject {
16522 	OSDeclareDefaultStructors(OSDextCrash);
16523 public:
16524 	static OSPtr<OSDextCrash> withTimestamp(uint64_t timestamp);
16525 	uint64_t getTimestamp();
16526 
16527 private:
16528 	virtual bool initWithTimestamp(uint64_t timestamp);
16529 	uint64_t fTimestamp;
16530 };
16531 
16532 OSDefineMetaClassAndStructors(OSDextCrash, OSObject);
16533 
16534 OSSharedPtr<OSDextCrash>
16535 OSDextCrash::withTimestamp(uint64_t timestamp)
16536 {
16537 	OSSharedPtr<OSDextCrash> result = OSMakeShared<OSDextCrash>();
16538 	if (!result->initWithTimestamp(timestamp)) {
16539 		return NULL;
16540 	}
16541 	return result;
16542 }
16543 
16544 bool
16545 OSDextCrash::initWithTimestamp(uint64_t timestamp)
16546 {
16547 	if (!OSObject::init()) {
16548 		return false;
16549 	}
16550 	fTimestamp = timestamp;
16551 	return true;
16552 }
16553 
16554 uint64_t
16555 OSDextCrash::getTimestamp()
16556 {
16557 	return fTimestamp;
16558 }
16559 
16560 OSSharedPtr<OSDextStatistics>
16561 OSDextStatistics::create()
16562 {
16563 	OSSharedPtr<OSDextStatistics> result = OSMakeShared<OSDextStatistics>();
16564 	if (!result->init()) {
16565 		return NULL;
16566 	}
16567 	return result;
16568 }
16569 
16570 bool
16571 OSDextStatistics::init()
16572 {
16573 	if (!OSObject::init()) {
16574 		return false;
16575 	}
16576 
16577 	lock = IOLockAlloc();
16578 	crashes = OSArray::withCapacity(kMaxDextCrashesInOneDay);
16579 	return true;
16580 }
16581 
16582 void
16583 OSDextStatistics::free()
16584 {
16585 	if (lock) {
16586 		IOLockFree(lock);
16587 	}
16588 	crashes.reset();
16589 	OSObject::free();
16590 }
16591 
16592 OSDextCrashPolicy
16593 OSDextStatistics::recordCrash()
16594 {
16595 	size_t i = 0;
16596 	uint64_t timestamp = mach_continuous_time();
16597 	uint64_t interval;
16598 	nanoseconds_to_absolutetime(86400 * NSEC_PER_SEC /* 1 day */, &interval);
16599 	uint64_t lastTimestamp = timestamp > interval ? timestamp - interval : 0;
16600 	OSDextCrashPolicy policy;
16601 
16602 	IOLockLock(lock);
16603 	OSSharedPtr<OSDextCrash> crash = OSDextCrash::withTimestamp(timestamp);
16604 	for (i = 0; i < crashes->getCount();) {
16605 		OSDextCrash * current = OSDynamicCast(OSDextCrash, crashes->getObject(i));
16606 		assert(current != NULL);
16607 		if (current->getTimestamp() < lastTimestamp) {
16608 			crashes->removeObject(i);
16609 		} else {
16610 			i++;
16611 		}
16612 	}
16613 
16614 	crashes->setObject(crash);
16615 
16616 	if (crashes->getCount() > kMaxDextCrashesInOneDay) {
16617 		policy = kOSDextCrashPolicyReboot;
16618 	} else {
16619 		policy = kOSDextCrashPolicyNone;
16620 	}
16621 
16622 	IOLockUnlock(lock);
16623 
16624 	return policy;
16625 }
16626 
16627 size_t
16628 OSDextStatistics::getCrashCount()
16629 {
16630 	size_t result = 0;
16631 	IOLockLock(lock);
16632 	result = crashes->getCount();
16633 	IOLockUnlock(lock);
16634 	return result;
16635 }
16636 
16637 static int
16638 sysctl_willuserspacereboot
16639 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
16640 {
16641 	int new_value = 0, old_value = 0, changed = 0;
16642 	int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
16643 	if (error) {
16644 		return error;
16645 	}
16646 	if (changed) {
16647 		OSKext::willUserspaceReboot();
16648 	}
16649 	return 0;
16650 }
16651 
16652 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot,
16653     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
16654     NULL, 0, sysctl_willuserspacereboot, "I", "");
16655