xref: /xnu-12377.61.12/libkern/c++/OSKext.cpp (revision 4d495c6e23c53686cf65f45067f79024cf5dcee8)
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_xnu.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 <sys/reboot.h>
54 #include <pexpert/pexpert.h>
55 #include <pexpert/device_tree.h>
56 
57 #include <sys/pgo.h>
58 
59 #if CONFIG_CSR
60 #include <sys/csr.h>
61 #include <sys/stat.h>
62 #include <sys/vnode.h>
63 #endif /* CONFIG_CSR */
64 };
65 
66 #if CONFIG_MACF
67 #include <sys/kauth.h>
68 #include <security/mac_framework.h>
69 #endif
70 
71 #include <vm/vm_kern_xnu.h>
72 #include <sys/sysctl.h>
73 #include <kern/task.h>
74 #include <os/cpp_util.h>
75 
76 #include <libkern/OSKextLibPrivate.h>
77 #include <libkern/c++/OSKext.h>
78 #include <libkern/c++/OSLib.h>
79 
80 #include <IOKit/IOLib.h>
81 #include <IOKit/IOCatalogue.h>
82 #include <IOKit/IORegistryEntry.h>
83 #include <IOKit/IOService.h>
84 #include <IOKit/IOUserServer.h>
85 
86 #include <IOKit/IOStatisticsPrivate.h>
87 #include <IOKit/IOBSD.h>
88 #include <IOKit/IOPlatformExpert.h>
89 
90 #include <san/kasan.h>
91 
92 #if CONFIG_SPTM
93 #include <arm64/sptm/sptm.h>
94 #endif
95 
96 #if PRAGMA_MARK
97 #pragma mark External & Internal Function Protos
98 #endif
99 /*********************************************************************
100 *********************************************************************/
101 extern "C" {
102 extern int  IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
103 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
104 
105 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
106 extern int dtrace_keep_kernel_symbols(void);
107 
108 #if defined(__x86_64__) || defined(__i386__)
109 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide);
110 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers);
111 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size);
112 static void *allocate_kcfileset_map_entry_list(void);
113 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size);
114 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable);
115 int vnode_put(struct vnode *vp);
116 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size,
117     void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot);
118 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size);
119 void * ubc_getobject(struct vnode *vp, __unused int flags);
120 #endif //(__x86_64__) || defined(__i386__)
121 }
122 
123 extern unsigned long gVirtBase;
124 extern unsigned long gPhysBase;
125 
126 bool pageableKCloaded = false;
127 bool auxKCloaded = false;
128 bool resetAuxKCSegmentOnUnload = false;
129 
130 extern boolean_t pageablekc_uuid_valid;
131 extern uuid_t pageablekc_uuid;
132 extern uuid_string_t pageablekc_uuid_string;
133 
134 extern boolean_t auxkc_uuid_valid;
135 extern uuid_t auxkc_uuid;
136 extern uuid_string_t auxkc_uuid_string;
137 
138 static OSReturn _OSKextCreateRequest(
139 	const char    * predicate,
140 	OSSharedPtr<OSDictionary> & requestP);
141 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
142 static OSObject * _OSKextGetRequestArgument(
143 	OSDictionary * requestDict,
144 	const char   * argName);
145 static bool _OSKextSetRequestArgument(
146 	OSDictionary    * requestDict,
147 	const char      * argName,
148 	OSMetaClassBase * value);
149 template <typename T>
150 static T * _OSKextExtractPointer(OSValueObject<T *> * wrapper);
151 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper);
152 static OSReturn _OSDictionarySetCStringValue(
153 	OSDictionary * dict,
154 	const char   * key,
155 	const char   * value);
156 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
157 #if CONFIG_KXLD
158 static bool _OSKextInPrelinkRebuildWindow(void);
159 #endif
160 
161 // We really should add containsObject() & containsCString to OSCollection & subclasses.
162 // So few pad slots, though....
163 static bool _OSArrayContainsCString(OSArray * array, const char * cString);
164 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code);
165 
166 static const char *getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size);
167 
168 /* Prelinked arm kexts do not have VM entries because the method we use to
169  * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
170  * not work on ARM.  To get around that, we must free prelinked kext
171  * executables with ml_static_mfree() instead of kext_free().
172  */
173 #if __i386__ || __x86_64__
174 #define VM_MAPPED_KEXTS 1
175 #define KASLR_KEXT_DEBUG 0
176 #define KASLR_IOREG_DEBUG 0
177 #elif __arm__ || __arm64__
178 #define VM_MAPPED_KEXTS 0
179 #define KASLR_KEXT_DEBUG 0
180 #else
181 #error Unsupported architecture
182 #endif
183 
184 #if PRAGMA_MARK
185 #pragma mark Constants & Macros
186 #endif
187 /*********************************************************************
188 * Constants & Macros
189 *********************************************************************/
190 
191 /* Use this number to create containers.
192  */
193 #define kOSKextTypicalLoadCount      (150)
194 #define kOSKextTypicalUpgradeCount     (5)
195 
196 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
197  * A loaded kext will no dependents or external retains will have 2 retains.
198  */
199 #define kOSKextMinRetainCount        (1)
200 #define kOSKextMinLoadedRetainCount  (2)
201 
202 #define kOSKextMaxDextLaunchedCount  (~((uint32_t)0))
203 #define KOSBundleDextUniqueIdentifierMaxStringLength (KOSBundleDextUniqueIdentifierMaxLength * 2 +1)
204 
205 /**********
206  * Strings and substrings used in dependency resolution.
207  */
208 #define APPLE_KEXT_PREFIX            "com.apple."
209 #define KERNEL_LIB                   "com.apple.kernel"
210 
211 #define PRIVATE_KPI                  "com.apple.kpi.private"
212 
213 /* Version for compatbility pseudokexts (com.apple.kernel.*),
214  * compatible back to v6.0.
215  */
216 #define KERNEL6_LIB                  "com.apple.kernel.6.0"
217 #define KERNEL6_VERSION              "7.9.9"
218 
219 #define KERNEL_LIB_PREFIX            "com.apple.kernel."
220 #define KPI_LIB_PREFIX               "com.apple.kpi."
221 
222 #define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0)
223 
224 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
225 #define MINIMUM_WAKEUP_SECONDS (30)
226 
227 /*********************************************************************
228 * infoDict keys for internally-stored data. Saves on ivar slots for
229 * objects we don't keep around past boot time or during active load.
230 *********************************************************************/
231 
232 /* A usable, uncompressed file is stored under this key.
233  */
234 #define _kOSKextExecutableKey                "_OSKextExecutable"
235 
236 /* An indirect reference to the executable file from an mkext
237  * is stored under this key.
238  */
239 #define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference"
240 
241 /* If the file is contained in a larger buffer laid down by the booter or
242  * sent from user space, the OSKext stores that OSData under this key so that
243  * references are properly tracked. This is always an mkext, right now.
244  */
245 #define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData"
246 
247 #define OS_LOG_HDR_VERSION  1
248 #define NUM_OS_LOG_SECTIONS 3
249 
250 #define OS_LOG_SECT_IDX         0
251 #define CSTRING_SECT_IDX        1
252 #define ASAN_CSTRING_SECT_IDX   2
253 
254 #if PRAGMA_MARK
255 #pragma mark Typedefs
256 #endif
257 /*********************************************************************
258 * Typedefs
259 *********************************************************************/
260 
261 /*********************************************************************
262 * osLogDataHeaderRef describes the header information of an OSData
263 * object that is returned when querying for kOSBundleLogStringsKey.
264 * We currently return information regarding 2 sections - os_log and
265 * cstring. In the case that the os_log section doesn't exist, we just
266 * return an offset and length of 0 for that section.
267 *********************************************************************/
268 typedef struct osLogDataHeader {
269 	uint32_t version;
270 	uint32_t sect_count;
271 	struct {
272 		uint32_t sect_offset;
273 		uint32_t sect_size;
274 	} sections[0];
275 } osLogDataHeaderRef;
276 
277 /*********************************************************************
278 * MkextEntryRef describes the contents of an OSData object
279 * referencing a file entry from an mkext so that we can uncompress
280 * (if necessary) and extract it on demand.
281 *
282 * It contains the mkextVersion in case we ever wind up supporting
283 * multiple mkext formats. Mkext format 1 is officially retired as of
284 * Snow Leopard.
285 *********************************************************************/
286 typedef struct MkextEntryRef {
287 	mkext_basic_header * mkext; // beginning of whole mkext file
288 	void               * fileinfo;// mkext2_file_entry or equiv; see mkext.h
289 } MkextEntryRef;
290 
291 #if PRAGMA_MARK
292 #pragma mark Global and static Module Variables
293 #endif
294 /*********************************************************************
295 * Global & static variables, used to keep track of kexts.
296 *********************************************************************/
297 
298 static  bool                sPrelinkBoot               = false;
299 static  bool                sSafeBoot                  = false;
300 static  bool                sKeepSymbols               = false;
301 static  bool                sPanicOnKCMismatch         = false;
302 static  bool                sOSKextWasResetAfterUserspaceReboot = false;
303 
304 /*********************************************************************
305  * sKextLock is the principal lock for OSKext, and guards all static
306  * and global variables not owned by other locks (declared further
307  * below). It must be taken by any entry-point method or function,
308  * including internal functions called on scheduled threads.
309  *
310  * sKextLock and sKextInnerLock are recursive due to multiple functions
311  * that are called both externally and internally. The other locks are
312  * nonrecursive.
313  *
314  * Which locks are taken depends on what they protect, but if more than
315  * one must be taken, they must always be locked in this order
316  * (and unlocked in reverse order) to prevent deadlocks:
317  *
318  *    1. sKextLock
319  *    2. sKextInnerLock
320  *    3. sKextSummariesLock
321  *    4. sKextLoggingLock
322  */
323 static IORecursiveLock    * sKextLock                  = NULL;
324 
325 static OSSharedPtr<OSDictionary>   sKextsByID;
326 static OSSharedPtr<OSDictionary>   sExcludeListByID;
327 static OSKextVersion               sExcludeListVersion        = 0;
328 static OSSharedPtr<OSArray>        sLoadedKexts;
329 static OSSharedPtr<OSDictionary>   sNonLoadableKextsByID;
330 static OSSharedPtr<OSArray>        sUnloadedPrelinkedKexts;
331 static OSSharedPtr<OSArray>        sLoadedDriverKitKexts;
332 static OSSharedPtr<OSDictionary>   sDriverKitToUpgradeByID;
333 
334 // Requests to the IOKit daemon waiting to be picked up.
335 static OSSharedPtr<OSArray>        sKernelRequests;
336 // Identifier of kext load requests in sKernelRequests
337 static OSSharedPtr<OSSet>          sPostedKextLoadIdentifiers;
338 static OSSharedPtr<OSArray>        sRequestCallbackRecords;
339 
340 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
341 static OSSharedPtr<OSSet>          sAllKextLoadIdentifiers;
342 #if CONFIG_KXLD
343 static KXLDContext        * sKxldContext               = NULL;
344 #endif
345 static uint32_t             sNextLoadTag               = 0;
346 static uint32_t             sNextRequestTag            = 0;
347 
348 static bool                 sUserLoadsActive           = false;
349 static bool                 sIOKitDaemonActive         = false;
350 static bool                 sDeferredLoadSucceeded     = false;
351 static bool                 sConsiderUnloadsExecuted   = false;
352 
353 #if NO_KEXTD
354 static bool                 sKernelRequestsEnabled     = false;
355 #else
356 static bool                 sKernelRequestsEnabled     = true;
357 #endif
358 static bool                 sLoadEnabled               = true;
359 static bool                 sUnloadEnabled             = true;
360 
361 /*********************************************************************
362  * Stuff for the OSKext representing the kernel itself.
363  **********/
364 static OSKext          * sKernelKext             = NULL;
365 
366 /* Load Tag IDs used by statically loaded binaries (e.g, the kernel itself). */
367 enum : uint32_t {
368 	kOSKextKernelLoadTag = 0,
369 #if CONFIG_SPTM
370 	kOSKextSPTMLoadTag   = 1,
371 	kOSKextTXMLoadTag    = 2,
372 #endif /* CONFIG_SPTM */
373 	kOSKextLoadTagCount
374 };
375 
376 /* Set up a fake kmod_info struct for the kernel.
377  * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
378  * before OSKext is initialized; that call only needs the name
379  * and address to be set correctly.
380  *
381  * We don't do much else with the kerne's kmod_info; we never
382  * put it into the kmod list, never adjust the reference count,
383  * and never have kernel components reference it.
384  * For that matter, we don't do much with kmod_info structs
385  * at all anymore! We just keep them filled in for gdb and
386  * binary compability.
387  */
388 kmod_info_t g_kernel_kmod_info = {
389 	.next =            NULL,
390 	.info_version =    KMOD_INFO_VERSION,
391 	.id =              kOSKextKernelLoadTag,   // loadTag: kernel is always 0
392 	.name =            kOSKextKernelIdentifier,// bundle identifier
393 	.version =         "0",           // filled in in OSKext::initialize()
394 	.reference_count = -1,            // never adjusted; kernel never unloads
395 	.reference_list =  NULL,
396 	.address =         0,
397 	.size =            0,             // filled in in OSKext::initialize()
398 	.hdr_size =        0,
399 	.start =           NULL,
400 	.stop =            NULL
401 };
402 
403 #if CONFIG_SPTM
404 /* The SPTM and TXM need fake kmod structures just like the kernel. */
405 kmod_info_t g_sptm_kmod_info = {
406 	.next =            NULL,
407 	.info_version =    KMOD_INFO_VERSION,
408 	.id =              kOSKextSPTMLoadTag,   // Always one after the kernel
409 	.name =            kOSKextSPTMIdentifier,// bundle identifier
410 	.version =         "0",           // filled in by OSKext::initialize()
411 	.reference_count = -1,            // never adjusted; SPTM never unloads
412 	.reference_list =  NULL,
413 	.address =         0,
414 	.size =            0,             // filled in by OSKext::initialize()
415 	.hdr_size =        0,
416 	.start =           NULL,
417 	.stop =            NULL
418 };
419 
420 kmod_info_t g_txm_kmod_info = {
421 	.next =            NULL,
422 	.info_version =    KMOD_INFO_VERSION,
423 	.id =              kOSKextTXMLoadTag,   // Always one after the SPTM
424 	.name =            kOSKextTXMIdentifier,// bundle identifier
425 	.version =         "0",           // filled in by OSKext::initialize()
426 	.reference_count = -1,            // never adjusted; TXM never unloads
427 	.reference_list =  NULL,
428 	.address =         0,
429 	.size =            0,             // filled in by OSKext::initialize()
430 	.hdr_size =        0,
431 	.start =           NULL,
432 	.stop =            NULL
433 };
434 #endif /* CONFIG_SPTM */
435 
436 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
437 
438 kmod_info_t invalid_kmod_info = {
439 	.next =            NULL,
440 	.info_version =    KMOD_INFO_VERSION,
441 	.id =              UINT32_MAX,
442 	.name =            "invalid",
443 	.version =         "0",
444 	.reference_count = -1,
445 	.reference_list =  NULL,
446 	.address =         0,
447 	.size =            0,
448 	.hdr_size =        0,
449 	.start =           NULL,
450 	.stop =            NULL
451 };
452 
453 extern "C" {
454 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
455 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
456 // misc_protos.h, db_low_trace.c, kgmacros
457 // 'kmod' is a holdover from the old kmod system, we can't rename it.
458 kmod_info_t * kmod = NULL;
459 
460 #define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE)
461 
462 
463 static char     * loaded_kext_paniclist         = NULL;
464 static uint32_t   loaded_kext_paniclist_size    = 0;
465 
466 AbsoluteTime      last_loaded_timestamp;
467 static char       last_loaded_str_buf[2 * KMOD_MAX_NAME];
468 static u_long     last_loaded_strlen            = 0;
469 static void     * last_loaded_address           = NULL;
470 static u_long     last_loaded_size              = 0;
471 
472 AbsoluteTime      last_unloaded_timestamp;
473 static char       last_unloaded_str_buf[2 * KMOD_MAX_NAME];
474 static u_long     last_unloaded_strlen          = 0;
475 static void     * last_unloaded_address         = NULL;
476 static u_long     last_unloaded_size            = 0;
477 
478 // Statically linked kmods described by several mach-o sections:
479 //
480 // kPrelinkInfoSegment:kBuiltinInfoSection
481 // Array of pointers to kmod_info_t structs.
482 //
483 // kPrelinkInfoSegment:kBuiltinInfoSection
484 // Array of pointers to an embedded mach-o header.
485 //
486 // __DATA:kBuiltinInitSection, kBuiltinTermSection
487 // Structors for all kmods. Has to be filtered by proc address.
488 //
489 
490 static uint32_t gBuiltinKmodsCount;
491 static kernel_section_t * gBuiltinKmodsSectionInfo;
492 static kernel_section_t * gBuiltinKmodsSectionStart;
493 
494 const OSSymbol              * gIOSurfaceIdentifier;
495 vm_tag_t                      gIOSurfaceTag;
496 
497 /*********************************************************************
498  * sKextInnerLock protects against cross-calls with IOService and
499  * IOCatalogue, and owns the variables declared immediately below.
500  *
501  * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
502  *
503  * When both sKextLock and sKextInnerLock need to be taken,
504  * always lock sKextLock first and unlock it second. Never take both
505  * locks in an entry point to OSKext; if you need to do so, you must
506  * spawn an independent thread to avoid potential deadlocks for threads
507  * calling into OSKext.
508  **********/
509 static IORecursiveLock *    sKextInnerLock             = NULL;
510 
511 #if XNU_TARGET_OS_OSX
512 static bool                 sAutounloadEnabled         = true;
513 #endif
514 static bool                 sConsiderUnloadsCalled     = false;
515 static bool                 sConsiderUnloadsPending    = false;
516 
517 static unsigned int         sConsiderUnloadDelay       = 60;     // seconds
518 static thread_call_t        sUnloadCallout             = NULL;
519 #if CONFIG_KXLD
520 static thread_call_t        sDestroyLinkContextThread  = NULL;   // one-shot, one-at-a-time thread
521 #endif // CONFIG_KXLD
522 static bool                 sSystemSleep               = false;  // true when system going to sleep
523 static AbsoluteTime         sLastWakeTime;                       // last time we woke up
524 
525 /*********************************************************************
526  * Backtraces can be printed at various times so we need a tight lock
527  * on data used for that. sKextSummariesLock protects the variables
528  * declared immediately below.
529  *
530  * gLoadedKextSummaries is accessed by other modules, but only during
531  * a panic so the lock isn't needed then.
532  *
533  * gLoadedKextSummaries has the "used" attribute in order to ensure
534  * that it remains visible even when we are performing extremely
535  * aggressive optimizations, as it is needed to allow the debugger
536  * to automatically parse the list of loaded kexts.
537  **********/
538 static IOLock                 * sKextSummariesLock                = NULL;
539 extern "C" lck_grp_t            vm_page_lck_grp_bucket;
540 static lck_grp_t              * sKextAccountsLockGrp = &vm_page_lck_grp_bucket;
541 #define sKextAccountsLock       (&vm_allocation_sites_lock)
542 
543 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
544 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
545 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
546 static size_t sLoadedKextSummariesAllocSize = 0;
547 
548 static OSKextActiveAccount    * sKextAccounts;
549 static uint32_t                 sKextAccountsCount;
550 };
551 
552 /*********************************************************************
553  * sKextLoggingLock protects the logging variables declared immediately below.
554  **********/
555 __static_testable IOLock      * sKextLoggingLock           = NULL;
556 
557 static  const OSKextLogSpec     kDefaultKernelLogFilter    = kOSKextLogBasicLevel |
558     kOSKextLogVerboseFlagsMask;
559 static  OSKextLogSpec           sKernelLogFilter           = kDefaultKernelLogFilter;
560 static  bool                    sBootArgLogFilterFound     = false;
561 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
562     0, "kernel kext logging");
563 
564 static  OSKextLogSpec           sUserSpaceKextLogFilter    = kOSKextLogSilentFilter;
565 static  OSSharedPtr<OSArray>    sUserSpaceLogSpecArray;
566 static  OSSharedPtr<OSArray>    sUserSpaceLogMessageArray;
567 
568 /*********
569  * End scope for sKextInnerLock-protected variables.
570  *********************************************************************/
571 
572 /*********************************************************************
573  * OSValueObject concrete type instantiations
574  **********/
575 OSDefineValueObjectForDependentType(void*)
576 OSDefineValueObjectForDependentType(OSKextRequestResourceCallback)
577 
578 
579 /**********************************************************************/
580 
581 TUNABLE(uint32_t, kMaxDextCrashesInOneDay, "daily_max_dext_crashes", kMaxDextCrashesInOneDayDefault);
582 
583 /*********************************************************************
584  *  helper function used for collecting PGO data upon unload of a kext
585  */
586 
587 static int OSKextGrabPgoDataLocked(OSKext *kext,
588     bool metadata,
589     uuid_t instance_uuid,
590     uint64_t *pSize,
591     char *pBuffer,
592     uint64_t bufferSize);
593 
594 /**********************************************************************/
595 
596 
597 
598 #if PRAGMA_MARK
599 #pragma mark OSData callbacks (need to move to OSData)
600 #endif
601 /*********************************************************************
602 * C functions used for callbacks.
603 *********************************************************************/
604 extern "C" {
605 void
osdata_kmem_free(void * ptr,unsigned int length)606 osdata_kmem_free(void * ptr, unsigned int length)
607 {
608 	kmem_free(kernel_map, (vm_address_t)ptr, length);
609 	return;
610 }
611 
612 void
osdata_phys_free(void * ptr,unsigned int length)613 osdata_phys_free(void * ptr, unsigned int length)
614 {
615 	ml_static_mfree((vm_offset_t)ptr, length);
616 	return;
617 }
618 
619 void
osdata_vm_deallocate(void * ptr,unsigned int length)620 osdata_vm_deallocate(void * ptr, unsigned int length)
621 {
622 	(void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
623 	return;
624 }
625 
626 void
osdata_kext_free(void * ptr,unsigned int length)627 osdata_kext_free(void * ptr, unsigned int length)
628 {
629 	(void)kext_free((vm_offset_t)ptr, length);
630 }
631 };
632 
633 #if PRAGMA_MARK
634 #pragma mark KXLD Allocation Callback
635 #endif
636 #if CONFIG_KXLD
637 /*********************************************************************
638 * KXLD Allocation Callback
639 *********************************************************************/
640 kxld_addr_t
kern_allocate(u_long size,KXLDAllocateFlags * flags,void * user_data)641 kern_allocate(
642 	u_long              size,
643 	KXLDAllocateFlags * flags,
644 	void              * user_data)
645 {
646 	vm_address_t  result       = 0; // returned
647 	kern_return_t mach_result  = KERN_FAILURE;
648 	bool          success      = false;
649 	OSKext      * theKext      = (OSKext *)user_data;
650 	unsigned int  roundSize    = 0;
651 	OSSharedPtr<OSData>      linkBuffer;
652 
653 	if (round_page(size) > UINT_MAX) {
654 		OSKextLog(theKext,
655 		    kOSKextLogErrorLevel |
656 		    kOSKextLogGeneralFlag,
657 		    "%s: Requested memory size is greater than UINT_MAX.",
658 		    theKext->getIdentifierCString());
659 		goto finish;
660 	}
661 
662 	roundSize = (unsigned int)round_page(size);
663 
664 	mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
665 	if (mach_result != KERN_SUCCESS) {
666 		OSKextLog(theKext,
667 		    kOSKextLogErrorLevel |
668 		    kOSKextLogGeneralFlag,
669 		    "Can't allocate kernel memory to link %s.",
670 		    theKext->getIdentifierCString());
671 		goto finish;
672 	}
673 
674 	/* Create an OSData wrapper for the allocated buffer.
675 	 */
676 	linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
677 	if (!linkBuffer) {
678 		OSKextLog(theKext,
679 		    kOSKextLogErrorLevel |
680 		    kOSKextLogGeneralFlag,
681 		    "Can't allocate linked executable wrapper for %s.",
682 		    theKext->getIdentifierCString());
683 		goto finish;
684 	}
685 	linkBuffer->setDeallocFunction(osdata_kext_free);
686 	OSKextLog(theKext,
687 	    kOSKextLogProgressLevel |
688 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
689 	    "Allocated link buffer for kext %s at %p (%lu bytes).",
690 	    theKext->getIdentifierCString(),
691 	    (void *)result, (unsigned long)roundSize);
692 
693 	theKext->setLinkedExecutable(linkBuffer.get());
694 
695 	*flags = kKxldAllocateWritable;
696 	success = true;
697 
698 finish:
699 	if (!success && result) {
700 		kext_free(result, roundSize);
701 		result = 0;
702 	}
703 
704 	return (kxld_addr_t)result;
705 }
706 
707 /*********************************************************************
708 *********************************************************************/
709 void
kxld_log_callback(KXLDLogSubsystem subsystem,KXLDLogLevel level,const char * format,va_list argList,void * user_data)710 kxld_log_callback(
711 	KXLDLogSubsystem    subsystem,
712 	KXLDLogLevel        level,
713 	const char        * format,
714 	va_list             argList,
715 	void              * user_data)
716 {
717 	OSKext *theKext = (OSKext *) user_data;
718 	OSKextLogSpec logSpec = 0;
719 
720 	switch (subsystem) {
721 	case kKxldLogLinking:
722 		logSpec |= kOSKextLogLinkFlag;
723 		break;
724 	case kKxldLogPatching:
725 		logSpec |= kOSKextLogPatchFlag;
726 		break;
727 	}
728 
729 	switch (level) {
730 	case kKxldLogExplicit:
731 		logSpec |= kOSKextLogExplicitLevel;
732 		break;
733 	case kKxldLogErr:
734 		logSpec |= kOSKextLogErrorLevel;
735 		break;
736 	case kKxldLogWarn:
737 		logSpec |= kOSKextLogWarningLevel;
738 		break;
739 	case kKxldLogBasic:
740 		logSpec |= kOSKextLogProgressLevel;
741 		break;
742 	case kKxldLogDetail:
743 		logSpec |= kOSKextLogDetailLevel;
744 		break;
745 	case kKxldLogDebug:
746 		logSpec |= kOSKextLogDebugLevel;
747 		break;
748 	}
749 
750 	OSKextVLog(theKext, logSpec, format, argList);
751 }
752 #endif // CONFIG_KXLD
753 
754 #if PRAGMA_MARK
755 #pragma mark IOStatistics defines
756 #endif
757 
758 #if IOKITSTATS
759 
760 #define notifyKextLoadObservers(kext, kmod_info) \
761 do { \
762     IOStatistics::onKextLoad(kext, kmod_info); \
763 } while (0)
764 
765 #define notifyKextUnloadObservers(kext) \
766 do { \
767     IOStatistics::onKextUnload(kext); \
768 } while (0)
769 
770 #define notifyAddClassObservers(kext, addedClass, flags) \
771 do { \
772     IOStatistics::onClassAdded(kext, addedClass); \
773 } while (0)
774 
775 #define notifyRemoveClassObservers(kext, removedClass, flags) \
776 do { \
777     IOStatistics::onClassRemoved(kext, removedClass); \
778 } while (0)
779 
780 #else
781 
782 #define notifyKextLoadObservers(kext, kmod_info)
783 #define notifyKextUnloadObservers(kext)
784 #define notifyAddClassObservers(kext, addedClass, flags)
785 #define notifyRemoveClassObservers(kext, removedClass, flags)
786 
787 #endif /* IOKITSTATS */
788 
789 #if PRAGMA_MARK
790 #pragma mark Module Config (Startup & Shutdown)
791 #endif
792 /*********************************************************************
793 * Module Config (Class Definition & Class Methods)
794 *********************************************************************/
795 #define super OSObject
796 OSDefineMetaClassAndStructors(OSKext, OSObject)
797 
798 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject);
799 
800 OSDefineMetaClassAndStructors(OSDextStatistics, OSObject);
801 
802 /*********************************************************************
803 *********************************************************************/
804 /**
805  * Allocate and intialize a fake/representative OSKext object for a statically
806  * loaded (by iBoot) binary (e.g., the XNU kernel itself).
807  *
808  * @param kmod_info Pointer to the kmod_info structure for the binary being
809  *                  setup. At least the "name" and "id" fields needs to already
810  *                  be set correctly.
811  *
812  * @return The allocated and initialized OSKext object.
813  */
814 /* static */
815 OSKext *
allocAndInitFakeKext(kmod_info_t * kmod_info)816 OSKext::allocAndInitFakeKext(kmod_info_t *kmod_info)
817 {
818 	vm_offset_t load_address = 0;
819 	const char *bundle_name = NULL;
820 	bool macho_is_unslid = false;
821 	bool set_custom_path = false;
822 	const char *executable_fallback_name = NULL;
823 
824 	if (kmod_info->id == kOSKextKernelLoadTag) {
825 		load_address = (vm_offset_t)&_mh_execute_header;
826 		bundle_name = "mach_kernel";
827 
828 		/* The kernel Mach-O header is fixed up to slide all of its addresses. */
829 		macho_is_unslid = false;
830 
831 		/**
832 		 * No path to the binary is set for the kernel in its OSKext object. The
833 		 * kernel binary is located in fixed directories depending on the OS.
834 		 */
835 		set_custom_path = false;
836 		executable_fallback_name = NULL;
837 #if CONFIG_SPTM
838 	} else if (kmod_info->id == kOSKextSPTMLoadTag) {
839 		load_address = (vm_offset_t)SPTMArgs->debug_header->image[DEBUG_HEADER_ENTRY_SPTM];
840 		bundle_name = "sptm";
841 
842 		/* The addresses in the SPTM Mach-O header are all unslid. */
843 		macho_is_unslid = true;
844 
845 		set_custom_path = true;
846 		executable_fallback_name = "sptm.no.binname.in.macho";
847 	} else if (kmod_info->id == kOSKextTXMLoadTag) {
848 		load_address = (vm_offset_t)SPTMArgs->debug_header->image[DEBUG_HEADER_ENTRY_TXM];
849 		bundle_name = "txm";
850 
851 		/* The addresses in the TXM Mach-O header are all unslid. */
852 		macho_is_unslid = true;
853 
854 		set_custom_path = true;
855 		executable_fallback_name = "txm.no.binname.in.macho";
856 #endif /* CONFIG_SPTM */
857 	} else {
858 		panic("%s: Unsupported kmod_info->id (%d)", __func__, kmod_info->id);
859 	}
860 
861 	/* Set up an OSKext instance to represent the statically loaded binary. */
862 	OSKext *fakeKext = new OSKext;
863 	assert(fakeKext);
864 	assert(load_address != 0);
865 
866 	/*
867 	 * The start address is always a slid address whereas the last VA returned
868 	 * by getlastaddr() might be unslid depending on the Mach-O. If the address
869 	 * coming from the Mach-O is unslid, then unslide the start address before
870 	 * computing the length of the executable.
871 	 */
872 	size_t binaryLength = getlastaddr((kernel_mach_header_t*)load_address);
873 	binaryLength -= (macho_is_unslid) ? ml_static_unslide(load_address) : load_address;
874 	assert(binaryLength <= UINT_MAX);
875 
876 	/**
877 	 * The load address is always slid. That value will be unslid before being
878 	 * exposed to userspace.
879 	 */
880 	OSSharedPtr<OSData> executable = OSData::withBytesNoCopy(
881 		(void*)load_address, (unsigned int)binaryLength);
882 	assert(executable);
883 
884 	fakeKext->loadTag = sNextLoadTag++;
885 	fakeKext->bundleID = OSSymbol::withCString(kmod_info->name);
886 
887 	fakeKext->version = OSKextParseVersionString(osrelease);
888 	fakeKext->compatibleVersion = fakeKext->version;
889 	fakeKext->linkedExecutable = os::move(executable);
890 	fakeKext->interfaceUUID = fakeKext->copyUUID();
891 
892 	fakeKext->flags.hasAllDependencies = 1;
893 	fakeKext->flags.kernelComponent = 1;
894 	fakeKext->flags.prelinked = 0;
895 	fakeKext->flags.loaded = 1;
896 	fakeKext->flags.started = 1;
897 	fakeKext->flags.CPPInitialized = 0;
898 	fakeKext->flags.jettisonLinkeditSeg = 0;
899 	fakeKext->flags.unslidMachO = macho_is_unslid;
900 
901 #if CONFIG_SPTM
902 	if (set_custom_path) {
903 		/* Only SPTM/TXM should have custom paths to their executables set. */
904 		assert((kmod_info->id == kOSKextSPTMLoadTag) ||
905 		    (kmod_info->id == kOSKextTXMLoadTag));
906 
907 		/* All SPTM/TXM binaries are placed into the same path on internal systems. */
908 		fakeKext->path = OSString::withCStringNoCopy("/usr/appleinternal/standalone/platform");
909 
910 		/**
911 		 * Each SPTM/TXM Mach-O should contain a __TEXT,__binname section which contains
912 		 * a character array representing the name of the Mach-O executable.
913 		 */
914 		kernel_section_t *binname_sect =
915 		    getsectbynamefromheader((kernel_mach_header_t*)load_address, "__TEXT", "__binname");
916 
917 		if (binname_sect != NULL) {
918 			const char *binname = (const char *)ml_static_slide(binname_sect->addr);
919 			fakeKext->executableRelPath = OSString::withCStringNoCopy(binname);
920 		} else {
921 			fakeKext->executableRelPath = OSString::withCStringNoCopy(executable_fallback_name);
922 		}
923 	}
924 #endif /* CONFIG_SPTM */
925 
926 	fakeKext->kmod_info = kmod_info;
927 	strlcpy(kmod_info->version, osrelease,
928 	    sizeof(kmod_info->version));
929 	kmod_info->size = binaryLength;
930 	assert(kmod_info->id == fakeKext->loadTag);
931 
932 	/*
933 	 * Con up an info dict, so we don't have to have special-case checking all
934 	 * over.
935 	 */
936 	fakeKext->infoDict = OSDictionary::withCapacity(5);
937 	assert(fakeKext->infoDict);
938 	bool setResult = fakeKext->infoDict->setObject(kCFBundleIdentifierKey,
939 	    fakeKext->bundleID.get());
940 	assert(setResult);
941 	setResult = fakeKext->infoDict->setObject(kOSKernelResourceKey,
942 	    kOSBooleanTrue);
943 	assert(setResult);
944 
945 	{
946 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease));
947 		assert(scratchString);
948 		setResult = fakeKext->infoDict->setObject(kCFBundleVersionKey,
949 		    scratchString.get());
950 		assert(setResult);
951 	}
952 
953 	{
954 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(bundle_name));
955 		assert(scratchString);
956 		setResult = fakeKext->infoDict->setObject(kCFBundleNameKey,
957 		    scratchString.get());
958 		assert(setResult);
959 	}
960 
961 	return fakeKext;
962 }
963 
964 /* static */
965 void
initialize(void)966 OSKext::initialize(void)
967 {
968 	OSSharedPtr<OSData>     kernelExecutable   = NULL;// do not release
969 	IORegistryEntry * registryRoot       = NULL;// do not release
970 	OSSharedPtr<OSNumber> kernelCPUType;
971 	OSSharedPtr<OSNumber> kernelCPUSubtype;
972 	OSKextLogSpec     bootLogFilter      = kOSKextLogSilentFilter;
973 	bool              setResult          = false;
974 	uint64_t        * timestamp          = NULL;
975 	__unused char     bootArgBuffer[16];// for PE_parse_boot_argn w/strings
976 
977 	/* This must be the first thing allocated. Everything else grabs this lock.
978 	 */
979 	sKextLock = IORecursiveLockAlloc();
980 	sKextInnerLock = IORecursiveLockAlloc();
981 	sKextSummariesLock = IOLockAlloc();
982 	sKextLoggingLock = IOLockAlloc();
983 	assert(sKextLock);
984 	assert(sKextInnerLock);
985 	assert(sKextSummariesLock);
986 	assert(sKextLoggingLock);
987 
988 	sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
989 	sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
990 	sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
991 	sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
992 	sKernelRequests = OSArray::withCapacity(0);
993 	sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
994 	sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
995 	sRequestCallbackRecords = OSArray::withCapacity(0);
996 	sDriverKitToUpgradeByID = OSDictionary::withCapacity(kOSKextTypicalUpgradeCount);
997 
998 	assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests &&
999 	    sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
1000 	    sRequestCallbackRecords && sUnloadedPrelinkedKexts && sDriverKitToUpgradeByID);
1001 
1002 	/* Read the log flag boot-args and set the log flags.
1003 	 */
1004 	if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
1005 		sBootArgLogFilterFound = true;
1006 		sKernelLogFilter = bootLogFilter;
1007 		// log this if any flags are set
1008 		OSKextLog(/* kext */ NULL,
1009 		    kOSKextLogBasicLevel |
1010 		    kOSKextLogFlagsMask,
1011 		    "Kernel kext log filter 0x%x per kextlog boot arg.",
1012 		    (unsigned)sKernelLogFilter);
1013 	}
1014 
1015 #if !defined(__arm__) && !defined(__arm64__)
1016 	/*
1017 	 * On our ARM targets, the kernelcache/boot kernel collection contains
1018 	 * the set of kexts required to boot, as specified by KCB.  Safeboot is
1019 	 * either unsupported, or is supported by the bootloader only loading
1020 	 * the boot kernel collection; as a result OSKext has no role to play
1021 	 * in safeboot policy on ARM.
1022 	 */
1023 	sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
1024 	    sizeof(bootArgBuffer)) ? true : false;
1025 #endif /* defined(__arm__) && defined(__arm64__) */
1026 
1027 	if (sSafeBoot) {
1028 		OSKextLog(/* kext */ NULL,
1029 		    kOSKextLogWarningLevel |
1030 		    kOSKextLogGeneralFlag,
1031 		    "SAFE BOOT DETECTED - "
1032 		    "only valid OSBundleRequired kexts will be loaded.");
1033 	}
1034 
1035 	PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
1036 #if CONFIG_DTRACE
1037 	if (dtrace_keep_kernel_symbols()) {
1038 		sKeepSymbols = true;
1039 	}
1040 #endif /* CONFIG_DTRACE */
1041 #if KASAN_DYNAMIC_DENYLIST
1042 	/* needed for function lookup */
1043 	sKeepSymbols = true;
1044 #endif /* KASAN_DYNAMIC_DENYLIST */
1045 
1046 	/*
1047 	 * Should we panic when the SystemKC is not linked against the
1048 	 * BootKC that was loaded by the booter? By default: yes, if the
1049 	 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic
1050 	 * on mis-match and instead just print an error and continue.
1051 	 */
1052 	sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer,
1053 	    sizeof(bootArgBuffer)) ? false : true;
1054 
1055 	/* Set up an OSKext instance to represent the kernel itself. */
1056 	sKernelKext = allocAndInitFakeKext(&g_kernel_kmod_info);
1057 	assert(sKernelKext);
1058 
1059 #if CONFIG_SPTM
1060 	/* Set up OSKext instances to represent the SPTM/TXM. */
1061 	OSKext *SPTMKext = allocAndInitFakeKext(&g_sptm_kmod_info);
1062 	OSKext *TXMKext = allocAndInitFakeKext(&g_txm_kmod_info);
1063 #endif
1064 
1065 	/* Add the kernel kext to the bookkeeping dictionaries. Note that
1066 	 * the kernel kext doesn't have a kmod_info struct. copyInfo()
1067 	 * gathers info from other places anyhow.
1068 	 */
1069 	setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext);
1070 	assert(setResult);
1071 	setResult = sLoadedKexts->setObject(sKernelKext);
1072 	assert(setResult);
1073 
1074 #if CONFIG_SPTM
1075 	setResult = sKextsByID->setObject(SPTMKext->bundleID.get(), SPTMKext);
1076 	assert(setResult);
1077 	setResult = sLoadedKexts->setObject(SPTMKext);
1078 	assert(setResult);
1079 
1080 	setResult = sKextsByID->setObject(TXMKext->bundleID.get(), TXMKext);
1081 	assert(setResult);
1082 	setResult = sLoadedKexts->setObject(TXMKext);
1083 	assert(setResult);
1084 #endif /* CONFIG_SPTM */
1085 
1086 	// XXX: better way with OSSharedPtr?
1087 	// sKernelKext remains a valid pointer even after the decref
1088 	sKernelKext->release();
1089 #if CONFIG_SPTM
1090 	SPTMKext->release();
1091 	TXMKext->release();
1092 #endif /* CONFIG_SPTM */
1093 
1094 	registryRoot = IORegistryEntry::getRegistryRoot();
1095 	kernelCPUType = OSNumber::withNumber(
1096 		(long long unsigned int)_mh_execute_header.cputype,
1097 		8 * sizeof(_mh_execute_header.cputype));
1098 	kernelCPUSubtype = OSNumber::withNumber(
1099 		(long long unsigned int)_mh_execute_header.cpusubtype,
1100 		8 * sizeof(_mh_execute_header.cpusubtype));
1101 	assert(registryRoot && kernelCPUSubtype && kernelCPUType);
1102 
1103 	registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get());
1104 	registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get());
1105 
1106 	gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
1107 	if (gBuiltinKmodsSectionInfo) {
1108 		uint32_t count;
1109 
1110 		assert(gBuiltinKmodsSectionInfo->addr);
1111 		assert(gBuiltinKmodsSectionInfo->size);
1112 		assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX);
1113 		gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
1114 
1115 		gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
1116 		assert(gBuiltinKmodsSectionStart);
1117 		assert(gBuiltinKmodsSectionStart->addr);
1118 		assert(gBuiltinKmodsSectionStart->size);
1119 		assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX);
1120 		count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
1121 		// one extra pointer for the end of last kmod
1122 		assert(count == (gBuiltinKmodsCount + 1));
1123 
1124 		vm_kernel_builtinkmod_text     = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
1125 		vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
1126 	}
1127 
1128 	// Don't track this object -- it's never released
1129 	gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach();
1130 
1131 	timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
1132 	*timestamp = 0;
1133 	timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
1134 	*timestamp = 0;
1135 	timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
1136 	*timestamp = 0;
1137 
1138 	OSKextLog(/* kext */ NULL,
1139 	    kOSKextLogProgressLevel |
1140 	    kOSKextLogGeneralFlag,
1141 	    "Kext system initialized.");
1142 
1143 	notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
1144 #if CONFIG_SPTM
1145 	notifyKextLoadObservers(SPTMKext, SPTMKext->kmod_info);
1146 	notifyKextLoadObservers(TXMKext, TXMKext->kmod_info);
1147 #endif
1148 
1149 	return;
1150 }
1151 
1152 /*********************************************************************
1153 * This is expected to be called exactly once, from exactly one thread
1154 * context, during kernel bootstrap.
1155 *********************************************************************/
1156 /* static */
1157 OSReturn
removeKextBootstrap(void)1158 OSKext::removeKextBootstrap(void)
1159 {
1160 	OSReturn                   result                = kOSReturnError;
1161 
1162 	const char               * dt_kernel_header_name = "Kernel-__HEADER";
1163 	const char               * dt_kernel_symtab_name = "Kernel-__SYMTAB";
1164 	kernel_mach_header_t     * dt_mach_header        = NULL;
1165 	int                        dt_mach_header_size   = 0;
1166 	struct symtab_command    * dt_symtab             = NULL;
1167 	int                        dt_symtab_size        = 0;
1168 	int                        dt_result             = 0;
1169 
1170 	kernel_segment_command_t * seg_kld               = NULL;
1171 	kernel_segment_command_t * seg_klddata           = NULL;
1172 	kernel_segment_command_t * seg_linkedit          = NULL;
1173 
1174 	const char __unused      * dt_segment_name       = NULL;
1175 	void       __unused      * segment_paddress      = NULL;
1176 	int        __unused        segment_size          = 0;
1177 
1178 	OSKextLog(/* kext */ NULL,
1179 	    kOSKextLogProgressLevel |
1180 	    kOSKextLogGeneralFlag,
1181 	    "Jettisoning kext bootstrap segments.");
1182 
1183 	/*
1184 	 * keep the linkedit segment around when booted from a new MH_FILESET
1185 	 * KC because all the kexts shared a linkedit segment.
1186 	 */
1187 	kc_format_t kc_format;
1188 	if (!PE_get_primary_kc_format(&kc_format)) {
1189 		OSKextLog(/* kext */ NULL,
1190 		    kOSKextLogErrorLevel |
1191 		    kOSKextLogGeneralFlag,
1192 		    "Unable to determine primary KC format");
1193 	}
1194 
1195 	/*****
1196 	 * Dispose of unnecessary stuff that the booter didn't need to load.
1197 	 */
1198 	dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
1199 	    (void **)&dt_mach_header, &dt_mach_header_size);
1200 	if (dt_result == 0 && dt_mach_header) {
1201 		IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
1202 		    round_page_32(dt_mach_header_size));
1203 	}
1204 	dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
1205 	    (void **)&dt_symtab, &dt_symtab_size);
1206 	if (dt_result == 0 && dt_symtab) {
1207 		IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
1208 		    round_page_32(dt_symtab_size));
1209 	}
1210 
1211 	/*****
1212 	 * KLD & KLDDATA bootstrap segments.
1213 	 */
1214 	// xxx - should rename KLD segment
1215 	seg_kld = getsegbyname("__KLD");
1216 	seg_klddata = getsegbyname("__KLDDATA");
1217 	if (seg_klddata) {
1218 		// __mod_term_func is part of __KLDDATA
1219 		OSRuntimeUnloadCPPForSegment(seg_klddata);
1220 	}
1221 
1222 #if __arm__ || __arm64__
1223 	/* Free the memory that was set up by iBoot.
1224 	 */
1225 #if !defined(KERNEL_INTEGRITY_KTRR) && !defined(KERNEL_INTEGRITY_CTRR) && !defined(KERNEL_INTEGRITY_PV_CTRR)
1226 	/* We cannot free the KLD segment with CTRR enabled as it contains text and
1227 	 * is covered by the contiguous rorgn.
1228 	 */
1229 	dt_segment_name = "Kernel-__KLD";
1230 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1231 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1232 		    (int)segment_size); // calls ml_static_mfree
1233 	} else if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1234 		/* With fileset KCs, the Kernel KLD segment is not recorded in the DT. */
1235 #if !CONFIG_SPTM
1236 		ml_static_mfree(ml_static_ptovirt(seg_kld->vmaddr - gVirtBase + gPhysBase),
1237 		    seg_kld->vmsize);
1238 #else
1239 		ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize);
1240 #endif
1241 	}
1242 #endif
1243 	dt_segment_name = "Kernel-__KLDDATA";
1244 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1245 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1246 		    (int)segment_size);  // calls ml_static_mfree
1247 	} else if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1248 		/* With fileset KCs, the Kernel KLDDATA segment is not recorded in the DT. */
1249 #if !CONFIG_SPTM
1250 		ml_static_mfree(ml_static_ptovirt(seg_klddata->vmaddr - gVirtBase + gPhysBase),
1251 		    seg_klddata->vmsize);
1252 #else
1253 		ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize);
1254 #endif
1255 	}
1256 #elif __i386__ || __x86_64__
1257 	/* On x86, use the mapping data from the segment load command to
1258 	 * unload KLD & KLDDATA directly.
1259 	 * This may invalidate any assumptions about  "avail_start"
1260 	 * defining the lower bound for valid physical addresses.
1261 	 */
1262 	if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1263 		bzero((void *)seg_kld->vmaddr, seg_kld->vmsize);
1264 		ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize);
1265 	}
1266 	if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1267 		bzero((void *)seg_klddata->vmaddr, seg_klddata->vmsize);
1268 		ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize);
1269 	}
1270 #else
1271 #error arch
1272 #endif
1273 
1274 	/*****
1275 	 * Prelinked kernel's symtab (if there is one).
1276 	 */
1277 	if (kc_format != KCFormatFileset) {
1278 		kernel_section_t * sect;
1279 		sect = getsectbyname("__PRELINK", "__symtab");
1280 		if (sect && sect->addr && sect->size) {
1281 			ml_static_mfree(sect->addr, sect->size);
1282 		}
1283 	}
1284 
1285 	seg_linkedit = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
1286 
1287 	/* kxld always needs the kernel's __LINKEDIT segment, but we can make it
1288 	 * pageable, unless keepsyms is set.  To do that, we have to copy it from
1289 	 * its booter-allocated memory, free the booter memory, reallocate proper
1290 	 * managed memory, then copy the segment back in.
1291 	 *
1292 	 * NOTE: This optimization is not valid for fileset KCs because each
1293 	 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment
1294 	 * that points to one fileset-global LINKEDIT segment. This
1295 	 * optimization is also only valid for platforms that support vm
1296 	 * mapped kexts or mapped kext collections (pageable KCs)
1297 	 */
1298 #if VM_MAPPED_KEXTS
1299 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1300 		kern_return_t mem_result;
1301 		void *seg_copy = NULL;
1302 		void *seg_data = NULL;
1303 		vm_map_offset_t seg_offset = 0;
1304 		vm_map_offset_t seg_copy_offset = 0;
1305 		vm_map_size_t seg_length = 0;
1306 
1307 		seg_data = (void *) seg_linkedit->vmaddr;
1308 		seg_offset = (vm_map_offset_t) seg_linkedit->vmaddr;
1309 		seg_length = (vm_map_size_t) seg_linkedit->vmsize;
1310 
1311 		/* Allocate space for the LINKEDIT copy.
1312 		 */
1313 		mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
1314 		    seg_length, KMA_ZERO, VM_KERN_MEMORY_KEXT);
1315 		if (mem_result != KERN_SUCCESS) {
1316 			OSKextLog(/* kext */ NULL,
1317 			    kOSKextLogErrorLevel |
1318 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1319 			    "Can't copy __LINKEDIT segment for VM reassign.");
1320 			return result;
1321 		}
1322 		seg_copy_offset = (vm_map_offset_t) seg_copy;
1323 
1324 		/* Copy it out.
1325 		 */
1326 		memcpy(seg_copy, seg_data, seg_length);
1327 
1328 		/* Dump the booter memory.
1329 		 */
1330 		ml_static_mfree(seg_offset, seg_length);
1331 
1332 		/* Set up the VM region.
1333 		 */
1334 		mem_result = mach_vm_map_kernel(
1335 			kernel_map,
1336 			&seg_offset,
1337 			seg_length, /* mask */ 0,
1338 			VM_MAP_KERNEL_FLAGS_FIXED(.vmf_overwrite = true),
1339 			(ipc_port_t)NULL,
1340 			(vm_object_offset_t) 0,
1341 			/* copy */ FALSE,
1342 			/* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
1343 			/* max_protection */ VM_PROT_ALL,
1344 			/* inheritance */ VM_INHERIT_DEFAULT);
1345 		if ((mem_result != KERN_SUCCESS) ||
1346 		    (seg_offset != (vm_map_offset_t) seg_data)) {
1347 			OSKextLog(/* kext */ NULL,
1348 			    kOSKextLogErrorLevel |
1349 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1350 			    "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1351 			    seg_data, seg_length, mem_result);
1352 			return result;
1353 		}
1354 
1355 		/* And copy it back.
1356 		 */
1357 		memcpy(seg_data, seg_copy, seg_length);
1358 
1359 		/* Free the copy.
1360 		 */
1361 		kmem_free(kernel_map, seg_copy_offset, seg_length);
1362 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1363 		/* Remove the linkedit segment of the Boot KC */
1364 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1365 		OSKext::jettisonFileSetLinkeditSegment(mh);
1366 	}
1367 #else // !VM_MAPPED_KEXTS
1368 	/*****
1369 	 * Dump the LINKEDIT segment, unless keepsyms is set.
1370 	 */
1371 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1372 		dt_segment_name = "Kernel-__LINKEDIT";
1373 		if (0 == IODTGetLoaderInfo(dt_segment_name,
1374 		    &segment_paddress, &segment_size)) {
1375 #ifdef SECURE_KERNEL
1376 			vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
1377 			bzero((void*)vmaddr, segment_size);
1378 #endif
1379 			IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1380 			    (int)segment_size);
1381 		}
1382 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1383 		/* Remove the linkedit segment of the Boot KC */
1384 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1385 		OSKext::jettisonFileSetLinkeditSegment(mh);
1386 	} else {
1387 		OSKextLog(/* kext */ NULL,
1388 		    kOSKextLogBasicLevel |
1389 		    kOSKextLogGeneralFlag,
1390 		    "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1391 	}
1392 #endif // VM_MAPPED_KEXTS
1393 
1394 	result = kOSReturnSuccess;
1395 
1396 	return result;
1397 }
1398 
1399 #if CONFIG_KXLD
1400 /*********************************************************************
1401 *********************************************************************/
1402 void
flushNonloadedKexts(Boolean flushPrelinkedKexts)1403 OSKext::flushNonloadedKexts(
1404 	Boolean flushPrelinkedKexts)
1405 {
1406 	OSSharedPtr<OSSet>                keepKexts;
1407 
1408 	/* TODO: make this more efficient with MH_FILESET kexts */
1409 
1410 	// Do not unload prelinked kexts on arm because the kernelcache is not
1411 	// structured in a way that allows them to be unmapped
1412 #if !defined(__x86_64__)
1413 	flushPrelinkedKexts = false;
1414 #endif /* defined(__x86_64__) */
1415 
1416 	IORecursiveLockLock(sKextLock);
1417 
1418 	OSKextLog(/* kext */ NULL,
1419 	    kOSKextLogProgressLevel |
1420 	    kOSKextLogKextBookkeepingFlag,
1421 	    "Flushing nonloaded kexts and other unused data.");
1422 
1423 	OSKext::considerDestroyingLinkContext();
1424 
1425 	/* If we aren't flushing unused prelinked kexts, we have to put them
1426 	 * aside while we flush everything else so make a container for them.
1427 	 */
1428 	keepKexts = OSSet::withCapacity(16);
1429 	if (!keepKexts) {
1430 		goto finish;
1431 	}
1432 
1433 	/* Set aside prelinked kexts (in-use or not) and break
1434 	 * any lingering inter-kext references for nonloaded kexts
1435 	 * so they have min. retain counts.
1436 	 */
1437 	{
1438 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1439 			OSKext * thisKext = OSDynamicCast(OSKext, obj);
1440 			if (!thisKext) {
1441 			        return false;
1442 			}
1443 			if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
1444 			        keepKexts->setObject(thisKext);
1445 			} else if (!thisKext->declaresExecutable()) {
1446 			        /*
1447 			         * Don't unload codeless kexts, because they never appear in the loadedKexts array.
1448 			         * Requesting one from the IOKit daemon will load it and then immediately remove it by calling
1449 			         * flushNonloadedKexts().
1450 			         * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
1451 			         */
1452 			        keepKexts->setObject(thisKext);
1453 			} else if (thisKext->isInFileset()) {
1454 			        /* keep all kexts in the new MH_FILESET KC */
1455 			        keepKexts->setObject(thisKext);
1456 			}
1457 
1458 			thisKext->flushDependencies(/* forceIfLoaded */ false);
1459 			return false;
1460 		});
1461 	}
1462 	/* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1463 	 */
1464 	sKextsByID->flushCollection();
1465 
1466 	/* Now put the loaded kexts back into the ID dictionary.
1467 	 */
1468 	sLoadedKexts->iterateObjects(^bool (OSObject * obj) {
1469 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1470 		if (!thisKext) {
1471 		        return false;
1472 		}
1473 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1474 		return false;
1475 	});
1476 
1477 	/* Finally, put back the kept kexts if we saved any.
1478 	 */
1479 	keepKexts->iterateObjects(^bool (OSObject * obj) {
1480 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1481 		if (!thisKext) {
1482 		        return false;
1483 		}
1484 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1485 		return false;
1486 	});
1487 
1488 finish:
1489 	IORecursiveLockUnlock(sKextLock);
1490 	return;
1491 }
1492 #else /* !CONFIG_KXLD */
1493 
1494 void
flushNonloadedKexts(Boolean flushPrelinkedKexts __unused)1495 OSKext::flushNonloadedKexts(
1496 	Boolean flushPrelinkedKexts __unused)
1497 {
1498 	IORecursiveLockLock(sKextLock);
1499 
1500 	OSKextLog(/* kext */ NULL,
1501 	    kOSKextLogProgressLevel |
1502 	    kOSKextLogKextBookkeepingFlag,
1503 	    "Flushing dependency info for non-loaded kexts.");
1504 
1505 	/*
1506 	 * In a world where we don't dynamically link kexts, they all come
1507 	 * from a kext collection that's either in wired memory, or
1508 	 * wire-on-demand. We don't need to mess around with moving kexts in
1509 	 * and out of the sKextsByID array - they can all just stay there.
1510 	 * Here we just flush the dependency list for kexts that are not
1511 	 * loaded.
1512 	 */
1513 	sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1514 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1515 		if (!thisKext) {
1516 		        return false;
1517 		}
1518 		thisKext->flushDependencies(/* forceIfLoaded */ false);
1519 		return false;
1520 	});
1521 
1522 	IORecursiveLockUnlock(sKextLock);
1523 	return;
1524 }
1525 
1526 #endif /* CONFIG_KXLD */
1527 
1528 /*********************************************************************
1529 *********************************************************************/
1530 /* static */
1531 void
setIOKitDaemonActive(bool active)1532 OSKext::setIOKitDaemonActive(bool active)
1533 {
1534 	IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
1535 	IORecursiveLockLock(sKextLock);
1536 	sIOKitDaemonActive = active;
1537 	if (sKernelRequests->getCount()) {
1538 		OSKext::pingIOKitDaemon();
1539 	}
1540 	IORecursiveLockUnlock(sKextLock);
1541 
1542 	return;
1543 }
1544 
1545 /*********************************************************************
1546 * OSKextLib.cpp might need access to this someday but for now it's
1547 * private.
1548 *********************************************************************/
1549 extern "C" {
1550 extern void ipc_port_release_send(ipc_port_t);
1551 };
1552 
1553 /* static */
1554 OSReturn
pingIOKitDaemon(void)1555 OSKext::pingIOKitDaemon(void)
1556 {
1557 	OSReturn    result     = kOSReturnError;
1558 #if !NO_KEXTD
1559 	mach_port_t kextd_port = IPC_PORT_NULL;
1560 
1561 	if (!sIOKitDaemonActive) {
1562 		result = kOSKextReturnDisabled; // basically unavailable
1563 		goto finish;
1564 	}
1565 
1566 	result = host_get_kextd_port(host_priv_self(), &kextd_port);
1567 	if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1568 		OSKextLog(/* kext */ NULL,
1569 		    kOSKextLogErrorLevel |
1570 		    kOSKextLogIPCFlag,
1571 		    "Can't get " kIOKitDaemonName " port.");
1572 		goto finish;
1573 	}
1574 
1575 	result = kextd_ping(kextd_port);
1576 	if (result != KERN_SUCCESS) {
1577 		OSKextLog(/* kext */ NULL,
1578 		    kOSKextLogErrorLevel |
1579 		    kOSKextLogIPCFlag,
1580 		    kIOKitDaemonName " ping failed (0x%x).", (int)result);
1581 		goto finish;
1582 	}
1583 
1584 finish:
1585 	if (IPC_PORT_VALID(kextd_port)) {
1586 		ipc_port_release_send(kextd_port);
1587 	}
1588 #endif
1589 
1590 	return result;
1591 }
1592 
1593 /*********************************************************************
1594 *********************************************************************/
1595 /* static */
1596 
1597 bool
driverkitEnabled(void)1598 OSKext::driverkitEnabled(void)
1599 {
1600 	#if XNU_TARGET_OS_WATCH
1601 	/*
1602 	 * Driverkit support is available on watchOS only if the device
1603 	 * tree has the "supports-driverkit" property in its "/product" node
1604 	 */
1605 	DTEntry entry;
1606 	void const *prop = NULL;
1607 	unsigned int prop_size;
1608 
1609 	if (kSuccess != SecureDTLookupEntry(NULL, "/product", &entry)) {
1610 		return false;
1611 	}
1612 	if (kSuccess != SecureDTGetProperty(entry, "supports-driverkit", &prop, &prop_size)) {
1613 		return false;
1614 	}
1615 	#endif /* XNU_TARGET_OS_WATCH */
1616 
1617 	return true;
1618 }
1619 
1620 /*********************************************************************
1621 *********************************************************************/
1622 /* static */
1623 bool
iokitDaemonAvailable(void)1624 OSKext::iokitDaemonAvailable(void)
1625 {
1626 #if !XNU_TARGET_OS_IOS && !XNU_TARGET_OS_OSX && !XNU_TARGET_OS_WATCH
1627 	int notused;
1628 	if (PE_parse_boot_argn("-restore", &notused, sizeof(notused))) {
1629 		return false;
1630 	}
1631 #endif /* !XNU_TARGET_OS_IOS && !XNU_TARGET_OS_OSX && !XNU_TARGET_OS_WATCH */
1632 	return driverkitEnabled();
1633 }
1634 
1635 /*********************************************************************
1636 *********************************************************************/
1637 /* static */
1638 void
setDeferredLoadSucceeded(Boolean succeeded)1639 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1640 {
1641 	IORecursiveLockLock(sKextLock);
1642 	sDeferredLoadSucceeded = succeeded;
1643 	IORecursiveLockUnlock(sKextLock);
1644 
1645 	return;
1646 }
1647 
1648 /*********************************************************************
1649 * Called from IOSystemShutdownNotification.
1650 *********************************************************************/
1651 /* static */
1652 void
willShutdown(void)1653 OSKext::willShutdown(void)
1654 {
1655 #if !NO_KEXTD
1656 	OSReturn       checkResult = kOSReturnError;
1657 #endif
1658 	OSSharedPtr<OSDictionary> exitRequest;
1659 
1660 	IORecursiveLockLock(sKextLock);
1661 
1662 	OSKext::setLoadEnabled(false);
1663 	OSKext::setUnloadEnabled(false);
1664 	OSKext::setAutounloadsEnabled(false);
1665 	OSKext::setKernelRequestsEnabled(false);
1666 
1667 #if defined(__x86_64__) || defined(__i386__)
1668 	if (IOPMRootDomainGetWillShutdown()) {
1669 		OSKext::freeKCFileSetcontrol();
1670 	}
1671 #endif // (__x86_64__) || defined(__i386__)
1672 
1673 #if !NO_KEXTD
1674 	OSKextLog(/* kext */ NULL,
1675 	    kOSKextLogProgressLevel |
1676 	    kOSKextLogGeneralFlag,
1677 	    "System shutdown; requesting immediate " kIOKitDaemonName " exit.");
1678 
1679 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit,
1680 	    exitRequest);
1681 	if (checkResult != kOSReturnSuccess) {
1682 		goto finish;
1683 	}
1684 	if (!sKernelRequests->setObject(exitRequest.get())) {
1685 		goto finish;
1686 	}
1687 
1688 	OSKext::pingIOKitDaemon();
1689 
1690 finish:
1691 #endif
1692 
1693 	IORecursiveLockUnlock(sKextLock);
1694 	return;
1695 }
1696 
1697 void
setWillUserspaceReboot(void)1698 OSKext::setWillUserspaceReboot(void)
1699 {
1700 	OSKext::willShutdown();
1701 	IOService::setWillUserspaceReboot();
1702 	gIOCatalogue->terminateDriversForUserspaceReboot();
1703 }
1704 
1705 void
resetAfterUserspaceReboot(void)1706 OSKext::resetAfterUserspaceReboot(void)
1707 {
1708 	OSSharedPtr<OSArray> arr = OSArray::withCapacity(1);
1709 	IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */);
1710 
1711 	IORecursiveLockLock(sKextLock);
1712 	gIOCatalogue->resetAfterUserspaceReboot();
1713 	IOService::userSpaceDidReboot();
1714 	OSKext::removeDaemonExitRequests();
1715 	OSKext::setLoadEnabled(true);
1716 	OSKext::setUnloadEnabled(true);
1717 	OSKext::setAutounloadsEnabled(true);
1718 	OSKext::setKernelRequestsEnabled(true);
1719 	sOSKextWasResetAfterUserspaceReboot = true;
1720 	IORecursiveLockUnlock(sKextLock);
1721 }
1722 
1723 extern "C" int
OSKextIsInUserspaceReboot(void)1724 OSKextIsInUserspaceReboot(void)
1725 {
1726 	return IOService::getWillUserspaceReboot();
1727 }
1728 
1729 extern "C" void
OSKextResetAfterUserspaceReboot(void)1730 OSKextResetAfterUserspaceReboot(void)
1731 {
1732 	OSKext::resetAfterUserspaceReboot();
1733 }
1734 
1735 /*
1736  * Remove daemon exit requests from sKernelRequests
1737  *
1738  * If we sent a daemon exit request during a userspace reboot and launchd
1739  * killed the IOKit daemon before it was able to dequeue the exit request, the
1740  * next time the daemon starts up it will immediately exit as it gets the old exit request.
1741  *
1742  * This removes exit requests so that this does not happen.
1743  */
1744 void
removeDaemonExitRequests(void)1745 OSKext::removeDaemonExitRequests(void)
1746 {
1747 	OSDictionary * current = NULL;
1748 	OSString     * predicate = NULL;
1749 	size_t         index     = 0;
1750 	OSSharedPtr<const OSSymbol> predicateKey = OSSymbol::withCString(kKextRequestPredicateKey);
1751 
1752 	while (index < sKernelRequests->getCount()) {
1753 		current = OSDynamicCast(OSDictionary, sKernelRequests->getObject(index));
1754 		if (current) {
1755 			predicate = OSDynamicCast(OSString, current->getObject(predicateKey.get()));
1756 			if (predicate && predicate->isEqualTo(kKextRequestPredicateRequestDaemonExit)) {
1757 				sKernelRequests->removeObject(index);
1758 				continue;
1759 			}
1760 		}
1761 		index++;
1762 	}
1763 }
1764 
1765 /*********************************************************************
1766 *********************************************************************/
1767 /* static */
1768 bool
getLoadEnabled(void)1769 OSKext::getLoadEnabled(void)
1770 {
1771 	bool result;
1772 
1773 	IORecursiveLockLock(sKextLock);
1774 	result = sLoadEnabled;
1775 	IORecursiveLockUnlock(sKextLock);
1776 	return result;
1777 }
1778 
1779 /*********************************************************************
1780 *********************************************************************/
1781 /* static */
1782 bool
setLoadEnabled(bool flag)1783 OSKext::setLoadEnabled(bool flag)
1784 {
1785 	bool result;
1786 
1787 	IORecursiveLockLock(sKextLock);
1788 	result = sLoadEnabled;
1789 	sLoadEnabled = (flag ? true : false);
1790 
1791 	if (sLoadEnabled != result) {
1792 		OSKextLog(/* kext */ NULL,
1793 		    kOSKextLogBasicLevel |
1794 		    kOSKextLogLoadFlag,
1795 		    "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1796 	}
1797 
1798 	IORecursiveLockUnlock(sKextLock);
1799 
1800 	return result;
1801 }
1802 
1803 /*********************************************************************
1804 *********************************************************************/
1805 /* static */
1806 bool
getUnloadEnabled(void)1807 OSKext::getUnloadEnabled(void)
1808 {
1809 	bool result;
1810 
1811 	IORecursiveLockLock(sKextLock);
1812 	result = sUnloadEnabled;
1813 	IORecursiveLockUnlock(sKextLock);
1814 	return result;
1815 }
1816 
1817 /*********************************************************************
1818 *********************************************************************/
1819 /* static */
1820 bool
setUnloadEnabled(bool flag)1821 OSKext::setUnloadEnabled(bool flag)
1822 {
1823 	bool result;
1824 
1825 	IORecursiveLockLock(sKextLock);
1826 	result = sUnloadEnabled;
1827 	sUnloadEnabled = (flag ? true : false);
1828 	IORecursiveLockUnlock(sKextLock);
1829 
1830 	if (sUnloadEnabled != result) {
1831 		OSKextLog(/* kext */ NULL,
1832 		    kOSKextLogBasicLevel |
1833 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1834 		    "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1835 	}
1836 
1837 	return result;
1838 }
1839 
1840 /*********************************************************************
1841 * Do not call any function that takes sKextLock here!
1842 *********************************************************************/
1843 /* static */
1844 bool
getAutounloadEnabled(void)1845 OSKext::getAutounloadEnabled(void)
1846 {
1847 #if XNU_TARGET_OS_OSX
1848 	bool result;
1849 
1850 	IORecursiveLockLock(sKextInnerLock);
1851 	result = sAutounloadEnabled ? true : false;
1852 	IORecursiveLockUnlock(sKextInnerLock);
1853 	return result;
1854 #else
1855 	return false;
1856 #endif /* XNU_TARGET_OS_OSX */
1857 }
1858 
1859 /*********************************************************************
1860 * Do not call any function that takes sKextLock here!
1861 *********************************************************************/
1862 /* static */
1863 bool
setAutounloadsEnabled(bool flag)1864 OSKext::setAutounloadsEnabled(bool flag)
1865 {
1866 #if XNU_TARGET_OS_OSX
1867 	bool result;
1868 
1869 	IORecursiveLockLock(sKextInnerLock);
1870 
1871 	result = sAutounloadEnabled;
1872 	sAutounloadEnabled = (flag ? true : false);
1873 	if (!sAutounloadEnabled && sUnloadCallout) {
1874 		thread_call_cancel(sUnloadCallout);
1875 	}
1876 
1877 	if (sAutounloadEnabled != result) {
1878 		OSKextLog(/* kext */ NULL,
1879 		    kOSKextLogBasicLevel |
1880 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1881 		    "Kext autounloading now %sabled.",
1882 		    sAutounloadEnabled ? "en" : "dis");
1883 	}
1884 
1885 	IORecursiveLockUnlock(sKextInnerLock);
1886 
1887 	return result;
1888 #else
1889 	(void)flag;
1890 	return false;
1891 #endif /* XNU_TARGET_OS_OSX */
1892 }
1893 
1894 /*********************************************************************
1895 *********************************************************************/
1896 /* instance method operating on OSKext field */
1897 bool
setAutounloadEnabled(bool flag)1898 OSKext::setAutounloadEnabled(bool flag)
1899 {
1900 	bool result = flags.autounloadEnabled ? true : false;
1901 	flags.autounloadEnabled = flag ? (0 == flags.unloadUnsupported) : 0;
1902 
1903 	if (result != (flag ? true : false)) {
1904 		OSKextLog(this,
1905 		    kOSKextLogProgressLevel |
1906 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1907 		    "Autounloading for kext %s now %sabled.",
1908 		    getIdentifierCString(),
1909 		    flags.autounloadEnabled ? "en" : "dis");
1910 	}
1911 	return result;
1912 }
1913 
1914 /*********************************************************************
1915 *********************************************************************/
1916 /* static */
1917 bool
setKernelRequestsEnabled(bool flag)1918 OSKext::setKernelRequestsEnabled(bool flag)
1919 {
1920 	bool result;
1921 
1922 	IORecursiveLockLock(sKextLock);
1923 	result = sKernelRequestsEnabled;
1924 	sKernelRequestsEnabled = flag ? true : false;
1925 
1926 	if (sKernelRequestsEnabled != result) {
1927 		OSKextLog(/* kext */ NULL,
1928 		    kOSKextLogBasicLevel |
1929 		    kOSKextLogGeneralFlag,
1930 		    "Kernel requests now %sabled.",
1931 		    sKernelRequestsEnabled ? "en" : "dis");
1932 	}
1933 	IORecursiveLockUnlock(sKextLock);
1934 	return result;
1935 }
1936 
1937 /*********************************************************************
1938 *********************************************************************/
1939 /* static */
1940 bool
getKernelRequestsEnabled(void)1941 OSKext::getKernelRequestsEnabled(void)
1942 {
1943 	bool result;
1944 
1945 	IORecursiveLockLock(sKextLock);
1946 	result = sKernelRequestsEnabled;
1947 	IORecursiveLockUnlock(sKextLock);
1948 	return result;
1949 }
1950 
1951 static bool
segmentIsMutable(kernel_segment_command_t * seg)1952 segmentIsMutable(kernel_segment_command_t *seg)
1953 {
1954 	/* Mutable segments have to have VM_PROT_WRITE */
1955 	if ((seg->maxprot & VM_PROT_WRITE) == 0) {
1956 		return false;
1957 	}
1958 	/* Exclude the __DATA_CONST segment */
1959 	if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) {
1960 		return false;
1961 	}
1962 	/* Exclude __LINKEDIT */
1963 	if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) {
1964 		return false;
1965 	}
1966 	return true;
1967 }
1968 
1969 #if PRAGMA_MARK
1970 #pragma mark Kext Life Cycle
1971 #endif
1972 /*********************************************************************
1973 *********************************************************************/
1974 OSSharedPtr<OSKext>
withPrelinkedInfoDict(OSDictionary * anInfoDict,bool doCoalescedSlides,kc_kind_t type)1975 OSKext::withPrelinkedInfoDict(
1976 	OSDictionary * anInfoDict,
1977 	bool doCoalescedSlides,
1978 	kc_kind_t type)
1979 {
1980 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
1981 
1982 	if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) {
1983 		return NULL;
1984 	}
1985 
1986 	return newKext;
1987 }
1988 
1989 OSData *
parseDextUniqueID(OSDictionary * anInfoDict,const char * dextIDCS)1990 OSKext::parseDextUniqueID(
1991 	OSDictionary * anInfoDict,
1992 	const char *dextIDCS)
1993 {
1994 	OSData *ret = NULL;
1995 	OSData *data_duid = OSDynamicCast(OSData, anInfoDict->getObject(kOSBundleDextUniqueIdentifierKey));
1996 	if (data_duid != NULL) {
1997 		if (data_duid->getLength() > KOSBundleDextUniqueIdentifierMaxLength) {
1998 			OSKextLog(NULL,
1999 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2000 			    "Dext %s DextUniqueIdentifier too long.",
2001 			    dextIDCS);
2002 		} else {
2003 			/*
2004 			 * If the DextUniqueID exists it should be
2005 			 * present also into the personalities.
2006 			 */
2007 			setDextUniqueIDInPersonalities(anInfoDict, data_duid);
2008 			ret = data_duid;
2009 		}
2010 	} else {
2011 		OSKextLog(NULL,
2012 		    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2013 		    "Dext %s does not have a DextUniqueIdentifier",
2014 		    dextIDCS);
2015 	}
2016 	return ret;
2017 }
2018 
2019 void
setDextUniqueIDInPersonalities(OSDictionary * anInfoDict,OSData * dextUniqueID)2020 OSKext::setDextUniqueIDInPersonalities(
2021 	OSDictionary * anInfoDict,
2022 	OSData * dextUniqueID)
2023 {
2024 	OSDictionary * dextPersonalities = NULL;
2025 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
2026 	OSString * personalityName = NULL;
2027 
2028 	dextPersonalities = OSDynamicCast(OSDictionary,
2029 	    anInfoDict->getObject(kIOKitPersonalitiesKey));
2030 	if (!dextPersonalities || !dextPersonalities->getCount()) {
2031 		return;
2032 	}
2033 
2034 	personalitiesIterator =
2035 	    OSCollectionIterator::withCollection(dextPersonalities);
2036 	if (!personalitiesIterator) {
2037 		return;
2038 	}
2039 	while ((personalityName = OSDynamicCast(OSString,
2040 	    personalitiesIterator->getNextObject()))) {
2041 		OSDictionary * personality = OSDynamicCast(OSDictionary,
2042 		    dextPersonalities->getObject(personalityName));
2043 		if (personality) {
2044 			OSObject *duid = personality->getObject(kOSBundleDextUniqueIdentifierKey);
2045 			if (duid == NULL) {
2046 				personality->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID);
2047 			}
2048 		}
2049 	}
2050 }
2051 /*********************************************************************
2052 *********************************************************************/
2053 bool
initWithPrelinkedInfoDict(OSDictionary * anInfoDict,bool doCoalescedSlides,kc_kind_t type)2054 OSKext::initWithPrelinkedInfoDict(
2055 	OSDictionary * anInfoDict,
2056 	bool doCoalescedSlides,
2057 	kc_kind_t type)
2058 {
2059 	bool            result              = false;
2060 	OSString      * kextPath            = NULL;                // do not release
2061 	OSNumber      * addressNum          = NULL;                // reused; do not release
2062 	OSNumber      * lengthNum           = NULL;                // reused; do not release
2063 	OSBoolean     * scratchBool         = NULL;                // do not release
2064 	void          * data                = NULL;                // do not free
2065 	void          * srcData             = NULL;                // do not free
2066 	OSSharedPtr<OSData>        prelinkedExecutable;
2067 	uint32_t        length              = 0;                // reused
2068 	uintptr_t       kext_slide          = PE_get_kc_slide(type);
2069 	bool            shouldSaveSegments  = false;
2070 	kc_format     format                = KCFormatUnknown;
2071 
2072 	if (!super::init()) {
2073 		goto finish;
2074 	}
2075 
2076 	/* Get the path. Don't look for an arch-specific path property.
2077 	 */
2078 	kextPath = OSDynamicCast(OSString,
2079 	    anInfoDict->getObject(kPrelinkBundlePathKey));
2080 
2081 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2082 		goto finish;
2083 	}
2084 
2085 #if KASLR_KEXT_DEBUG
2086 	IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString());
2087 #endif
2088 
2089 	/* Also get the executable's bundle-relative path if present.
2090 	 * Don't look for an arch-specific path property.
2091 	 */
2092 	executableRelPath.reset(OSDynamicCast(OSString,
2093 	    anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain);
2094 	userExecutableRelPath.reset(OSDynamicCast(OSString,
2095 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
2096 
2097 	/* Don't need the paths to be in the info dictionary any more.
2098 	 */
2099 	anInfoDict->removeObject(kPrelinkBundlePathKey);
2100 	anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
2101 
2102 	scratchBool = OSDynamicCast(OSBoolean,
2103 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
2104 	if (scratchBool == kOSBooleanTrue) {
2105 		flags.requireExplicitLoad = 1;
2106 	}
2107 
2108 	/* Create an OSData wrapper around the linked executable.
2109 	 */
2110 	addressNum = OSDynamicCast(OSNumber,
2111 	    anInfoDict->getObject(kPrelinkExecutableLoadKey));
2112 	if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) {
2113 		lengthNum = OSDynamicCast(OSNumber,
2114 		    anInfoDict->getObject(kPrelinkExecutableSizeKey));
2115 		if (!lengthNum) {
2116 			OSKextLog(this,
2117 			    kOSKextLogErrorLevel |
2118 			    kOSKextLogArchiveFlag,
2119 			    "Kext %s can't find prelinked kext executable size.",
2120 			    getIdentifierCString());
2121 			return result;
2122 		}
2123 
2124 		data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
2125 		length = (uint32_t) (lengthNum->unsigned32BitValue());
2126 
2127 #if KASLR_KEXT_DEBUG
2128 		IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
2129 		    (unsigned long)ml_static_unslide((vm_offset_t)data),
2130 		    (unsigned long)data,
2131 		    length);
2132 #endif
2133 
2134 		anInfoDict->removeObject(kPrelinkExecutableLoadKey);
2135 		anInfoDict->removeObject(kPrelinkExecutableSizeKey);
2136 
2137 		/* If the kext's load address differs from its source address, allocate
2138 		 * space in the kext map at the load address and copy the kext over.
2139 		 */
2140 		addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
2141 		if (addressNum) {
2142 			srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
2143 
2144 #if KASLR_KEXT_DEBUG
2145 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
2146 			    (unsigned long)ml_static_unslide((vm_offset_t)srcData),
2147 			    (unsigned long)srcData);
2148 #endif
2149 
2150 			if (data != srcData) {
2151 #if __LP64__
2152 				kern_return_t alloc_result;
2153 
2154 				alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
2155 				if (alloc_result != KERN_SUCCESS) {
2156 					OSKextLog(this,
2157 					    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2158 					    "Failed to allocate space for prelinked kext %s.",
2159 					    getIdentifierCString());
2160 					goto finish;
2161 				}
2162 				memcpy(data, srcData, length);
2163 #else
2164 				OSKextLog(this,
2165 				    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2166 				    "Error: prelinked kext %s - source and load addresses "
2167 				    "differ on ILP32 architecture.",
2168 				    getIdentifierCString());
2169 				goto finish;
2170 #endif /* __LP64__ */
2171 			}
2172 
2173 			anInfoDict->removeObject(kPrelinkExecutableSourceKey);
2174 		}
2175 
2176 		prelinkedExecutable = OSData::withBytesNoCopy(data, length);
2177 		if (!prelinkedExecutable) {
2178 			OSKextLog(this,
2179 			    kOSKextLogErrorLevel |
2180 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
2181 			    "Kext %s failed to create executable wrapper.",
2182 			    getIdentifierCString());
2183 			goto finish;
2184 		}
2185 
2186 		/*
2187 		 * Fileset KCs are mapped as a whole by iBoot.
2188 		 * Individual kext executables should not be unmapped
2189 		 * by xnu.
2190 		 * Doing so may result in panics like rdar://85419651
2191 		 */
2192 		if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
2193 			prelinkedExecutable->setDeallocFunction(NULL);
2194 		} else { // Not from a Fileset KC
2195 #if VM_MAPPED_KEXTS
2196 			prelinkedExecutable->setDeallocFunction(osdata_kext_free);
2197 #else
2198 			prelinkedExecutable->setDeallocFunction(osdata_phys_free);
2199 #endif
2200 		}
2201 		setLinkedExecutable(prelinkedExecutable.get());
2202 		addressNum = OSDynamicCast(OSNumber,
2203 		    anInfoDict->getObject(kPrelinkKmodInfoKey));
2204 		if (!addressNum) {
2205 			OSKextLog(this,
2206 			    kOSKextLogErrorLevel |
2207 			    kOSKextLogArchiveFlag,
2208 			    "Kext %s can't find prelinked kext kmod_info address.",
2209 			    getIdentifierCString());
2210 			goto finish;
2211 		}
2212 
2213 		if (addressNum->unsigned64BitValue() != 0) {
2214 			kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
2215 			if (kmod_info->address) {
2216 				kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide);
2217 			} else {
2218 				kmod_info->address = (uintptr_t)data;
2219 				kmod_info->size = length;
2220 			}
2221 #if KASLR_KEXT_DEBUG
2222 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
2223 			    (unsigned long)((vm_offset_t)kmod_info) - kext_slide,
2224 			    (unsigned long)kmod_info);
2225 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
2226 			    (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide,
2227 			    (unsigned long)kmod_info->address);
2228  #endif
2229 		}
2230 
2231 		anInfoDict->removeObject(kPrelinkKmodInfoKey);
2232 	}
2233 
2234 	if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) {
2235 		uintptr_t builtinTextStart;
2236 		uintptr_t builtinTextEnd;
2237 
2238 		flags.builtin = true;
2239 		builtinKmodIdx = addressNum->unsigned32BitValue();
2240 		assert(builtinKmodIdx < gBuiltinKmodsCount);
2241 
2242 		builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx];
2243 		builtinTextEnd   = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1];
2244 
2245 		kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx];
2246 		kmod_info->address = builtinTextStart;
2247 		kmod_info->size    = builtinTextEnd - builtinTextStart;
2248 	}
2249 
2250 	/* If the plist has a UUID for an interface, save that off.
2251 	 */
2252 	if (isInterface()) {
2253 		interfaceUUID.reset(OSDynamicCast(OSData,
2254 		    anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain);
2255 		if (interfaceUUID) {
2256 			anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
2257 		}
2258 	}
2259 
2260 	result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides));
2261 	if (!result) {
2262 		goto finish;
2263 	}
2264 
2265 	kc_type = type;
2266 	/* Exclude builtin and codeless kexts */
2267 	if (prelinkedExecutable && kmod_info) {
2268 		switch (kc_type) {
2269 		case KCKindPrimary:
2270 			shouldSaveSegments = (
2271 				getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue ||
2272 				getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue);
2273 			if (shouldSaveSegments) {
2274 				flags.resetSegmentsFromImmutableCopy = 1;
2275 			} else {
2276 				flags.unloadUnsupported = 1;
2277 			}
2278 			break;
2279 		case KCKindPageable:
2280 			flags.resetSegmentsFromVnode = 1;
2281 			break;
2282 		case KCKindAuxiliary:
2283 			if (!pageableKCloaded) {
2284 				flags.resetSegmentsFromImmutableCopy = 1;
2285 			} else if (resetAuxKCSegmentOnUnload) {
2286 				flags.resetSegmentsFromVnode = 1;
2287 			} else {
2288 				flags.unloadUnsupported = 1;
2289 			}
2290 			break;
2291 		default:
2292 			break;
2293 		}
2294 	}
2295 
2296 	if (flags.resetSegmentsFromImmutableCopy) {
2297 		/* Save a pristine copy of the mutable segments */
2298 		kernel_segment_command_t *seg = NULL;
2299 		kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
2300 
2301 		savedMutableSegments = OSArray::withCapacity(0);
2302 
2303 		for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) {
2304 			if (!segmentIsMutable(seg)) {
2305 				continue;
2306 			}
2307 			uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
2308 			uint64_t vmsize = seg->vmsize;
2309 			OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2310 			    "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2311 			OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg);
2312 			if (!savedSegment) {
2313 				OSKextLog(this,
2314 				    kOSKextLogErrorLevel |
2315 				    kOSKextLogGeneralFlag,
2316 				    "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2317 				result = false;
2318 				goto finish;
2319 			}
2320 			savedMutableSegments->setObject(savedSegment);
2321 		}
2322 	}
2323 
2324 	if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) {
2325 		/*
2326 		 * set VM protections now, wire pages for the old style Aux KC now,
2327 		 * wire pages for the rest of the KC types at load time.
2328 		 */
2329 		result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false));
2330 		if (!result) {
2331 			goto finish;
2332 		}
2333 	}
2334 
2335 	flags.prelinked = true;
2336 
2337 	if (isDriverKit()) {
2338 		dextStatistics = OSDextStatistics::create();
2339 		dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
2340 		dextLaunchedCount = 0;
2341 	}
2342 
2343 	/* If we created a kext from prelink info,
2344 	 * we must be booting from a prelinked kernel.
2345 	 */
2346 	sPrelinkBoot = true;
2347 
2348 	result = (registerIdentifier() == kOSKextInitialized);
2349 finish:
2350 	return result;
2351 }
2352 
2353 /*********************************************************************
2354 *********************************************************************/
2355 /* static */
2356 OSSharedPtr<OSKext>
withCodelessInfo(OSDictionary * anInfoDict,OSKextInitResult * result)2357 OSKext::withCodelessInfo(OSDictionary * anInfoDict, OSKextInitResult *result)
2358 {
2359 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
2360 	if (!newKext) {
2361 		return NULL;
2362 	}
2363 
2364 	OSKextInitResult ret = newKext->initWithCodelessInfo(anInfoDict);
2365 	if (result != NULL) {
2366 		*result = ret;
2367 	}
2368 	if (ret != kOSKextInitialized) {
2369 		return NULL;
2370 	}
2371 
2372 	return newKext;
2373 }
2374 
2375 /*********************************************************************
2376 *********************************************************************/
2377 OSKextInitResult
initWithCodelessInfo(OSDictionary * anInfoDict)2378 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict)
2379 {
2380 	OSKextInitResult result          = kOSKextInitFailure;
2381 	OSString  * kextPath             = NULL;        // do not release
2382 	OSBoolean * scratchBool          = NULL;        // do not release
2383 
2384 	if (anInfoDict == NULL || !super::init()) {
2385 		goto finish;
2386 	}
2387 
2388 	/*
2389 	 * Get the path. Don't look for an arch-specific path property.
2390 	 */
2391 	kextPath = OSDynamicCast(OSString,
2392 	    anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey));
2393 	if (!kextPath) {
2394 		OSKextLog(NULL,
2395 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2396 		    "Requested codeless kext dictionary does not contain the '%s' key",
2397 		    kKextRequestArgumentCodelessInfoBundlePathKey);
2398 		goto finish;
2399 	}
2400 
2401 	uniquePersonalityProperties(anInfoDict);
2402 
2403 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2404 		goto finish;
2405 	}
2406 
2407 	/*
2408 	 * This path is meant to initialize codeless kexts only. Refuse
2409 	 * anything that looks like it has an executable and/or declares
2410 	 * itself as a kernel component.
2411 	 */
2412 	if (declaresExecutable() || isKernelComponent()) {
2413 		OSKextLog(NULL,
2414 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2415 		    "Refusing to register codeless kext that declares an executable/kernel component: %s",
2416 		    getIdentifierCString());
2417 		goto finish;
2418 	}
2419 
2420 	if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
2421 		boolean_t updated = updateExcludeList(infoDict.get());
2422 		if (updated) {
2423 			OSKextLog(this,
2424 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2425 			    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
2426 		}
2427 	}
2428 
2429 	kc_type = KCKindNone;
2430 
2431 	scratchBool = OSDynamicCast(OSBoolean,
2432 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
2433 	if (scratchBool == kOSBooleanTrue) {
2434 		flags.requireExplicitLoad = 1;
2435 	}
2436 
2437 	/* Also get the executable's bundle-relative path if present.
2438 	 * Don't look for an arch-specific path property.
2439 	 */
2440 	userExecutableRelPath.reset(OSDynamicCast(OSString,
2441 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
2442 
2443 	/* remove unnecessary paths from the info dict */
2444 	anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey);
2445 
2446 	if (isDriverKit()) {
2447 		dextStatistics = OSDextStatistics::create();
2448 		dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
2449 		dextLaunchedCount = 0;
2450 	}
2451 
2452 	result = registerIdentifier();
2453 
2454 finish:
2455 	return result;
2456 }
2457 
2458 /*********************************************************************
2459 *********************************************************************/
2460 /* static */
2461 void
setAllVMAttributes(void)2462 OSKext::setAllVMAttributes(void)
2463 {
2464 	OSSharedPtr<OSCollectionIterator> kextIterator;
2465 	const OSSymbol * thisID                 = NULL;        // do not release
2466 
2467 	IORecursiveLockLock(sKextLock);
2468 
2469 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
2470 	if (!kextIterator) {
2471 		goto finish;
2472 	}
2473 
2474 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
2475 		OSKext *    thisKext;        // do not release
2476 
2477 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
2478 		if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
2479 			continue;
2480 		}
2481 
2482 		if (!thisKext->flags.resetSegmentsFromVnode) {
2483 			/*
2484 			 * set VM protections now, wire pages for the old style Aux KC now,
2485 			 * wire pages for the rest of the KC types at load time.
2486 			 */
2487 			thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false);
2488 		}
2489 	}
2490 
2491 finish:
2492 	IORecursiveLockUnlock(sKextLock);
2493 
2494 	return;
2495 }
2496 
2497 /*********************************************************************
2498 *********************************************************************/
2499 OSSharedPtr<OSKext>
withBooterData(OSString * deviceTreeName,OSData * booterData)2500 OSKext::withBooterData(
2501 	OSString * deviceTreeName,
2502 	OSData   * booterData)
2503 {
2504 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
2505 
2506 	if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
2507 		return NULL;
2508 	}
2509 
2510 	return newKext;
2511 }
2512 
2513 /*********************************************************************
2514 *********************************************************************/
2515 typedef struct _BooterKextFileInfo {
2516 	uint32_t  infoDictPhysAddr;
2517 	uint32_t  infoDictLength;
2518 	uint32_t  executablePhysAddr;
2519 	uint32_t  executableLength;
2520 	uint32_t  bundlePathPhysAddr;
2521 	uint32_t  bundlePathLength;
2522 } _BooterKextFileInfo;
2523 
2524 bool
initWithBooterData(OSString * deviceTreeName,OSData * booterData)2525 OSKext::initWithBooterData(
2526 	OSString * deviceTreeName,
2527 	OSData   * booterData)
2528 {
2529 	bool                  result         = false;
2530 	_BooterKextFileInfo * kextFileInfo   = NULL;        // do not free
2531 	char                * infoDictAddr   = NULL;        // do not free
2532 	void                * executableAddr = NULL;        // do not free
2533 	char                * bundlePathAddr = NULL;        // do not free
2534 
2535 	OSDictionary        * theInfoDict    = NULL;        // do not release
2536 	OSSharedPtr<OSObject> parsedXML;
2537 	OSSharedPtr<OSString> kextPath;
2538 
2539 	OSSharedPtr<OSString> errorString;
2540 	OSSharedPtr<OSData>   executable;
2541 
2542 	if (!super::init()) {
2543 		goto finish;
2544 	}
2545 
2546 	kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
2547 	if (!kextFileInfo) {
2548 		OSKextLog(this,
2549 		    kOSKextLogErrorLevel |
2550 		    kOSKextLogGeneralFlag,
2551 		    "No booter-provided data for kext device tree entry %s.",
2552 		    deviceTreeName->getCStringNoCopy());
2553 		goto finish;
2554 	}
2555 
2556 	/* The info plist must exist or we can't read the kext.
2557 	 */
2558 	if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
2559 		OSKextLog(this,
2560 		    kOSKextLogErrorLevel |
2561 		    kOSKextLogGeneralFlag,
2562 		    "No kext info dictionary for booter device tree entry %s.",
2563 		    deviceTreeName->getCStringNoCopy());
2564 		goto finish;
2565 	}
2566 
2567 	infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
2568 	if (!infoDictAddr) {
2569 		OSKextLog(this,
2570 		    kOSKextLogErrorLevel |
2571 		    kOSKextLogGeneralFlag,
2572 		    "Can't translate physical address 0x%x of kext info dictionary "
2573 		    "for device tree entry %s.",
2574 		    (int)kextFileInfo->infoDictPhysAddr,
2575 		    deviceTreeName->getCStringNoCopy());
2576 		goto finish;
2577 	}
2578 
2579 	parsedXML = OSUnserializeXML(infoDictAddr, errorString);
2580 	if (parsedXML) {
2581 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
2582 	}
2583 	if (!theInfoDict) {
2584 		const char * errorCString = "(unknown error)";
2585 
2586 		if (errorString && errorString->getCStringNoCopy()) {
2587 			errorCString = errorString->getCStringNoCopy();
2588 		} else if (parsedXML) {
2589 			errorCString = "not a dictionary";
2590 		}
2591 		OSKextLog(this,
2592 		    kOSKextLogErrorLevel |
2593 		    kOSKextLogGeneralFlag,
2594 		    "Error unserializing info dictionary for device tree entry %s: %s.",
2595 		    deviceTreeName->getCStringNoCopy(), errorCString);
2596 		goto finish;
2597 	}
2598 
2599 	/* A bundle path is not mandatory.
2600 	 */
2601 	if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
2602 		bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
2603 		if (!bundlePathAddr) {
2604 			OSKextLog(this,
2605 			    kOSKextLogErrorLevel |
2606 			    kOSKextLogGeneralFlag,
2607 			    "Can't translate physical address 0x%x of kext bundle path "
2608 			    "for device tree entry %s.",
2609 			    (int)kextFileInfo->bundlePathPhysAddr,
2610 			    deviceTreeName->getCStringNoCopy());
2611 			goto finish;
2612 		}
2613 		bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0';         // just in case!
2614 
2615 		kextPath = OSString::withCString(bundlePathAddr);
2616 		if (!kextPath) {
2617 			OSKextLog(this,
2618 			    kOSKextLogErrorLevel |
2619 			    kOSKextLogGeneralFlag,
2620 			    "Failed to create wrapper for device tree entry %s kext path %s.",
2621 			    deviceTreeName->getCStringNoCopy(), bundlePathAddr);
2622 			goto finish;
2623 		}
2624 	}
2625 
2626 	if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) {
2627 		goto finish;
2628 	}
2629 
2630 	/* An executable is not mandatory.
2631 	 */
2632 	if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
2633 		executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
2634 		if (!executableAddr) {
2635 			OSKextLog(this,
2636 			    kOSKextLogErrorLevel |
2637 			    kOSKextLogGeneralFlag,
2638 			    "Can't translate physical address 0x%x of kext executable "
2639 			    "for device tree entry %s.",
2640 			    (int)kextFileInfo->executablePhysAddr,
2641 			    deviceTreeName->getCStringNoCopy());
2642 			goto finish;
2643 		}
2644 
2645 		executable = OSData::withBytesNoCopy(executableAddr,
2646 		    kextFileInfo->executableLength);
2647 		if (!executable) {
2648 			OSKextLog(this,
2649 			    kOSKextLogErrorLevel |
2650 			    kOSKextLogGeneralFlag,
2651 			    "Failed to create executable wrapper for device tree entry %s.",
2652 			    deviceTreeName->getCStringNoCopy());
2653 			goto finish;
2654 		}
2655 
2656 		/* A kext with an executable needs to retain the whole booterData
2657 		 * object to keep the executable in memory.
2658 		 */
2659 		if (!setExecutable(executable.get(), booterData)) {
2660 			OSKextLog(this,
2661 			    kOSKextLogErrorLevel |
2662 			    kOSKextLogGeneralFlag,
2663 			    "Failed to set kext executable for device tree entry %s.",
2664 			    deviceTreeName->getCStringNoCopy());
2665 			goto finish;
2666 		}
2667 	}
2668 
2669 	if (isDriverKit()) {
2670 		dextStatistics = OSDextStatistics::create();
2671 		dextUniqueID.reset(parseDextUniqueID(theInfoDict, getIdentifierCString()), OSRetain);
2672 		dextLaunchedCount = 0;
2673 	}
2674 
2675 	result = (registerIdentifier() == kOSKextInitialized);
2676 
2677 finish:
2678 	return result;
2679 }
2680 
2681 /*********************************************************************
2682 *********************************************************************/
2683 OSKextInitResult
registerIdentifier(void)2684 OSKext::registerIdentifier(void)
2685 {
2686 	OSKextInitResult  result                  = kOSKextInitFailure;
2687 	OSKext        * existingKext              = NULL;        // do not release
2688 	bool            existingIsLoaded          = false;
2689 	bool            existingIsPrelinked       = false;
2690 	bool            existingIsCodeless        = false;
2691 	bool            existingIsDext            = false;
2692 	OSKextVersion   newVersion                = -1;
2693 	OSKextVersion   existingVersion           = -1;
2694 	char            newVersionCString[kOSKextVersionMaxLength];
2695 	char            existingVersionCString[kOSKextVersionMaxLength];
2696 	OSSharedPtr<OSData> newUUID;
2697 	OSSharedPtr<OSData> existingUUID;
2698 	const char *newDextUniqueIDCString = NULL;
2699 	const char *existingDextUniqueIDCString = NULL;
2700 	unsigned int newDextUniqueIDCStringSize = 0;
2701 	unsigned int existingDextUniqueIDCStringSize = 0;
2702 
2703 	IORecursiveLockLock(sKextLock);
2704 
2705 	/* Get the new kext's version for checks & log messages.
2706 	 */
2707 	newVersion = getVersion();
2708 	OSKextVersionGetString(newVersion, newVersionCString,
2709 	    kOSKextVersionMaxLength);
2710 
2711 	/* If we don't have an existing kext with this identifier,
2712 	 * just record the new kext and we're done!
2713 	 */
2714 	existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get()));
2715 	if (!existingKext) {
2716 		sKextsByID->setObject(bundleID.get(), this);
2717 		result = kOSKextInitialized;
2718 		goto finish;
2719 	}
2720 
2721 	/* Get the existing kext's version for checks & log messages.
2722 	 */
2723 	existingVersion = existingKext->getVersion();
2724 	OSKextVersionGetString(existingVersion,
2725 	    existingVersionCString, kOSKextVersionMaxLength);
2726 
2727 	existingIsLoaded = existingKext->isLoaded();
2728 	existingIsPrelinked = existingKext->isPrelinked();
2729 	existingIsDext = existingKext->isDriverKit();
2730 	existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext;
2731 
2732 	/*
2733 	 * Check if we are trying to upgrade a dext
2734 	 * with another dext.
2735 	 */
2736 	if (isDriverKit() && existingIsDext) {
2737 		OSData *newDextUID = getDextUniqueID();
2738 		if (!newDextUID) {
2739 			OSKextLog(this,
2740 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2741 			    "New dext %s, v%s requested does not have a unique dext identifier\n",
2742 			    getIdentifierCString(), newVersionCString);
2743 			goto finish;
2744 		}
2745 		newDextUniqueIDCString = getDextUniqueIDCString(newDextUID, &newDextUniqueIDCStringSize);
2746 		assert(newDextUniqueIDCString != NULL);
2747 
2748 		OSData *existingDextUID = existingKext->getDextUniqueID();
2749 		if (!existingDextUID) {
2750 			OSKextLog(this,
2751 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2752 			    "Found a dext %s, v%s: with no unique dext identifier\n",
2753 			    existingKext->getIdentifierCString(), existingVersionCString);
2754 			goto finish;
2755 		}
2756 		existingDextUniqueIDCString = getDextUniqueIDCString(existingDextUID, &existingDextUniqueIDCStringSize);
2757 		assert(existingDextUniqueIDCString != NULL);
2758 
2759 		/*
2760 		 * We might get multiple requests to save the same dext.
2761 		 * Check if we already have saved it or if this is an upgrade
2762 		 * for a dext with the same BundleID.
2763 		 * Dexts are uniquely identified by DextUniqueID, if a new DextUniqueID
2764 		 * is requested for a BundleID we are going to upgrade to the newest
2765 		 * received irrespective from the dext version.
2766 		 */
2767 		if (newDextUID->isEqualTo(existingDextUID) && existingKext->flags.dextToReplace == 0) {
2768 			OSKextLog(this,
2769 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2770 			    "Refusing new dext %s, v%s:"
2771 			    "a dext v %s with the same unique dext identifier (%s) already exists\n",
2772 			    getIdentifierCString(), newVersionCString,
2773 			    existingVersionCString, newDextUniqueIDCString);
2774 			result = kOSKextAlreadyExist;
2775 			goto finish;
2776 		}
2777 
2778 		bool upgraded = upgradeDext(existingKext, this);
2779 		if (upgraded) {
2780 			/* If the dext was upgraded existingKext might have been deallocated */
2781 			existingKext = NULL;
2782 			OSKextLog(this,
2783 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2784 			    "Dext %s, v%s , unique dext identifier %s "
2785 			    "Upgraded to v%s, unique dext identifier %s \n",
2786 			    getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
2787 			    newVersionCString, newDextUniqueIDCString);
2788 			result = kOSKextInitialized;
2789 		} else {
2790 			OSKextLog(this,
2791 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2792 			    "Upgrade delayed for %s v%s, unique dext identifier %s "
2793 			    "with v%s, unique dext identifier %s.\n",
2794 			    getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
2795 			    newVersionCString, newDextUniqueIDCString);
2796 			result = kOSKextAlreadyExist;
2797 		}
2798 
2799 		goto finish;
2800 	}
2801 
2802 	/* If we have a non-codeless kext with this identifier that's already
2803 	 * loaded/prelinked, we can't use the new one, but let's be really
2804 	 * thorough and check how the two are related for a precise diagnostic
2805 	 * log message.
2806 	 *
2807 	 * This check is valid for kexts that declare an executable and for
2808 	 * dexts, but not for codeless kexts - we can just replace those.
2809 	 */
2810 	if ((!existingIsCodeless || existingIsDext) &&
2811 	    (existingIsLoaded || existingIsPrelinked)) {
2812 		bool sameVersion = (newVersion == existingVersion);
2813 		bool sameExecutable = true;         // assume true unless we have UUIDs
2814 
2815 		/* Only get the UUID if the existing kext is loaded. Doing so
2816 		 * might have to uncompress an mkext executable and we shouldn't
2817 		 * take that hit when neither kext is loaded.
2818 		 *
2819 		 * Note: there is no decompression that happens when all kexts
2820 		 * are loaded from kext collecitons.
2821 		 */
2822 		newUUID = copyUUID();
2823 		existingUUID = existingKext->copyUUID();
2824 
2825 		if (existingIsDext && !isDriverKit()) {
2826 			OSKextLog(this,
2827 			    kOSKextLogWarningLevel |
2828 			    kOSKextLogKextBookkeepingFlag,
2829 			    "Notice - new kext %s, v%s matches a %s dext"
2830 			    "with the same bundle ID, v%s.",
2831 			    getIdentifierCString(), newVersionCString,
2832 			    (existingIsLoaded ? "loaded" : "prelinked"),
2833 			    existingVersionCString);
2834 			goto finish;
2835 		}
2836 
2837 		/* I'm entirely too paranoid about checking equivalence of executables,
2838 		 * but I remember nasty problems with it in the past.
2839 		 *
2840 		 * - If we have UUIDs for both kexts, compare them.
2841 		 * - If only one kext has a UUID, they're definitely different.
2842 		 */
2843 		if (newUUID && existingUUID) {
2844 			sameExecutable = newUUID->isEqualTo(existingUUID.get());
2845 		} else if (newUUID || existingUUID) {
2846 			sameExecutable = false;
2847 		}
2848 
2849 		if (!newUUID && !existingUUID) {
2850 			/* If there are no UUIDs, we can't really tell that the executables
2851 			 * are *different* without a lot of work; the loaded kext's
2852 			 * unrelocated executable is no longer around (and we never had it
2853 			 * in-kernel for a prelinked kext). We certainly don't want to do
2854 			 * a whole fake link for the new kext just to compare, either.
2855 			 */
2856 			OSKextLog(this,
2857 			    kOSKextLogWarningLevel |
2858 			    kOSKextLogKextBookkeepingFlag,
2859 			    "Notice - new kext %s, v%s matches %s kext "
2860 			    "but can't determine if executables are the same (no UUIDs).",
2861 			    getIdentifierCString(),
2862 			    newVersionCString,
2863 			    (existingIsLoaded ? "loaded" : "prelinked"));
2864 		}
2865 
2866 		if (sameVersion && sameExecutable) {
2867 			OSKextLog(this,
2868 			    (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
2869 			    kOSKextLogKextBookkeepingFlag,
2870 			    "Refusing new kext %s, v%s: a %s copy is already present "
2871 			    "(same version and executable).",
2872 			    getIdentifierCString(), newVersionCString,
2873 			    (existingIsLoaded ? "loaded" : "prelinked"));
2874 		} else {
2875 			if (!sameVersion) {
2876 				/* This condition is significant so log it under warnings.
2877 				 */
2878 				OSKextLog(this,
2879 				    kOSKextLogWarningLevel |
2880 				    kOSKextLogKextBookkeepingFlag,
2881 				    "Refusing new kext %s, v%s: already have %s v%s.",
2882 				    getIdentifierCString(),
2883 				    newVersionCString,
2884 				    (existingIsLoaded ? "loaded" : "prelinked"),
2885 				    existingVersionCString);
2886 			} else {
2887 				/* This condition is significant so log it under warnings.
2888 				 */
2889 				OSKextLog(this,
2890 				    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2891 				    "Refusing new kext %s, v%s: a %s copy with a different "
2892 				    "executable UUID is already present.",
2893 				    getIdentifierCString(), newVersionCString,
2894 				    (existingIsLoaded ? "loaded" : "prelinked"));
2895 			}
2896 		}
2897 		goto finish;
2898 	} /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */
2899 
2900 	/* Refuse to allow an existing loaded codeless kext be replaced by a
2901 	 * normal kext with the same bundle ID.
2902 	 */
2903 	if (existingIsCodeless && declaresExecutable()) {
2904 		OSKextLog(this,
2905 		    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2906 		    "Refusing new kext %s, v%s: a codeless copy is already %s",
2907 		    getIdentifierCString(), newVersionCString,
2908 		    (existingIsLoaded ? "loaded" : "prelinked"));
2909 		goto finish;
2910 	}
2911 
2912 	/* Dexts packaged in the BootKC will be protected against replacement
2913 	 * by non-dexts by the logic above which checks if they are prelinked.
2914 	 * Dexts which are prelinked into the System KC will be registered
2915 	 * before any other kexts in the AuxKC are registered, and we never
2916 	 * put dexts in the AuxKC. Therefore, there is no need to check if an
2917 	 * existing object is a dext and is being replaced by a non-dext.
2918 	 * The scenario cannot happen by construction.
2919 	 *
2920 	 * See: OSKext::loadFileSetKexts()
2921 	 */
2922 
2923 
2924 	/* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2925 	 * user loads are happening or if we're still in early boot. User agents are
2926 	 * supposed to resolve dependencies topside and include only the exact
2927 	 * kexts needed; so we always accept the new kext (in fact we should never
2928 	 * see an older unloaded copy hanging around).
2929 	 */
2930 	if (sUserLoadsActive) {
2931 		sKextsByID->setObject(bundleID.get(), this);
2932 		result = kOSKextInitialized;
2933 
2934 		OSKextLog(this,
2935 		    kOSKextLogStepLevel |
2936 		    kOSKextLogKextBookkeepingFlag,
2937 		    "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2938 		    getIdentifierCString(),
2939 		    existingVersionCString,
2940 		    newVersionCString);
2941 
2942 		goto finish;
2943 	}
2944 
2945 	/* During early boot, the kext with the highest version always wins out.
2946 	 * Prelinked kernels will never hit this, but mkexts and booter-read
2947 	 * kexts might have duplicates.
2948 	 */
2949 	if (newVersion > existingVersion) {
2950 		sKextsByID->setObject(bundleID.get(), this);
2951 		result = kOSKextInitialized;
2952 
2953 		OSKextLog(this,
2954 		    kOSKextLogStepLevel |
2955 		    kOSKextLogKextBookkeepingFlag,
2956 		    "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2957 		    existingVersionCString,
2958 		    getIdentifierCString(),
2959 		    newVersionCString);
2960 	} else {
2961 		OSKextLog(this,
2962 		    kOSKextLogStepLevel |
2963 		    kOSKextLogKextBookkeepingFlag,
2964 		    "Kext %s is already registered with a higher/same version (v%s); "
2965 		    "dropping newly-added (v%s).",
2966 		    getIdentifierCString(),
2967 		    existingVersionCString,
2968 		    newVersionCString);
2969 	}
2970 
2971 	/* result has been set appropriately by now. */
2972 
2973 finish:
2974 
2975 	IORecursiveLockUnlock(sKextLock);
2976 
2977 	if (newDextUniqueIDCString != NULL) {
2978 		kfree_data(newDextUniqueIDCString, newDextUniqueIDCStringSize);
2979 	}
2980 	if (existingDextUniqueIDCString != NULL) {
2981 		kfree_data(existingDextUniqueIDCString, existingDextUniqueIDCStringSize);
2982 	}
2983 
2984 	if (result == kOSKextInitialized) {
2985 		OSKextLog(this,
2986 		    kOSKextLogStepLevel |
2987 		    kOSKextLogKextBookkeepingFlag,
2988 		    "Kext %s, v%s registered and available for loading.",
2989 		    getIdentifierCString(), newVersionCString);
2990 	}
2991 
2992 	return result;
2993 }
2994 
2995 /*********************************************************************
2996  * Does the bare minimum validation to look up a kext.
2997  * All other validation is done on the spot as needed.
2998  **********************************************************************/
2999 bool
setInfoDictionaryAndPath(OSDictionary * aDictionary,OSString * aPath)3000 OSKext::setInfoDictionaryAndPath(
3001 	OSDictionary * aDictionary,
3002 	OSString     * aPath)
3003 {
3004 	bool           result                   = false;
3005 	OSString     * bundleIDString           = NULL;        // do not release
3006 	OSString     * versionString            = NULL;        // do not release
3007 	OSString     * compatibleVersionString  = NULL;        // do not release
3008 	const char   * versionCString           = NULL;        // do not free
3009 	const char   * compatibleVersionCString = NULL;        // do not free
3010 	OSBoolean    * scratchBool              = NULL;        // do not release
3011 	OSDictionary * scratchDict              = NULL;        // do not release
3012 
3013 	if (infoDict) {
3014 		panic("Attempt to set info dictionary on a kext "
3015 		    "that already has one (%s).",
3016 		    getIdentifierCString());
3017 	}
3018 
3019 	if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
3020 		goto finish;
3021 	}
3022 
3023 	infoDict.reset(aDictionary, OSRetain);
3024 
3025 	/* Check right away if the info dictionary has any log flags.
3026 	 */
3027 	scratchBool = OSDynamicCast(OSBoolean,
3028 	    getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
3029 	if (scratchBool == kOSBooleanTrue) {
3030 		flags.loggingEnabled = 1;
3031 	}
3032 
3033 	/* The very next thing to get is the bundle identifier. Unlike
3034 	 * in user space, a kext with no bundle identifier gets axed
3035 	 * immediately.
3036 	 */
3037 	bundleIDString = OSDynamicCast(OSString,
3038 	    getPropertyForHostArch(kCFBundleIdentifierKey));
3039 	if (!bundleIDString) {
3040 		OSKextLog(this,
3041 		    kOSKextLogErrorLevel |
3042 		    kOSKextLogValidationFlag,
3043 		    "CFBundleIdentifier missing/invalid type in kext %s.",
3044 		    aPath ? aPath->getCStringNoCopy() : "(unknown)");
3045 		goto finish;
3046 	}
3047 	bundleID = OSSymbol::withString(bundleIDString);
3048 	if (!bundleID) {
3049 		OSKextLog(this,
3050 		    kOSKextLogErrorLevel |
3051 		    kOSKextLogValidationFlag,
3052 		    "Can't copy bundle identifier as symbol for kext %s.",
3053 		    bundleIDString->getCStringNoCopy());
3054 		goto finish;
3055 	}
3056 
3057 	/* Save the path if we got one (it should always be available but it's
3058 	 * just something nice to have for bookkeeping).
3059 	 */
3060 	if (aPath) {
3061 		path.reset(aPath, OSRetain);
3062 	}
3063 
3064 	/*****
3065 	 * Minimal validation to initialize. We'll do other validation on the spot.
3066 	 */
3067 	if (bundleID->getLength() >= KMOD_MAX_NAME) {
3068 		OSKextLog(this,
3069 		    kOSKextLogErrorLevel |
3070 		    kOSKextLogValidationFlag,
3071 		    "Kext %s error - CFBundleIdentifier over max length %d.",
3072 		    getIdentifierCString(), KMOD_MAX_NAME - 1);
3073 		goto finish;
3074 	}
3075 
3076 	version = compatibleVersion = -1;
3077 
3078 	versionString = OSDynamicCast(OSString,
3079 	    getPropertyForHostArch(kCFBundleVersionKey));
3080 	if (!versionString) {
3081 		OSKextLog(this,
3082 		    kOSKextLogErrorLevel |
3083 		    kOSKextLogValidationFlag,
3084 		    "Kext %s error - CFBundleVersion missing/invalid type.",
3085 		    getIdentifierCString());
3086 		goto finish;
3087 	}
3088 	versionCString = versionString->getCStringNoCopy();
3089 	version = OSKextParseVersionString(versionCString);
3090 	if (version < 0) {
3091 		OSKextLog(this,
3092 		    kOSKextLogErrorLevel |
3093 		    kOSKextLogValidationFlag,
3094 		    "Kext %s error - CFBundleVersion bad value '%s'.",
3095 		    getIdentifierCString(), versionCString);
3096 		goto finish;
3097 	}
3098 
3099 	compatibleVersion = -1;         // set to illegal value for kexts that don't have
3100 
3101 	compatibleVersionString = OSDynamicCast(OSString,
3102 	    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
3103 	if (compatibleVersionString) {
3104 		compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
3105 		compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
3106 		if (compatibleVersion < 0) {
3107 			OSKextLog(this,
3108 			    kOSKextLogErrorLevel |
3109 			    kOSKextLogValidationFlag,
3110 			    "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
3111 			    getIdentifierCString(), compatibleVersionCString);
3112 			goto finish;
3113 		}
3114 
3115 		if (compatibleVersion > version) {
3116 			OSKextLog(this,
3117 			    kOSKextLogErrorLevel |
3118 			    kOSKextLogValidationFlag,
3119 			    "Kext %s error - %s %s > %s %s (must be <=).",
3120 			    getIdentifierCString(),
3121 			    kOSBundleCompatibleVersionKey, compatibleVersionCString,
3122 			    kCFBundleVersionKey, versionCString);
3123 			goto finish;
3124 		}
3125 	}
3126 
3127 	/* Check to see if this kext is in exclude list */
3128 	if (isInExcludeList()) {
3129 		OSKextLog(this,
3130 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3131 		    "Kext %s is in exclude list, not loadable",
3132 		    getIdentifierCString());
3133 		goto finish;
3134 	}
3135 
3136 	/* Set flags for later use if the infoDict gets flushed. We only
3137 	 * check for true values, not false ones(!)
3138 	 */
3139 	scratchBool = OSDynamicCast(OSBoolean,
3140 	    getPropertyForHostArch(kOSBundleIsInterfaceKey));
3141 	if (scratchBool == kOSBooleanTrue) {
3142 		flags.interface = 1;
3143 	}
3144 
3145 	scratchBool = OSDynamicCast(OSBoolean,
3146 	    getPropertyForHostArch(kOSKernelResourceKey));
3147 	if (scratchBool == kOSBooleanTrue) {
3148 		flags.kernelComponent = 1;
3149 		flags.interface = 1;         // xxx - hm. the kernel itself isn't an interface...
3150 		flags.started = 1;
3151 
3152 		/* A kernel component has one implicit dependency on the kernel.
3153 		 */
3154 		flags.hasAllDependencies = 1;
3155 	}
3156 
3157 	/* Make sure common string values in personalities are uniqued to OSSymbols.
3158 	 */
3159 	scratchDict = OSDynamicCast(OSDictionary,
3160 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
3161 	if (scratchDict) {
3162 		uniquePersonalityProperties(scratchDict);
3163 	}
3164 
3165 	result = true;
3166 
3167 finish:
3168 
3169 	return result;
3170 }
3171 
3172 /*********************************************************************
3173 * Not used for prelinked kernel boot as there is no unrelocated
3174 * executable.
3175 *********************************************************************/
3176 bool
setExecutable(OSData * anExecutable,OSData * externalData,bool externalDataIsMkext)3177 OSKext::setExecutable(
3178 	OSData * anExecutable,
3179 	OSData * externalData,
3180 	bool     externalDataIsMkext)
3181 {
3182 	bool         result        = false;
3183 	const char * executableKey = NULL;         // do not free
3184 
3185 	if (!anExecutable) {
3186 		infoDict->removeObject(_kOSKextExecutableKey);
3187 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
3188 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
3189 		result = true;
3190 		goto finish;
3191 	}
3192 
3193 	if (infoDict->getObject(_kOSKextExecutableKey) ||
3194 	    infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
3195 		panic("Attempt to set an executable on a kext "
3196 		    "that already has one (%s).",
3197 		    getIdentifierCString());
3198 		goto finish;
3199 	}
3200 
3201 	if (externalDataIsMkext) {
3202 		executableKey = _kOSKextMkextExecutableReferenceKey;
3203 	} else {
3204 		executableKey = _kOSKextExecutableKey;
3205 	}
3206 
3207 	if (anExecutable) {
3208 		infoDict->setObject(executableKey, anExecutable);
3209 		if (externalData) {
3210 			infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
3211 		}
3212 	}
3213 
3214 	result = true;
3215 
3216 finish:
3217 	return result;
3218 }
3219 
3220 /*********************************************************************
3221 *********************************************************************/
3222 static void
uniqueStringPlistProperty(OSDictionary * dict,const char * key)3223 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
3224 {
3225 	OSObject       * value       = NULL;        // do not release
3226 	OSString       * stringValue = NULL;        // do not release
3227 	OSSharedPtr<const OSSymbol> symbolValue;
3228 
3229 	value = dict->getObject(key);
3230 	if (!value) {
3231 		goto finish;
3232 	}
3233 	if (OSDynamicCast(OSSymbol, value)) {
3234 		/* this is already an OSSymbol: we're good */
3235 		goto finish;
3236 	}
3237 
3238 	stringValue = OSDynamicCast(OSString, value);
3239 	if (!stringValue) {
3240 		goto finish;
3241 	}
3242 
3243 	symbolValue = OSSymbol::withString(stringValue);
3244 	if (!symbolValue) {
3245 		goto finish;
3246 	}
3247 
3248 	dict->setObject(key, symbolValue.get());
3249 
3250 finish:
3251 	return;
3252 }
3253 
3254 /*********************************************************************
3255 *********************************************************************/
3256 static void
uniqueStringPlistProperty(OSDictionary * dict,const OSString * key)3257 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
3258 {
3259 	OSObject       * value       = NULL;        // do not release
3260 	OSString       * stringValue = NULL;        // do not release
3261 	OSSharedPtr<const OSSymbol> symbolValue;
3262 
3263 	value = dict->getObject(key);
3264 	if (!value) {
3265 		goto finish;
3266 	}
3267 	if (OSDynamicCast(OSSymbol, value)) {
3268 		/* this is already an OSSymbol: we're good */
3269 		goto finish;
3270 	}
3271 
3272 	stringValue = OSDynamicCast(OSString, value);
3273 	if (!stringValue) {
3274 		goto finish;
3275 	}
3276 
3277 	symbolValue = OSSymbol::withString(stringValue);
3278 	if (!symbolValue) {
3279 		goto finish;
3280 	}
3281 
3282 	dict->setObject(key, symbolValue.get());
3283 
3284 finish:
3285 	return;
3286 }
3287 
3288 void
uniquePersonalityProperties(OSDictionary * personalityDict)3289 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
3290 {
3291 	OSKext::uniquePersonalityProperties(personalityDict, true);
3292 }
3293 
3294 /*********************************************************************
3295 * Replace common personality property values with uniqued instances
3296 * to save on wired memory.
3297 *********************************************************************/
3298 /* static */
3299 void
uniquePersonalityProperties(OSDictionary * personalityDict,bool defaultAddKernelBundleIdentifier)3300 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier)
3301 {
3302 	/* Properties every personality has.
3303 	 */
3304 	uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
3305 	uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
3306 	uniqueStringPlistProperty(personalityDict, gIOClassKey.get());
3307 	if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) {
3308 		uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey);
3309 	} else if (defaultAddKernelBundleIdentifier) {
3310 		personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey));
3311 	}
3312 
3313 	/* Other commonly used properties.
3314 	 */
3315 	uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
3316 	uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
3317 	uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
3318 
3319 	uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
3320 	uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
3321 	uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
3322 	uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
3323 	uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
3324 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
3325 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
3326 	uniqueStringPlistProperty(personalityDict, "Vendor");
3327 	uniqueStringPlistProperty(personalityDict, "Vendor Identification");
3328 	uniqueStringPlistProperty(personalityDict, "Vendor Name");
3329 	uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
3330 	uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
3331 	uniqueStringPlistProperty(personalityDict, "idProduct");
3332 
3333 	return;
3334 }
3335 
3336 /*********************************************************************
3337 *********************************************************************/
3338 void
free(void)3339 OSKext::free(void)
3340 {
3341 	if (isLoaded()) {
3342 		panic("Attempt to free loaded kext %s.", getIdentifierCString());
3343 	}
3344 
3345 	if (isDriverKit()) {
3346 		if (dextLaunchedCount > 0) {
3347 			panic("Freeing dext %s but dextLaunchedCount is %d\n", getIdentifierCString(), dextLaunchedCount);
3348 		}
3349 	}
3350 
3351 	infoDict.reset();
3352 	bundleID.reset();
3353 	path.reset();
3354 	executableRelPath.reset();
3355 	userExecutableRelPath.reset();
3356 	dependencies.reset();
3357 	linkedExecutable.reset();
3358 	metaClasses.reset();
3359 	interfaceUUID.reset();
3360 	driverKitUUID.reset();
3361 	dextStatistics.reset();
3362 	dextUniqueID.reset();
3363 
3364 	if (isInterface() && kmod_info) {
3365 		kfree_type(kmod_info_t, kmod_info);
3366 	}
3367 
3368 	super::free();
3369 	return;
3370 }
3371 
3372 #if PRAGMA_MARK
3373 #pragma mark Mkext files
3374 #endif
3375 
3376 #if CONFIG_KXLD
3377 /*
3378  * mkext archives are really only relevant on kxld-enabled kernels.
3379  * Without a dynamic kernel linker, we don't need to support any mkexts.
3380  */
3381 
3382 /*********************************************************************
3383 *********************************************************************/
3384 OSReturn
readMkextArchive(OSData * mkextData,uint32_t * checksumPtr)3385 OSKext::readMkextArchive(OSData * mkextData,
3386     uint32_t * checksumPtr)
3387 {
3388 	OSReturn       result       = kOSKextReturnBadData;
3389 	uint32_t       mkextLength  = 0;
3390 	mkext_header * mkextHeader  = NULL;        // do not free
3391 	uint32_t       mkextVersion = 0;
3392 
3393 	/* Note default return of kOSKextReturnBadData above.
3394 	 */
3395 	mkextLength = mkextData->getLength();
3396 	if (mkextLength < sizeof(mkext_basic_header)) {
3397 		OSKextLog(/* kext */ NULL,
3398 		    kOSKextLogErrorLevel |
3399 		    kOSKextLogArchiveFlag,
3400 		    "Mkext archive too small to be valid.");
3401 		goto finish;
3402 	}
3403 
3404 	mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
3405 
3406 	if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
3407 	    MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
3408 		OSKextLog(/* kext */ NULL,
3409 		    kOSKextLogErrorLevel |
3410 		    kOSKextLogArchiveFlag,
3411 		    "Mkext archive has invalid magic or signature.");
3412 		goto finish;
3413 	}
3414 
3415 	if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
3416 		OSKextLog(/* kext */ NULL,
3417 		    kOSKextLogErrorLevel |
3418 		    kOSKextLogArchiveFlag,
3419 		    "Mkext archive recorded length doesn't match actual file length.");
3420 		goto finish;
3421 	}
3422 
3423 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3424 
3425 	if (mkextVersion == MKEXT_VERS_2) {
3426 		result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
3427 	} else {
3428 		OSKextLog(/* kext */ NULL,
3429 		    kOSKextLogErrorLevel |
3430 		    kOSKextLogArchiveFlag,
3431 		    "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
3432 		result = kOSKextReturnUnsupported;
3433 	}
3434 
3435 finish:
3436 	return result;
3437 }
3438 
3439 /*********************************************************************
3440 * Assumes magic, signature, version, length have been checked.
3441 * xxx - need to add further bounds checking for each file entry
3442 *
3443 * Should keep track of all kexts created so far, and if we hit a
3444 * fatal error halfway through, remove those kexts. If we've dropped
3445 * an older version that had already been read, whoops! Might want to
3446 * add a level of buffering?
3447 *********************************************************************/
3448 /* static */
3449 OSReturn
readMkext2Archive(OSData * mkextData,OSDictionary ** mkextPlistOut,uint32_t * checksumPtr)3450 OSKext::readMkext2Archive(
3451 	OSData        * mkextData,
3452 	OSDictionary ** mkextPlistOut,
3453 	uint32_t      * checksumPtr)
3454 {
3455 	OSReturn        result                     = kOSReturnError;
3456 	uint32_t        mkextLength;
3457 	mkext2_header * mkextHeader                = NULL;        // do not free
3458 	void          * mkextEnd                   = NULL;        // do not free
3459 	uint32_t        mkextVersion;
3460 	uint8_t       * crc_address                = NULL;
3461 	size_t          crc_buffer_size            = 0;
3462 	uint32_t        checksum;
3463 	uint32_t        mkextPlistOffset;
3464 	uint32_t        mkextPlistCompressedSize;
3465 	char          * mkextPlistEnd              = NULL;        // do not free
3466 	uint32_t        mkextPlistFullSize;
3467 	OSSharedPtr<OSString>     errorString;
3468 	OSSharedPtr<OSData>       mkextPlistUncompressedData;
3469 	const char    * mkextPlistDataBuffer       = NULL;        // do not free
3470 	OSSharedPtr<OSObject>      parsedXML;
3471 	OSDictionary  * mkextPlist                 = NULL;        // do not release
3472 	OSArray       * mkextInfoDictArray         = NULL;        // do not release
3473 	uint32_t        count, i;
3474 	kc_format_t kc_format;
3475 
3476 	if (!PE_get_primary_kc_format(&kc_format)) {
3477 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3478 		    "Unable to determine primary KC format");
3479 		goto finish;
3480 	}
3481 
3482 	mkextLength = mkextData->getLength();
3483 	mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
3484 	mkextEnd = (char *)mkextHeader + mkextLength;
3485 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3486 
3487 	crc_address = (u_int8_t *)&mkextHeader->version;
3488 	crc_buffer_size = (uintptr_t)mkextHeader +
3489 	    MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address;
3490 	if (crc_buffer_size > INT32_MAX) {
3491 		OSKextLog(/* kext */ NULL,
3492 		    kOSKextLogErrorLevel |
3493 		    kOSKextLogArchiveFlag,
3494 		    "Mkext archive size is too large (%lu > INT32_MAX).",
3495 		    crc_buffer_size);
3496 		result = kOSKextReturnBadData;
3497 		goto finish;
3498 	}
3499 	checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size);
3500 
3501 	if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
3502 		OSKextLog(/* kext */ NULL,
3503 		    kOSKextLogErrorLevel |
3504 		    kOSKextLogArchiveFlag,
3505 		    "Mkext archive has bad checksum.");
3506 		result = kOSKextReturnBadData;
3507 		goto finish;
3508 	}
3509 
3510 	if (checksumPtr) {
3511 		*checksumPtr = checksum;
3512 	}
3513 
3514 	/* Check that the CPU type & subtype match that of the running kernel. */
3515 	if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
3516 		OSKextLog(/* kext */ NULL,
3517 		    kOSKextLogErrorLevel |
3518 		    kOSKextLogArchiveFlag,
3519 		    "Mkext archive must have a specific CPU type.");
3520 		result = kOSKextReturnBadData;
3521 		goto finish;
3522 	} else {
3523 		if ((UInt32)_mh_execute_header.cputype !=
3524 		    MKEXT_GET_CPUTYPE(mkextHeader)) {
3525 			OSKextLog(/* kext */ NULL,
3526 			    kOSKextLogErrorLevel |
3527 			    kOSKextLogArchiveFlag,
3528 			    "Mkext archive does not match the running kernel's CPU type.");
3529 			result = kOSKextReturnArchNotFound;
3530 			goto finish;
3531 		}
3532 	}
3533 
3534 	mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
3535 	mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
3536 	mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
3537 	    mkextPlistCompressedSize;
3538 	if (mkextPlistEnd > mkextEnd) {
3539 		OSKextLog(/* kext */ NULL,
3540 		    kOSKextLogErrorLevel |
3541 		    kOSKextLogArchiveFlag,
3542 		    "Mkext archive file overrun.");
3543 		result = kOSKextReturnBadData;
3544 	}
3545 
3546 	mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
3547 	if (mkextPlistCompressedSize) {
3548 		mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
3549 			(UInt8 *)mkextHeader + mkextPlistOffset,
3550 			"plist",
3551 			mkextPlistCompressedSize, mkextPlistFullSize);
3552 		if (!mkextPlistUncompressedData) {
3553 			goto finish;
3554 		}
3555 		mkextPlistDataBuffer = (const char *)
3556 		    mkextPlistUncompressedData->getBytesNoCopy();
3557 	} else {
3558 		mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
3559 	}
3560 
3561 	/* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
3562 	 */
3563 	parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString);
3564 	if (parsedXML) {
3565 		mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get());
3566 	}
3567 	if (!mkextPlist) {
3568 		const char * errorCString = "(unknown error)";
3569 
3570 		if (errorString && errorString->getCStringNoCopy()) {
3571 			errorCString = errorString->getCStringNoCopy();
3572 		} else if (parsedXML) {
3573 			errorCString = "not a dictionary";
3574 		}
3575 		OSKextLog(/* kext */ NULL,
3576 		    kOSKextLogErrorLevel |
3577 		    kOSKextLogArchiveFlag,
3578 		    "Error unserializing mkext plist: %s.", errorCString);
3579 		goto finish;
3580 	}
3581 
3582 	mkextInfoDictArray = OSDynamicCast(OSArray,
3583 	    mkextPlist->getObject(kMKEXTInfoDictionariesKey));
3584 	if (!mkextInfoDictArray) {
3585 		OSKextLog(/* kext */ NULL,
3586 		    kOSKextLogErrorLevel |
3587 		    kOSKextLogArchiveFlag,
3588 		    "Mkext archive contains no kext info dictionaries.");
3589 		goto finish;
3590 	}
3591 
3592 	count = mkextInfoDictArray->getCount();
3593 	for (i = 0; i < count; i++) {
3594 		OSDictionary * infoDict;
3595 
3596 
3597 		infoDict = OSDynamicCast(OSDictionary,
3598 		    mkextInfoDictArray->getObject(i));
3599 
3600 		/* Create the kext for the entry, then release it, because the
3601 		 * kext system keeps them around until explicitly removed.
3602 		 * Any creation/registration failures are already logged for us.
3603 		 */
3604 		if (infoDict) {
3605 			OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData);
3606 
3607 			/* Fail dynamic loading of a kext when booted from MH_FILESET */
3608 			if (kc_format == KCFormatFileset &&
3609 			    newKext &&
3610 			    !(newKext->isPrelinked()) &&
3611 			    newKext->declaresExecutable()) {
3612 				result = kOSReturnError;
3613 				printf("Kext LOG: Dynamic loading of kext denied for kext %s\n",
3614 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3615 
3616 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
3617 				    "Dynamic loading of kext denied for kext %s\n",
3618 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3619 				goto finish;
3620 			}
3621 		}
3622 	}
3623 
3624 	/* If the caller needs the plist, hand them back our copy
3625 	 */
3626 	if (mkextPlistOut) {
3627 		*mkextPlistOut = mkextPlist;
3628 		parsedXML.detach();
3629 	}
3630 
3631 	/* Even if we didn't keep any kexts from the mkext, we may have a load
3632 	 * request to process, so we are successful (no errors occurred).
3633 	 */
3634 	result = kOSReturnSuccess;
3635 
3636 finish:
3637 	return result;
3638 }
3639 
3640 /* static */
3641 OSReturn
readMkext2Archive(OSData * mkextData,OSSharedPtr<OSDictionary> & mkextPlistOut,uint32_t * checksumPtr)3642 OSKext::readMkext2Archive(
3643 	OSData        * mkextData,
3644 	OSSharedPtr<OSDictionary> &mkextPlistOut,
3645 	uint32_t      * checksumPtr)
3646 {
3647 	OSDictionary * mkextPlist = NULL;
3648 	OSReturn ret;
3649 
3650 	if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData,
3651 	    &mkextPlist,
3652 	    checksumPtr))) {
3653 		mkextPlistOut.reset(mkextPlist, OSNoRetain);
3654 	}
3655 	return ret;
3656 }
3657 
3658 /*********************************************************************
3659 *********************************************************************/
3660 /* static */
3661 OSSharedPtr<OSKext>
withMkext2Info(OSDictionary * anInfoDict,OSData * mkextData)3662 OSKext::withMkext2Info(
3663 	OSDictionary * anInfoDict,
3664 	OSData       * mkextData)
3665 {
3666 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
3667 
3668 	if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
3669 		return NULL;
3670 	}
3671 
3672 	return newKext;
3673 }
3674 
3675 /*********************************************************************
3676 *********************************************************************/
3677 bool
initWithMkext2Info(OSDictionary * anInfoDict,OSData * mkextData)3678 OSKext::initWithMkext2Info(
3679 	OSDictionary * anInfoDict,
3680 	OSData       * mkextData)
3681 {
3682 	bool                   result              = false;
3683 	OSString             * kextPath            = NULL;        // do not release
3684 	OSNumber             * executableOffsetNum = NULL;        // do not release
3685 	OSSharedPtr<OSData>               executable;
3686 
3687 	if (anInfoDict == NULL || !super::init()) {
3688 		goto finish;
3689 	}
3690 
3691 	/* Get the path. Don't look for an arch-specific path property.
3692 	 */
3693 	kextPath = OSDynamicCast(OSString,
3694 	    anInfoDict->getObject(kMKEXTBundlePathKey));
3695 
3696 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
3697 		goto finish;
3698 	}
3699 
3700 	/* If we have a path to the executable, save it.
3701 	 */
3702 	executableRelPath.reset(OSDynamicCast(OSString,
3703 	    anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain);
3704 
3705 	/* Don't need the paths to be in the info dictionary any more.
3706 	 */
3707 	anInfoDict->removeObject(kMKEXTBundlePathKey);
3708 	anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
3709 
3710 	executableOffsetNum = OSDynamicCast(OSNumber,
3711 	    infoDict->getObject(kMKEXTExecutableKey));
3712 	if (executableOffsetNum) {
3713 		executable = createMkext2FileEntry(mkextData,
3714 		    executableOffsetNum, "executable");
3715 		infoDict->removeObject(kMKEXTExecutableKey);
3716 		if (!executable) {
3717 			goto finish;
3718 		}
3719 		if (!setExecutable(executable.get(), mkextData, true)) {
3720 			goto finish;
3721 		}
3722 	}
3723 
3724 	result = (registerIdentifier() == kOSKextInitialized);
3725 finish:
3726 	return result;
3727 }
3728 
3729 /*********************************************************************
3730 *********************************************************************/
3731 OSSharedPtr<OSData>
createMkext2FileEntry(OSData * mkextData,OSNumber * offsetNum,const char * name)3732 OSKext::createMkext2FileEntry(
3733 	OSData     * mkextData,
3734 	OSNumber   * offsetNum,
3735 	const char * name)
3736 {
3737 	OSSharedPtr<OSData> result;
3738 	MkextEntryRef   entryRef;
3739 	uint8_t       * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
3740 	uint32_t        entryOffset = offsetNum->unsigned32BitValue();
3741 
3742 	result = OSData::withCapacity(sizeof(entryRef));
3743 	if (!result) {
3744 		goto finish;
3745 	}
3746 
3747 	entryRef.mkext = (mkext_basic_header *)mkextBuffer;
3748 	entryRef.fileinfo = mkextBuffer + entryOffset;
3749 	if (!result->appendValue(entryRef)) {
3750 		result.reset();
3751 		goto finish;
3752 	}
3753 
3754 finish:
3755 	if (!result) {
3756 		OSKextLog(this,
3757 		    kOSKextLogErrorLevel |
3758 		    kOSKextLogArchiveFlag,
3759 		    "Can't create wrapper for mkext file entry '%s' of kext %s.",
3760 		    name, getIdentifierCString());
3761 	}
3762 	return result;
3763 }
3764 
3765 /*********************************************************************
3766 *********************************************************************/
3767 extern "C" {
3768 static void * z_alloc(void *, u_int items, u_int size);
3769 static void   z_free(void *, void *ptr);
3770 
3771 typedef struct z_mem {
3772 	uint32_t alloc_size;
3773 	uint8_t  data[0];
3774 } z_mem;
3775 
3776 /*
3777  * Space allocation and freeing routines for use by zlib routines.
3778  */
3779 void *
z_alloc(void * notused __unused,u_int num_items,u_int size)3780 z_alloc(void * notused __unused, u_int num_items, u_int size)
3781 {
3782 	void     * result = NULL;
3783 	z_mem    * zmem = NULL;
3784 
3785 	uint64_t   total = ((uint64_t)num_items) * ((uint64_t)size);
3786 	//Check for overflow due to multiplication
3787 	if (total > UINT32_MAX) {
3788 		panic("z_alloc(%p, %x, %x): overflow caused by %x * %x",
3789 		    notused, num_items, size, num_items, size);
3790 	}
3791 
3792 	uint64_t   allocSize64 =  total + ((uint64_t)sizeof(zmem));
3793 	//Check for overflow due to addition
3794 	if (allocSize64 > UINT32_MAX) {
3795 		panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx",
3796 		    notused, num_items, size, (uint32_t)total, sizeof(zmem));
3797 	}
3798 	uint32_t allocSize = (uint32_t)allocSize64;
3799 
3800 	zmem = (z_mem *)kalloc_data_tag(allocSize, Z_WAITOK,
3801 	    VM_KERN_MEMORY_OSKEXT);
3802 	if (!zmem) {
3803 		goto finish;
3804 	}
3805 	zmem->alloc_size = allocSize;
3806 	result = (void *)&(zmem->data);
3807 finish:
3808 	return result;
3809 }
3810 
3811 void
z_free(void * notused __unused,void * ptr)3812 z_free(void * notused __unused, void * ptr)
3813 {
3814 	uint32_t * skipper = (uint32_t *)ptr - 1;
3815 	z_mem    * zmem = (z_mem *)skipper;
3816 	kfree_data(zmem, zmem->alloc_size);
3817 }
3818 };
3819 
3820 OSSharedPtr<OSData>
extractMkext2FileData(UInt8 * data,const char * name,uint32_t compressedSize,uint32_t fullSize)3821 OSKext::extractMkext2FileData(
3822 	UInt8      * data,
3823 	const char * name,
3824 	uint32_t     compressedSize,
3825 	uint32_t     fullSize)
3826 {
3827 	OSSharedPtr<OSData>      result;
3828 	OSSharedPtr<OSData>      uncompressedData;        // release on error
3829 
3830 	uint8_t     * uncompressedDataBuffer = NULL;        // do not free
3831 	unsigned long uncompressedSize;
3832 	z_stream      zstream;
3833 	bool          zstream_inited = false;
3834 	int           zlib_result;
3835 
3836 	/* If the file isn't compressed, we want to make a copy
3837 	 * so that we don't have the tie to the larger mkext file buffer any more.
3838 	 */
3839 	if (!compressedSize) {
3840 		uncompressedData = OSData::withBytes(data, fullSize);
3841 		// xxx - no check for failure?
3842 		result = uncompressedData;
3843 		goto finish;
3844 	}
3845 
3846 	if (KERN_SUCCESS != kmem_alloc(kernel_map,
3847 	    (vm_offset_t*)&uncompressedDataBuffer, fullSize,
3848 	    KMA_DATA_SHARED, VM_KERN_MEMORY_OSKEXT)) {
3849 		/* How's this for cheesy? The kernel is only asked to extract
3850 		 * kext plists so we tailor the log messages.
3851 		 */
3852 		if (isKernel()) {
3853 			OSKextLog(this,
3854 			    kOSKextLogErrorLevel |
3855 			    kOSKextLogArchiveFlag,
3856 			    "Allocation failure extracting %s from mkext.", name);
3857 		} else {
3858 			OSKextLog(this,
3859 			    kOSKextLogErrorLevel |
3860 			    kOSKextLogArchiveFlag,
3861 			    "Allocation failure extracting %s from mkext for kext %s.",
3862 			    name, getIdentifierCString());
3863 		}
3864 
3865 		goto finish;
3866 	}
3867 	uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
3868 	if (!uncompressedData) {
3869 		if (isKernel()) {
3870 			OSKextLog(this,
3871 			    kOSKextLogErrorLevel |
3872 			    kOSKextLogArchiveFlag,
3873 			    "Allocation failure extracting %s from mkext.", name);
3874 		} else {
3875 			OSKextLog(this,
3876 			    kOSKextLogErrorLevel |
3877 			    kOSKextLogArchiveFlag,
3878 			    "Allocation failure extracting %s from mkext for kext %s.",
3879 			    name, getIdentifierCString());
3880 		}
3881 		goto finish;
3882 	}
3883 	uncompressedData->setDeallocFunction(&osdata_kmem_free);
3884 
3885 	if (isKernel()) {
3886 		OSKextLog(this,
3887 		    kOSKextLogDetailLevel |
3888 		    kOSKextLogArchiveFlag,
3889 		    "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3890 		    name, compressedSize, fullSize);
3891 	} else {
3892 		OSKextLog(this,
3893 		    kOSKextLogDetailLevel |
3894 		    kOSKextLogArchiveFlag,
3895 		    "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3896 		    getIdentifierCString(), name, compressedSize, fullSize);
3897 	}
3898 
3899 	bzero(&zstream, sizeof(zstream));
3900 	zstream.next_in   = (UInt8 *)data;
3901 	zstream.avail_in  = compressedSize;
3902 
3903 	zstream.next_out  = uncompressedDataBuffer;
3904 	zstream.avail_out = fullSize;
3905 
3906 	zstream.zalloc    = z_alloc;
3907 	zstream.zfree     = z_free;
3908 
3909 	zlib_result = inflateInit(&zstream);
3910 	if (Z_OK != zlib_result) {
3911 		if (isKernel()) {
3912 			OSKextLog(this,
3913 			    kOSKextLogErrorLevel |
3914 			    kOSKextLogArchiveFlag,
3915 			    "Mkext error; zlib inflateInit failed (%d) for %s.",
3916 			    zlib_result, name);
3917 		} else {
3918 			OSKextLog(this,
3919 			    kOSKextLogErrorLevel |
3920 			    kOSKextLogArchiveFlag,
3921 			    "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3922 			    getIdentifierCString(), zlib_result, name);
3923 		}
3924 		goto finish;
3925 	} else {
3926 		zstream_inited = true;
3927 	}
3928 
3929 	zlib_result = inflate(&zstream, Z_FINISH);
3930 
3931 	if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
3932 		uncompressedSize = zstream.total_out;
3933 	} else {
3934 		if (isKernel()) {
3935 			OSKextLog(this,
3936 			    kOSKextLogErrorLevel |
3937 			    kOSKextLogArchiveFlag,
3938 			    "Mkext error; zlib inflate failed (%d) for %s.",
3939 			    zlib_result, name);
3940 		} else {
3941 			OSKextLog(this,
3942 			    kOSKextLogErrorLevel |
3943 			    kOSKextLogArchiveFlag,
3944 			    "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3945 			    getIdentifierCString(), zlib_result, name);
3946 		}
3947 		if (zstream.msg) {
3948 			OSKextLog(this,
3949 			    kOSKextLogErrorLevel |
3950 			    kOSKextLogArchiveFlag,
3951 			    "zlib error: %s.", zstream.msg);
3952 		}
3953 		goto finish;
3954 	}
3955 
3956 	if (uncompressedSize != fullSize) {
3957 		if (isKernel()) {
3958 			OSKextLog(this,
3959 			    kOSKextLogErrorLevel |
3960 			    kOSKextLogArchiveFlag,
3961 			    "Mkext error; zlib inflate discrepancy for %s, "
3962 			    "uncompressed size != original size.", name);
3963 		} else {
3964 			OSKextLog(this,
3965 			    kOSKextLogErrorLevel |
3966 			    kOSKextLogArchiveFlag,
3967 			    "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3968 			    "uncompressed size != original size.",
3969 			    getIdentifierCString(), name);
3970 		}
3971 		goto finish;
3972 	}
3973 
3974 	result = os::move(uncompressedData);
3975 
3976 finish:
3977 	/* Don't bother checking return, nothing we can do on fail.
3978 	 */
3979 	if (zstream_inited) {
3980 		inflateEnd(&zstream);
3981 	}
3982 
3983 	return result;
3984 }
3985 
3986 /*********************************************************************
3987 *********************************************************************/
3988 /* static */
3989 OSReturn
loadFromMkext(OSKextLogSpec clientLogFilter,char * mkextBuffer,uint32_t mkextBufferLength,char ** logInfoOut,uint32_t * logInfoLengthOut)3990 OSKext::loadFromMkext(
3991 	OSKextLogSpec   clientLogFilter,
3992 	char          * mkextBuffer,
3993 	uint32_t        mkextBufferLength,
3994 	char         ** logInfoOut,
3995 	uint32_t      * logInfoLengthOut)
3996 {
3997 	OSReturn         result                      = kOSReturnError;
3998 	OSReturn         tempResult                  = kOSReturnError;
3999 
4000 	OSSharedPtr<OSData>        mkextData;
4001 	OSSharedPtr<OSDictionary>  mkextPlist;
4002 
4003 	OSSharedPtr<OSArray>       logInfoArray;
4004 	OSSharedPtr<OSSerialize>   serializer;
4005 
4006 	OSString       * predicate                   = NULL;        // do not release
4007 	OSDictionary   * requestArgs                 = NULL;        // do not release
4008 
4009 	OSString       * kextIdentifier              = NULL;        // do not release
4010 	OSNumber       * startKextExcludeNum         = NULL;        // do not release
4011 	OSNumber       * startMatchingExcludeNum     = NULL;        // do not release
4012 	OSBoolean      * delayAutounloadBool         = NULL;        // do not release
4013 	OSArray        * personalityNames            = NULL;        // do not release
4014 
4015 	/* Default values for these two options: regular autounload behavior,
4016 	 * load all kexts, send no personalities.
4017 	 */
4018 	Boolean            delayAutounload           = false;
4019 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
4020 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
4021 
4022 	IORecursiveLockLock(sKextLock);
4023 
4024 	if (logInfoOut) {
4025 		*logInfoOut = NULL;
4026 		*logInfoLengthOut = 0;
4027 	}
4028 
4029 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
4030 
4031 	OSKextLog(/* kext */ NULL,
4032 	    kOSKextLogDebugLevel |
4033 	    kOSKextLogIPCFlag,
4034 	    "Received kext load request from user space.");
4035 
4036 	/* Regardless of processing, the fact that we have gotten here means some
4037 	 * user-space program is up and talking to us, so we'll switch our kext
4038 	 * registration to reflect that.
4039 	 */
4040 	if (!sUserLoadsActive) {
4041 		OSKextLog(/* kext */ NULL,
4042 		    kOSKextLogProgressLevel |
4043 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
4044 		    "Switching to late startup (user-space) kext loading policy.");
4045 
4046 		sUserLoadsActive = true;
4047 	}
4048 
4049 	if (!sLoadEnabled) {
4050 		OSKextLog(/* kext */ NULL,
4051 		    kOSKextLogErrorLevel |
4052 		    kOSKextLogLoadFlag,
4053 		    "Kext loading is disabled.");
4054 		result = kOSKextReturnDisabled;
4055 		goto finish;
4056 	}
4057 
4058 	/* Note that we do not set a dealloc function on this OSData
4059 	 * object! No references to it can remain after the loadFromMkext()
4060 	 * call since we are in a MIG function, and will vm_deallocate()
4061 	 * the buffer.
4062 	 */
4063 	mkextData = OSData::withBytesNoCopy(mkextBuffer,
4064 	    mkextBufferLength);
4065 	if (!mkextData) {
4066 		OSKextLog(/* kext */ NULL,
4067 		    kOSKextLogErrorLevel |
4068 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
4069 		    "Failed to create wrapper for kext load request.");
4070 		result = kOSKextReturnNoMemory;
4071 		goto finish;
4072 	}
4073 
4074 	result = readMkext2Archive(mkextData.get(), mkextPlist, NULL);
4075 	if (result != kOSReturnSuccess) {
4076 		OSKextLog(/* kext */ NULL,
4077 		    kOSKextLogErrorLevel |
4078 		    kOSKextLogLoadFlag,
4079 		    "Failed to read kext load request.");
4080 		goto finish;
4081 	}
4082 
4083 	predicate = _OSKextGetRequestPredicate(mkextPlist.get());
4084 	if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
4085 		OSKextLog(/* kext */ NULL,
4086 		    kOSKextLogErrorLevel |
4087 		    kOSKextLogLoadFlag,
4088 		    "Received kext load request with no predicate; skipping.");
4089 		result = kOSKextReturnInvalidArgument;
4090 		goto finish;
4091 	}
4092 
4093 	requestArgs = OSDynamicCast(OSDictionary,
4094 	    mkextPlist->getObject(kKextRequestArgumentsKey));
4095 	if (!requestArgs || !requestArgs->getCount()) {
4096 		OSKextLog(/* kext */ NULL,
4097 		    kOSKextLogErrorLevel |
4098 		    kOSKextLogLoadFlag,
4099 		    "Received kext load request with no arguments.");
4100 		result = kOSKextReturnInvalidArgument;
4101 		goto finish;
4102 	}
4103 
4104 	kextIdentifier = OSDynamicCast(OSString,
4105 	    requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
4106 
4107 	if (!kextIdentifier) {
4108 		OSKextLog(/* kext */ NULL,
4109 		    kOSKextLogErrorLevel |
4110 		    kOSKextLogLoadFlag,
4111 		    "Received kext load request with no kext identifier.");
4112 		result = kOSKextReturnInvalidArgument;
4113 		goto finish;
4114 	}
4115 
4116 	startKextExcludeNum = OSDynamicCast(OSNumber,
4117 	    requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
4118 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
4119 	    requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
4120 	delayAutounloadBool = OSDynamicCast(OSBoolean,
4121 	    requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
4122 	personalityNames = OSDynamicCast(OSArray,
4123 	    requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
4124 
4125 	if (delayAutounloadBool) {
4126 		delayAutounload = delayAutounloadBool->getValue();
4127 	}
4128 	if (startKextExcludeNum) {
4129 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
4130 	}
4131 	if (startMatchingExcludeNum) {
4132 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
4133 	}
4134 
4135 	OSKextLog(/* kext */ NULL,
4136 	    kOSKextLogProgressLevel |
4137 	    kOSKextLogIPCFlag,
4138 	    "Received request from user space to load kext %s.",
4139 	    kextIdentifier->getCStringNoCopy());
4140 
4141 	/* Load the kext, with no deferral, since this is a load from outside
4142 	 * the kernel.
4143 	 * xxx - Would like a better way to handle the default values for the
4144 	 * xxx - start/match opt args.
4145 	 */
4146 	result = OSKext::loadKextWithIdentifier(
4147 		kextIdentifier,
4148 		/* kextRef */ NULL,
4149 		/* allowDefer */ false,
4150 		delayAutounload,
4151 		startKextExcludeLevel,
4152 		startMatchingExcludeLevel,
4153 		personalityNames);
4154 	if (result != kOSReturnSuccess) {
4155 		goto finish;
4156 	}
4157 	/* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue
4158 	 * for matching via a separate IOKit calldown.
4159 	 */
4160 
4161 finish:
4162 
4163 	/* Gather up the collected log messages for user space. Any
4164 	 * error messages past this call will not make it up as log messages
4165 	 * but will be in the system log.
4166 	 */
4167 	logInfoArray = OSKext::clearUserSpaceLogFilter();
4168 
4169 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
4170 		tempResult = OSKext::serializeLogInfo(logInfoArray.get(),
4171 		    logInfoOut, logInfoLengthOut);
4172 		if (tempResult != kOSReturnSuccess) {
4173 			result = tempResult;
4174 		}
4175 	}
4176 
4177 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
4178 
4179 	IORecursiveLockUnlock(sKextLock);
4180 
4181 	/* Note: mkextDataObject will have been retained by every kext w/an
4182 	 * executable in it. That should all have been flushed out at the
4183 	 * and of the load operation, but you never know....
4184 	 */
4185 	if (mkextData && mkextData->getRetainCount() > 1) {
4186 		OSKextLog(/* kext */ NULL,
4187 		    kOSKextLogErrorLevel |
4188 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
4189 		    "Kext load request buffer from user space still retained by a kext; "
4190 		    "probable memory leak.");
4191 	}
4192 
4193 	return result;
4194 }
4195 
4196 #endif // CONFIG_KXLD
4197 
4198 /*********************************************************************
4199 *********************************************************************/
4200 /* static */
4201 OSReturn
serializeLogInfo(OSArray * logInfoArray,char ** logInfoOut,uint32_t * logInfoLengthOut)4202 OSKext::serializeLogInfo(
4203 	OSArray   * logInfoArray,
4204 	char     ** logInfoOut,
4205 	uint32_t  * logInfoLengthOut)
4206 {
4207 	OSReturn        result      = kOSReturnError;
4208 	char          * buffer      = NULL;
4209 	kern_return_t   kmem_result = KERN_FAILURE;
4210 	OSSharedPtr<OSSerialize>  serializer;
4211 	char         * logInfo            = NULL;        // returned by reference
4212 	uint32_t       logInfoLength      = 0;
4213 
4214 	if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
4215 		OSKextLog(/* kext */ NULL,
4216 		    kOSKextLogErrorLevel |
4217 		    kOSKextLogIPCFlag,
4218 		    "Internal error; invalid arguments to OSKext::serializeLogInfo().");
4219 		/* Bad programmer. */
4220 		result = kOSKextReturnInvalidArgument;
4221 		goto finish;
4222 	}
4223 
4224 	serializer = OSSerialize::withCapacity(0);
4225 	if (!serializer) {
4226 		OSKextLog(/* kext */ NULL,
4227 		    kOSKextLogErrorLevel |
4228 		    kOSKextLogIPCFlag,
4229 		    "Failed to create serializer on log info for request from user space.");
4230 		/* Incidental error; we're going to (try to) allow the request
4231 		 * itself to succeed. */
4232 	} else {
4233 		if (!logInfoArray->serialize(serializer.get())) {
4234 			OSKextLog(/* kext */ NULL,
4235 			    kOSKextLogErrorLevel |
4236 			    kOSKextLogIPCFlag,
4237 			    "Failed to serialize log info for request from user space.");
4238 			/* Incidental error; we're going to (try to) allow the request
4239 			 * itself to succeed. */
4240 		} else {
4241 			logInfo = serializer->text();
4242 			logInfoLength = serializer->getLength();
4243 
4244 			kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength),
4245 			    KMA_DATA_SHARED, VM_KERN_MEMORY_OSKEXT);
4246 			if (kmem_result != KERN_SUCCESS) {
4247 				OSKextLog(/* kext */ NULL,
4248 				    kOSKextLogErrorLevel |
4249 				    kOSKextLogIPCFlag,
4250 				    "Failed to copy log info for request from user space.");
4251 				/* Incidental error; we're going to (try to) allow the request
4252 				 * to succeed. */
4253 			} else {
4254 				/* 11981737 - clear uninitialized data in last page */
4255 				bzero((void *)(buffer + logInfoLength),
4256 				    (round_page(logInfoLength) - logInfoLength));
4257 				memcpy(buffer, logInfo, logInfoLength);
4258 				*logInfoOut = buffer;
4259 				*logInfoLengthOut = logInfoLength;
4260 			}
4261 		}
4262 	}
4263 
4264 	result = kOSReturnSuccess;
4265 finish:
4266 	return result;
4267 }
4268 
4269 #if PRAGMA_MARK
4270 #pragma mark Instance Management Methods
4271 #endif
4272 /*********************************************************************
4273 *********************************************************************/
4274 OSSharedPtr<OSKext>
lookupKextWithIdentifier(const char * kextIdentifier)4275 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
4276 {
4277 	OSSharedPtr<OSKext> foundKext;
4278 
4279 	IORecursiveLockLock(sKextLock);
4280 	foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain);
4281 	IORecursiveLockUnlock(sKextLock);
4282 
4283 	return foundKext;
4284 }
4285 
4286 /*********************************************************************
4287 *********************************************************************/
4288 OSSharedPtr<OSKext>
lookupKextWithIdentifier(OSString * kextIdentifier)4289 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
4290 {
4291 	return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
4292 }
4293 
4294 /*********************************************************************
4295 *********************************************************************/
4296 OSSharedPtr<OSKext>
lookupDextWithIdentifier(OSString * dextIdentifier,OSData * dextUniqueIdentifier)4297 OSKext::lookupDextWithIdentifier(OSString * dextIdentifier, OSData *dextUniqueIdentifier)
4298 {
4299 	OSSharedPtr<OSKext> foundDext;
4300 	foundDext.reset();
4301 
4302 	IORecursiveLockLock(sKextLock);
4303 	OSKext *dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIdentifier->getCStringNoCopy()));
4304 	if (dext != NULL && dext->isDriverKit()) {
4305 		if (dext->dextUniqueID == NULL || dext->dextUniqueID->isEqualTo(dextUniqueIdentifier)) {
4306 			foundDext.reset(dext, OSRetain);
4307 		}
4308 	}
4309 	IORecursiveLockUnlock(sKextLock);
4310 
4311 	return foundDext;
4312 }
4313 
4314 /*********************************************************************
4315 *********************************************************************/
4316 OSSharedPtr<OSKext>
lookupKextWithLoadTag(uint32_t aTag)4317 OSKext::lookupKextWithLoadTag(uint32_t aTag)
4318 {
4319 	OSSharedPtr<OSKext> foundKext;             // returned
4320 	uint32_t i, j;
4321 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4322 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4323 
4324 	IORecursiveLockLock(sKextLock);
4325 
4326 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4327 		for (i = 0; i < count[j]; i++) {
4328 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4329 			if (thisKext->getLoadTag() == aTag) {
4330 				foundKext.reset(thisKext, OSRetain);
4331 				goto finish;
4332 			}
4333 		}
4334 	}
4335 
4336 finish:
4337 	IORecursiveLockUnlock(sKextLock);
4338 
4339 	return foundKext;
4340 }
4341 
4342 /*********************************************************************
4343 *********************************************************************/
4344 OSSharedPtr<OSKext>
lookupKextWithAddress(vm_address_t address)4345 OSKext::lookupKextWithAddress(vm_address_t address)
4346 {
4347 	OSSharedPtr<OSKext> foundKext;             // returned
4348 	uint32_t count, i;
4349 	kmod_info_t *kmod_info;
4350 	vm_address_t originalAddress;
4351 #if defined(__arm64__)
4352 	uint64_t   textExecBase;
4353 	size_t     textExecSize;
4354 #endif /* defined(__arm64__) */
4355 
4356 	originalAddress = address;
4357 #if  __has_feature(ptrauth_calls)
4358 	address = (vm_address_t)VM_KERNEL_STRIP_PTR(address);
4359 #endif /*  __has_feature(ptrauth_calls) */
4360 
4361 	IORecursiveLockLock(sKextLock);
4362 
4363 	count = sLoadedKexts->getCount();
4364 	for (i = 0; i < count; i++) {
4365 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
4366 		if (thisKext == sKernelKext) {
4367 			continue;
4368 		}
4369 		if (thisKext->kmod_info && thisKext->kmod_info->address) {
4370 			kmod_info = thisKext->kmod_info;
4371 			vm_address_t kext_start = kmod_info->address;
4372 			vm_address_t kext_end = kext_start + kmod_info->size;
4373 			if ((kext_start <= address) && (address < kext_end)) {
4374 				foundKext.reset(thisKext, OSRetain);
4375 				goto finish;
4376 			}
4377 #if defined(__arm64__)
4378 			textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize);
4379 
4380 			/**
4381 			 * If the addresses within the Mach-O are unslid, then manually
4382 			 * slide any addresses coming from the Mach-O before usage.
4383 			 */
4384 			if (thisKext->flags.unslidMachO) {
4385 				textExecBase = (uintptr_t) ml_static_slide((vm_offset_t) textExecBase);
4386 			}
4387 
4388 			if ((textExecBase <= address) && (address < textExecBase + textExecSize)) {
4389 				foundKext.reset(thisKext, OSRetain);
4390 				goto finish;
4391 			}
4392 #endif /* defined (__arm64__) */
4393 		}
4394 	}
4395 	if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) {
4396 		foundKext.reset(sKernelKext, OSRetain);
4397 		goto finish;
4398 	}
4399 	/*
4400 	 * DriverKit userspace executables do not have a kernel linkedExecutable,
4401 	 * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address
4402 	 * here, so use the original address passed to this method.
4403 	 *
4404 	 * This is supposed to be used for logging reasons only. When logd
4405 	 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
4406 	 * remove it here before checking it against the LoadTag.
4407 	 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
4408 	 */
4409 
4410 	address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
4411 	count = sLoadedDriverKitKexts->getCount();
4412 	for (i = 0; i < count; i++) {
4413 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
4414 		if (thisKext->getLoadTag() == address) {
4415 			foundKext.reset(thisKext, OSRetain);
4416 		}
4417 	}
4418 
4419 finish:
4420 	IORecursiveLockUnlock(sKextLock);
4421 
4422 	return foundKext;
4423 }
4424 
4425 OSSharedPtr<OSData>
copyKextUUIDForAddress(OSNumber * address)4426 OSKext::copyKextUUIDForAddress(OSNumber *address)
4427 {
4428 	OSSharedPtr<OSData>   uuid;
4429 	OSSharedPtr<OSKext>   kext;
4430 
4431 	if (!address) {
4432 		return NULL;
4433 	}
4434 
4435 #if CONFIG_MACF
4436 	/* Is the calling process allowed to query kext info? */
4437 	if (current_task() != kernel_task) {
4438 		int macCheckResult = 0;
4439 		kauth_cred_t cred = NULL;
4440 
4441 		cred = kauth_cred_get_with_ref();
4442 		macCheckResult = mac_kext_check_query(cred);
4443 		kauth_cred_unref(&cred);
4444 
4445 		if (macCheckResult != 0) {
4446 			OSKextLog(/* kext */ NULL,
4447 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
4448 			    "Failed to query kext UUID (MAC policy error 0x%x).",
4449 			    macCheckResult);
4450 			return NULL;
4451 		}
4452 	}
4453 #endif
4454 
4455 	uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue());
4456 	if (slidAddress != 0) {
4457 		kext = lookupKextWithAddress(slidAddress);
4458 		if (kext) {
4459 			uuid = kext->copyTextUUID();
4460 		}
4461 	}
4462 
4463 	if (!uuid) {
4464 		/*
4465 		 * If we still don't have a UUID, then we failed to match the slid + stripped address with
4466 		 * a kext. This might have happened because the log message came from a dext.
4467 		 *
4468 		 * Try again with the original address.
4469 		 */
4470 		kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue());
4471 		if (kext && kext->isDriverKit()) {
4472 			uuid = kext->copyTextUUID();
4473 		}
4474 	}
4475 
4476 	return uuid;
4477 }
4478 
4479 /*********************************************************************
4480 *********************************************************************/
4481 OSSharedPtr<OSKext>
lookupKextWithUUID(uuid_t wanted)4482 OSKext::lookupKextWithUUID(uuid_t wanted)
4483 {
4484 	OSSharedPtr<OSKext> foundKext;             // returned
4485 	uint32_t j, i;
4486 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4487 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4488 
4489 
4490 	IORecursiveLockLock(sKextLock);
4491 
4492 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4493 		for (i = 0; i < count[j]; i++) {
4494 			OSKext   * thisKext     = NULL;
4495 
4496 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4497 			if (!thisKext) {
4498 				continue;
4499 			}
4500 
4501 			OSSharedPtr<OSData> uuid_data = thisKext->copyUUID();
4502 			if (!uuid_data) {
4503 				continue;
4504 			}
4505 
4506 			uuid_t uuid;
4507 			memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
4508 
4509 			if (0 == uuid_compare(wanted, uuid)) {
4510 				foundKext.reset(thisKext, OSRetain);
4511 				goto finish;
4512 			}
4513 		}
4514 	}
4515 finish:
4516 	IORecursiveLockUnlock(sKextLock);
4517 
4518 	return foundKext;
4519 }
4520 
4521 
4522 
4523 
4524 /*********************************************************************
4525 *********************************************************************/
4526 /* static */
4527 bool
isKextWithIdentifierLoaded(const char * kextIdentifier)4528 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
4529 {
4530 	bool result = false;
4531 	OSKext * foundKext = NULL;             // returned
4532 
4533 	IORecursiveLockLock(sKextLock);
4534 
4535 	foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4536 	if (foundKext && foundKext->isLoaded()) {
4537 		result = true;
4538 	}
4539 
4540 	IORecursiveLockUnlock(sKextLock);
4541 
4542 	return result;
4543 }
4544 
4545 /*********************************************************************
4546 * xxx - should spawn a separate thread so a kext can safely have
4547 * xxx - itself unloaded.
4548 *********************************************************************/
4549 /* static */
4550 OSReturn
removeKext(OSKext * aKext,__unused bool terminateServicesAndRemovePersonalitiesFlag)4551 OSKext::removeKext(
4552 	OSKext * aKext,
4553 #if CONFIG_EMBEDDED
4554 	__unused
4555 #endif
4556 	bool     terminateServicesAndRemovePersonalitiesFlag)
4557 {
4558 #if CONFIG_EMBEDDED
4559 	if (!aKext->isDriverKit()) {
4560 		OSKextLog(aKext,
4561 		    kOSKextLogErrorLevel |
4562 		    kOSKextLogKextBookkeepingFlag,
4563 		    "removeKext() called for %s, only supported on embedded for DriverKit dexts",
4564 		    aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
4565 
4566 		return kOSReturnSuccess;
4567 	}
4568 #endif /* CONFIG_EMBEDDED */
4569 	OSReturn result    = kOSKextReturnInUse;
4570 	OSKext * checkKext = NULL;         // do not release
4571 #if CONFIG_MACF
4572 	int macCheckResult = 0;
4573 	kauth_cred_t cred  = NULL;
4574 #endif
4575 
4576 	IORecursiveLockLock(sKextLock);
4577 
4578 	/* If the kext has no identifier, it failed to init
4579 	 * so isn't in sKextsByID and it isn't loaded.
4580 	 */
4581 	if (!aKext->getIdentifier()) {
4582 		result = kOSReturnSuccess;
4583 		goto finish;
4584 	}
4585 
4586 	checkKext = OSDynamicCast(OSKext,
4587 	    sKextsByID->getObject(aKext->getIdentifier()));
4588 	if (checkKext != aKext) {
4589 		result = kOSKextReturnNotFound;
4590 		goto finish;
4591 	}
4592 
4593 	if (aKext->isLoaded() || aKext->isDriverKit()) {
4594 #if CONFIG_MACF
4595 		if (current_task() != kernel_task) {
4596 			cred = kauth_cred_get_with_ref();
4597 			macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
4598 			kauth_cred_unref(&cred);
4599 		}
4600 
4601 		if (macCheckResult != 0) {
4602 			result = kOSReturnError;
4603 			OSKextLog(aKext,
4604 			    kOSKextLogErrorLevel |
4605 			    kOSKextLogKextBookkeepingFlag,
4606 			    "Failed to remove kext %s (MAC policy error 0x%x).",
4607 			    aKext->getIdentifierCString(), macCheckResult);
4608 			goto finish;
4609 		}
4610 #endif
4611 
4612 		/* make sure there are no resource requests in flight - 17187548 */
4613 		if (aKext->declaresExecutable() && aKext->countRequestCallbacks()) {
4614 			goto finish;
4615 		}
4616 		if (aKext->flags.unloadUnsupported) {
4617 			result = kOSKextReturnInUse;
4618 			OSKextLog(aKext,
4619 			    kOSKextLogErrorLevel |
4620 			    kOSKextLogKextBookkeepingFlag,
4621 			    "Can't remove kext %s; unsupported by cache.",
4622 			    aKext->getIdentifierCString());
4623 			goto finish;
4624 		}
4625 
4626 		/* If we are terminating, send the request to the IOCatalogue
4627 		 * (which will actually call us right back but that's ok we have
4628 		 * a recursive lock don't you know) but do not ask the IOCatalogue
4629 		 * to call back with an unload, we'll do that right here.
4630 		 */
4631 		if (terminateServicesAndRemovePersonalitiesFlag) {
4632 			result = gIOCatalogue->terminateDriversForModule(
4633 				aKext->getIdentifierCString(), /* unload */ false);
4634 			if (result != kOSReturnSuccess) {
4635 				OSKextLog(aKext,
4636 				    kOSKextLogErrorLevel |
4637 				    kOSKextLogKextBookkeepingFlag,
4638 				    "Can't remove kext %s; services failed to terminate - 0x%x.",
4639 				    aKext->getIdentifierCString(), result);
4640 				goto finish;
4641 			}
4642 		}
4643 
4644 		result = aKext->unload();
4645 		if (result != kOSReturnSuccess) {
4646 			OSKextLog(aKext,
4647 			    kOSKextLogErrorLevel |
4648 			    kOSKextLogKextBookkeepingFlag,
4649 			    "Can't remove kext %s; kext failed to unload - 0x%x.",
4650 			    aKext->getIdentifierCString(), result);
4651 			goto finish;
4652 		}
4653 	}
4654 
4655 	/* Remove personalities as requested. This is a bit redundant for a loaded
4656 	 * kext as IOCatalogue::terminateDriversForModule() removes driver
4657 	 * personalities, but it doesn't restart matching, which we always want
4658 	 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
4659 	 * that happens.
4660 	 */
4661 	if (terminateServicesAndRemovePersonalitiesFlag) {
4662 		aKext->removePersonalitiesFromCatalog();
4663 	}
4664 
4665 	if (aKext->isInFileset()) {
4666 		OSKextLog(aKext,
4667 		    kOSKextLogProgressLevel |
4668 		    kOSKextLogKextBookkeepingFlag,
4669 		    "Fileset kext %s unloaded.",
4670 		    aKext->getIdentifierCString());
4671 	} else {
4672 		OSKextLog(aKext,
4673 		    kOSKextLogProgressLevel |
4674 		    kOSKextLogKextBookkeepingFlag,
4675 		    "Removing kext %s.",
4676 		    aKext->getIdentifierCString());
4677 
4678 		sKextsByID->removeObject(aKext->getIdentifier());
4679 	}
4680 	result = kOSReturnSuccess;
4681 
4682 finish:
4683 	IORecursiveLockUnlock(sKextLock);
4684 	return result;
4685 }
4686 
4687 /*********************************************************************
4688 *********************************************************************/
4689 /* static */
4690 OSReturn
removeKextWithIdentifier(const char * kextIdentifier,bool terminateServicesAndRemovePersonalitiesFlag)4691 OSKext::removeKextWithIdentifier(
4692 	const char * kextIdentifier,
4693 	bool         terminateServicesAndRemovePersonalitiesFlag)
4694 {
4695 	OSReturn result = kOSReturnError;
4696 
4697 	IORecursiveLockLock(sKextLock);
4698 
4699 	OSKext * aKext = OSDynamicCast(OSKext,
4700 	    sKextsByID->getObject(kextIdentifier));
4701 	if (!aKext) {
4702 		result = kOSKextReturnNotFound;
4703 		OSKextLog(/* kext */ NULL,
4704 		    kOSKextLogErrorLevel |
4705 		    kOSKextLogKextBookkeepingFlag,
4706 		    "Can't remove kext %s - not found.",
4707 		    kextIdentifier);
4708 		goto finish;
4709 	}
4710 
4711 	result = OSKext::removeKext(aKext,
4712 	    terminateServicesAndRemovePersonalitiesFlag);
4713 
4714 finish:
4715 	IORecursiveLockUnlock(sKextLock);
4716 
4717 	return result;
4718 }
4719 
4720 /*********************************************************************
4721 *********************************************************************/
4722 /* static */
4723 OSReturn
removeKextWithLoadTag(OSKextLoadTag loadTag,bool terminateServicesAndRemovePersonalitiesFlag)4724 OSKext::removeKextWithLoadTag(
4725 	OSKextLoadTag loadTag,
4726 	bool          terminateServicesAndRemovePersonalitiesFlag)
4727 {
4728 	OSReturn result    = kOSReturnError;
4729 	OSKext * foundKext = NULL;
4730 	uint32_t i, j;
4731 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4732 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4733 
4734 
4735 	IORecursiveLockLock(sKextLock);
4736 
4737 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4738 		for (i = 0; i < count[j]; i++) {
4739 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4740 			if (thisKext->loadTag == loadTag) {
4741 				foundKext = thisKext;
4742 				break;
4743 			}
4744 		}
4745 	}
4746 
4747 	if (!foundKext) {
4748 		result = kOSKextReturnNotFound;
4749 		OSKextLog(/* kext */ NULL,
4750 		    kOSKextLogErrorLevel |
4751 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4752 		    "Can't remove kext with load tag %d - not found.",
4753 		    loadTag);
4754 		goto finish;
4755 	}
4756 
4757 	result = OSKext::removeKext(foundKext,
4758 	    terminateServicesAndRemovePersonalitiesFlag);
4759 
4760 finish:
4761 	IORecursiveLockUnlock(sKextLock);
4762 
4763 	return result;
4764 }
4765 
4766 /*********************************************************************
4767 *********************************************************************/
4768 OSSharedPtr<OSDictionary>
copyKexts(void)4769 OSKext::copyKexts(void)
4770 {
4771 	OSSharedPtr<OSDictionary> result;
4772 
4773 	IORecursiveLockLock(sKextLock);
4774 	result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection());
4775 	IORecursiveLockUnlock(sKextLock);
4776 
4777 	return result;
4778 }
4779 
4780 /*********************************************************************
4781 *********************************************************************/
4782 #define BOOTER_KEXT_PREFIX   "Driver-"
4783 
4784 typedef struct _DeviceTreeBuffer {
4785 	uint32_t paddr;
4786 	uint32_t length;
4787 } _DeviceTreeBuffer;
4788 
4789 /*********************************************************************
4790 * Create a dictionary of excluded kexts from the given booter data.
4791 *********************************************************************/
4792 /* static */
4793 void
createExcludeListFromBooterData(OSDictionary * theDictionary,OSCollectionIterator * theIterator)4794 OSKext::createExcludeListFromBooterData(
4795 	OSDictionary *          theDictionary,
4796 	OSCollectionIterator *  theIterator )
4797 {
4798 	OSString                  * deviceTreeName      = NULL;        // do not release
4799 	const _DeviceTreeBuffer   * deviceTreeBuffer    = NULL;        // do not release
4800 	char                      * booterDataPtr       = NULL;        // do not release
4801 	_BooterKextFileInfo       * kextFileInfo        = NULL;        // do not release
4802 	char                      * infoDictAddr        = NULL;        // do not release
4803 	OSSharedPtr<OSObject>       parsedXML;
4804 	OSDictionary              * theInfoDict         = NULL;        // do not release
4805 
4806 	theIterator->reset();
4807 
4808 	/* look for AppleKextExcludeList.kext */
4809 	while ((deviceTreeName =
4810 	    OSDynamicCast(OSString, theIterator->getNextObject()))) {
4811 		const char *    devTreeNameCString;
4812 		OSData *        deviceTreeEntry;        // do not release
4813 		OSString *      myBundleID;        // do not release
4814 
4815 		deviceTreeEntry =
4816 		    OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
4817 		if (!deviceTreeEntry) {
4818 			continue;
4819 		}
4820 
4821 		/* Make sure it is a kext */
4822 		devTreeNameCString = deviceTreeName->getCStringNoCopy();
4823 		if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
4824 		    (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
4825 			OSKextLog(NULL,
4826 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4827 			    "\"%s\" not a kext",
4828 			    devTreeNameCString);
4829 			continue;
4830 		}
4831 
4832 		deviceTreeBuffer = (const _DeviceTreeBuffer *)
4833 		    deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
4834 		if (!deviceTreeBuffer) {
4835 			continue;
4836 		}
4837 
4838 		booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
4839 		if (!booterDataPtr) {
4840 			continue;
4841 		}
4842 
4843 		kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
4844 		if (!kextFileInfo->infoDictPhysAddr ||
4845 		    !kextFileInfo->infoDictLength) {
4846 			continue;
4847 		}
4848 
4849 		infoDictAddr = (char *)
4850 		    ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
4851 		if (!infoDictAddr) {
4852 			continue;
4853 		}
4854 
4855 		parsedXML = OSUnserializeXML(infoDictAddr);
4856 		if (!parsedXML) {
4857 			continue;
4858 		}
4859 
4860 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
4861 		if (!theInfoDict) {
4862 			continue;
4863 		}
4864 
4865 		myBundleID =
4866 		    OSDynamicCast(OSString,
4867 		    theInfoDict->getObject(kCFBundleIdentifierKey));
4868 		if (myBundleID &&
4869 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4870 			boolean_t updated = updateExcludeList(theInfoDict);
4871 			if (!updated) {
4872 				/* 25322874 */
4873 				panic("Missing OSKextExcludeList dictionary");
4874 			}
4875 			break;
4876 		}
4877 	}         // while ( (deviceTreeName = ...) )
4878 
4879 	return;
4880 }
4881 
4882 /*********************************************************************
4883 * Create a dictionary of excluded kexts from the given prelink
4884 * info (kernelcache).
4885 *********************************************************************/
4886 /* static */
4887 void
createExcludeListFromPrelinkInfo(OSArray * theInfoArray)4888 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
4889 {
4890 	OSDictionary *  myInfoDict = NULL;        // do not release
4891 	OSString *      myBundleID;        // do not release
4892 	u_int           i;
4893 
4894 	/* Find the Apple Kext Exclude List. */
4895 	for (i = 0; i < theInfoArray->getCount(); i++) {
4896 		myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
4897 		if (!myInfoDict) {
4898 			continue;
4899 		}
4900 		myBundleID =
4901 		    OSDynamicCast(OSString,
4902 		    myInfoDict->getObject(kCFBundleIdentifierKey));
4903 		if (myBundleID &&
4904 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4905 			boolean_t updated = updateExcludeList(myInfoDict);
4906 			if (!updated) {
4907 				/* 25322874 */
4908 				panic("Missing OSKextExcludeList dictionary");
4909 			}
4910 			break;
4911 		}
4912 	}         // for (i = 0; i < theInfoArray->getCount()...
4913 
4914 	return;
4915 }
4916 
4917 /* static */
4918 boolean_t
updateExcludeList(OSDictionary * infoDict)4919 OSKext::updateExcludeList(OSDictionary *infoDict)
4920 {
4921 	OSDictionary *myTempDict = NULL;         // do not free
4922 	OSString     *myTempString = NULL;        // do not free
4923 	OSKextVersion newVersion = 0;
4924 	boolean_t updated = false;
4925 
4926 	if (!infoDict) {
4927 		return false;
4928 	}
4929 
4930 	myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
4931 	if (!myTempDict) {
4932 		return false;
4933 	}
4934 
4935 	myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
4936 	if (!myTempString) {
4937 		return false;
4938 	}
4939 
4940 	newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
4941 	if (newVersion == 0) {
4942 		return false;
4943 	}
4944 
4945 	IORecursiveLockLock(sKextLock);
4946 
4947 	if (newVersion > sExcludeListVersion) {
4948 		sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
4949 		sExcludeListVersion = newVersion;
4950 		updated = true;
4951 	}
4952 
4953 	IORecursiveLockUnlock(sKextLock);
4954 	return updated;
4955 }
4956 
4957 #if PRAGMA_MARK
4958 #pragma mark Accessors
4959 #endif
4960 
4961 /*********************************************************************
4962 *********************************************************************/
4963 const OSObject *
getBundleExecutable(void)4964 OSKext::getBundleExecutable(void)
4965 {
4966 	return infoDict->getObject(kCFBundleExecutableKey);
4967 }
4968 
4969 /*********************************************************************
4970 *********************************************************************/
4971 const OSSymbol *
getIdentifier(void)4972 OSKext::getIdentifier(void)
4973 {
4974 	return bundleID.get();
4975 }
4976 
4977 /*********************************************************************
4978 * A kext must have a bundle identifier to even survive initialization;
4979 * this is guaranteed to exist past then.
4980 *********************************************************************/
4981 const char *
getIdentifierCString(void)4982 OSKext::getIdentifierCString(void)
4983 {
4984 	return bundleID->getCStringNoCopy();
4985 }
4986 
4987 /*********************************************************************
4988 *********************************************************************/
4989 OSKextVersion
getVersion(void)4990 OSKext::getVersion(void)
4991 {
4992 	return version;
4993 }
4994 
4995 /*********************************************************************
4996 *********************************************************************/
4997 OSKextVersion
getCompatibleVersion(void)4998 OSKext::getCompatibleVersion(void)
4999 {
5000 	return compatibleVersion;
5001 }
5002 
5003 /*********************************************************************
5004 *********************************************************************/
5005 bool
isLibrary(void)5006 OSKext::isLibrary(void)
5007 {
5008 	return getCompatibleVersion() > 0;
5009 }
5010 
5011 /*********************************************************************
5012 *********************************************************************/
5013 bool
isCompatibleWithVersion(OSKextVersion aVersion)5014 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
5015 {
5016 	if ((compatibleVersion > -1 && version > -1) &&
5017 	    (compatibleVersion <= version && aVersion <= version)) {
5018 		return true;
5019 	}
5020 	return false;
5021 }
5022 
5023 /*********************************************************************
5024 *********************************************************************/
5025 bool
declaresExecutable(void)5026 OSKext::declaresExecutable(void)
5027 {
5028 	if (isDriverKit()) {
5029 		return false;
5030 	}
5031 	return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
5032 }
5033 
5034 /*********************************************************************
5035 *********************************************************************/
5036 OSData *
getExecutable(void)5037 OSKext::getExecutable(void)
5038 {
5039 	OSData * result              = NULL;
5040 	OSSharedPtr<OSData> extractedExecutable;
5041 
5042 	if (flags.builtin) {
5043 		return sKernelKext->linkedExecutable.get();
5044 	}
5045 
5046 	result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
5047 	if (result) {
5048 		return result;
5049 	}
5050 
5051 #if CONFIG_KXLD
5052 	OSData * mkextExecutableRef  = NULL;        // do not release
5053 	mkextExecutableRef = OSDynamicCast(OSData,
5054 	    getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
5055 
5056 	if (mkextExecutableRef) {
5057 		MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
5058 		    mkextExecutableRef->getBytesNoCopy();
5059 		uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
5060 		if (mkextVersion == MKEXT_VERS_2) {
5061 			mkext2_file_entry * fileinfo =
5062 			    (mkext2_file_entry *)mkextEntryRef->fileinfo;
5063 			uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
5064 			uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
5065 			extractedExecutable = extractMkext2FileData(
5066 				MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
5067 				compressedSize, fullSize);
5068 		} else {
5069 			OSKextLog(this, kOSKextLogErrorLevel |
5070 			    kOSKextLogArchiveFlag,
5071 			    "Kext %s - unknown mkext version 0x%x for executable.",
5072 			    getIdentifierCString(), mkextVersion);
5073 		}
5074 
5075 		/* Regardless of success, remove the mkext executable,
5076 		 * and drop one reference on the mkext.  (setExecutable() does not
5077 		 * replace, it removes, or panics if asked to replace.)
5078 		 */
5079 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
5080 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
5081 
5082 		if (extractedExecutable && extractedExecutable->getLength()) {
5083 			if (!setExecutable(extractedExecutable.get())) {
5084 				goto finish;
5085 			}
5086 			result = extractedExecutable.get();
5087 		} else {
5088 			goto finish;
5089 		}
5090 	}
5091 
5092 finish:
5093 #endif // CONFIG_KXLD
5094 	return result;
5095 }
5096 
5097 /*********************************************************************
5098 *********************************************************************/
5099 bool
isInterface(void)5100 OSKext::isInterface(void)
5101 {
5102 	return flags.interface;
5103 }
5104 
5105 /*********************************************************************
5106 *********************************************************************/
5107 bool
isKernel(void)5108 OSKext::isKernel(void)
5109 {
5110 	return this == sKernelKext;
5111 }
5112 
5113 /*********************************************************************
5114 *********************************************************************/
5115 bool
isKernelComponent(void)5116 OSKext::isKernelComponent(void)
5117 {
5118 	return flags.kernelComponent ? true : false;
5119 }
5120 
5121 /*********************************************************************
5122 *********************************************************************/
5123 bool
isExecutable(void)5124 OSKext::isExecutable(void)
5125 {
5126 	return !isKernel() && !isInterface() && declaresExecutable();
5127 }
5128 
5129 /*********************************************************************
5130 *********************************************************************/
5131 bool
isSpecialKernelBinary(void)5132 OSKext::isSpecialKernelBinary(void)
5133 {
5134 #if CONFIG_SPTM
5135 	return (this->kmod_info) &&
5136 	       ((this->kmod_info->id == kOSKextSPTMLoadTag) ||
5137 	       (this->kmod_info->id == kOSKextTXMLoadTag));
5138 #else
5139 	return false;
5140 #endif
5141 }
5142 
5143 /*********************************************************************
5144 * We might want to check this recursively for all dependencies,
5145 * since a subtree of dependencies could get loaded before we hit
5146 * a dependency that isn't safe-boot-loadable.
5147 *
5148 * xxx - Might want to return false if OSBundleEnableKextLogging or
5149 * OSBundleDebugLevel
5150 * or IOKitDebug is nonzero too (we used to do that, but I don't see
5151 * the point except it's usually development drivers, which might
5152 * cause panics on startup, that have those properties). Heh; could
5153 * use a "kx" boot-arg!
5154 *********************************************************************/
5155 bool
isLoadableInSafeBoot(void)5156 OSKext::isLoadableInSafeBoot(void)
5157 {
5158 	bool       result   = false;
5159 	OSString * required = NULL;         // do not release
5160 
5161 	if (isKernel()) {
5162 		result = true;
5163 		goto finish;
5164 	}
5165 
5166 	if (isDriverKit()) {
5167 		result = true;
5168 		goto finish;
5169 	}
5170 
5171 	required = OSDynamicCast(OSString,
5172 	    getPropertyForHostArch(kOSBundleRequiredKey));
5173 	if (!required) {
5174 		goto finish;
5175 	}
5176 	if (required->isEqualTo(kOSBundleRequiredRoot) ||
5177 	    required->isEqualTo(kOSBundleRequiredLocalRoot) ||
5178 	    required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
5179 	    required->isEqualTo(kOSBundleRequiredSafeBoot) ||
5180 	    required->isEqualTo(kOSBundleRequiredConsole)) {
5181 		result = true;
5182 	}
5183 
5184 finish:
5185 	return result;
5186 }
5187 
5188 /*********************************************************************
5189 *********************************************************************/
5190 bool
isPrelinked(void)5191 OSKext::isPrelinked(void)
5192 {
5193 	return flags.prelinked ? true : false;
5194 }
5195 
5196 /*********************************************************************
5197 *********************************************************************/
5198 bool
isLoaded(void)5199 OSKext::isLoaded(void)
5200 {
5201 	return flags.loaded ? true : false;
5202 }
5203 
5204 /*********************************************************************
5205 *********************************************************************/
5206 bool
isStarted(void)5207 OSKext::isStarted(void)
5208 {
5209 	return flags.started ? true : false;
5210 }
5211 
5212 /*********************************************************************
5213 *********************************************************************/
5214 bool
isCPPInitialized(void)5215 OSKext::isCPPInitialized(void)
5216 {
5217 	return flags.CPPInitialized;
5218 }
5219 
5220 /*********************************************************************
5221 *********************************************************************/
5222 void
setCPPInitialized(bool initialized)5223 OSKext::setCPPInitialized(bool initialized)
5224 {
5225 	flags.CPPInitialized = initialized;
5226 }
5227 
5228 /*********************************************************************
5229 *********************************************************************/
5230 uint32_t
getLoadTag(void)5231 OSKext::getLoadTag(void)
5232 {
5233 	return loadTag;
5234 }
5235 
5236 /*********************************************************************
5237 *********************************************************************/
5238 void
getSizeInfo(uint32_t * loadSize,uint32_t * wiredSize)5239 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
5240 {
5241 	if (linkedExecutable) {
5242 		*loadSize = linkedExecutable->getLength();
5243 
5244 		/* If we have a kmod_info struct, calculated the wired size
5245 		 * from that. Otherwise it's the full load size.
5246 		 */
5247 		if (kmod_info) {
5248 			*wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size;
5249 		} else {
5250 			*wiredSize = *loadSize;
5251 		}
5252 	} else {
5253 		*wiredSize = 0;
5254 		*loadSize = 0;
5255 	}
5256 }
5257 
5258 /*********************************************************************
5259 *********************************************************************/
5260 OSSharedPtr<OSData>
copyUUID(void)5261 OSKext::copyUUID(void)
5262 {
5263 	OSSharedPtr<OSData>          result;
5264 	OSData                     * theExecutable = NULL;        // do not release
5265 	const kernel_mach_header_t * header;
5266 
5267 	/* An interface kext doesn't have a linked executable with an LC_UUID,
5268 	 * we create one when it's linked.
5269 	 */
5270 	if (interfaceUUID) {
5271 		result = interfaceUUID;
5272 		goto finish;
5273 	}
5274 
5275 	if (flags.builtin || isInterface()) {
5276 		return sKernelKext->copyUUID();
5277 	}
5278 
5279 	if (isDriverKit() && infoDict) {
5280 		return driverKitUUID;
5281 	}
5282 
5283 	/* For real kexts, try to get the UUID from the linked executable,
5284 	 * or if is hasn't been linked yet, the unrelocated executable.
5285 	 */
5286 	theExecutable = linkedExecutable.get();
5287 	if (!theExecutable) {
5288 		theExecutable = getExecutable();
5289 	}
5290 
5291 	if (!theExecutable) {
5292 		goto finish;
5293 	}
5294 
5295 	header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
5296 	result = copyMachoUUID(header);
5297 
5298 finish:
5299 	return result;
5300 }
5301 
5302 /*********************************************************************
5303 *********************************************************************/
5304 OSSharedPtr<OSData>
copyTextUUID(void)5305 OSKext::copyTextUUID(void)
5306 {
5307 	if (flags.builtin) {
5308 		return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
5309 	}
5310 	return copyUUID();
5311 }
5312 
5313 /*********************************************************************
5314 *********************************************************************/
5315 OSSharedPtr<OSData>
copyMachoUUID(const kernel_mach_header_t * header)5316 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
5317 {
5318 	OSSharedPtr<OSData>                     result;
5319 	const struct load_command  * load_cmd      = NULL;
5320 	const struct uuid_command  * uuid_cmd      = NULL;
5321 	uint32_t                     i;
5322 
5323 	load_cmd = (const struct load_command *)&header[1];
5324 
5325 	if (header->magic != MH_MAGIC_KERNEL) {
5326 		OSKextLog(NULL,
5327 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
5328 		    "%s: bad header %p",
5329 		    __func__,
5330 		    header);
5331 		goto finish;
5332 	}
5333 
5334 	for (i = 0; i < header->ncmds; i++) {
5335 		if (load_cmd->cmd == LC_UUID) {
5336 			uuid_cmd = (struct uuid_command *)load_cmd;
5337 			result = OSData::withValue(uuid_cmd->uuid);
5338 			goto finish;
5339 		}
5340 		load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
5341 	}
5342 
5343 finish:
5344 	return result;
5345 }
5346 
5347 void
setDriverKitUUID(OSData * uuid)5348 OSKext::setDriverKitUUID(OSData *uuid)
5349 {
5350 	if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
5351 		OSSafeReleaseNULL(uuid);
5352 	}
5353 }
5354 
5355 OSData *
getDextUniqueID(void)5356 OSKext::getDextUniqueID(void)
5357 {
5358 	if (isDriverKit() && dextUniqueID != NULL) {
5359 		return dextUniqueID.get();
5360 	}
5361 
5362 	return NULL;
5363 }
5364 
5365 /*
5366  * In case a DextUniqueID exists this function returns
5367  * an allocated char* with the hexadecimal represantition of
5368  * DextUniqueID.
5369  * The returned pinter needs to be freed with kfree_data, the
5370  * size of the allocated buffer is returned in size.
5371  */
5372 static const char *
getDextUniqueIDCString(OSData * dextUniqueID,unsigned int * size)5373 getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size)
5374 {
5375 	if (dextUniqueID != NULL) {
5376 		char *s_buffer = NULL;
5377 		unsigned int d_length = dextUniqueID->getLength();
5378 		/*
5379 		 * We are converting in hex, so for every byte we will have
5380 		 * 2 hex chars and one last \0.
5381 		 */
5382 		unsigned int s_length = d_length * 2 + 1;
5383 		s_buffer = (char *) kalloc_data(s_length, Z_WAITOK_ZERO);
5384 
5385 		char *uid = (char*) dextUniqueID->getBytesNoCopy();
5386 		int cpos = 0;
5387 		for (unsigned int i = 0; i < d_length && cpos < (s_length - 1); i++) {
5388 			int ret = snprintf(s_buffer + cpos, s_length - cpos - 1, "%02X", uid[i]);
5389 			if (ret <= 0) {
5390 				break;
5391 			}
5392 			cpos += ret;
5393 		}
5394 		*size = s_length;
5395 
5396 		return s_buffer;
5397 	}
5398 
5399 	return NULL;
5400 }
5401 
5402 /*
5403  * Atomically swaps the olddext with newdext.
5404  * olddext will be unloaded, so it might be freed
5405  * after this call unless it was previously retained.
5406  *
5407  * If newdext is NULL, this unloads olddext and does not perform an upgrade
5408  */
5409 void
replaceDextInternal(OSKext * olddext,OSKext * newdext)5410 OSKext::replaceDextInternal(OSKext *olddext, OSKext *newdext)
5411 {
5412 	OSReturn result;
5413 	const OSSymbol * dextID = olddext->getIdentifier();
5414 	OSData * oldDextUniqueIdentifier = olddext->getDextUniqueID();
5415 	OSSharedPtr<OSArray> new_personalities;
5416 	OSSharedPtr<OSString> kextIdentifier;
5417 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5418 	assert(lock_held);
5419 
5420 	// The old dext will be unloaded and release dextID, so we need to retain dextID here
5421 	dextID->retain();
5422 
5423 	if (newdext != NULL) {
5424 		__assert_only bool eq = dextID->isEqualTo(newdext->getIdentifier());
5425 		assert(eq);
5426 	}
5427 
5428 	if (newdext != NULL) {
5429 		/*
5430 		 * Swap the catalog personalities.
5431 		 */
5432 		new_personalities = newdext->copyPersonalitiesArray();
5433 		olddext->updatePersonalitiesInCatalog(new_personalities.get());
5434 	}
5435 
5436 	if (NULL != oldDextUniqueIdentifier) {
5437 		oldDextUniqueIdentifier->retain();
5438 	}
5439 
5440 	/*
5441 	 * Unload the dext.
5442 	 */
5443 	result = olddext->unload();
5444 	if (result != kOSReturnSuccess) {
5445 		OSKextLog(NULL,
5446 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5447 		    "Cannot unload dext for upgrade %s: %d\n",
5448 		    dextID->getCStringNoCopy(), result);
5449 	}
5450 
5451 	if (newdext != NULL) {
5452 		/*
5453 		 * Swap the dexts on the OSKext dictionary.
5454 		 * This might free the dext.
5455 		 */
5456 		sKextsByID->setObject(dextID, newdext);
5457 	} else {
5458 		/*
5459 		 * Remove the old dext
5460 		 */
5461 		removeKext(olddext, true);
5462 	}
5463 
5464 	/*
5465 	 * Inform userspace.
5466 	 */
5467 	if (newdext != NULL) {
5468 		result = notifyDextUpgrade(OSDynamicCast(OSString, dextID), newdext->getDextUniqueID());
5469 		if (result != kOSReturnSuccess) {
5470 			OSKextLog(NULL,
5471 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5472 			    "Cannot send upgrade notification for %s\n",
5473 			    dextID->getCStringNoCopy());
5474 		}
5475 	} else {
5476 		// notify dext removal
5477 		queueKextNotification(kKextRequestPredicateUnloadNotification,
5478 		    OSDynamicCast(OSString, dextID), oldDextUniqueIdentifier);
5479 	}
5480 
5481 	OSSafeReleaseNULL(dextID);
5482 	OSSafeReleaseNULL(oldDextUniqueIdentifier);
5483 }
5484 
5485 /*
5486  * To be called with sKextLock held.
5487  * NOTE: this could unload the olddext.
5488  */
5489 bool
upgradeDext(OSKext * olddext,OSKext * newdext)5490 OSKext::upgradeDext(OSKext *olddext, OSKext *newdext)
5491 {
5492 	const char * dextIDCS = newdext->getIdentifierCString();
5493 	__assert_only bool old_isDext = olddext->isDriverKit();
5494 	__assert_only bool new_isDext = newdext->isDriverKit();
5495 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5496 
5497 	assert(old_isDext && new_isDext);
5498 	assert(lock_held);
5499 
5500 	/*
5501 	 * New dext and old dext have the same ID.
5502 	 * We use this ID as key on the OSKext
5503 	 * dictionarys/arrays.
5504 	 */
5505 	const OSSymbol * dextID = newdext->getIdentifier();
5506 	__assert_only bool eq = dextID->isEqualTo(olddext->getIdentifier());
5507 	assert(eq);
5508 
5509 	/*
5510 	 * Set this OSKect as to update.
5511 	 * Note that this flags will never be removed once set.
5512 	 * When a OSKext is marked, it will be substitued by a new
5513 	 * OSKext, and every subsystem having a reference on this
5514 	 * OSKext need to know they have check if they can use
5515 	 * this OSKext or look for a new one.
5516 	 */
5517 	olddext->flags.dextToReplace = 1;
5518 
5519 	/*
5520 	 * Check if the current OSKext has any
5521 	 * userspace processes launched.
5522 	 * In this case we cannot upgrade and we have to
5523 	 * delay the upgrade until all processes
5524 	 * are done.
5525 	 */
5526 	if (olddext->dextLaunchedCount == 0) {
5527 		/*
5528 		 * Be sure that if there are no launched dexts, no
5529 		 * pending upgrades exist.
5530 		 * This is an error if it happens, as the decrement
5531 		 * should have removed the dext from sDriverKitToUpgradeByID
5532 		 * in case it reached 0.
5533 		 */
5534 		OSObject *pending_upgdare = sDriverKitToUpgradeByID->getObject(dextID);
5535 		if (pending_upgdare != NULL) {
5536 			OSKextLog(NULL,
5537 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5538 			    "Pending upgrade found for %s but dextLaunchedCount is 0!\n",
5539 			    dextIDCS);
5540 			goto out;
5541 		}
5542 
5543 		replaceDextInternal(olddext, newdext);
5544 		return true;
5545 	}
5546 
5547 out:
5548 
5549 	/*
5550 	 * Delay the upgrade.
5551 	 * Make the new dext available in sDriverKitToUpgradeByID.
5552 	 * In case there was already a pending upgrade, this will
5553 	 * overwrite it.
5554 	 */
5555 	sDriverKitToUpgradeByID->setObject(dextID, newdext);
5556 	return false;
5557 }
5558 
5559 /*
5560  * To be called with sKextLock held.
5561  * NOTE: this could unload the dext.
5562  */
5563 bool
removeDext(OSKext * dext)5564 OSKext::removeDext(OSKext *dext)
5565 {
5566 	__assert_only bool dext_isDext = dext->isDriverKit();
5567 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5568 	IOReturn result;
5569 
5570 	assert(dext_isDext);
5571 	assert(lock_held);
5572 
5573 	/*
5574 	 * Set this OSKext to be unloaded when all running instances exit.
5575 	 */
5576 	dext->flags.dextToReplace = 1;
5577 
5578 	result = gIOCatalogue->terminateDriversForModule(
5579 		dext->getIdentifierCString(), /* unload */ false, /* asynchronous */ true);
5580 	if (result != kOSReturnSuccess) {
5581 		OSKextLog(dext,
5582 		    kOSKextLogErrorLevel |
5583 		    kOSKextLogKextBookkeepingFlag,
5584 		    "%s services failed to terminate - 0x%x.",
5585 		    dext->getIdentifierCString(), result);
5586 	}
5587 
5588 	dext->removePersonalitiesFromCatalog();
5589 	sDriverKitToUpgradeByID->removeObject(dext->getIdentifier());
5590 
5591 	/*
5592 	 * Check if the current OSKext has any
5593 	 * userspace processes launched.
5594 	 * In this case we cannot unload and we have to
5595 	 * delay the unload until all processes
5596 	 * are done.
5597 	 */
5598 	if (dext->dextLaunchedCount == 0) {
5599 		replaceDextInternal(dext, NULL);
5600 		return true;
5601 	}
5602 
5603 	return false;
5604 }
5605 
5606 bool
incrementDextLaunchCount(OSKext * dext,OSData * dextUniqueIDToMatch)5607 OSKext::incrementDextLaunchCount(OSKext *dext, OSData *dextUniqueIDToMatch)
5608 {
5609 	bool ret = false;
5610 	__assert_only bool isDext = dext->isDriverKit();
5611 	assert(isDext);
5612 
5613 	const char * dextIDCS = dext->getIdentifierCString();
5614 	OSData *myDextUniqueID = dext->getDextUniqueID();
5615 
5616 	if (!myDextUniqueID || !dextUniqueIDToMatch) {
5617 		OSKextLog(dext,
5618 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5619 		    "Cannot find dext UniqueID for %s, cannot increment dext launches\n",
5620 		    dextIDCS);
5621 		return ret;
5622 	}
5623 
5624 	unsigned int dextUniqueIDCStringSize = 0, dextUniqueIDToMatchCStringSize = 0;
5625 	const char *dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
5626 	const char *dextUniqueIDToMatchCString = getDextUniqueIDCString(dextUniqueIDToMatch, &dextUniqueIDToMatchCStringSize);
5627 	assert(dextUniqueIDCString != NULL);
5628 	assert(dextUniqueIDToMatchCString != NULL);
5629 
5630 	IORecursiveLockLock(sKextLock);
5631 
5632 	/*
5633 	 * Check that the dext we are referencing is the same
5634 	 * looked for the match.
5635 	 */
5636 	if (myDextUniqueID->isEqualTo(dextUniqueIDToMatch)) {
5637 		if (dext->flags.dextToReplace == 0 || dext->dextLaunchedCount > 0) {
5638 			if (dext->dextLaunchedCount == kOSKextMaxDextLaunchedCount) {
5639 				OSKextLog(dext,
5640 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5641 				    "Too many dexts launched for %s UniqueID %s\n",
5642 				    dextIDCS, dextUniqueIDCString);
5643 			} else {
5644 				dext->dextLaunchedCount++;
5645 				ret = true;
5646 
5647 				OSKextLog(dext,
5648 				    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5649 				    "New dext launched for  %s UniqueID %s",
5650 				    dextIDCS, dextUniqueIDCString);
5651 			}
5652 		} else {
5653 			OSKextLog(dext,
5654 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5655 			    "Dext %s UniqueID %s requires update, cannot launch a new dext\n",
5656 			    dextIDCS, dextUniqueIDCString);
5657 		}
5658 	} else {
5659 		OSKextLog(dext,
5660 		    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5661 		    "Dext %s: UniqueID %s does not match UniqueID looked for %s, cannot launch a new dext\n",
5662 		    dextIDCS, dextUniqueIDCString, dextUniqueIDToMatchCString);
5663 	}
5664 
5665 	IORecursiveLockUnlock(sKextLock);
5666 
5667 	if (dextUniqueIDCString != NULL) {
5668 		kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
5669 	}
5670 	if (dextUniqueIDToMatchCString != NULL) {
5671 		kfree_data(dextUniqueIDToMatchCString, dextUniqueIDToMatchCStringSize);
5672 	}
5673 	return ret;
5674 }
5675 
5676 bool
decrementDextLaunchCount(OSString * bundleID)5677 OSKext::decrementDextLaunchCount(OSString *bundleID)
5678 {
5679 	bool ret = false;
5680 	const char * dextIDCS;
5681 	OSData *myDextUniqueID;
5682 	unsigned int dextUniqueIDCStringSize = 0;
5683 	const char * dextUniqueIDCString = NULL;
5684 	OSKext* dext = NULL;
5685 
5686 	if (!bundleID) {
5687 		return ret;
5688 	}
5689 	dextIDCS = bundleID->getCStringNoCopy();
5690 
5691 	IORecursiveLockLock(sKextLock);
5692 
5693 	/*
5694 	 * Look for the dext with the bundle it. This
5695 	 * call is triggered only if a previous increment was
5696 	 * performed. It means that the dext could have not
5697 	 * been upgraded as its dextLaunchedCount was at least 1.
5698 	 * Because of this it still needs to be available
5699 	 * in sKextsByID.
5700 	 */
5701 	dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIDCS));
5702 	if (!dext || !dext->isDriverKit()) {
5703 		OSKextLog(NULL,
5704 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5705 		    "Cannot find dext for %s, cannot decrement dext launches\n",
5706 		    dextIDCS);
5707 
5708 		goto out_locked;
5709 	}
5710 
5711 	myDextUniqueID = dext->getDextUniqueID();
5712 	if (!myDextUniqueID) {
5713 		OSKextLog(dext,
5714 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5715 		    "Cannot find dext UniqueID for %s, cannot decrement dext launches\n",
5716 		    dextIDCS);
5717 
5718 		goto out_locked;
5719 	}
5720 	dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
5721 	assert(dextUniqueIDCString != NULL);
5722 
5723 	if (dext->dextLaunchedCount == 0) {
5724 		OSKextLog(dext,
5725 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5726 		    "Over decrementing dext launch for %s UniqueID %s\n",
5727 		    dextIDCS, dextUniqueIDCString);
5728 
5729 		goto out_locked;
5730 	}
5731 
5732 	dext->dextLaunchedCount--;
5733 
5734 	OSKextLog(dext,
5735 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5736 	    "Dext terminated for %s UniqueID %s",
5737 	    dextIDCS, dextUniqueIDCString);
5738 
5739 	if (dext->dextLaunchedCount == 0 && dext->flags.dextToReplace == 1) {
5740 		/*
5741 		 * Find the upgraded dext.
5742 		 */
5743 		OSKext *newdext = OSDynamicCast(OSKext, sDriverKitToUpgradeByID->getObject(dextIDCS));
5744 		if (newdext) {
5745 			OSKextLog(dext,
5746 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5747 			    "Dext upgrade for %s UniqueID %s",
5748 			    dextIDCS, dextUniqueIDCString);
5749 			replaceDextInternal(dext, newdext);
5750 			/* NOTE dext could have been freed past this point */
5751 
5752 			sDriverKitToUpgradeByID->removeObject(dextIDCS);
5753 		} else {
5754 			OSKextLog(dext,
5755 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5756 			    "Dext unload for %s UniqueID %s",
5757 			    dextIDCS, dextUniqueIDCString);
5758 			replaceDextInternal(dext, NULL);
5759 		}
5760 
5761 		ret = true;
5762 	}
5763 out_locked:
5764 	IORecursiveLockUnlock(sKextLock);
5765 
5766 	if (dextUniqueIDCString != NULL) {
5767 		kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
5768 	}
5769 
5770 	return ret;
5771 }
5772 
5773 /*********************************************************************
5774 *********************************************************************/
5775 #if defined (__arm__)
5776 #include <arm/arch.h>
5777 #endif
5778 
5779 #if   defined (__x86_64__)
5780 #define ARCHNAME "x86_64"
5781 #elif defined (__arm64__)
5782 #define ARCHNAME "arm64"
5783 #elif defined (__arm__)
5784 
5785 #if defined (__ARM_ARCH_7S__)
5786 #define ARCHNAME "armv7s"
5787 #elif defined (__ARM_ARCH_7F__)
5788 #define ARCHNAME "armv7f"
5789 #elif defined (__ARM_ARCH_7K__)
5790 #define ARCHNAME "armv7k"
5791 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
5792 #define ARCHNAME "armv7"
5793 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
5794 #define ARCHNAME "armv6"
5795 #endif
5796 
5797 #elif defined (__arm64__)
5798 #define ARCHNAME "arm64"
5799 #else
5800 #error architecture not supported
5801 #endif
5802 
5803 #define ARCH_SEPARATOR_CHAR  '_'
5804 
5805 static char *
makeHostArchKey(const char * key,size_t * keySizeOut)5806 makeHostArchKey(const char * key, size_t * keySizeOut)
5807 {
5808 	char     * result = NULL;
5809 	size_t     keyLength = strlen(key);
5810 	size_t     keySize;
5811 
5812 	/* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
5813 	 */
5814 	keySize = 1 + 1 + keyLength + strlen(ARCHNAME);
5815 	result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
5816 
5817 	if (!result) {
5818 		goto finish;
5819 	}
5820 	strlcpy(result, key, keySize);
5821 	result[keyLength++] = ARCH_SEPARATOR_CHAR;
5822 	result[keyLength] = '\0';
5823 	strlcat(result, ARCHNAME, keySize);
5824 	*keySizeOut = keySize;
5825 
5826 finish:
5827 	return result;
5828 }
5829 
5830 /*********************************************************************
5831 *********************************************************************/
5832 OSObject *
getPropertyForHostArch(const char * key)5833 OSKext::getPropertyForHostArch(const char * key)
5834 {
5835 	OSObject * result           = NULL;// do not release
5836 	size_t     hostArchKeySize  = 0;
5837 	char     * hostArchKey      = NULL;// must kfree
5838 
5839 	if (!key || !infoDict) {
5840 		goto finish;
5841 	}
5842 
5843 	/* Some properties are not allowed to be arch-variant:
5844 	 * - Any CFBundle... property.
5845 	 * - OSBundleIsInterface.
5846 	 * - OSKernelResource.
5847 	 */
5848 	if (STRING_HAS_PREFIX(key, "OS") ||
5849 	    STRING_HAS_PREFIX(key, "IO")) {
5850 		hostArchKey = makeHostArchKey(key, &hostArchKeySize);
5851 		if (!hostArchKey) {
5852 			OSKextLog(/* kext (this isn't about a kext) */ NULL,
5853 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
5854 			    "Allocation failure.");
5855 			goto finish;
5856 		}
5857 		result = infoDict->getObject(hostArchKey);
5858 	}
5859 
5860 	if (!result) {
5861 		result = infoDict->getObject(key);
5862 	}
5863 
5864 finish:
5865 	if (hostArchKey) {
5866 		kfree_data(hostArchKey, hostArchKeySize);
5867 	}
5868 	return result;
5869 }
5870 
5871 #if PRAGMA_MARK
5872 #pragma mark Load/Start/Stop/Unload
5873 #endif
5874 
5875 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
5876 
5877 /*********************************************************************
5878 * sExcludeListByID is a dictionary with keys / values of:
5879 *  key = bundleID string of kext we will not allow to load
5880 *  value = version string(s) of the kext that is to be denied loading.
5881 *      The version strings can be comma delimited.  For example if kext
5882 *      com.foocompany.fookext has two versions that we want to deny
5883 *      loading then the version strings might look like:
5884 *      1.0.0, 1.0.1
5885 *      If the current fookext has a version of 1.0.0 OR 1.0.1 we will
5886 *      not load the kext.
5887 *
5888 *      Value may also be in the form of "LE 2.0.0" (version numbers
5889 *      less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
5890 *      number less than 2.0.0 will not load)
5891 *
5892 *      NOTE - we cannot use the characters "<=" or "<" because we have code
5893 *      that serializes plists and treats '<' as a special character.
5894 *********************************************************************/
5895 bool
isInExcludeList(void)5896 OSKext::isInExcludeList(void)
5897 {
5898 	OSString *      versionString           = NULL;        // do not release
5899 	char *          versionCString          = NULL;        // do not free
5900 	size_t          i;
5901 	boolean_t       wantLessThan = false;
5902 	boolean_t       wantLessThanEqualTo = false;
5903 	boolean_t       isInExcludeList = true;
5904 	char            myBuffer[32];
5905 
5906 	IORecursiveLockLock(sKextLock);
5907 
5908 	if (!sExcludeListByID) {
5909 		isInExcludeList = false;
5910 	} else {
5911 		/* look up by bundleID in our exclude list and if found get version
5912 		 * string (or strings) that we will not allow to load
5913 		 */
5914 		versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get()));
5915 		if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
5916 			isInExcludeList = false;
5917 		}
5918 	}
5919 
5920 	IORecursiveLockUnlock(sKextLock);
5921 
5922 	if (!isInExcludeList) {
5923 		return false;
5924 	}
5925 
5926 	/* parse version strings */
5927 	versionCString = (char *) versionString->getCStringNoCopy();
5928 
5929 	/* look for "LT" or "LE" form of version string, must be in first two
5930 	 * positions.
5931 	 */
5932 	if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
5933 		wantLessThan = true;
5934 		versionCString += 2;
5935 	} else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
5936 		wantLessThanEqualTo = true;
5937 		versionCString += 2;
5938 	}
5939 
5940 	for (i = 0; *versionCString != 0x00; versionCString++) {
5941 		/* skip whitespace */
5942 		if (isWhiteSpace(*versionCString)) {
5943 			continue;
5944 		}
5945 
5946 		/* peek ahead for version string separator or null terminator */
5947 		if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
5948 			/* OK, we have a version string */
5949 			myBuffer[i++] = *versionCString;
5950 			myBuffer[i] = 0x00;
5951 
5952 			OSKextVersion excludeVers;
5953 			excludeVers = OSKextParseVersionString(myBuffer);
5954 
5955 			if (wantLessThanEqualTo) {
5956 				if (version <= excludeVers) {
5957 					return true;
5958 				}
5959 			} else if (wantLessThan) {
5960 				if (version < excludeVers) {
5961 					return true;
5962 				}
5963 			} else if (version == excludeVers) {
5964 				return true;
5965 			}
5966 
5967 			/* reset for the next (if any) version string */
5968 			i = 0;
5969 			wantLessThan = false;
5970 			wantLessThanEqualTo = false;
5971 		} else {
5972 			/* save valid version character */
5973 			myBuffer[i++] = *versionCString;
5974 
5975 			/* make sure bogus version string doesn't overrun local buffer */
5976 			if (i >= sizeof(myBuffer)) {
5977 				break;
5978 			}
5979 		}
5980 	}
5981 
5982 	return false;
5983 }
5984 
5985 /*********************************************************************
5986 * sNonLoadableKextsByID is a dictionary with keys / values of:
5987 *  key = bundleID string of kext we will not allow to load
5988 *  value = boolean (true == loadable, false == not loadable)
5989 *
5990 *  Only kexts which are in the AuxKC will be marked as "not loadble,"
5991 *  i.e., the value for the kext's bundleID will be false. All kexts in
5992 *  the primary and system KCs will always be marked as "loadable."
5993 *
5994 *  This list ultimately comes from kexts which have been uninstalled
5995 *  in user space by deleting the kext from disk, but which have not
5996 *  yet been removed from the AuxKC. Because the user could choose to
5997 *  re-install the exact same version of the kext, we need to keep
5998 *  a dictionary of boolean values so that user space only needs to
5999 *  keep a simple list of "uninstalled" or "missing" bundles. When
6000 *  a bundle is re-installed, the iokit daemon can use the
6001 *  AucKCBundleAvailable  predicate to set the individual kext's
6002 *  availability to true.
6003 *********************************************************************/
6004 bool
isLoadable(void)6005 OSKext::isLoadable(void)
6006 {
6007 	bool isLoadable = true;
6008 
6009 	if (kc_type != KCKindAuxiliary) {
6010 		/* this filtering only applies to kexts in the auxkc */
6011 		return true;
6012 	}
6013 
6014 	IORecursiveLockLock(sKextLock);
6015 
6016 	if (sNonLoadableKextsByID) {
6017 		/* look up by bundleID in our exclude list and if found get version
6018 		 * string (or strings) that we will not allow to load
6019 		 */
6020 		OSBoolean *loadableVal;
6021 		loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get()));
6022 		if (loadableVal && !loadableVal->getValue()) {
6023 			isLoadable = false;
6024 		}
6025 	}
6026 	IORecursiveLockUnlock(sKextLock);
6027 
6028 	return isLoadable;
6029 }
6030 
6031 /*********************************************************************
6032 *********************************************************************/
6033 /* static */
6034 OSReturn
loadKextWithIdentifier(const char * kextIdentifierCString,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)6035 OSKext::loadKextWithIdentifier(
6036 	const char       * kextIdentifierCString,
6037 	Boolean            allowDeferFlag,
6038 	Boolean            delayAutounloadFlag,
6039 	OSKextExcludeLevel startOpt,
6040 	OSKextExcludeLevel startMatchingOpt,
6041 	OSArray          * personalityNames)
6042 {
6043 	OSReturn   result         = kOSReturnError;
6044 	OSSharedPtr<OSString> kextIdentifier;
6045 
6046 	kextIdentifier = OSString::withCString(kextIdentifierCString);
6047 	if (!kextIdentifier) {
6048 		result = kOSKextReturnNoMemory;
6049 		goto finish;
6050 	}
6051 	result = OSKext::loadKextWithIdentifier(kextIdentifier.get(),
6052 	    NULL /* kextRef */,
6053 	    allowDeferFlag, delayAutounloadFlag,
6054 	    startOpt, startMatchingOpt, personalityNames);
6055 
6056 finish:
6057 	return result;
6058 }
6059 
6060 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSSharedPtr<OSObject> & kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)6061 OSKext::loadKextWithIdentifier(
6062 	OSString          * kextIdentifier,
6063 	OSSharedPtr<OSObject>         &kextRef,
6064 	Boolean             allowDeferFlag,
6065 	Boolean             delayAutounloadFlag,
6066 	OSKextExcludeLevel  startOpt,
6067 	OSKextExcludeLevel  startMatchingOpt,
6068 	OSArray           * personalityNames)
6069 {
6070 	OSObject * kextRefRaw = NULL;
6071 	OSReturn result;
6072 
6073 	result = loadKextWithIdentifier(kextIdentifier,
6074 	    &kextRefRaw,
6075 	    allowDeferFlag,
6076 	    delayAutounloadFlag,
6077 	    startOpt,
6078 	    startMatchingOpt,
6079 	    personalityNames);
6080 	if ((kOSReturnSuccess == result) && kextRefRaw) {
6081 		kextRef.reset(kextRefRaw, OSNoRetain);
6082 	}
6083 	return result;
6084 }
6085 
6086 /*********************************************************************
6087 *********************************************************************/
6088 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSObject ** kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)6089 OSKext::loadKextWithIdentifier(
6090 	OSString          * kextIdentifier,
6091 	OSObject         ** kextRef,
6092 	Boolean             allowDeferFlag,
6093 	Boolean             delayAutounloadFlag,
6094 	OSKextExcludeLevel  startOpt,
6095 	OSKextExcludeLevel  startMatchingOpt,
6096 	OSArray           * personalityNames)
6097 {
6098 	OSReturn          result               = kOSReturnError;
6099 	OSReturn          pingResult           = kOSReturnError;
6100 	OSKext          * theKext              = NULL;        // do not release
6101 	OSSharedPtr<OSDictionary>   loadRequest;
6102 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
6103 
6104 	if (kextRef) {
6105 		*kextRef = NULL;
6106 	}
6107 
6108 	IORecursiveLockLock(sKextLock);
6109 
6110 	if (!kextIdentifier) {
6111 		result = kOSKextReturnInvalidArgument;
6112 		goto finish;
6113 	}
6114 
6115 	OSKext::recordIdentifierRequest(kextIdentifier);
6116 
6117 	theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
6118 	if (!theKext) {
6119 		if (!allowDeferFlag) {
6120 			OSKextLog(/* kext */ NULL,
6121 			    kOSKextLogErrorLevel |
6122 			    kOSKextLogLoadFlag,
6123 			    "Can't load kext %s - not found.",
6124 			    kextIdentifier->getCStringNoCopy());
6125 			goto finish;
6126 		}
6127 
6128 		if (!sKernelRequestsEnabled) {
6129 			OSKextLog(theKext,
6130 			    kOSKextLogErrorLevel |
6131 			    kOSKextLogLoadFlag,
6132 			    "Can't load kext %s - requests to user space are disabled.",
6133 			    kextIdentifier->getCStringNoCopy());
6134 			result = kOSKextReturnDisabled;
6135 			goto finish;
6136 		}
6137 
6138 		/* Create a new request unless one is already sitting
6139 		 * in sKernelRequests for this bundle identifier
6140 		 */
6141 		kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
6142 		if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
6143 			result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
6144 			    loadRequest);
6145 			if (result != kOSReturnSuccess) {
6146 				goto finish;
6147 			}
6148 			if (!_OSKextSetRequestArgument(loadRequest.get(),
6149 			    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
6150 				result = kOSKextReturnNoMemory;
6151 				goto finish;
6152 			}
6153 			if (!sKernelRequests->setObject(loadRequest.get())) {
6154 				result = kOSKextReturnNoMemory;
6155 				goto finish;
6156 			}
6157 
6158 			if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
6159 				result = kOSKextReturnNoMemory;
6160 				goto finish;
6161 			}
6162 
6163 			OSKextLog(theKext,
6164 			    kOSKextLogDebugLevel |
6165 			    kOSKextLogLoadFlag,
6166 			    "Kext %s not found; queued load request to user space.",
6167 			    kextIdentifier->getCStringNoCopy());
6168 		}
6169 
6170 		pingResult = OSKext::pingIOKitDaemon();
6171 		if (pingResult == kOSKextReturnDisabled) {
6172 			OSKextLog(/* kext */ NULL,
6173 			    ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
6174 			    kOSKextLogLoadFlag,
6175 			    "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.",
6176 			    kextIdentifier->getCStringNoCopy());
6177 		}
6178 
6179 		result = kOSKextReturnDeferred;
6180 		goto finish;
6181 	}
6182 
6183 	result = theKext->load(startOpt, startMatchingOpt, personalityNames);
6184 
6185 	if (result != kOSReturnSuccess) {
6186 		OSKextLog(theKext,
6187 		    kOSKextLogErrorLevel |
6188 		    kOSKextLogLoadFlag,
6189 		    "Failed to load kext %s (error 0x%x).",
6190 		    kextIdentifier->getCStringNoCopy(), (int)result);
6191 
6192 		if (theKext->kc_type == KCKindUnknown) {
6193 			OSKext::removeKext(theKext,
6194 			    /* terminateService/removePersonalities */ true);
6195 		}
6196 		goto finish;
6197 	}
6198 
6199 	if (delayAutounloadFlag) {
6200 		OSKextLog(theKext,
6201 		    kOSKextLogProgressLevel |
6202 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6203 		    "Setting delayed autounload for %s.",
6204 		    kextIdentifier->getCStringNoCopy());
6205 		theKext->flags.delayAutounload = 1;
6206 	}
6207 
6208 finish:
6209 	if ((kOSReturnSuccess == result) && kextRef) {
6210 		*kextRef = theKext;
6211 		theKext->matchingRefCount++;
6212 		theKext->retain();
6213 	}
6214 
6215 	IORecursiveLockUnlock(sKextLock);
6216 
6217 	return result;
6218 }
6219 
6220 /*********************************************************************
6221 *********************************************************************/
6222 /* static */
6223 OSReturn
loadKextFromKC(OSKext * theKext,OSDictionary * requestDict)6224 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict)
6225 {
6226 	OSReturn  result = kOSReturnError;
6227 
6228 	OSBoolean *delayAutounloadBool     = NULL; // do not release
6229 	OSNumber  *startKextExcludeNum     = NULL; // do not release
6230 	OSNumber  *startMatchingExcludeNum = NULL; // do not release
6231 	OSArray   *personalityNames        = NULL; // do not release
6232 
6233 	/*
6234 	 * Default values for these options:
6235 	 *      regular autounload behavior
6236 	 *      start the kext
6237 	 *      send all personalities to the catalog
6238 	 */
6239 	Boolean            delayAutounload           = false;
6240 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
6241 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone;
6242 
6243 	IORecursiveLockLock(sKextLock);
6244 
6245 	OSKextLog(/* kext */ NULL,
6246 	    kOSKextLogDebugLevel |
6247 	    kOSKextLogIPCFlag,
6248 	    "Received kext KC load request from user space.");
6249 
6250 	/* Regardless of processing, the fact that we have gotten here means some
6251 	 * user-space program is up and talking to us, so we'll switch our kext
6252 	 * registration to reflect that.
6253 	 */
6254 	if (!sUserLoadsActive) {
6255 		OSKextLog(/* kext */ NULL,
6256 		    kOSKextLogProgressLevel |
6257 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6258 		    "Switching to late startup (user-space) kext loading policy.");
6259 		sUserLoadsActive = true;
6260 	}
6261 
6262 	delayAutounloadBool = OSDynamicCast(OSBoolean,
6263 	    _OSKextGetRequestArgument(requestDict,
6264 	    kKextRequestArgumentDelayAutounloadKey));
6265 	startKextExcludeNum = OSDynamicCast(OSNumber,
6266 	    _OSKextGetRequestArgument(requestDict,
6267 	    kKextRequestArgumentStartExcludeKey));
6268 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
6269 	    _OSKextGetRequestArgument(requestDict,
6270 	    kKextRequestArgumentStartMatchingExcludeKey));
6271 	personalityNames = OSDynamicCast(OSArray,
6272 	    _OSKextGetRequestArgument(requestDict,
6273 	    kKextRequestArgumentPersonalityNamesKey));
6274 
6275 	if (delayAutounloadBool) {
6276 		delayAutounload = delayAutounloadBool->getValue();
6277 	}
6278 	if (startKextExcludeNum) {
6279 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
6280 	}
6281 	if (startMatchingExcludeNum) {
6282 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
6283 	}
6284 
6285 	OSKextLog(/* kext */ NULL,
6286 	    kOSKextLogProgressLevel |
6287 	    kOSKextLogIPCFlag,
6288 	    "Received request from user space to load KC kext %s.",
6289 	    theKext->getIdentifierCString());
6290 
6291 	/* this could be in the Auxiliary KC, so record the load request */
6292 	OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier()));
6293 
6294 	/*
6295 	 * Load the kext
6296 	 */
6297 	result = theKext->load(startKextExcludeLevel,
6298 	    startMatchingExcludeLevel, personalityNames);
6299 
6300 	if (result != kOSReturnSuccess) {
6301 		OSKextLog(theKext,
6302 		    kOSKextLogErrorLevel |
6303 		    kOSKextLogLoadFlag,
6304 		    "Failed to load kext %s (error 0x%x).",
6305 		    theKext->getIdentifierCString(), (int)result);
6306 
6307 		OSKext::removeKext(theKext,
6308 		    /* terminateService/removePersonalities */ true);
6309 		goto finish;
6310 	} else {
6311 		OSKextLog(theKext,
6312 		    kOSKextLogProgressLevel |
6313 		    kOSKextLogLoadFlag,
6314 		    "Kext %s Loaded successfully from %s KC",
6315 		    theKext->getIdentifierCString(), theKext->getKCTypeString());
6316 	}
6317 
6318 	if (delayAutounload) {
6319 		OSKextLog(theKext,
6320 		    kOSKextLogProgressLevel |
6321 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6322 		    "Setting delayed autounload for %s.",
6323 		    theKext->getIdentifierCString());
6324 		theKext->flags.delayAutounload = 1;
6325 	}
6326 
6327 finish:
6328 	IORecursiveLockUnlock(sKextLock);
6329 
6330 	return result;
6331 }
6332 
6333 /*********************************************************************
6334 *********************************************************************/
6335 /* static */
6336 OSReturn
loadCodelessKext(OSString * kextIdentifier,OSDictionary * requestDict)6337 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict)
6338 {
6339 	OSReturn  result = kOSReturnError;
6340 	OSDictionary *anInfoDict = NULL; // do not release
6341 
6342 	anInfoDict = OSDynamicCast(OSDictionary,
6343 	    _OSKextGetRequestArgument(requestDict,
6344 	    kKextRequestArgumentCodelessInfoKey));
6345 	if (anInfoDict == NULL) {
6346 		OSKextLog(/* kext */ NULL,
6347 		    kOSKextLogErrorLevel |
6348 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6349 		    "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.",
6350 		    kextIdentifier->getCStringNoCopy());
6351 		return kOSKextReturnInvalidArgument;
6352 	}
6353 
6354 	IORecursiveLockLock(sKextLock);
6355 
6356 	OSKextLog(/* kext */ NULL,
6357 	    kOSKextLogProgressLevel |
6358 	    kOSKextLogIPCFlag,
6359 	    "Received request from user space to load codeless kext %s.",
6360 	    kextIdentifier->getCStringNoCopy());
6361 
6362 	{
6363 		// instantiate a new kext, and don't hold a reference
6364 		// (the kext subsystem will hold one implicitly)
6365 		OSKextInitResult ret;
6366 		OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict, &ret);
6367 		if (!newKext) {
6368 			/*
6369 			 * We might have failed to create a new OSKext
6370 			 * because the old one should still be used.
6371 			 * Check if that is the case.
6372 			 */
6373 			if (ret != kOSKextInitFailure) {
6374 				result = kOSReturnSuccess;
6375 				goto finish;
6376 			}
6377 			OSKextLog(/* kext */ NULL,
6378 			    kOSKextLogErrorLevel |
6379 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6380 			    "Could not instantiate codeless kext.");
6381 			result = kOSKextReturnNotLoadable;
6382 			goto finish;
6383 		}
6384 		if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) {
6385 			OSKextLog(/* kext */ NULL,
6386 			    kOSKextLogErrorLevel |
6387 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6388 			    "Codeless kext identifiers don't match '%s' != '%s'",
6389 			    kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString());
6390 
6391 			OSKext::removeKext(newKext.get(), false);
6392 			result = kOSKextReturnInvalidArgument;
6393 			goto finish;
6394 		}
6395 
6396 		/* Record the request for the codeless kext */
6397 		OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier()));
6398 
6399 		result = kOSReturnSuccess;
6400 		/* Send the kext's personalities to the IOCatalog. This is an explicit load. */
6401 		result = newKext->sendPersonalitiesToCatalog(true, NULL);
6402 	}
6403 
6404 finish:
6405 	IORecursiveLockUnlock(sKextLock);
6406 
6407 	return result;
6408 }
6409 
6410 /*********************************************************************
6411 *********************************************************************/
6412 /* static */
6413 void
dropMatchingReferences(OSSet * kexts)6414 OSKext::dropMatchingReferences(
6415 	OSSet * kexts)
6416 {
6417 	IORecursiveLockLock(sKextLock);
6418 	kexts->iterateObjects(^bool (OSObject * obj) {
6419 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
6420 		if (!thisKext) {
6421 		        return false;
6422 		}
6423 		thisKext->matchingRefCount--;
6424 		return false;
6425 	});
6426 	IORecursiveLockUnlock(sKextLock);
6427 }
6428 
6429 /*********************************************************************
6430 *********************************************************************/
6431 /* static */
6432 void
recordIdentifierRequest(OSString * kextIdentifier)6433 OSKext::recordIdentifierRequest(
6434 	OSString * kextIdentifier)
6435 {
6436 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
6437 	bool             fail                 = false;
6438 
6439 	if (!sAllKextLoadIdentifiers || !kextIdentifier) {
6440 		goto finish;
6441 	}
6442 
6443 	kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
6444 	if (!kextIdentifierSymbol) {
6445 		// xxx - this is really a basic alloc failure
6446 		fail = true;
6447 		goto finish;
6448 	}
6449 
6450 	IORecursiveLockLock(sKextLock);
6451 	if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
6452 		if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
6453 			fail = true;
6454 		} else {
6455 			// xxx - need to find a way to associate this whole func w/the kext
6456 			OSKextLog(/* kext */ NULL,
6457 			    // xxx - check level
6458 			    kOSKextLogStepLevel |
6459 			    kOSKextLogArchiveFlag,
6460 			    "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
6461 			    kextIdentifier->getCStringNoCopy());
6462 		}
6463 	}
6464 	IORecursiveLockUnlock(sKextLock);
6465 
6466 finish:
6467 
6468 	if (fail) {
6469 		OSKextLog(/* kext */ NULL,
6470 		    kOSKextLogErrorLevel |
6471 		    kOSKextLogArchiveFlag,
6472 		    "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
6473 		    kextIdentifier->getCStringNoCopy());
6474 	}
6475 	return;
6476 }
6477 
6478 /*********************************************************************
6479 *********************************************************************/
6480 OSReturn
load(OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)6481 OSKext::load(
6482 	OSKextExcludeLevel   startOpt,
6483 	OSKextExcludeLevel   startMatchingOpt,
6484 	OSArray            * personalityNames)
6485 {
6486 	OSReturn             result                       = kOSReturnError;
6487 	OSKextExcludeLevel   dependenciesStartOpt         = startOpt;
6488 	OSKextExcludeLevel   dependenciesStartMatchingOpt = startMatchingOpt;
6489 	unsigned int         i, count;
6490 	Boolean              alreadyLoaded                = false;
6491 	OSKext             * lastLoadedKext               = NULL;        // do not release
6492 
6493 	if (isInExcludeList()) {
6494 		OSKextLog(this,
6495 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
6496 		    kOSKextLogLoadFlag,
6497 		    "Kext %s is in exclude list, not loadable",
6498 		    getIdentifierCString());
6499 
6500 		result = kOSKextReturnNotLoadable;
6501 		goto finish;
6502 	}
6503 	if (!isLoadable()) {
6504 		OSKextLog(this,
6505 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
6506 		    kOSKextLogLoadFlag,
6507 		    "Kext %s is not loadable",
6508 		    getIdentifierCString());
6509 
6510 		result = kOSKextReturnNotLoadable;
6511 		goto finish;
6512 	}
6513 
6514 	if (isLoaded()) {
6515 		alreadyLoaded = true;
6516 		result = kOSReturnSuccess;
6517 
6518 		OSKextLog(this,
6519 		    kOSKextLogDebugLevel |
6520 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6521 		    "Kext %s is already loaded.",
6522 		    getIdentifierCString());
6523 		goto loaded;
6524 	}
6525 
6526 #if CONFIG_MACF
6527 	/*
6528 	 * On kxld and on embedded, only call into the MAC hook when on a
6529 	 * user thread, for access control over userspace kextloads.
6530 	 *
6531 	 * On non-kxld systems, additionally check the MAC hook for kexts in
6532 	 * the Pageable and Aux KCs, regardless of whether we are on a user
6533 	 * thread or not. This means on Apple silicon devices that the MAC
6534 	 * hook will only be useful to block 3rd party kexts loaded via
6535 	 * matching, and any kexts loaded from userspace kextloads.
6536 	 *
6537 	 * Note that this should _not_ be called on kexts loaded from the
6538 	 * kernel bootstrap thread as the kernel proc's cred struct is not
6539 	 * yet initialized! This won't happen on macOS because all the kexts
6540 	 * in the BootKC are self-contained and their kc_type = KCKindPrimary.
6541 	 */
6542 	if (current_task() != kernel_task
6543 #if XNU_TARGET_OS_OSX && !CONFIG_KXLD
6544 	    || (kc_type != KCKindPrimary && kc_type != KCKindUnknown)
6545 #endif
6546 	    ) {
6547 		int                 macCheckResult      = 0;
6548 		kauth_cred_t        cred                = NULL;
6549 
6550 		cred = kauth_cred_get_with_ref();
6551 		macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
6552 		kauth_cred_unref(&cred);
6553 
6554 		if (macCheckResult != 0) {
6555 			result = kOSReturnError;
6556 			OSKextLog(this,
6557 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6558 			    "Failed to load kext %s (MAC policy error 0x%x).",
6559 			    getIdentifierCString(), macCheckResult);
6560 			goto finish;
6561 		}
6562 	}
6563 #endif /* CONFIG_MACF */
6564 
6565 	if (!sLoadEnabled) {
6566 		OSKextLog(this,
6567 		    kOSKextLogErrorLevel |
6568 		    kOSKextLogLoadFlag,
6569 		    "Kext loading is disabled (attempt to load kext %s).",
6570 		    getIdentifierCString());
6571 		result = kOSKextReturnDisabled;
6572 		goto finish;
6573 	}
6574 
6575 	/* If we've pushed the next available load tag to the invalid value,
6576 	 * we can't load any more kexts.
6577 	 */
6578 	if (sNextLoadTag == kOSKextInvalidLoadTag) {
6579 		OSKextLog(this,
6580 		    kOSKextLogErrorLevel |
6581 		    kOSKextLogLoadFlag,
6582 		    "Can't load kext %s - no more load tags to assign.",
6583 		    getIdentifierCString());
6584 		result = kOSKextReturnNoResources;
6585 		goto finish;
6586 	}
6587 
6588 	/* This is a bit of a hack, because we shouldn't be handling
6589 	 * personalities within the load function.
6590 	 */
6591 	if (!declaresExecutable()) {
6592 		/* There is a special case where a non-executable kext can be loaded: the
6593 		 * AppleKextExcludeList.  Detect that special kext by bundle identifier and
6594 		 * load its metadata into the global data structures, if appropriate
6595 		 */
6596 		if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
6597 			boolean_t updated = updateExcludeList(infoDict.get());
6598 			if (updated) {
6599 				OSKextLog(this,
6600 				    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
6601 				    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
6602 			}
6603 		}
6604 
6605 		if (isDriverKit()) {
6606 			if (loadTag == 0) {
6607 				sLoadedDriverKitKexts->setObject(this);
6608 				loadTag = sNextLoadTag++;
6609 			}
6610 		}
6611 		result = kOSReturnSuccess;
6612 		goto loaded;
6613 	}
6614 
6615 	/* Are we in safe boot?
6616 	 */
6617 	if (sSafeBoot && !isLoadableInSafeBoot()) {
6618 		OSKextLog(this,
6619 		    kOSKextLogErrorLevel |
6620 		    kOSKextLogLoadFlag,
6621 		    "Can't load kext %s - not loadable during safe boot.",
6622 		    getIdentifierCString());
6623 		result = kOSKextReturnBootLevel;
6624 		goto finish;
6625 	}
6626 
6627 	OSKextLog(this,
6628 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
6629 	    "Loading kext %s.",
6630 	    getIdentifierCString());
6631 
6632 #if !VM_MAPPED_KEXTS
6633 	if (isPrelinked() == false) {
6634 		OSKextLog(this,
6635 		    kOSKextLogErrorLevel |
6636 		    kOSKextLogLoadFlag,
6637 		    "Can't load kext %s - not in a kext collection.",
6638 		    getIdentifierCString());
6639 		result = kOSKextReturnDisabled;
6640 		goto finish;
6641 	}
6642 #endif /* defined(__x86_64__) */
6643 
6644 #if CONFIG_KXLD
6645 	if (!sKxldContext) {
6646 		kern_return_t kxldResult;
6647 		kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
6648 		    &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
6649 		    /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
6650 		if (kxldResult) {
6651 			OSKextLog(this,
6652 			    kOSKextLogErrorLevel |
6653 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6654 			    "Can't load kext %s - failed to create link context.",
6655 			    getIdentifierCString());
6656 			result = kOSKextReturnNoMemory;
6657 			goto finish;
6658 		}
6659 	}
6660 #endif // CONFIG_KXLD
6661 
6662 	/* We only need to resolve dependencies once for the whole graph, but
6663 	 * resolveDependencies will just return if there's no work to do, so it's
6664 	 * safe to call it more than once.
6665 	 */
6666 	if (!resolveDependencies()) {
6667 		// xxx - check resolveDependencies() for log msg
6668 		OSKextLog(this,
6669 		    kOSKextLogErrorLevel |
6670 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6671 		    "Can't load kext %s - failed to resolve library dependencies.",
6672 		    getIdentifierCString());
6673 		result = kOSKextReturnDependencies;
6674 		goto finish;
6675 	}
6676 
6677 	/* If we are excluding just the kext being loaded now (and not its
6678 	 * dependencies), drop the exclusion level to none so dependencies
6679 	 * start and/or add their personalities.
6680 	 */
6681 	if (dependenciesStartOpt == kOSKextExcludeKext) {
6682 		dependenciesStartOpt = kOSKextExcludeNone;
6683 	}
6684 
6685 	if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
6686 		dependenciesStartMatchingOpt = kOSKextExcludeNone;
6687 	}
6688 
6689 	/* Load the dependencies, recursively.
6690 	 */
6691 	count = getNumDependencies();
6692 	for (i = 0; i < count; i++) {
6693 		OSKext * dependency = OSDynamicCast(OSKext,
6694 		    dependencies->getObject(i));
6695 		if (dependency == NULL) {
6696 			OSKextLog(this,
6697 			    kOSKextLogErrorLevel |
6698 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6699 			    "Internal error loading kext %s; dependency disappeared.",
6700 			    getIdentifierCString());
6701 			result = kOSKextReturnInternalError;
6702 			goto finish;
6703 		}
6704 
6705 		/* Dependencies must be started accorting to the opt,
6706 		 * but not given the personality names of the main kext.
6707 		 */
6708 		result = dependency->load(dependenciesStartOpt,
6709 		    dependenciesStartMatchingOpt,
6710 		    /* personalityNames */ NULL);
6711 		if (result != KERN_SUCCESS) {
6712 			OSKextLog(this,
6713 			    kOSKextLogErrorLevel |
6714 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6715 			    "Dependency %s of kext %s failed to load.",
6716 			    dependency->getIdentifierCString(),
6717 			    getIdentifierCString());
6718 
6719 			OSKext::removeKext(dependency,
6720 			    /* terminateService/removePersonalities */ true);
6721 			result = kOSKextReturnDependencyLoadError;
6722 
6723 			goto finish;
6724 		}
6725 	}
6726 
6727 	result = loadExecutable();
6728 	if (result != KERN_SUCCESS) {
6729 		goto finish;
6730 	}
6731 
6732 	pendingPgoHead.next = &pendingPgoHead;
6733 	pendingPgoHead.prev = &pendingPgoHead;
6734 
6735 	// The kernel PRNG is not initialized when the first kext is
6736 	// loaded, so use early random
6737 	uuid_generate_early_random(instance_uuid);
6738 	account = IOMallocType(OSKextAccount);
6739 
6740 	account->loadTag = kmod_info->id;
6741 	account->site.refcount = 0;
6742 	account->site.flags = VM_TAG_KMOD;
6743 
6744 #if DEVELOPMENT || DEBUG
6745 	/* Setup the task reference group. */
6746 	(void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name),
6747 	    "task_%s", getIdentifierCString());
6748 	account->task_refgrp.grp_name = account->task_refgrp_name;
6749 	account->task_refgrp.grp_parent = &task_external_refgrp;
6750 	account->task_refgrp.grp_flags = OS_REFGRP_F_ALWAYS_ENABLED;
6751 	os_ref_log_init(&account->task_refgrp);
6752 #endif /* DEVELOPMENT || DEBUG */
6753 
6754 	account->kext = this;
6755 	if (gIOSurfaceIdentifier == bundleID) {
6756 		vm_tag_alloc(&account->site);
6757 		gIOSurfaceTag = account->site.tag;
6758 	}
6759 
6760 	flags.loaded = true;
6761 
6762 	/* Add the kext to the list of loaded kexts and update the kmod_info
6763 	 * struct to point to that of the last loaded kext (which is the way
6764 	 * it's always been done, though I'd rather do them in order now).
6765 	 */
6766 	lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
6767 	sLoadedKexts->setObject(this);
6768 
6769 	/* Keep the kernel itself out of the kmod list.
6770 	 */
6771 	if (lastLoadedKext->isKernel()) {
6772 		lastLoadedKext = NULL;
6773 	}
6774 
6775 	if (lastLoadedKext) {
6776 		kmod_info->next = lastLoadedKext->kmod_info;
6777 	}
6778 
6779 	notifyKextLoadObservers(this, kmod_info);
6780 
6781 	/* Make the global kmod list point at the just-loaded kext. Note that the
6782 	 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
6783 	 * although we do report it in kextstat these days by using the newer
6784 	 * OSArray of loaded kexts, which does contain it.
6785 	 *
6786 	 * (The OSKext object representing the kernel doesn't even have a kmod_info
6787 	 * struct, though I suppose we could stick a pointer to it from the
6788 	 * static struct in OSRuntime.cpp.)
6789 	 */
6790 	kmod = kmod_info;
6791 
6792 	/* Save the list of loaded kexts in case we panic.
6793 	 */
6794 	OSKext::saveLoadedKextPanicList();
6795 
6796 	if (isExecutable()) {
6797 		OSKext::updateLoadedKextSummaries();
6798 		savePanicString(/* isLoading */ true);
6799 
6800 #if CONFIG_DTRACE
6801 		registerWithDTrace();
6802 #else
6803 		jettisonLinkeditSegment();
6804 #endif /* CONFIG_DTRACE */
6805 
6806 #if !VM_MAPPED_KEXTS
6807 		/* If there is a page (or more) worth of padding after the end
6808 		 * of the last data section but before the end of the data segment
6809 		 * then free it in the same manner the LinkeditSegment is freed
6810 		 */
6811 		jettisonDATASegmentPadding();
6812 #endif
6813 	}
6814 
6815 loaded:
6816 	if (isExecutable() && !flags.started) {
6817 		if (startOpt == kOSKextExcludeNone) {
6818 			result = start();
6819 			if (result != kOSReturnSuccess) {
6820 				OSKextLog(this,
6821 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6822 				    "Kext %s start failed (result 0x%x).",
6823 				    getIdentifierCString(), result);
6824 				result = kOSKextReturnStartStopError;
6825 			}
6826 		}
6827 	}
6828 
6829 	/* If not excluding matching, send the personalities to the kernel.
6830 	 * This never affects the result of the load operation.
6831 	 * This is a bit of a hack, because we shouldn't be handling
6832 	 * personalities within the load function.
6833 	 */
6834 	if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
6835 		result = sendPersonalitiesToCatalog(true, personalityNames);
6836 	}
6837 
6838 finish:
6839 
6840 	if (result != kOSReturnSuccess) {
6841 		OSKextLog(this,
6842 		    kOSKextLogErrorLevel |
6843 		    kOSKextLogLoadFlag,
6844 		    "Kext %s failed to load (0x%x).",
6845 		    getIdentifierCString(), (int)result);
6846 	} else if (!alreadyLoaded) {
6847 		OSKextLog(this,
6848 		    kOSKextLogProgressLevel |
6849 		    kOSKextLogLoadFlag,
6850 		    "Kext %s loaded.",
6851 		    getIdentifierCString());
6852 
6853 		queueKextNotification(kKextRequestPredicateLoadNotification,
6854 		    OSDynamicCast(OSString, bundleID.get()), getDextUniqueID());
6855 	}
6856 	return result;
6857 }
6858 
6859 #if CONFIG_KXLD
6860 /*********************************************************************
6861 *
6862 *********************************************************************/
6863 static char *
strdup(const char * string)6864 strdup(const char * string)
6865 {
6866 	char * result = NULL;
6867 	size_t size;
6868 
6869 	if (!string) {
6870 		goto finish;
6871 	}
6872 
6873 	size = 1 + strlen(string);
6874 	result = (char *)kalloc_data_tag(size, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
6875 	if (!result) {
6876 		goto finish;
6877 	}
6878 
6879 	memcpy(result, string, size);
6880 
6881 finish:
6882 	return result;
6883 }
6884 #endif // CONFIG_KXLD
6885 
6886 /*********************************************************************
6887 *
6888 *********************************************************************/
6889 
6890 kernel_section_t *
lookupSection(const char * segname,const char * secname)6891 OSKext::lookupSection(const char *segname, const char *secname)
6892 {
6893 	kernel_section_t         * found_section = NULL;
6894 	kernel_mach_header_t     * mh            = NULL;
6895 	kernel_segment_command_t * seg           = NULL;
6896 	kernel_section_t         * sec           = NULL;
6897 
6898 	if (!linkedExecutable) {
6899 		return NULL;
6900 	}
6901 
6902 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6903 
6904 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6905 		if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) {
6906 			continue;
6907 		}
6908 
6909 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6910 			if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) {
6911 				found_section = sec;
6912 				goto out;
6913 			}
6914 		}
6915 	}
6916 
6917 out:
6918 	return found_section;
6919 }
6920 
6921 /*********************************************************************
6922 *
6923 *********************************************************************/
6924 
6925 OSReturn
slidePrelinkedExecutable(bool doCoalescedSlides)6926 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides)
6927 {
6928 	OSReturn                       result           = kOSKextReturnBadData;
6929 	kernel_mach_header_t         * mh               = NULL;
6930 	kernel_segment_command_t     * seg              = NULL;
6931 	kernel_segment_command_t     * linkeditSeg      = NULL;
6932 	kernel_section_t             * sec              = NULL;
6933 	char                         * linkeditBase     = NULL;
6934 	bool                           haveLinkeditBase = false;
6935 	char                         * relocBase        = NULL;
6936 	bool                           haveRelocBase    = false;
6937 	struct dysymtab_command      * dysymtab         = NULL;
6938 	struct linkedit_data_command * segmentSplitInfo = NULL;
6939 	struct symtab_command        * symtab           = NULL;
6940 	kernel_nlist_t               * sym              = NULL;
6941 	struct relocation_info       * reloc            = NULL;
6942 	uint32_t                       i                = 0;
6943 	int                            reloc_size;
6944 	vm_offset_t                    new_kextsize;
6945 	kc_format                    format             = KCFormatUnknown;
6946 
6947 	if (linkedExecutable == NULL || flags.builtin) {
6948 		result = kOSReturnSuccess;
6949 		goto finish;
6950 	}
6951 
6952 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6953 	if (kernel_mach_header_is_in_fileset(mh)) {
6954 		// kexts in filesets are slid as part of collection sliding
6955 		result = kOSReturnSuccess;
6956 		goto finish;
6957 	}
6958 
6959 	segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
6960 
6961 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6962 		if (!seg->vmaddr) {
6963 			continue;
6964 		}
6965 
6966 		seg->vmaddr = ml_static_slide(seg->vmaddr);
6967 
6968 #if KASLR_KEXT_DEBUG
6969 		IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
6970 		    seg->segname,
6971 		    (unsigned long)ml_static_unslide(seg->vmaddr),
6972 		    (unsigned long)seg->vmaddr);
6973 #endif
6974 
6975 		if (!haveRelocBase) {
6976 			relocBase = (char *) seg->vmaddr;
6977 			haveRelocBase = true;
6978 		}
6979 		if (!strcmp(seg->segname, "__LINKEDIT")) {
6980 			linkeditBase = (char *) seg->vmaddr - seg->fileoff;
6981 			haveLinkeditBase = true;
6982 			linkeditSeg = seg;
6983 		}
6984 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6985 			sec->addr = ml_static_slide(sec->addr);
6986 
6987 #if KASLR_KEXT_DEBUG
6988 			IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
6989 			    sec->sectname,
6990 			    (unsigned long)ml_static_unslide(sec->addr),
6991 			    (unsigned long)sec->addr);
6992 #endif
6993 		}
6994 	}
6995 
6996 	dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
6997 
6998 	symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
6999 
7000 	if (symtab != NULL && doCoalescedSlides == false) {
7001 		/* Some pseudo-kexts have symbol tables without segments.
7002 		 * Ignore them. */
7003 		if (symtab->nsyms > 0 && haveLinkeditBase) {
7004 			sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
7005 			for (i = 0; i < symtab->nsyms; i++) {
7006 				if (sym[i].n_type & N_STAB) {
7007 					continue;
7008 				}
7009 				sym[i].n_value = ml_static_slide(sym[i].n_value);
7010 
7011 #if KASLR_KEXT_DEBUG
7012 #define MAX_SYMS_TO_LOG 5
7013 				if (i < MAX_SYMS_TO_LOG) {
7014 					IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
7015 					    (unsigned long)ml_static_unslide(sym[i].n_value),
7016 					    (unsigned long)sym[i].n_value);
7017 				}
7018 #endif
7019 			}
7020 		}
7021 	}
7022 
7023 	if (dysymtab != NULL && doCoalescedSlides == false) {
7024 		if (dysymtab->nextrel > 0) {
7025 			OSKextLog(this,
7026 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
7027 			    kOSKextLogLinkFlag,
7028 			    "Sliding kext %s: External relocations found.",
7029 			    getIdentifierCString());
7030 			goto finish;
7031 		}
7032 
7033 		if (dysymtab->nlocrel > 0) {
7034 			if (!haveLinkeditBase) {
7035 				OSKextLog(this,
7036 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
7037 				    kOSKextLogLinkFlag,
7038 				    "Sliding kext %s: No linkedit segment.",
7039 				    getIdentifierCString());
7040 				goto finish;
7041 			}
7042 
7043 			if (!haveRelocBase) {
7044 				OSKextLog(this,
7045 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
7046 				    kOSKextLogLinkFlag,
7047 #if __x86_64__
7048 				    "Sliding kext %s: No writable segments.",
7049 #else
7050 				    "Sliding kext %s: No segments.",
7051 #endif
7052 				    getIdentifierCString());
7053 				goto finish;
7054 			}
7055 
7056 			reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
7057 			reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
7058 
7059 			for (i = 0; i < dysymtab->nlocrel; i++) {
7060 				if (reloc[i].r_extern != 0
7061 				    || reloc[i].r_type != 0
7062 				    || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
7063 				    ) {
7064 					OSKextLog(this,
7065 					    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
7066 					    kOSKextLogLinkFlag,
7067 					    "Sliding kext %s: Unexpected relocation found.",
7068 					    getIdentifierCString());
7069 					goto finish;
7070 				}
7071 				if (reloc[i].r_pcrel != 0) {
7072 					continue;
7073 				}
7074 				uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
7075 				*relocAddr = ml_static_slide(*relocAddr);
7076 
7077 #if KASLR_KEXT_DEBUG
7078 #define MAX_DYSYMS_TO_LOG 5
7079 				if (i < MAX_DYSYMS_TO_LOG) {
7080 					IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
7081 					    (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
7082 					    (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
7083 				}
7084 #endif
7085 			}
7086 
7087 			/* We should free these relocations, not just delete the reference to them.
7088 			 * <rdar://problem/10535549> Free relocations from PIE kexts.
7089 			 *
7090 			 * For now, we do not free LINKEDIT for kexts with split segments.
7091 			 */
7092 			new_kextsize = round_page(kmod_info->size - reloc_size);
7093 			if (new_kextsize > UINT_MAX) {
7094 				OSKextLog(this,
7095 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
7096 				    kOSKextLogLinkFlag,
7097 				    "Kext %s: new kext size is too large.",
7098 				    getIdentifierCString());
7099 				goto finish;
7100 			}
7101 			if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
7102 				vm_offset_t     endofkext = kmod_info->address + kmod_info->size;
7103 				vm_offset_t     new_endofkext = kmod_info->address + new_kextsize;
7104 				vm_offset_t     endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
7105 				size_t          bytes_remaining = endofkext - endofrelocInfo;
7106 				OSSharedPtr<OSData>        new_osdata;
7107 
7108 				/* fix up symbol offsets if they are after the dsymtab local relocs */
7109 				if (symtab) {
7110 					if (dysymtab->locreloff < symtab->symoff) {
7111 						symtab->symoff -= reloc_size;
7112 					}
7113 					if (dysymtab->locreloff < symtab->stroff) {
7114 						symtab->stroff -= reloc_size;
7115 					}
7116 				}
7117 				if (dysymtab->locreloff < dysymtab->extreloff) {
7118 					dysymtab->extreloff -= reloc_size;
7119 				}
7120 
7121 				/* move data behind reloc info down to new offset */
7122 				if (endofrelocInfo < endofkext) {
7123 					memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
7124 				}
7125 
7126 				/* Create a new OSData for the smaller kext object and reflect
7127 				 * new linkedit segment size.
7128 				 */
7129 				linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
7130 				linkeditSeg->filesize = linkeditSeg->vmsize;
7131 
7132 				new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize);
7133 				if (new_osdata) {
7134 					/* Fix up kmod info and linkedExecutable.
7135 					 */
7136 					kmod_info->size = new_kextsize;
7137 					/*
7138 					 * Fileset KCs are mapped as a whole by iBoot.
7139 					 * Individual kext executables should not be unmapped
7140 					 * by xnu.
7141 					 * Doing so may result in panics like rdar://85419651
7142 					 */
7143 					if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
7144 						new_osdata->setDeallocFunction(NULL);
7145 					} else { // Not from a Fileset KC
7146 #if VM_MAPPED_KEXTS
7147 						new_osdata->setDeallocFunction(osdata_kext_free);
7148 #else
7149 						new_osdata->setDeallocFunction(osdata_phys_free);
7150 #endif
7151 					}
7152 					linkedExecutable->setDeallocFunction(NULL);
7153 					linkedExecutable = os::move(new_osdata);
7154 
7155 #if VM_MAPPED_KEXTS
7156 					kext_free(new_endofkext, (endofkext - new_endofkext));
7157 #else
7158 					ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
7159 #endif
7160 				}
7161 			}
7162 			dysymtab->nlocrel = 0;
7163 			dysymtab->locreloff = 0;
7164 		}
7165 	}
7166 
7167 	result = kOSReturnSuccess;
7168 finish:
7169 	return result;
7170 }
7171 
7172 /*********************************************************************
7173 * called only by load()
7174 *********************************************************************/
7175 OSReturn
loadExecutable()7176 OSKext::loadExecutable()
7177 {
7178 	OSReturn              result             = kOSReturnError;
7179 	OSSharedPtr<OSArray>  linkDependencies;
7180 	uint32_t              num_kmod_refs      = 0;
7181 	OSData              * theExecutable      = NULL;        // do not release
7182 	OSString            * versString         = NULL;        // do not release
7183 	const char          * versCString        = NULL;        // do not free
7184 	const char          * string             = NULL;        // do not free
7185 
7186 #if CONFIG_KXLD
7187 	unsigned int          i;
7188 	uint32_t              numDirectDependencies   = 0;
7189 	kern_return_t         kxldResult;
7190 	KXLDDependency     *  kxlddeps           = NULL;        // must kfree
7191 	uint32_t              num_kxlddeps       = 0;
7192 	struct mach_header ** kxldHeaderPtr      = NULL;        // do not free
7193 	struct mach_header  * kxld_header        = NULL;        // xxx - need to free here?
7194 #endif // CONFIG_KXLD
7195 
7196 	/* We need the version string for a variety of bits below.
7197 	 */
7198 	versString = OSDynamicCast(OSString,
7199 	    getPropertyForHostArch(kCFBundleVersionKey));
7200 	if (!versString) {
7201 		goto finish;
7202 	}
7203 	versCString = versString->getCStringNoCopy();
7204 
7205 	if (isKernelComponent()) {
7206 		if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
7207 			if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
7208 				OSKextLog(this,
7209 				    kOSKextLogErrorLevel |
7210 				    kOSKextLogLoadFlag,
7211 				    "Kernel component %s has incorrect version %s; "
7212 				    "expected %s.",
7213 				    getIdentifierCString(),
7214 				    versCString, KERNEL6_VERSION);
7215 				result = kOSKextReturnInternalError;
7216 				goto finish;
7217 			} else if (strcmp(versCString, osrelease)) {
7218 				OSKextLog(this,
7219 				    kOSKextLogErrorLevel |
7220 				    kOSKextLogLoadFlag,
7221 				    "Kernel component %s has incorrect version %s; "
7222 				    "expected %s.",
7223 				    getIdentifierCString(),
7224 				    versCString, osrelease);
7225 				result = kOSKextReturnInternalError;
7226 				goto finish;
7227 			}
7228 		}
7229 	}
7230 
7231 #if defined(__x86_64__) || defined(__i386__)
7232 	if (flags.resetSegmentsFromVnode) {
7233 		/* Fixup the chains and slide the mach headers */
7234 		kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address;
7235 
7236 		if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) {
7237 			result = kOSKextReturnValidation;
7238 			goto finish;
7239 		}
7240 	}
7241 #endif //(__x86_64__) || defined(__i386__)
7242 
7243 	if (isPrelinked()) {
7244 		goto register_kmod;
7245 	}
7246 
7247 	/* <rdar://problem/21444003> all callers must be entitled */
7248 	if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) {
7249 		OSKextLog(this,
7250 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7251 		    "Not entitled to link kext '%s'",
7252 		    getIdentifierCString());
7253 		result = kOSKextReturnNotPrivileged;
7254 		goto finish;
7255 	}
7256 
7257 	theExecutable = getExecutable();
7258 	if (!theExecutable) {
7259 		if (declaresExecutable()) {
7260 			OSKextLog(this,
7261 			    kOSKextLogErrorLevel |
7262 			    kOSKextLogLoadFlag,
7263 			    "Can't load kext %s - executable is missing.",
7264 			    getIdentifierCString());
7265 			result = kOSKextReturnValidation;
7266 			goto finish;
7267 		}
7268 		goto register_kmod;
7269 	}
7270 
7271 	if (isInterface()) {
7272 		OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable);
7273 		if (executableCopy) {
7274 			setLinkedExecutable(executableCopy.get());
7275 		}
7276 		goto register_kmod;
7277 	}
7278 
7279 #if CONFIG_KXLD
7280 	numDirectDependencies = getNumDependencies();
7281 
7282 	if (flags.hasBleedthrough) {
7283 		linkDependencies = dependencies;
7284 	} else {
7285 		linkDependencies = OSArray::withArray(dependencies.get());
7286 		if (!linkDependencies) {
7287 			OSKextLog(this,
7288 			    kOSKextLogErrorLevel |
7289 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7290 			    "Can't allocate link dependencies to load kext %s.",
7291 			    getIdentifierCString());
7292 			goto finish;
7293 		}
7294 
7295 		for (i = 0; i < numDirectDependencies; ++i) {
7296 			OSKext * dependencyKext = OSDynamicCast(OSKext,
7297 			    dependencies->getObject(i));
7298 			dependencyKext->addBleedthroughDependencies(linkDependencies.get());
7299 		}
7300 	}
7301 
7302 	num_kxlddeps = linkDependencies->getCount();
7303 	if (!num_kxlddeps) {
7304 		OSKextLog(this,
7305 		    kOSKextLogErrorLevel |
7306 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
7307 		    "Can't load kext %s - it has no library dependencies.",
7308 		    getIdentifierCString());
7309 		goto finish;
7310 	}
7311 
7312 	kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
7313 	if (!kxlddeps) {
7314 		OSKextLog(this,
7315 		    kOSKextLogErrorLevel |
7316 		    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7317 		    "Can't allocate link context to load kext %s.",
7318 		    getIdentifierCString());
7319 		goto finish;
7320 	}
7321 	bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
7322 
7323 	for (i = 0; i < num_kxlddeps; ++i) {
7324 		OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
7325 
7326 		if (dependency->isInterface()) {
7327 			OSKext *interfaceTargetKext = NULL;        //do not release
7328 			OSData * interfaceTarget = NULL;        //do not release
7329 
7330 			if (dependency->isKernelComponent()) {
7331 				interfaceTargetKext = sKernelKext;
7332 				interfaceTarget = sKernelKext->linkedExecutable.get();
7333 			} else {
7334 				interfaceTargetKext = OSDynamicCast(OSKext,
7335 				    dependency->dependencies->getObject(0));
7336 
7337 				interfaceTarget = interfaceTargetKext->linkedExecutable.get();
7338 			}
7339 
7340 			if (!interfaceTarget) {
7341 				// panic?
7342 				goto finish;
7343 			}
7344 
7345 			/* The names set here aren't actually logged yet <rdar://problem/7941514>,
7346 			 * it will be useful to have them in the debugger.
7347 			 * strdup() failing isn't critical right here so we don't check that.
7348 			 */
7349 			kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
7350 			kxlddeps[i].kext_size = interfaceTarget->getLength();
7351 			kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
7352 
7353 			if (dependency->linkedExecutable != NULL) {
7354 				kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
7355 				kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
7356 			} else {
7357 				kxlddeps[i].interface = (u_char *) NULL;
7358 				kxlddeps[i].interface_size = 0;
7359 			}
7360 			kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
7361 		} else {
7362 			kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
7363 			kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
7364 			kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
7365 		}
7366 
7367 		kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
7368 	}
7369 
7370 	kxldHeaderPtr = &kxld_header;
7371 
7372 #if DEBUG
7373 	OSKextLog(this,
7374 	    kOSKextLogExplicitLevel |
7375 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7376 	    "Kext %s - calling kxld_link_file:\n"
7377 	    "    kxld_context: %p\n"
7378 	    "    executable: %p    executable_length: %d\n"
7379 	    "    user_data: %p\n"
7380 	    "    kxld_dependencies: %p    num_dependencies: %d\n"
7381 	    "    kxld_header_ptr: %p    kmod_info_ptr: %p\n",
7382 	    getIdentifierCString(), sKxldContext,
7383 	    theExecutable->getBytesNoCopy(), theExecutable->getLength(),
7384 	    this, kxlddeps, num_kxlddeps,
7385 	    kxldHeaderPtr, &kmod_info);
7386 #endif
7387 
7388 	/* After this call, the linkedExecutable instance variable
7389 	 * should exist.
7390 	 */
7391 	kxldResult = kxld_link_file(sKxldContext,
7392 	    (u_char *)theExecutable->getBytesNoCopy(),
7393 	    theExecutable->getLength(),
7394 	    getIdentifierCString(), this, kxlddeps, num_kxlddeps,
7395 	    (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
7396 
7397 	if (kxldResult != KERN_SUCCESS) {
7398 		// xxx - add kxldResult here?
7399 		OSKextLog(this,
7400 		    kOSKextLogErrorLevel |
7401 		    kOSKextLogLoadFlag,
7402 		    "Can't load kext %s - link failed.",
7403 		    getIdentifierCString());
7404 		result = kOSKextReturnLinkError;
7405 		goto finish;
7406 	}
7407 
7408 	/* We've written data & instructions into kernel memory, so flush the data
7409 	 * cache and invalidate the instruction cache.
7410 	 * I/D caches are coherent on x86
7411 	 */
7412 #if !defined(__i386__) && !defined(__x86_64__)
7413 	flush_dcache(kmod_info->address, kmod_info->size, false);
7414 	invalidate_icache(kmod_info->address, kmod_info->size, false);
7415 #endif
7416 
7417 #else // !CONFIG_KXLD
7418 	OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7419 	    "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString());
7420 	result = kOSKextReturnLinkError;
7421 	goto finish;
7422 #endif // CONFIG_KXLD
7423 
7424 register_kmod:
7425 
7426 	if (isInterface()) {
7427 		/* Whip up a fake kmod_info entry for the interface kext.
7428 		 */
7429 		kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
7430 		if (!kmod_info) {
7431 			result = KERN_MEMORY_ERROR;
7432 			goto finish;
7433 		}
7434 
7435 		/* A pseudokext has almost nothing in its kmod_info struct.
7436 		 */
7437 		kmod_info->info_version = KMOD_INFO_VERSION;
7438 
7439 		/* An interface kext doesn't have a linkedExecutable, so save a
7440 		 * copy of the UUID out of the original executable via copyUUID()
7441 		 * while we still have the original executable.
7442 		 */
7443 		interfaceUUID = copyUUID();
7444 	}
7445 
7446 	kmod_info->id = loadTag = sNextLoadTag++;
7447 	kmod_info->reference_count = 0;         // KMOD_DECL... sets it to -1 (invalid).
7448 
7449 	/* Stamp the bundle ID and version from the OSKext over anything
7450 	 * resident inside the kmod_info.
7451 	 */
7452 	string = getIdentifierCString();
7453 	strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
7454 
7455 	string = versCString;
7456 	strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
7457 
7458 	/* Add the dependencies' kmod_info structs as kmod_references.
7459 	 */
7460 	num_kmod_refs = getNumDependencies();
7461 	if (num_kmod_refs) {
7462 		kmod_info->reference_list = kalloc_type_tag(kmod_reference_t,
7463 		    num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT);
7464 		if (!kmod_info->reference_list) {
7465 			result = KERN_MEMORY_ERROR;
7466 			goto finish;
7467 		}
7468 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
7469 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
7470 			OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
7471 			ref->info = refKext->kmod_info;
7472 			ref->info->reference_count++;
7473 
7474 			if (refIndex + 1 < num_kmod_refs) {
7475 				ref->next = kmod_info->reference_list + refIndex + 1;
7476 			}
7477 		}
7478 	}
7479 
7480 	if (kmod_info->hdr_size > UINT32_MAX) {
7481 		OSKextLog(this,
7482 		    kOSKextLogErrorLevel |
7483 		    kOSKextLogLoadFlag,
7484 #if __LP64__
7485 		    "Kext %s header size is too large (%lu > UINT32_MAX).",
7486 #else
7487 		    "Kext %s header size is too large (%u > UINT32_MAX).",
7488 #endif
7489 		    kmod_info->name,
7490 		    kmod_info->hdr_size);
7491 		result = KERN_FAILURE;
7492 		goto finish;
7493 	}
7494 
7495 	if (kmod_info->size > UINT32_MAX) {
7496 		OSKextLog(this,
7497 		    kOSKextLogErrorLevel |
7498 		    kOSKextLogLoadFlag,
7499 #if __LP64__
7500 		    "Kext %s size is too large (%lu > UINT32_MAX).",
7501 #else
7502 		    "Kext %s size is too large (%u > UINT32_MAX).",
7503 #endif
7504 		    kmod_info->name,
7505 		    kmod_info->size);
7506 		result = KERN_FAILURE;
7507 		goto finish;
7508 	}
7509 
7510 	if (!isInterface() && linkedExecutable) {
7511 		OSKextLog(this,
7512 		    kOSKextLogProgressLevel |
7513 		    kOSKextLogLoadFlag,
7514 		    "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
7515 		    kmod_info->name,
7516 		    (unsigned)kmod_info->size / PAGE_SIZE,
7517 		    (unsigned long)ml_static_unslide(kmod_info->address),
7518 		    (unsigned)kmod_info->id);
7519 	}
7520 
7521 	/* VM protections and wiring for the Aux KC are done at collection loading time */
7522 	if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) {
7523 		/* if prelinked and primary KC, VM protections are already set */
7524 		result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true);
7525 		if (result != KERN_SUCCESS) {
7526 			goto finish;
7527 		}
7528 	}
7529 
7530 #if KASAN
7531 	if (linkedExecutable) {
7532 		kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
7533 		    linkedExecutable->getLength(), getIdentifierCString());
7534 	}
7535 #else
7536 	if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
7537 		OSKextLog(this,
7538 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7539 		    "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
7540 		    getIdentifierCString()
7541 		    );
7542 		result = KERN_FAILURE;
7543 		goto finish;
7544 	}
7545 #endif
7546 
7547 	result = kOSReturnSuccess;
7548 
7549 finish:
7550 
7551 #if CONFIG_KXLD
7552 	/* Clear up locally allocated dependency info.
7553 	 */
7554 	for (i = 0; i < num_kxlddeps; ++i) {
7555 		size_t size;
7556 
7557 		if (kxlddeps[i].kext_name) {
7558 			size = 1 + strlen(kxlddeps[i].kext_name);
7559 			kfree_data(kxlddeps[i].kext_name, size);
7560 		}
7561 		if (kxlddeps[i].interface_name) {
7562 			size = 1 + strlen(kxlddeps[i].interface_name);
7563 			kfree_data(kxlddeps[i].interface_name, size);
7564 		}
7565 	}
7566 	if (kxlddeps) {
7567 		kfree_type(KXLDDependency, num_kxlddeps, kxlddeps);
7568 	}
7569 #endif // CONFIG_KXLD
7570 
7571 	/* We no longer need the unrelocated executable (which the linker
7572 	 * has altered anyhow).
7573 	 */
7574 	setExecutable(NULL);
7575 
7576 	if (result != kOSReturnSuccess) {
7577 		OSKextLog(this,
7578 		    kOSKextLogErrorLevel |
7579 		    kOSKextLogLoadFlag,
7580 		    "Failed to load executable for kext %s.",
7581 		    getIdentifierCString());
7582 
7583 		if (kmod_info && kmod_info->reference_list) {
7584 			kfree_type(kmod_reference_t, num_kmod_refs,
7585 			    kmod_info->reference_list);
7586 		}
7587 		if (isInterface()) {
7588 			kfree_type(kmod_info_t, kmod_info);
7589 			kmod_info = NULL;
7590 		}
7591 		if (kc_type == KCKindUnknown) {
7592 			kmod_info = NULL;
7593 			if (linkedExecutable) {
7594 				linkedExecutable.reset();
7595 			}
7596 		}
7597 	}
7598 
7599 	return result;
7600 }
7601 
7602 /* static */
7603 void
jettisonFileSetLinkeditSegment(kernel_mach_header_t * mh)7604 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh)
7605 {
7606 	kernel_segment_command_t *linkeditseg = NULL;
7607 
7608 	linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT);
7609 	if (linkeditseg == NULL) {
7610 		panic("FileSet booted with no Linkedit segment");
7611 	}
7612 
7613 #if VM_MAPPED_KEXTS
7614 	/* BootKC on x86_64 is not vm mapped */
7615 	ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize);
7616 
7617 	OSKextLog(/* kext */ NULL,
7618 	    kOSKextLogProgressLevel |
7619 	    kOSKextLogGeneralFlag,
7620 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
7621 	    linkeditseg->vmaddr, linkeditseg->vmsize);
7622 #else
7623 	/* BootKC on arm64 is not vm mapped, but is slid */
7624 #if !CONFIG_SPTM
7625 	vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase));
7626 #else
7627 	vm_offset_t linkedit_vmaddr = linkeditseg->vmaddr;
7628 #endif
7629 
7630 	ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize);
7631 
7632 	OSKextLog(/* kext */ NULL,
7633 	    kOSKextLogProgressLevel |
7634 	    kOSKextLogGeneralFlag,
7635 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
7636 	    (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize);
7637 #endif /* VM_MAPPED_KEXTS */
7638 }
7639 
7640 /*********************************************************************
7641 * The linkedit segment is used by the kext linker for dependency
7642 * resolution, and by dtrace for probe initialization. We can free it
7643 * for non-library kexts, since no kexts depend on non-library kexts
7644 * by definition, once dtrace has been initialized.
7645 *********************************************************************/
7646 void
jettisonLinkeditSegment(void)7647 OSKext::jettisonLinkeditSegment(void)
7648 {
7649 	kernel_mach_header_t     * machhdr = (kernel_mach_header_t *)kmod_info->address;
7650 	kernel_segment_command_t * linkedit = NULL;
7651 	vm_offset_t                start;
7652 	vm_size_t                  linkeditsize, kextsize;
7653 	OSSharedPtr<OSData>        data;
7654 	kc_format                format    = KCFormatUnknown;
7655 
7656 	if (isInFileset()) {
7657 		return;
7658 	}
7659 
7660 #if NO_KEXTD
7661 	/* We can free symbol tables for all embedded kexts because we don't
7662 	 * support runtime kext linking.
7663 	 */
7664 	if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
7665 #else
7666 	if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
7667 #endif
7668 		goto finish;
7669 	}
7670 
7671 	/* Find the linkedit segment.  If it's not the last segment, then freeing
7672 	 * it will fragment the kext into multiple VM regions, which OSKext is not
7673 	 * designed to handle, so we'll have to skip it.
7674 	 */
7675 	linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
7676 	if (!linkedit) {
7677 		goto finish;
7678 	}
7679 
7680 	if (round_page(kmod_info->address + kmod_info->size) !=
7681 	    round_page(linkedit->vmaddr + linkedit->vmsize)) {
7682 		goto finish;
7683 	}
7684 
7685 	/* Create a new OSData for the smaller kext object.
7686 	 */
7687 	linkeditsize = round_page(linkedit->vmsize);
7688 	kextsize = kmod_info->size - linkeditsize;
7689 	start = linkedit->vmaddr;
7690 
7691 	if (kextsize > UINT_MAX) {
7692 		goto finish;
7693 	}
7694 	data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize);
7695 	if (!data) {
7696 		goto finish;
7697 	}
7698 
7699 	/* Fix the kmod info and linkedExecutable.
7700 	 */
7701 	kmod_info->size = kextsize;
7702 
7703 	/*
7704 	 * Fileset KCs are mapped as a whole by iBoot.
7705 	 * Individual kext executables should not be unmapped by xnu
7706 	 * Doing so may result in panics like rdar://85419651
7707 	 */
7708 	if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
7709 		data->setDeallocFunction(NULL);
7710 	} else { // Not from a Fileset KC
7711 #if VM_MAPPED_KEXTS
7712 		data->setDeallocFunction(osdata_kext_free);
7713 #else
7714 		data->setDeallocFunction(osdata_phys_free);
7715 #endif
7716 	}
7717 	linkedExecutable->setDeallocFunction(NULL);
7718 	linkedExecutable = os::move(data);
7719 	flags.jettisonLinkeditSeg = 1;
7720 
7721 	/* Free the linkedit segment.
7722 	 */
7723 #if VM_MAPPED_KEXTS
7724 	kext_free(start, linkeditsize);
7725 #else
7726 	ml_static_mfree(start, linkeditsize);
7727 #endif
7728 
7729 finish:
7730 	return;
7731 }
7732 
7733 /*********************************************************************
7734 * If there are whole pages that are unused betweem the last section
7735 * of the DATA segment and the end of the DATA segment then we can free
7736 * them
7737 *********************************************************************/
7738 void
7739 OSKext::jettisonDATASegmentPadding(void)
7740 {
7741 	kernel_mach_header_t * mh;
7742 	kernel_segment_command_t * dataSeg;
7743 	kernel_section_t * sec, * lastSec;
7744 	vm_offset_t dataSegEnd, lastSecEnd;
7745 	vm_size_t padSize;
7746 
7747 	if (flags.builtin) {
7748 		return;
7749 	}
7750 	mh = (kernel_mach_header_t *)kmod_info->address;
7751 
7752 	if (isInFileset()) {
7753 		return;
7754 	}
7755 
7756 	dataSeg = getsegbynamefromheader(mh, SEG_DATA);
7757 	if (dataSeg == NULL) {
7758 		return;
7759 	}
7760 
7761 	lastSec = NULL;
7762 	sec = firstsect(dataSeg);
7763 	while (sec != NULL) {
7764 		lastSec = sec;
7765 		sec = nextsect(dataSeg, sec);
7766 	}
7767 
7768 	if (lastSec == NULL) {
7769 		return;
7770 	}
7771 
7772 	if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
7773 	    (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
7774 		return;
7775 	}
7776 
7777 	dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
7778 	lastSecEnd = round_page(lastSec->addr + lastSec->size);
7779 
7780 	if (dataSegEnd <= lastSecEnd) {
7781 		return;
7782 	}
7783 
7784 	padSize = dataSegEnd - lastSecEnd;
7785 
7786 	if (padSize >= PAGE_SIZE) {
7787 #if VM_MAPPED_KEXTS
7788 		kext_free(lastSecEnd, padSize);
7789 #else
7790 		ml_static_mfree(lastSecEnd, padSize);
7791 #endif
7792 	}
7793 }
7794 
7795 /*********************************************************************
7796 *********************************************************************/
7797 void
7798 OSKext::setLinkedExecutable(OSData * anExecutable)
7799 {
7800 	if (linkedExecutable) {
7801 		panic("Attempt to set linked executable on kext "
7802 		    "that already has one (%s).\n",
7803 		    getIdentifierCString());
7804 	}
7805 	linkedExecutable.reset(anExecutable, OSRetain);
7806 	return;
7807 }
7808 
7809 #if CONFIG_DTRACE
7810 /*********************************************************************
7811 * Go through all loaded kexts and tell them to register with dtrace.
7812 * The instance method only registers if necessary.
7813 *********************************************************************/
7814 /* static */
7815 void
7816 OSKext::registerKextsWithDTrace(void)
7817 {
7818 	uint32_t count = sLoadedKexts->getCount();
7819 	uint32_t i;
7820 
7821 	IORecursiveLockLock(sKextLock);
7822 
7823 	for (i = 0; i < count; i++) {
7824 		OSKext   * thisKext     = NULL;        // do not release
7825 
7826 		thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
7827 		if (!thisKext || !thisKext->isExecutable()) {
7828 			continue;
7829 		}
7830 
7831 		thisKext->registerWithDTrace();
7832 	}
7833 
7834 	IORecursiveLockUnlock(sKextLock);
7835 
7836 	return;
7837 }
7838 
7839 extern "C" {
7840 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
7841 extern int (*dtrace_modunload)(struct kmod_info *);
7842 };
7843 
7844 /*********************************************************************
7845 *********************************************************************/
7846 void
7847 OSKext::registerWithDTrace(void)
7848 {
7849 	/* Register kext with dtrace. A dtrace_modload failure should not
7850 	 * prevent a kext from loading, so we ignore the return code.
7851 	 */
7852 	if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
7853 		uint32_t modflag = 0;
7854 		OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
7855 
7856 		if (!sKeepSymbols && kc_type == KCKindPrimary) {
7857 			if (forceInit == kOSBooleanTrue) {
7858 				OSKextLog(this,
7859 				    kOSKextLogBasicLevel |
7860 				    kOSKextLogGeneralFlag,
7861 				    "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s",
7862 				    getIdentifierCString());
7863 				forceInit = kOSBooleanFalse;
7864 			}
7865 			/* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */
7866 			modflag |= KMOD_DTRACE_NO_KERNEL_SYMS;
7867 		}
7868 
7869 		if (forceInit == kOSBooleanTrue) {
7870 			modflag |= KMOD_DTRACE_FORCE_INIT;
7871 		}
7872 		if (flags.builtin) {
7873 			modflag |= KMOD_DTRACE_STATIC_KEXT;
7874 		}
7875 
7876 		(void)(*dtrace_modload)(kmod_info, modflag);
7877 		flags.dtraceInitialized = true;
7878 		jettisonLinkeditSegment();
7879 	}
7880 	return;
7881 }
7882 /*********************************************************************
7883 *********************************************************************/
7884 void
7885 OSKext::unregisterWithDTrace(void)
7886 {
7887 	/* Unregister kext with dtrace. A dtrace_modunload failure should not
7888 	 * prevent a kext from loading, so we ignore the return code.
7889 	 */
7890 	if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
7891 		(void)(*dtrace_modunload)(kmod_info);
7892 		flags.dtraceInitialized = false;
7893 	}
7894 	return;
7895 }
7896 #endif /* CONFIG_DTRACE */
7897 
7898 
7899 /*********************************************************************
7900 * called only by loadExecutable()
7901 *********************************************************************/
7902 #if !VM_MAPPED_KEXTS
7903 #if defined(__arm__) || defined(__arm64__)
7904 static inline kern_return_t
7905 OSKext_protect(
7906 	kernel_mach_header_t *kext_mh,
7907 	vm_map_t   map,
7908 	vm_map_offset_t    start,
7909 	vm_map_size_t      size,
7910 	vm_prot_t  new_prot,
7911 	boolean_t  set_max,
7912 	kc_kind_t  kc_type)
7913 {
7914 	vm_map_offset_t    end = start + size;
7915 
7916 #pragma unused(kext_mh,map,kc_type)
7917 	assert(map == kernel_map);         // we can handle KEXTs arising from the PRELINK segment and no others
7918 	assert(start <= end);
7919 	if (start >= end) {
7920 		return KERN_SUCCESS;         // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
7921 	} else if (set_max) {
7922 		return KERN_SUCCESS;         // Punt set_max, as there's no mechanism to record that state
7923 	} else {
7924 		return ml_static_protect(start, size, new_prot);
7925 	}
7926 }
7927 
7928 static inline kern_return_t
7929 OSKext_wire(
7930 	kernel_mach_header_t *kext_mh,
7931 	vm_map_t   map,
7932 	vm_map_offset_t    start,
7933 	vm_map_offset_t    end,
7934 	vm_prot_t  access_type,
7935 	boolean_t       user_wire,
7936 	kc_kind_t       kc_type)
7937 {
7938 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type)
7939 	return KERN_SUCCESS;         // No-op as PRELINK kexts are cemented into physical memory at boot
7940 }
7941 #else
7942 #error Unrecognized architecture
7943 #endif
7944 #else
7945 static inline kern_return_t
7946 OSKext_protect(
7947 	kernel_mach_header_t *kext_mh,
7948 	vm_map_t   map,
7949 	vm_map_offset_t    start,
7950 	vm_map_size_t      size,
7951 	vm_prot_t  new_prot,
7952 	boolean_t  set_max,
7953 	kc_kind_t  kc_type)
7954 {
7955 	vm_map_offset_t    end = start + size;
7956 
7957 	if (start == end) {         // 10538581
7958 		return KERN_SUCCESS;
7959 	}
7960 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7961 		/*
7962 		 * XXX: This will probably need to be different for AuxKC and
7963 		 * pageableKC!
7964 		 */
7965 		return ml_static_protect(start, size, new_prot);
7966 	}
7967 	return mach_vm_protect(map, start, size, set_max, new_prot);
7968 }
7969 
7970 static inline kern_return_t
7971 OSKext_wire(
7972 	kernel_mach_header_t *kext_mh,
7973 	vm_map_t   map,
7974 	vm_map_offset_t    start,
7975 	vm_map_offset_t    end,
7976 	vm_prot_t  access_type,
7977 	boolean_t       user_wire,
7978 	kc_kind_t       kc_type)
7979 {
7980 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7981 		/* TODO: we may need to hook this for the pageableKC */
7982 		return KERN_SUCCESS;
7983 	}
7984 	return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
7985 }
7986 #endif
7987 
7988 OSReturn
7989 OSKext::setVMAttributes(bool protect, bool wire)
7990 {
7991 	vm_map_t                    kext_map        = NULL;
7992 	kernel_segment_command_t  * seg             = NULL;
7993 	vm_map_offset_t             start_protect   = 0;
7994 	vm_map_offset_t             start_wire      = 0;
7995 	vm_map_offset_t             end_protect     = 0;
7996 	vm_map_size_t               size_protect    = 0;
7997 	vm_map_offset_t             end_wire        = 0;
7998 	OSReturn                    result          = kOSReturnError;
7999 
8000 	if (isInterface() || !declaresExecutable() || flags.builtin) {
8001 		result = kOSReturnSuccess;
8002 		goto finish;
8003 	}
8004 
8005 	/* Get the kext's vm map */
8006 	kext_map = kext_get_vm_map(kmod_info);
8007 	if (!kext_map) {
8008 		result = KERN_MEMORY_ERROR;
8009 		goto finish;
8010 	}
8011 
8012 #if !VM_MAPPED_KEXTS
8013 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
8014 		/* This is a split kext in a prelinked kernelcache; we'll let the
8015 		 * platform code take care of protecting it.  It is already wired.
8016 		 */
8017 		/* TODO: Should this still allow protections for the first segment
8018 		 * to go through, in the event that we have a mix of split and
8019 		 * unsplit kexts?
8020 		 */
8021 		result = KERN_SUCCESS;
8022 		goto finish;
8023 	}
8024 
8025 	if (isInFileset() && kc_type != KCKindPageable) {
8026 		// kexts in filesets have protections setup as part of collection loading
8027 		result = KERN_SUCCESS;
8028 		goto finish;
8029 	}
8030 #endif
8031 
8032 	/* Protect the headers as read-only; they do not need to be wired */
8033 	result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address,
8034 	    kext_map, kmod_info->address,
8035 	    kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type)
8036 	    : KERN_SUCCESS;
8037 	if (result != KERN_SUCCESS) {
8038 		goto finish;
8039 	}
8040 
8041 	/* Set the VM protections and wire down each of the segments */
8042 	seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8043 	while (seg) {
8044 #if __arm__
8045 		/* We build all ARM kexts, so we can ensure they are aligned */
8046 		assert((seg->vmaddr & PAGE_MASK) == 0);
8047 		assert((seg->vmsize & PAGE_MASK) == 0);
8048 #endif
8049 
8050 		/*
8051 		 * For the non page aligned segments, the range calculation for protection
8052 		 * and wiring differ as follows:
8053 		 *
8054 		 * Protection: The non page aligned data at the start or at the end of the
8055 		 * segment is excluded from the protection. This exclusion is needed to make
8056 		 * sure OSKext_protect is not called twice on same page, if the page is shared
8057 		 * between two segments.
8058 		 *
8059 		 * Wiring: The non page aligned data at the start or at the end of the
8060 		 * segment is included in the wiring range, this inclusion is needed to make sure
8061 		 * all the data of the segment is wired.
8062 		 */
8063 		start_protect = round_page(seg->vmaddr);
8064 		end_protect = trunc_page(seg->vmaddr + seg->vmsize);
8065 		size_protect = end_protect - start_protect;
8066 
8067 		start_wire = trunc_page(seg->vmaddr);
8068 		end_wire = round_page(seg->vmaddr + seg->vmsize);
8069 
8070 		/*
8071 		 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared
8072 		 * across kexts and data from kexts is not page aligned
8073 		 */
8074 		if (protect && (end_protect > start_protect) &&
8075 		    ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 &&
8076 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) ||
8077 		    (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) {
8078 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
8079 			    kext_map, start_protect, size_protect, seg->maxprot, TRUE, kc_type);
8080 			if (result != KERN_SUCCESS) {
8081 				OSKextLog(this,
8082 				    kOSKextLogErrorLevel |
8083 				    kOSKextLogLoadFlag,
8084 				    "Kext %s failed to set maximum VM protections "
8085 				    "for segment %s - 0x%x.",
8086 				    getIdentifierCString(), seg->segname, (int)result);
8087 				goto finish;
8088 			}
8089 
8090 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
8091 			    kext_map, start_protect, size_protect, seg->initprot, FALSE, kc_type);
8092 			if (result != KERN_SUCCESS) {
8093 				OSKextLog(this,
8094 				    kOSKextLogErrorLevel |
8095 				    kOSKextLogLoadFlag,
8096 				    "Kext %s failed to set initial VM protections "
8097 				    "for segment %s - 0x%x.",
8098 				    getIdentifierCString(), seg->segname, (int)result);
8099 				goto finish;
8100 			}
8101 		}
8102 
8103 		if (segmentShouldBeWired(seg) && wire) {
8104 			result = OSKext_wire((kernel_mach_header_t *)kmod_info->address,
8105 			    kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type);
8106 			if (result != KERN_SUCCESS) {
8107 				goto finish;
8108 			}
8109 		}
8110 
8111 		seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8112 	}
8113 
8114 finish:
8115 	return result;
8116 }
8117 
8118 /*********************************************************************
8119 *********************************************************************/
8120 boolean_t
8121 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
8122 {
8123 	return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) &&
8124 	       strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)));
8125 }
8126 
8127 /*********************************************************************
8128 *********************************************************************/
8129 OSReturn
8130 OSKext::validateKextMapping(bool startFlag)
8131 {
8132 	OSReturn                              result      = kOSReturnError;
8133 	const char                          * whichOp = startFlag ? "start" : "stop";
8134 	kern_return_t                         kern_result = 0;
8135 	vm_map_t                              kext_map    = NULL;
8136 	kernel_segment_command_t            * seg         = NULL;
8137 	mach_vm_address_t                     address     = 0;
8138 	mach_vm_size_t                        size        = 0;
8139 	uint32_t                              depth       = 0;
8140 	uint64_t                              kext_segbase = 0;
8141 	uint64_t                              kext_segsize = 0;
8142 	mach_msg_type_number_t                count;
8143 	vm_region_submap_short_info_data_64_t info;
8144 	uintptr_t                             kext_slide = PE_get_kc_slide(kc_type);
8145 
8146 	if (flags.builtin) {
8147 		return kOSReturnSuccess;
8148 	}
8149 
8150 	count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
8151 	bzero(&info, sizeof(info));
8152 
8153 	// xxx - do we need a distinct OSReturn value for these or is "bad data"
8154 	// xxx - sufficient?
8155 
8156 	/* Verify that the kmod_info and start/stop pointers are non-NULL.
8157 	 */
8158 	if (!kmod_info) {
8159 		OSKextLog(this,
8160 		    kOSKextLogErrorLevel |
8161 		    kOSKextLogLoadFlag,
8162 		    "Kext %s - NULL kmod_info pointer.",
8163 		    getIdentifierCString());
8164 		result = kOSKextReturnBadData;
8165 		goto finish;
8166 	}
8167 
8168 	if (startFlag) {
8169 		address = (mach_vm_address_t)kmod_info->start;
8170 	} else {
8171 		address = (mach_vm_address_t)kmod_info->stop;
8172 	}
8173 
8174 	if (!address) {
8175 		OSKextLog(this,
8176 		    kOSKextLogErrorLevel |
8177 		    kOSKextLogLoadFlag,
8178 		    "Kext %s - NULL module %s pointer.",
8179 		    getIdentifierCString(), whichOp);
8180 		result = kOSKextReturnBadData;
8181 		goto finish;
8182 	}
8183 
8184 	kext_map = kext_get_vm_map(kmod_info);
8185 	depth = (kernel_map == kext_map) ? 1 : 2;
8186 	if (isInFileset()) {
8187 #if defined(HAS_APPLE_PAC)
8188 		address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0);
8189 #endif /* defined(HAS_APPLE_PAC) */
8190 	}
8191 
8192 	/* Verify that the start/stop function lies within the kext's address range.
8193 	 */
8194 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) ||
8195 	    isInFileset()) {
8196 		/* This will likely be how we deal with split kexts; walk the segments to
8197 		 * check that the function lies inside one of the segments of this kext.
8198 		 */
8199 		for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8200 		    seg != NULL;
8201 		    seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
8202 			if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
8203 				kext_segbase = seg->vmaddr;
8204 				kext_segsize = seg->vmsize;
8205 				break;
8206 			}
8207 		}
8208 
8209 		if (!seg) {
8210 			OSKextLog(this,
8211 			    kOSKextLogErrorLevel |
8212 			    kOSKextLogLoadFlag,
8213 			    "Kext %s module %s pointer is outside of kext range "
8214 			    "(%s %p - kext starts at %p).",
8215 			    getIdentifierCString(),
8216 			    whichOp,
8217 			    whichOp,
8218 			    (void *)(((uintptr_t)address) - kext_slide),
8219 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide));
8220 			result = kOSKextReturnBadData;
8221 			goto finish;
8222 		}
8223 
8224 		seg = NULL;
8225 	} else {
8226 		if (address < kmod_info->address + kmod_info->hdr_size ||
8227 		    kmod_info->address + kmod_info->size <= address) {
8228 			OSKextLog(this,
8229 			    kOSKextLogErrorLevel |
8230 			    kOSKextLogLoadFlag,
8231 			    "Kext %s module %s pointer is outside of kext range "
8232 			    "(%s %p - kext at %p-%p).",
8233 			    getIdentifierCString(),
8234 			    whichOp,
8235 			    whichOp,
8236 			    (void *)(((uintptr_t)address) - kext_slide),
8237 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide),
8238 			    (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size));
8239 			result = kOSKextReturnBadData;
8240 			goto finish;
8241 		}
8242 	}
8243 
8244 	/* Only do these checks before calling the start function;
8245 	 * If anything goes wrong with the mapping while the kext is running,
8246 	 * we'll likely have panicked well before any attempt to stop the kext.
8247 	 */
8248 	if (startFlag) {
8249 		if (!isInFileset() || kc_type != KCKindPrimary) {
8250 			/*
8251 			 * Verify that the start/stop function is executable.
8252 			 */
8253 			kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
8254 			    (vm_region_recurse_info_t)&info, &count);
8255 			if (kern_result != KERN_SUCCESS) {
8256 				OSKextLog(this,
8257 				    kOSKextLogErrorLevel |
8258 				    kOSKextLogLoadFlag,
8259 				    "Kext %s - bad %s pointer %p.",
8260 				    getIdentifierCString(),
8261 				    whichOp, (void *)ml_static_unslide(address));
8262 				result = kOSKextReturnBadData;
8263 				goto finish;
8264 			}
8265 		} else {
8266 			/*
8267 			 * Since kexts loaded from the primary KC are held in memory
8268 			 * allocated by efiboot, we cannot use mach_vm_region_recurse() to
8269 			 * discover that memory's protection flags.  Instead, we need to
8270 			 * get that information from the kernel pmap itself.  Above, we
8271 			 * (potentially) saved the size of the segment in which the address
8272 			 * in question was located.  If we have a non-zero size, verify
8273 			 * that all pages in the (address, address + kext_segsize) range
8274 			 * are marked executable.  If we somehow did not record the size
8275 			 * (or the base) just verify the single page that includes the address.
8276 			 */
8277 			if (kext_segbase == 0 || kext_segsize == 0) {
8278 				kext_segbase = address & ~(uint64_t)PAGE_MASK;
8279 				kext_segsize = PAGE_SIZE;
8280 			}
8281 		}
8282 
8283 #if VM_MAPPED_KEXTS
8284 		if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) ||
8285 		    ((isInFileset() && kc_type == KCKindPrimary) &&
8286 		    ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) {
8287 			OSKextLog(this,
8288 			    kOSKextLogErrorLevel |
8289 			    kOSKextLogLoadFlag,
8290 			    "Kext %s - memory region containing module %s function "
8291 			    "is not executable.",
8292 			    getIdentifierCString(), whichOp);
8293 			result = kOSKextReturnBadData;
8294 			goto finish;
8295 		}
8296 #endif
8297 
8298 		/* Verify that the kext's segments are backed by physical memory.
8299 		 */
8300 		seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8301 		while (seg) {
8302 			if (!verifySegmentMapping(seg)) {
8303 				result = kOSKextReturnBadData;
8304 				goto finish;
8305 			}
8306 
8307 			seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8308 		}
8309 	}
8310 
8311 	result = kOSReturnSuccess;
8312 finish:
8313 	return result;
8314 }
8315 
8316 /*********************************************************************
8317 *********************************************************************/
8318 boolean_t
8319 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
8320 {
8321 	mach_vm_address_t address = 0;
8322 
8323 	if (seg->vmsize > UINT32_MAX) {
8324 		return false;
8325 	}
8326 
8327 	if (!segmentShouldBeWired(seg)) {
8328 		return true;
8329 	}
8330 
8331 	for (address = seg->vmaddr;
8332 	    address < round_page(seg->vmaddr + seg->vmsize);
8333 	    address += PAGE_SIZE) {
8334 		if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
8335 			OSKextLog(this,
8336 			    kOSKextLogErrorLevel |
8337 			    kOSKextLogLoadFlag,
8338 			    "Kext %s - page %p is not backed by physical memory.",
8339 			    getIdentifierCString(),
8340 			    (void *)address);
8341 			return false;
8342 		}
8343 	}
8344 
8345 	return true;
8346 }
8347 
8348 /*********************************************************************
8349 *********************************************************************/
8350 static void
8351 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
8352 {
8353 	uint64_t                            stamp = 0;
8354 	firehose_tracepoint_id_u            trace_id;
8355 	struct firehose_trace_uuid_info_s   uuid_info_s;
8356 	firehose_trace_uuid_info_t          uuid_info = &uuid_info_s;
8357 	size_t                              uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
8358 	OSSharedPtr<OSData>                 uuid_data;
8359 
8360 	stamp = firehose_tracepoint_time(firehose_activity_flags_default);
8361 	trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
8362 
8363 	uuid_data = aKext->copyTextUUID();
8364 	if (uuid_data) {
8365 		memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
8366 	}
8367 
8368 	uuid_info->ftui_size    = size;
8369 	if (aKext->isDriverKit()) {
8370 		uuid_info->ftui_address = address;
8371 	} else {
8372 		uuid_info->ftui_address = ml_static_unslide(address);
8373 	}
8374 	os_log_encoded_metadata(trace_id, stamp, uuid_info, uuid_info_len);
8375 	return;
8376 }
8377 
8378 void
8379 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext)
8380 {
8381 	OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load);
8382 }
8383 
8384 /*********************************************************************
8385 *********************************************************************/
8386 OSReturn
8387 OSKext::start(bool startDependenciesFlag)
8388 {
8389 	OSReturn                            result = kOSReturnError;
8390 	kern_return_t                       (* startfunc)(kmod_info_t *, void *);
8391 	unsigned int                        i, count;
8392 	void                              * kmodStartData = NULL;
8393 
8394 	if (isStarted() || isInterface() || isKernelComponent()) {
8395 		result = kOSReturnSuccess;
8396 		goto finish;
8397 	}
8398 
8399 	if (!isLoaded()) {
8400 		OSKextLog(this,
8401 		    kOSKextLogErrorLevel |
8402 		    kOSKextLogLoadFlag,
8403 		    "Attempt to start nonloaded kext %s.",
8404 		    getIdentifierCString());
8405 		result = kOSKextReturnInvalidArgument;
8406 		goto finish;
8407 	}
8408 
8409 	if (!sLoadEnabled) {
8410 		OSKextLog(this,
8411 		    kOSKextLogErrorLevel |
8412 		    kOSKextLogLoadFlag,
8413 		    "Kext loading is disabled (attempt to start kext %s).",
8414 		    getIdentifierCString());
8415 		result = kOSKextReturnDisabled;
8416 		goto finish;
8417 	}
8418 
8419 	result = validateKextMapping(/* start? */ true);
8420 	if (result != kOSReturnSuccess) {
8421 		goto finish;
8422 	}
8423 
8424 	startfunc = kmod_info->start;
8425 
8426 	count = getNumDependencies();
8427 	for (i = 0; i < count; i++) {
8428 		OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
8429 		if (dependency == NULL) {
8430 			OSKextLog(this,
8431 			    kOSKextLogErrorLevel |
8432 			    kOSKextLogLoadFlag,
8433 			    "Kext %s start - internal error, dependency disappeared.",
8434 			    getIdentifierCString());
8435 			goto finish;
8436 		}
8437 		if (!dependency->isStarted()) {
8438 			if (startDependenciesFlag) {
8439 				OSReturn dependencyResult =
8440 				    dependency->start(startDependenciesFlag);
8441 				if (dependencyResult != KERN_SUCCESS) {
8442 					OSKextLog(this,
8443 					    kOSKextLogErrorLevel |
8444 					    kOSKextLogLoadFlag,
8445 					    "Kext %s start - dependency %s failed to start (error 0x%x).",
8446 					    getIdentifierCString(),
8447 					    dependency->getIdentifierCString(),
8448 					    dependencyResult);
8449 					goto finish;
8450 				}
8451 			} else {
8452 				OSKextLog(this,
8453 				    kOSKextLogErrorLevel |
8454 				    kOSKextLogLoadFlag,
8455 				    "Not starting %s - dependency %s not started yet.",
8456 				    getIdentifierCString(),
8457 				    dependency->getIdentifierCString());
8458 				result = kOSKextReturnStartStopError;         // xxx - make new return?
8459 				goto finish;
8460 			}
8461 		}
8462 	}
8463 
8464 	OSKextLog(this,
8465 	    kOSKextLogDetailLevel |
8466 	    kOSKextLogLoadFlag,
8467 	    "Kext %s calling module start function.",
8468 	    getIdentifierCString());
8469 
8470 	flags.starting = 1;
8471 
8472 	// Drop a log message so logd can grab the needed information to decode this kext
8473 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
8474 	result = OSRuntimeInitializeCPP(this);
8475 	if (result == KERN_SUCCESS) {
8476 		result = startfunc(kmod_info, kmodStartData);
8477 	}
8478 
8479 	flags.starting = 0;
8480 
8481 	/* On success overlap the setting of started/starting. On failure just
8482 	 * clear starting.
8483 	 */
8484 	if (result == KERN_SUCCESS) {
8485 		flags.started = 1;
8486 
8487 		// xxx - log start error from kernel?
8488 		OSKextLog(this,
8489 		    kOSKextLogProgressLevel |
8490 		    kOSKextLogLoadFlag,
8491 		    "Kext %s is now started.",
8492 		    getIdentifierCString());
8493 	} else {
8494 		invokeOrCancelRequestCallbacks(
8495 			/* result not actually used */ kOSKextReturnStartStopError,
8496 			/* invokeFlag */ false);
8497 		OSKextLog(this,
8498 		    kOSKextLogWarningLevel |
8499 		    kOSKextLogLoadFlag,
8500 		    "Kext %s did not start (return code 0x%x).",
8501 		    getIdentifierCString(), result);
8502 	}
8503 
8504 finish:
8505 	return result;
8506 }
8507 
8508 /*********************************************************************
8509 *********************************************************************/
8510 /* static */
8511 bool
8512 OSKext::canUnloadKextWithIdentifier(
8513 	OSString * kextIdentifier,
8514 	bool       checkClassesFlag)
8515 {
8516 	bool     result = false;
8517 	OSKext * aKext  = NULL;        // do not release
8518 
8519 	IORecursiveLockLock(sKextLock);
8520 
8521 	aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
8522 
8523 	if (!aKext) {
8524 		goto finish;         // can't unload what's not loaded
8525 	}
8526 
8527 	if (aKext->isLoaded()) {
8528 		if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
8529 			goto finish;
8530 		}
8531 		if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
8532 			goto finish;
8533 		}
8534 	}
8535 
8536 	result = true;
8537 
8538 finish:
8539 	IORecursiveLockUnlock(sKextLock);
8540 	return result;
8541 }
8542 
8543 /*********************************************************************
8544 *********************************************************************/
8545 OSReturn
8546 OSKext::stop(void)
8547 {
8548 	OSReturn result = kOSReturnError;
8549 	kern_return_t (*stopfunc)(kmod_info_t *, void *);
8550 
8551 	if (!isStarted() || isInterface()) {
8552 		result = kOSReturnSuccess;
8553 		goto finish;
8554 	}
8555 
8556 	if (!isLoaded()) {
8557 		OSKextLog(this,
8558 		    kOSKextLogErrorLevel |
8559 		    kOSKextLogLoadFlag,
8560 		    "Attempt to stop nonloaded kext %s.",
8561 		    getIdentifierCString());
8562 		result = kOSKextReturnInvalidArgument;
8563 		goto finish;
8564 	}
8565 
8566 	/* Refuse to stop if we have clients or instances. It is up to
8567 	 * the caller to make sure those aren't true.
8568 	 */
8569 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8570 		OSKextLog(this,
8571 		    kOSKextLogErrorLevel |
8572 		    kOSKextLogLoadFlag,
8573 		    "Kext %s - C++ instances; can't stop.",
8574 		    getIdentifierCString());
8575 		result = kOSKextReturnInUse;
8576 		goto finish;
8577 	}
8578 
8579 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8580 		OSKextLog(this,
8581 		    kOSKextLogErrorLevel |
8582 		    kOSKextLogLoadFlag,
8583 		    "Kext %s - has references (linkage or tracking object); "
8584 		    "can't stop.",
8585 		    getIdentifierCString());
8586 		result = kOSKextReturnInUse;
8587 		goto finish;
8588 	}
8589 
8590 	/* Note: If validateKextMapping fails on the stop & unload path,
8591 	 * we are in serious trouble and a kernel panic is likely whether
8592 	 * we stop & unload the kext or not.
8593 	 */
8594 	result = validateKextMapping(/* start? */ false);
8595 	if (result != kOSReturnSuccess) {
8596 		goto finish;
8597 	}
8598 
8599 	stopfunc = kmod_info->stop;
8600 	if (stopfunc) {
8601 		OSKextLog(this,
8602 		    kOSKextLogDetailLevel |
8603 		    kOSKextLogLoadFlag,
8604 		    "Kext %s calling module stop function.",
8605 		    getIdentifierCString());
8606 
8607 		flags.stopping = 1;
8608 
8609 		result = stopfunc(kmod_info, /* userData */ NULL);
8610 		if (result == KERN_SUCCESS) {
8611 			result = OSRuntimeFinalizeCPP(this);
8612 		}
8613 
8614 		flags.stopping = 0;
8615 
8616 		if (result == KERN_SUCCESS) {
8617 			flags.started = 0;
8618 
8619 			OSKextLog(this,
8620 			    kOSKextLogDetailLevel |
8621 			    kOSKextLogLoadFlag,
8622 			    "Kext %s is now stopped and ready to unload.",
8623 			    getIdentifierCString());
8624 		} else {
8625 			OSKextLog(this,
8626 			    kOSKextLogErrorLevel |
8627 			    kOSKextLogLoadFlag,
8628 			    "Kext %s did not stop (return code 0x%x).",
8629 			    getIdentifierCString(), result);
8630 			result = kOSKextReturnStartStopError;
8631 		}
8632 	}
8633 
8634 finish:
8635 	// Drop a log message so logd can update this kext's metadata
8636 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
8637 	return result;
8638 }
8639 
8640 /*********************************************************************
8641 *********************************************************************/
8642 OSReturn
8643 OSKext::unload(void)
8644 {
8645 	OSReturn        result = kOSReturnError;
8646 	unsigned int    index;
8647 	uint32_t        num_kmod_refs = 0;
8648 	OSKextAccount * freeAccount;
8649 	bool            in_fileset = false;
8650 
8651 	if (!sUnloadEnabled) {
8652 		OSKextLog(this,
8653 		    kOSKextLogErrorLevel |
8654 		    kOSKextLogLoadFlag,
8655 		    "Kext unloading is disabled (%s).",
8656 		    this->getIdentifierCString());
8657 
8658 		result = kOSKextReturnDisabled;
8659 		goto finish;
8660 	}
8661 
8662 	// cache this result so we don't need to access the kmod_info after
8663 	// it's been potentially free'd
8664 	in_fileset = isInFileset();
8665 
8666 	/* Refuse to unload if we have clients or instances. It is up to
8667 	 * the caller to make sure those aren't true.
8668 	 */
8669 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8670 		// xxx - Don't log under errors? this is more of an info thing
8671 		OSKextLog(this,
8672 		    kOSKextLogErrorLevel |
8673 		    kOSKextLogKextBookkeepingFlag,
8674 		    "Can't unload kext %s; outstanding references %d (linkage or tracking object).",
8675 		    getIdentifierCString(), getRetainCount());
8676 		result = kOSKextReturnInUse;
8677 		goto finish;
8678 	}
8679 
8680 	if (isDriverKit()) {
8681 		index = sLoadedDriverKitKexts->getNextIndexOfObject(this, 0);
8682 		if (index != (unsigned int)-1) {
8683 			sLoadedDriverKitKexts->removeObject(index);
8684 			OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
8685 			loadTag = 0;
8686 		}
8687 	}
8688 
8689 	if (!isLoaded()) {
8690 		result = kOSReturnSuccess;
8691 		goto finish;
8692 	}
8693 
8694 	if (isKernelComponent()) {
8695 		result = kOSKextReturnInvalidArgument;
8696 		goto finish;
8697 	}
8698 
8699 	if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) {
8700 		OSKextLog(this,
8701 		    kOSKextLogErrorLevel |
8702 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8703 		    "Can't unload kext %s; classes have instances:",
8704 		    getIdentifierCString());
8705 		reportOSMetaClassInstances(kOSKextLogErrorLevel |
8706 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
8707 		result = kOSKextReturnInUse;
8708 		goto finish;
8709 	}
8710 
8711 	/* Note that the kext is unloading before running any code that
8712 	 * might be in the kext (request callbacks, module stop function).
8713 	 * We will deny certain requests made against a kext in the process
8714 	 * of unloading.
8715 	 */
8716 	flags.unloading = 1;
8717 
8718 	/* Update the string describing the last kext to unload in case we panic.
8719 	 */
8720 	savePanicString(/* isLoading */ false);
8721 
8722 	if (isStarted()) {
8723 		result = stop();
8724 		if (result != KERN_SUCCESS) {
8725 			OSKextLog(this,
8726 			    kOSKextLogErrorLevel |
8727 			    kOSKextLogLoadFlag,
8728 			    "Kext %s can't unload - module stop returned 0x%x.",
8729 			    getIdentifierCString(), (unsigned)result);
8730 			result = kOSKextReturnStartStopError;
8731 			goto finish;
8732 		}
8733 	}
8734 
8735 	OSKextLog(this,
8736 	    kOSKextLogProgressLevel |
8737 	    kOSKextLogLoadFlag,
8738 	    "Kext %s unloading.",
8739 	    getIdentifierCString());
8740 
8741 	{
8742 		struct list_head *p;
8743 		struct list_head *prev;
8744 		struct list_head *next;
8745 		for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
8746 			OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
8747 			s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
8748 			prev = p->prev;
8749 			next = p->next;
8750 			prev->next = next;
8751 			next->prev = prev;
8752 			p->prev = p;
8753 			p->next = p;
8754 			IORecursiveLockWakeup(sKextLock, s, false);
8755 		}
8756 	}
8757 
8758 
8759 	/* Even if we don't call the stop function, we want to be sure we
8760 	 * have no OSMetaClass references before unloading the kext executable
8761 	 * from memory. OSMetaClasses may have pointers into the kext executable
8762 	 * and that would cause a panic on OSKext::free() when metaClasses is freed.
8763 	 */
8764 	if (metaClasses) {
8765 		metaClasses->flushCollection();
8766 	}
8767 	(void) OSRuntimeFinalizeCPP(this);
8768 
8769 	/* Remove the kext from the list of loaded kexts, patch the gap
8770 	 * in the kmod_info_t linked list, and reset "kmod" to point to the
8771 	 * last loaded kext that isn't the fake kernel kext (sKernelKext).
8772 	 */
8773 	index = sLoadedKexts->getNextIndexOfObject(this, 0);
8774 	if (index != (unsigned int)-1) {
8775 		sLoadedKexts->removeObject(index);
8776 
8777 		OSKext * nextKext = OSDynamicCast(OSKext,
8778 		    sLoadedKexts->getObject(index));
8779 
8780 		if (nextKext) {
8781 			if (index > 0) {
8782 				OSKext * gapKext = OSDynamicCast(OSKext,
8783 				    sLoadedKexts->getObject(index - 1));
8784 
8785 				nextKext->kmod_info->next = gapKext->kmod_info;
8786 			} else {         /* index == 0 */
8787 				nextKext->kmod_info->next = NULL;
8788 			}
8789 		}
8790 
8791 		OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
8792 		if (lastKext && !lastKext->isKernel()) {
8793 			kmod = lastKext->kmod_info;
8794 		} else {
8795 			kmod = NULL;         // clear the global kmod variable
8796 		}
8797 	}
8798 
8799 	/* Clear out the kmod references that we're keeping for compatibility
8800 	 * with current panic backtrace code & kgmacros.
8801 	 * xxx - will want to update those bits sometime and remove this.
8802 	 */
8803 	num_kmod_refs = getNumDependencies();
8804 	if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
8805 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
8806 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
8807 			ref->info->reference_count--;
8808 		}
8809 		kfree_type(kmod_reference_t, num_kmod_refs,
8810 		    kmod_info->reference_list);
8811 	}
8812 
8813 #if CONFIG_DTRACE
8814 	unregisterWithDTrace();
8815 #endif /* CONFIG_DTRACE */
8816 
8817 	notifyKextUnloadObservers(this);
8818 
8819 	freeAccount = NULL;
8820 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
8821 	account->kext = NULL;
8822 	if (account->site.tag) {
8823 		account->site.flags |= VM_TAG_UNLOAD;
8824 	} else {
8825 		freeAccount = account;
8826 	}
8827 
8828 #if DEVELOPMENT || DEBUG
8829 	assertf(account->task_refgrp.grp_count == 0,
8830 	    "unloading a kext with active task references");
8831 #endif /* DEVELOPMENT || DEBUG */
8832 
8833 	lck_ticket_unlock(sKextAccountsLock);
8834 	if (freeAccount) {
8835 		IOFreeType(freeAccount, OSKextAccount);
8836 	}
8837 
8838 	/* Unwire and free the linked executable.
8839 	 */
8840 	if (linkedExecutable) {
8841 #if KASAN
8842 		kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
8843 #endif
8844 
8845 #if VM_MAPPED_KEXTS
8846 		if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) {
8847 			kernel_segment_command_t *seg = NULL;
8848 			vm_map_t kext_map = kext_get_vm_map(kmod_info);
8849 
8850 			if (!kext_map) {
8851 				OSKextLog(this,
8852 				    kOSKextLogErrorLevel |
8853 				    kOSKextLogLoadFlag,
8854 				    "Failed to free kext %s; couldn't find the kext map.",
8855 				    getIdentifierCString());
8856 				result = kOSKextReturnInternalError;
8857 				goto finish;
8858 			}
8859 
8860 			OSKextLog(this,
8861 			    kOSKextLogProgressLevel |
8862 			    kOSKextLogLoadFlag,
8863 			    "Kext %s unwiring and unmapping linked executable.",
8864 			    getIdentifierCString());
8865 
8866 			seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8867 			while (seg) {
8868 				if (segmentShouldBeWired(seg)) {
8869 					vm_map_offset_t start_wire = trunc_page(seg->vmaddr);
8870 					vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize);
8871 
8872 					result = vm_map_unwire(kext_map, start_wire,
8873 					    end_wire, FALSE);
8874 					if (result != KERN_SUCCESS) {
8875 						OSKextLog(this,
8876 						    kOSKextLogErrorLevel |
8877 						    kOSKextLogLoadFlag,
8878 						    "Failed to unwire kext %s.",
8879 						    getIdentifierCString());
8880 						result = kOSKextReturnInternalError;
8881 						goto finish;
8882 					}
8883 				}
8884 
8885 				seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8886 			}
8887 #if defined(__x86_64__) || defined(__i386__)
8888 			if (in_fileset && flags.resetSegmentsFromVnode) {
8889 				IORecursiveLockLock(sKextLock);
8890 				resetKCFileSetSegments();
8891 				IORecursiveLockUnlock(sKextLock);
8892 			}
8893 #endif // (__x86_64__) || defined(__i386__)
8894 		}
8895 #endif /* VM_MAPPED_KEXTS */
8896 		if (flags.resetSegmentsFromImmutableCopy) {
8897 			result = resetMutableSegments();
8898 			if (result != kOSReturnSuccess) {
8899 				OSKextLog(this,
8900 				    kOSKextLogErrorLevel |
8901 				    kOSKextLogLoadFlag,
8902 				    "Failed to reset kext %s.",
8903 				    getIdentifierCString());
8904 				result = kOSKextReturnInternalError;
8905 				goto finish;
8906 			}
8907 		}
8908 		if (kc_type == KCKindUnknown) {
8909 			linkedExecutable.reset();
8910 		}
8911 	}
8912 
8913 	/* An interface kext has a fake kmod_info that was allocated,
8914 	 * so we have to free it.
8915 	 */
8916 	if (isInterface()) {
8917 		kfree_type(kmod_info_t, kmod_info);
8918 		kmod_info = NULL;
8919 	}
8920 
8921 	if (!in_fileset) {
8922 		kmod_info = NULL;
8923 	}
8924 
8925 	flags.loaded = false;
8926 	flushDependencies();
8927 
8928 	/* save a copy of the bundle ID for us to check when deciding to
8929 	 * rebuild the kernel cache file.  If a kext was already in the kernel
8930 	 * cache and unloaded then later loaded we do not need to rebuild the
8931 	 * kernel cache.  9055303
8932 	 */
8933 	if (isPrelinked()) {
8934 		if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) {
8935 			IORecursiveLockLock(sKextLock);
8936 			if (sUnloadedPrelinkedKexts) {
8937 				sUnloadedPrelinkedKexts->setObject(bundleID.get());
8938 			}
8939 			IORecursiveLockUnlock(sKextLock);
8940 		}
8941 	}
8942 
8943 	OSKextLog(this,
8944 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8945 	    "Kext %s unloaded.", getIdentifierCString());
8946 
8947 	queueKextNotification(kKextRequestPredicateUnloadNotification,
8948 	    OSDynamicCast(OSString, bundleID.get()), getDextUniqueID());
8949 
8950 finish:
8951 	OSKext::saveLoadedKextPanicList();
8952 	OSKext::updateLoadedKextSummaries();
8953 
8954 	flags.unloading = 0;
8955 	return result;
8956 }
8957 
8958 /*********************************************************************
8959 * Assumes sKextLock is held.
8960 *********************************************************************/
8961 /* static */
8962 OSReturn
8963 OSKext::queueKextNotification(
8964 	const char * notificationName,
8965 	OSString   * kextIdentifier,
8966 	OSData     * dextUniqueIdentifier)
8967 {
8968 	OSReturn          result               = kOSReturnError;
8969 	OSSharedPtr<OSDictionary>    loadRequest;
8970 
8971 	if (!kextIdentifier) {
8972 		result = kOSKextReturnInvalidArgument;
8973 		goto finish;
8974 	}
8975 
8976 	/* Create a new request unless one is already sitting
8977 	 * in sKernelRequests for this bundle identifier
8978 	 */
8979 	result = _OSKextCreateRequest(notificationName, loadRequest);
8980 	if (result != kOSReturnSuccess) {
8981 		goto finish;
8982 	}
8983 	if (!_OSKextSetRequestArgument(loadRequest.get(),
8984 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
8985 		result = kOSKextReturnNoMemory;
8986 		goto finish;
8987 	}
8988 	if (NULL != dextUniqueIdentifier) {
8989 		if (!_OSKextSetRequestArgument(loadRequest.get(),
8990 		    kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) {
8991 			result = kOSKextReturnNoMemory;
8992 			goto finish;
8993 		}
8994 	}
8995 	if (!sKernelRequests->setObject(loadRequest.get())) {
8996 		result = kOSKextReturnNoMemory;
8997 		goto finish;
8998 	}
8999 
9000 	/* We might want to only queue the notification if the IOKit daemon is active,
9001 	 * but that wouldn't work for embedded. Note that we don't care if
9002 	 * the ping immediately succeeds here so don't do anything with the
9003 	 * result of this call.
9004 	 */
9005 	OSKext::pingIOKitDaemon();
9006 
9007 	result = kOSReturnSuccess;
9008 
9009 finish:
9010 	return result;
9011 }
9012 
9013 
9014 #if CONFIG_KXLD
9015 /*********************************************************************
9016 *********************************************************************/
9017 static void
9018 _OSKextConsiderDestroyingLinkContext(
9019 	__unused thread_call_param_t p0,
9020 	__unused thread_call_param_t p1)
9021 {
9022 	/* Take multiple locks in the correct order.
9023 	 */
9024 	IORecursiveLockLock(sKextLock);
9025 	IORecursiveLockLock(sKextInnerLock);
9026 
9027 	/* The first time we destroy the kxldContext is in the first
9028 	 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
9029 	 * before calling this function. Thereafter any call to this function
9030 	 * will actually destroy the context.
9031 	 */
9032 	if (sConsiderUnloadsCalled && sKxldContext) {
9033 		kxld_destroy_context(sKxldContext);
9034 		sKxldContext = NULL;
9035 	}
9036 
9037 	/* Free the thread_call that was allocated to execute this function.
9038 	 */
9039 	if (sDestroyLinkContextThread) {
9040 		if (!thread_call_free(sDestroyLinkContextThread)) {
9041 			OSKextLog(/* kext */ NULL,
9042 			    kOSKextLogErrorLevel |
9043 			    kOSKextLogGeneralFlag,
9044 			    "thread_call_free() failed for kext link context.");
9045 		}
9046 		sDestroyLinkContextThread = NULL;
9047 	}
9048 
9049 	IORecursiveLockUnlock(sKextInnerLock);
9050 	IORecursiveLockUnlock(sKextLock);
9051 
9052 	return;
9053 }
9054 
9055 /*********************************************************************
9056 * Destroying the kxldContext requires checking variables under both
9057 * sKextInnerLock and sKextLock, so we do it on a separate thread
9058 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
9059 * call relationship.
9060 *
9061 * This function must be invoked with sKextInnerLock held.
9062 * Do not call any function that takes sKextLock here!
9063 *********************************************************************/
9064 /* static */
9065 void
9066 OSKext::considerDestroyingLinkContext(void)
9067 {
9068 	IORecursiveLockLock(sKextInnerLock);
9069 
9070 	/* If we have already queued a thread to destroy the link context,
9071 	 * don't bother resetting; that thread will take care of it.
9072 	 */
9073 	if (sDestroyLinkContextThread) {
9074 		goto finish;
9075 	}
9076 
9077 	/* The function to be invoked in the thread will deallocate
9078 	 * this thread_call, so don't share it around.
9079 	 */
9080 	sDestroyLinkContextThread = thread_call_allocate(
9081 		&_OSKextConsiderDestroyingLinkContext, NULL);
9082 	if (!sDestroyLinkContextThread) {
9083 		OSKextLog(/* kext */ NULL,
9084 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
9085 		    "Can't create thread to destroy kext link context.");
9086 		goto finish;
9087 	}
9088 
9089 	thread_call_enter(sDestroyLinkContextThread);
9090 
9091 finish:
9092 	IORecursiveLockUnlock(sKextInnerLock);
9093 	return;
9094 }
9095 
9096 #else // !CONFIG_KXLD
9097 
9098 /* static */
9099 void
9100 OSKext::considerDestroyingLinkContext(void)
9101 {
9102 	return;
9103 }
9104 
9105 #endif // CONFIG_KXLD
9106 
9107 #if PRAGMA_MARK
9108 #pragma mark Autounload
9109 #endif
9110 /*********************************************************************
9111 * This is a static method because the kext will be deallocated if it
9112 * does unload!
9113 *********************************************************************/
9114 /* static */
9115 OSReturn
9116 OSKext::autounloadKext(OSKext * aKext)
9117 {
9118 	OSReturn result = kOSKextReturnInUse;
9119 
9120 #if NO_KEXTD
9121 	/*
9122 	 * Do not unload prelinked kexts on platforms that do not have an
9123 	 * IOKit daemon as there is no way to reload the kext or restart
9124 	 * matching.
9125 	 */
9126 	if (aKext->isPrelinked()) {
9127 		goto finish;
9128 	}
9129 #endif /* defined(__x86_64__) */
9130 
9131 	/* Check for external references to this kext (usu. dependents),
9132 	 * instances of defined classes (or classes derived from them),
9133 	 * outstanding requests.
9134 	 */
9135 	if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
9136 	    !aKext->flags.autounloadEnabled ||
9137 	    aKext->isKernelComponent()) {
9138 		goto finish;
9139 	}
9140 
9141 	/* Skip a delay-autounload kext, once.
9142 	 */
9143 	if (aKext->flags.delayAutounload) {
9144 		OSKextLog(aKext,
9145 		    kOSKextLogProgressLevel |
9146 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
9147 		    "Kext %s has delayed autounload set; skipping and clearing flag.",
9148 		    aKext->getIdentifierCString());
9149 		aKext->flags.delayAutounload = 0;
9150 		goto finish;
9151 	}
9152 
9153 	if (aKext->hasOSMetaClassInstances() ||
9154 	    aKext->countRequestCallbacks()) {
9155 		goto finish;
9156 	}
9157 
9158 	result = OSKext::removeKext(aKext);
9159 
9160 finish:
9161 	return result;
9162 }
9163 
9164 /*********************************************************************
9165 *********************************************************************/
9166 void
9167 _OSKextConsiderUnloads(
9168 	__unused thread_call_param_t p0,
9169 	__unused thread_call_param_t p1)
9170 {
9171 	bool         didUnload = false;
9172 	unsigned int count, i;
9173 
9174 	/* Take multiple locks in the correct order
9175 	 * (note also sKextSummaries lock further down).
9176 	 */
9177 	IORecursiveLockLock(sKextLock);
9178 	IORecursiveLockLock(sKextInnerLock);
9179 
9180 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
9181 
9182 	/* If the system is powering down, don't try to unload anything.
9183 	 */
9184 	if (sSystemSleep) {
9185 		goto finish;
9186 	}
9187 
9188 	OSKextLog(/* kext */ NULL,
9189 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
9190 	    "Checking for unused kexts to autounload.");
9191 
9192 	/*****
9193 	 * Remove any request callbacks marked as stale,
9194 	 * and mark as stale any currently in flight.
9195 	 */
9196 	count = sRequestCallbackRecords->getCount();
9197 	if (count) {
9198 		i = count - 1;
9199 		do {
9200 			OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
9201 			    sRequestCallbackRecords->getObject(i));
9202 			if (callbackRecord) {
9203 				OSBoolean * stale = OSDynamicCast(OSBoolean,
9204 				    callbackRecord->getObject(kKextRequestStaleKey));
9205 
9206 				if (stale == kOSBooleanTrue) {
9207 					OSKext::invokeRequestCallback(callbackRecord,
9208 					    kOSKextReturnTimeout);
9209 				} else {
9210 					callbackRecord->setObject(kKextRequestStaleKey,
9211 					    kOSBooleanTrue);
9212 				}
9213 			}
9214 		} while (i--);
9215 	}
9216 
9217 	/*****
9218 	 * Make multiple passes through the array of loaded kexts until
9219 	 * we don't unload any. This handles unwinding of dependency
9220 	 * chains. We have to go *backwards* through the array because
9221 	 * kexts are removed from it when unloaded, and we cannot make
9222 	 * a copy or we'll mess up the retain counts we rely on to
9223 	 * check whether a kext will unload. If only we could have
9224 	 * nonretaining collections like CF has....
9225 	 */
9226 	do {
9227 		didUnload = false;
9228 
9229 		count = sLoadedKexts->getCount();
9230 		if (count) {
9231 			i = count - 1;
9232 			do {
9233 				OSKext * thisKext = OSDynamicCast(OSKext,
9234 				    sLoadedKexts->getObject(i));
9235 				didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
9236 			} while (i--);
9237 		}
9238 	} while (didUnload);
9239 
9240 finish:
9241 	sConsiderUnloadsPending = false;
9242 	sConsiderUnloadsExecuted = true;
9243 
9244 	(void) OSKext::considerRebuildOfPrelinkedKernel();
9245 
9246 	IORecursiveLockUnlock(sKextInnerLock);
9247 	IORecursiveLockUnlock(sKextLock);
9248 
9249 	return;
9250 }
9251 
9252 /*********************************************************************
9253 * Do not call any function that takes sKextLock here!
9254 *********************************************************************/
9255 void
9256 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
9257 {
9258 	AbsoluteTime when;
9259 
9260 	IORecursiveLockLock(sKextInnerLock);
9261 
9262 	if (!sUnloadCallout) {
9263 		sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL);
9264 	}
9265 
9266 	/* we only reset delay value for unloading if we already have something
9267 	 * pending.  rescheduleOnlyFlag should not start the count down.
9268 	 */
9269 	if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
9270 		goto finish;
9271 	}
9272 
9273 	thread_call_cancel(sUnloadCallout);
9274 	if (OSKext::getAutounloadEnabled() && !sSystemSleep
9275 #if !NO_KEXTD
9276 	    && sIOKitDaemonActive
9277 #endif
9278 	    ) {
9279 		clock_interval_to_deadline(sConsiderUnloadDelay,
9280 		    1000 * 1000 * 1000, &when);
9281 
9282 		OSKextLog(/* kext */ NULL,
9283 		    kOSKextLogProgressLevel |
9284 		    kOSKextLogLoadFlag,
9285 		    "%scheduling %sscan for unused kexts in %lu seconds.",
9286 		    sConsiderUnloadsPending ? "Res" : "S",
9287 		    sConsiderUnloadsCalled ? "" : "initial ",
9288 		    (unsigned long)sConsiderUnloadDelay);
9289 
9290 		sConsiderUnloadsPending = true;
9291 		thread_call_enter_delayed(sUnloadCallout, when);
9292 	}
9293 
9294 finish:
9295 	/* The kxld context should be reused throughout boot.  We mark the end of
9296 	 * period as the first time considerUnloads() is called, and we destroy
9297 	 * the first kxld context in that function.  Afterwards, it will be
9298 	 * destroyed in flushNonloadedKexts.
9299 	 */
9300 	if (!sConsiderUnloadsCalled) {
9301 		sConsiderUnloadsCalled = true;
9302 		OSKext::considerDestroyingLinkContext();
9303 	}
9304 
9305 	IORecursiveLockUnlock(sKextInnerLock);
9306 	return;
9307 }
9308 
9309 /*********************************************************************
9310 * Do not call any function that takes sKextLock here!
9311 *********************************************************************/
9312 extern "C" {
9313 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
9314 IOReturn
9315 OSKextSystemSleepOrWake(UInt32 messageType)
9316 {
9317 	IORecursiveLockLock(sKextInnerLock);
9318 
9319 	/* If the system is going to sleep, cancel the reaper thread timer,
9320 	 * and note that we're in a sleep state in case it just fired but hasn't
9321 	 * taken the lock yet. If we are coming back from sleep, just
9322 	 * clear the sleep flag; IOService's normal operation will cause
9323 	 * unloads to be considered soon enough.
9324 	 */
9325 	if (messageType == kIOMessageSystemWillSleep) {
9326 		if (sUnloadCallout) {
9327 			thread_call_cancel(sUnloadCallout);
9328 		}
9329 		sSystemSleep = true;
9330 		AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
9331 	} else if (messageType == kIOMessageSystemHasPoweredOn) {
9332 		sSystemSleep = false;
9333 		clock_get_uptime(&sLastWakeTime);
9334 	}
9335 	IORecursiveLockUnlock(sKextInnerLock);
9336 
9337 	return kIOReturnSuccess;
9338 }
9339 };
9340 
9341 
9342 #if PRAGMA_MARK
9343 #pragma mark Prelinked Kernel
9344 #endif
9345 
9346 #ifdef CONFIG_KXLD
9347 /*********************************************************************
9348 * Do not access sConsiderUnloads... variables other than
9349 * sConsiderUnloadsExecuted in this function. They are guarded by a
9350 * different lock.
9351 *********************************************************************/
9352 /* static */
9353 void
9354 OSKext::considerRebuildOfPrelinkedKernel(void)
9355 {
9356 	static bool     requestedPrelink        = false;
9357 	OSReturn        checkResult             = kOSReturnError;
9358 	OSSharedPtr<OSDictionary>         prelinkRequest;
9359 	OSSharedPtr<OSCollectionIterator> kextIterator;
9360 	const OSSymbol * thisID                 = NULL;        // do not release
9361 	bool            doRebuild               = false;
9362 	AbsoluteTime    my_abstime;
9363 	UInt64          my_ns;
9364 	SInt32          delta_secs;
9365 
9366 	/* Only one auto rebuild per boot and only on boot from prelinked kernel */
9367 	if (requestedPrelink || !sPrelinkBoot) {
9368 		return;
9369 	}
9370 
9371 	/* no direct return from this point */
9372 	IORecursiveLockLock(sKextLock);
9373 
9374 	/* We need to wait for the IOKit daemon to get up and running with unloads already done
9375 	 * and any new startup kexts loaded.
9376 	 */
9377 	if (!sConsiderUnloadsExecuted ||
9378 	    !sDeferredLoadSucceeded) {
9379 		goto finish;
9380 	}
9381 
9382 	/* we really only care about boot / system start up related kexts so bail
9383 	 * if we're here after REBUILD_MAX_TIME.
9384 	 */
9385 	if (!_OSKextInPrelinkRebuildWindow()) {
9386 		OSKextLog(/* kext */ NULL,
9387 		    kOSKextLogArchiveFlag,
9388 		    "%s prebuild rebuild has expired",
9389 		    __FUNCTION__);
9390 		requestedPrelink = true;
9391 		goto finish;
9392 	}
9393 
9394 	/* we do not want to trigger a rebuild if we get here too close to waking
9395 	 * up.  (see radar 10233768)
9396 	 */
9397 	IORecursiveLockLock(sKextInnerLock);
9398 
9399 	clock_get_uptime(&my_abstime);
9400 	delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
9401 	if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
9402 		SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
9403 		absolutetime_to_nanoseconds(my_abstime, &my_ns);
9404 		delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
9405 	}
9406 	IORecursiveLockUnlock(sKextInnerLock);
9407 
9408 	if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
9409 		/* too close to time of last wake from sleep */
9410 		goto finish;
9411 	}
9412 	requestedPrelink = true;
9413 
9414 	/* Now it's time to see if we have a reason to rebuild.  We may have done
9415 	 * some loads and unloads but the kernel cache didn't actually change.
9416 	 * We will rebuild if any kext is not marked prelinked AND is not in our
9417 	 * list of prelinked kexts that got unloaded.  (see radar 9055303)
9418 	 */
9419 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
9420 	if (!kextIterator) {
9421 		goto finish;
9422 	}
9423 
9424 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
9425 		OSKext *    thisKext;        // do not release
9426 
9427 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
9428 		if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
9429 			continue;
9430 		}
9431 
9432 		if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) {
9433 			continue;
9434 		}
9435 		/* kext is loaded and was not in current kernel cache so let's rebuild
9436 		 */
9437 		doRebuild = true;
9438 		OSKextLog(/* kext */ NULL,
9439 		    kOSKextLogArchiveFlag,
9440 		    "considerRebuildOfPrelinkedKernel %s triggered rebuild",
9441 		    thisKext->bundleID->getCStringNoCopy());
9442 		break;
9443 	}
9444 	sUnloadedPrelinkedKexts->flushCollection();
9445 
9446 	if (!doRebuild) {
9447 		goto finish;
9448 	}
9449 
9450 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
9451 	    prelinkRequest);
9452 	if (checkResult != kOSReturnSuccess) {
9453 		goto finish;
9454 	}
9455 
9456 	if (!sKernelRequests->setObject(prelinkRequest.get())) {
9457 		goto finish;
9458 	}
9459 
9460 	OSKext::pingIOKitDaemon();
9461 
9462 finish:
9463 	IORecursiveLockUnlock(sKextLock);
9464 
9465 	return;
9466 }
9467 
9468 #else /* !CONFIG_KXLD */
9469 
9470 void
9471 OSKext::considerRebuildOfPrelinkedKernel(void)
9472 {
9473 	/* in a non-dynamic kext loading world, there is never a reason to rebuild */
9474 	return;
9475 }
9476 
9477 #endif /* CONFIG_KXLD */
9478 
9479 #if PRAGMA_MARK
9480 #pragma mark Dependencies
9481 #endif
9482 /*********************************************************************
9483 *********************************************************************/
9484 bool
9485 OSKext::resolveDependencies(
9486 	OSArray * loopStack)
9487 {
9488 	bool                   result                   = false;
9489 	OSSharedPtr<OSArray>   localLoopStack;
9490 	bool                   addedToLoopStack         = false;
9491 	OSDictionary         * libraries                = NULL;        // do not release
9492 	OSSharedPtr<OSCollectionIterator> libraryIterator;
9493 	OSString             * libraryID                = NULL;        // do not release
9494 	OSKext               * libraryKext              = NULL;        // do not release
9495 	bool                   hasRawKernelDependency   = false;
9496 	bool                   hasKernelDependency      = false;
9497 	bool                   hasKPIDependency         = false;
9498 	bool                   hasPrivateKPIDependency  = false;
9499 	unsigned int           count;
9500 
9501 #if CONFIG_KXLD
9502 	OSString             * infoString               = NULL;        // do not release
9503 	OSString             * readableString           = NULL;        // do not release
9504 #endif // CONFIG_KXLD
9505 
9506 	/* A kernel component will automatically have this flag set,
9507 	 * and a loaded kext should also have it set (as should all its
9508 	 * loaded dependencies).
9509 	 */
9510 	if (flags.hasAllDependencies) {
9511 		result = true;
9512 		goto finish;
9513 	}
9514 
9515 	/* Check for loops in the dependency graph.
9516 	 */
9517 	if (loopStack) {
9518 		if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
9519 			OSKextLog(this,
9520 			    kOSKextLogErrorLevel |
9521 			    kOSKextLogDependenciesFlag,
9522 			    "Kext %s has a dependency loop; can't resolve dependencies.",
9523 			    getIdentifierCString());
9524 			goto finish;
9525 		}
9526 	} else {
9527 		OSKextLog(this,
9528 		    kOSKextLogStepLevel |
9529 		    kOSKextLogDependenciesFlag,
9530 		    "Kext %s resolving dependencies.",
9531 		    getIdentifierCString());
9532 
9533 		localLoopStack = OSArray::withCapacity(6);         // any small capacity will do
9534 		if (!localLoopStack) {
9535 			OSKextLog(this,
9536 			    kOSKextLogErrorLevel |
9537 			    kOSKextLogDependenciesFlag,
9538 			    "Kext %s can't create bookkeeping stack to resolve dependencies.",
9539 			    getIdentifierCString());
9540 			goto finish;
9541 		}
9542 		loopStack = localLoopStack.get();
9543 	}
9544 	if (!loopStack->setObject(this)) {
9545 		OSKextLog(this,
9546 		    kOSKextLogErrorLevel |
9547 		    kOSKextLogDependenciesFlag,
9548 		    "Kext %s - internal error resolving dependencies.",
9549 		    getIdentifierCString());
9550 		goto finish;
9551 	}
9552 	addedToLoopStack = true;
9553 
9554 	/* Purge any existing kexts in the dependency list and start over.
9555 	 */
9556 	flushDependencies();
9557 	if (dependencies) {
9558 		OSKextLog(this,
9559 		    kOSKextLogErrorLevel |
9560 		    kOSKextLogDependenciesFlag,
9561 		    "Kext %s - internal error resolving dependencies.",
9562 		    getIdentifierCString());
9563 	}
9564 
9565 	libraries = OSDynamicCast(OSDictionary,
9566 	    getPropertyForHostArch(kOSBundleLibrariesKey));
9567 	if (libraries == NULL || libraries->getCount() == 0) {
9568 		OSKextLog(this,
9569 		    kOSKextLogErrorLevel |
9570 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9571 		    "Kext %s - can't resolve dependencies; %s missing/invalid type.",
9572 		    getIdentifierCString(), kOSBundleLibrariesKey);
9573 		goto finish;
9574 	}
9575 
9576 	/* Make a new array to hold the dependencies (flush freed the old one).
9577 	 */
9578 	dependencies = OSArray::withCapacity(libraries->getCount());
9579 	if (!dependencies) {
9580 		OSKextLog(this,
9581 		    kOSKextLogErrorLevel |
9582 		    kOSKextLogDependenciesFlag,
9583 		    "Kext %s - can't allocate dependencies array.",
9584 		    getIdentifierCString());
9585 		goto finish;
9586 	}
9587 
9588 	// xxx - compat: We used to add an implicit dependency on kernel 6.0
9589 	// xxx - compat: if none were declared.
9590 
9591 	libraryIterator = OSCollectionIterator::withCollection(libraries);
9592 	if (!libraryIterator) {
9593 		OSKextLog(this,
9594 		    kOSKextLogErrorLevel |
9595 		    kOSKextLogDependenciesFlag,
9596 		    "Kext %s - can't allocate dependencies iterator.",
9597 		    getIdentifierCString());
9598 		goto finish;
9599 	}
9600 
9601 	while ((libraryID = OSDynamicCast(OSString,
9602 	    libraryIterator->getNextObject()))) {
9603 		const char * library_id = libraryID->getCStringNoCopy();
9604 
9605 		OSString * libraryVersion = OSDynamicCast(OSString,
9606 		    libraries->getObject(libraryID));
9607 		if (libraryVersion == NULL) {
9608 			OSKextLog(this,
9609 			    kOSKextLogErrorLevel |
9610 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9611 			    "Kext %s - illegal type in OSBundleLibraries.",
9612 			    getIdentifierCString());
9613 			goto finish;
9614 		}
9615 
9616 		OSKextVersion libraryVers =
9617 		    OSKextParseVersionString(libraryVersion->getCStringNoCopy());
9618 		if (libraryVers == -1) {
9619 			OSKextLog(this,
9620 			    kOSKextLogErrorLevel |
9621 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9622 			    "Kext %s - invalid library version %s.",
9623 			    getIdentifierCString(),
9624 			    libraryVersion->getCStringNoCopy());
9625 			goto finish;
9626 		}
9627 
9628 		libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
9629 		if (libraryKext == NULL) {
9630 			OSKextLog(this,
9631 			    kOSKextLogErrorLevel |
9632 			    kOSKextLogDependenciesFlag,
9633 			    "Kext %s - library kext %s not found.",
9634 			    getIdentifierCString(), library_id);
9635 			goto finish;
9636 		}
9637 
9638 		if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
9639 			OSKextLog(this,
9640 			    kOSKextLogErrorLevel |
9641 			    kOSKextLogDependenciesFlag,
9642 			    "Kext %s - library kext %s not compatible "
9643 			    "with requested version %s.",
9644 			    getIdentifierCString(), library_id,
9645 			    libraryVersion->getCStringNoCopy());
9646 			goto finish;
9647 		}
9648 
9649 		/* If a nonprelinked library somehow got into the mix for a
9650 		 * prelinked kext, at any point in the chain, we must fail
9651 		 * because the prelinked relocs for the library will be all wrong.
9652 		 */
9653 		if (this->isPrelinked() &&
9654 		    libraryKext->declaresExecutable() &&
9655 		    !libraryKext->isPrelinked()) {
9656 			OSKextLog(this,
9657 			    kOSKextLogErrorLevel |
9658 			    kOSKextLogDependenciesFlag,
9659 			    "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
9660 			    getIdentifierCString(), library_id,
9661 			    libraryVersion->getCStringNoCopy());
9662 			goto finish;
9663 		}
9664 
9665 		if (!libraryKext->resolveDependencies(loopStack)) {
9666 			goto finish;
9667 		}
9668 
9669 		/* Add the library directly only if it has an executable to link.
9670 		 * Otherwise it's just used to collect other dependencies, so put
9671 		 * *its* dependencies on the list for this kext.
9672 		 */
9673 		// xxx - We are losing info here; would like to make fake entries or
9674 		// xxx - keep these in the dependency graph for loaded kexts.
9675 		// xxx - I really want to make kernel components not a special case!
9676 		if (libraryKext->declaresExecutable() ||
9677 		    libraryKext->isInterface()) {
9678 			if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
9679 				dependencies->setObject(libraryKext);
9680 
9681 				OSKextLog(this,
9682 				    kOSKextLogDetailLevel |
9683 				    kOSKextLogDependenciesFlag,
9684 				    "Kext %s added dependency %s.",
9685 				    getIdentifierCString(),
9686 				    libraryKext->getIdentifierCString());
9687 			}
9688 		} else {
9689 			int       numLibDependencies  = libraryKext->getNumDependencies();
9690 			OSArray * libraryDependencies = libraryKext->getDependencies();
9691 			int       index;
9692 
9693 			if (numLibDependencies) {
9694 				// xxx - this msg level should be 1 lower than the per-kext one
9695 				OSKextLog(this,
9696 				    kOSKextLogDetailLevel |
9697 				    kOSKextLogDependenciesFlag,
9698 				    "Kext %s pulling %d dependencies from codeless library %s.",
9699 				    getIdentifierCString(),
9700 				    numLibDependencies,
9701 				    libraryKext->getIdentifierCString());
9702 			}
9703 			for (index = 0; index < numLibDependencies; index++) {
9704 				OSKext * thisLibDependency = OSDynamicCast(OSKext,
9705 				    libraryDependencies->getObject(index));
9706 				if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
9707 					dependencies->setObject(thisLibDependency);
9708 					OSKextLog(this,
9709 					    kOSKextLogDetailLevel |
9710 					    kOSKextLogDependenciesFlag,
9711 					    "Kext %s added dependency %s from codeless library %s.",
9712 					    getIdentifierCString(),
9713 					    thisLibDependency->getIdentifierCString(),
9714 					    libraryKext->getIdentifierCString());
9715 				}
9716 			}
9717 		}
9718 
9719 		if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
9720 		    0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
9721 			hasRawKernelDependency = true;
9722 		} else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
9723 			hasKernelDependency = true;
9724 		} else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
9725 			hasKPIDependency = true;
9726 			if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
9727 				hasPrivateKPIDependency = true;
9728 			}
9729 		}
9730 	}
9731 
9732 	if (hasRawKernelDependency) {
9733 		OSKextLog(this,
9734 		    kOSKextLogErrorLevel |
9735 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9736 		    "Error - kext %s declares a dependency on %s, which is not permitted.",
9737 		    getIdentifierCString(), KERNEL_LIB);
9738 		goto finish;
9739 	}
9740 #if __LP64__
9741 	if (hasKernelDependency) {
9742 		OSKextLog(this,
9743 		    kOSKextLogErrorLevel |
9744 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9745 		    "Error - kext %s declares %s dependencies. "
9746 		    "Only %s* dependencies are supported for 64-bit kexts.",
9747 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
9748 		goto finish;
9749 	}
9750 	if (!hasKPIDependency) {
9751 		OSKextLog(this,
9752 		    kOSKextLogWarningLevel |
9753 		    kOSKextLogDependenciesFlag,
9754 		    "Warning - kext %s declares no %s* dependencies. "
9755 		    "If it uses any KPIs, the link may fail with undefined symbols.",
9756 		    getIdentifierCString(), KPI_LIB_PREFIX);
9757 	}
9758 #else /* __LP64__ */
9759 	// xxx - will change to flatly disallow "kernel" dependencies at some point
9760 	// xxx - is it invalid to do both "com.apple.kernel" and any
9761 	// xxx - "com.apple.kernel.*"?
9762 
9763 	if (hasKernelDependency && hasKPIDependency) {
9764 		OSKextLog(this,
9765 		    kOSKextLogWarningLevel |
9766 		    kOSKextLogDependenciesFlag,
9767 		    "Warning - kext %s has immediate dependencies on both "
9768 		    "%s* and %s* components; use only one style.",
9769 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
9770 	}
9771 
9772 	if (!hasKernelDependency && !hasKPIDependency) {
9773 		// xxx - do we want to use validation flag for these too?
9774 		OSKextLog(this,
9775 		    kOSKextLogWarningLevel |
9776 		    kOSKextLogDependenciesFlag,
9777 		    "Warning - %s declares no kernel dependencies; using %s.",
9778 		    getIdentifierCString(), KERNEL6_LIB);
9779 		OSKext * kernelKext = OSDynamicCast(OSKext,
9780 		    sKextsByID->getObject(KERNEL6_LIB));
9781 		if (kernelKext) {
9782 			dependencies->setObject(kernelKext);
9783 		} else {
9784 			OSKextLog(this,
9785 			    kOSKextLogErrorLevel |
9786 			    kOSKextLogDependenciesFlag,
9787 			    "Error - Library %s not found for %s.",
9788 			    KERNEL6_LIB, getIdentifierCString());
9789 		}
9790 	}
9791 
9792 	/* If the kext doesn't have a raw kernel or KPI dependency, then add all of
9793 	 * its indirect dependencies to simulate old-style linking.  XXX - Should
9794 	 * check for duplicates.
9795 	 */
9796 	if (!hasKPIDependency) {
9797 		unsigned int i;
9798 
9799 		flags.hasBleedthrough = true;
9800 
9801 		count = getNumDependencies();
9802 
9803 		/* We add to the dependencies array in this loop, but do not iterate
9804 		 * past its original count.
9805 		 */
9806 		for (i = 0; i < count; i++) {
9807 			OSKext * dependencyKext = OSDynamicCast(OSKext,
9808 			    dependencies->getObject(i));
9809 			dependencyKext->addBleedthroughDependencies(dependencies.get());
9810 		}
9811 	}
9812 #endif /* __LP64__ */
9813 
9814 #if CONFIG_KXLD
9815 	/*
9816 	 * If we're not dynamically linking kexts, then we don't need to check
9817 	 * copyright strings. The linker in user space has already done this.
9818 	 */
9819 	if (hasPrivateKPIDependency) {
9820 		bool hasApplePrefix = false;
9821 		bool infoCopyrightIsValid = false;
9822 		bool readableCopyrightIsValid = false;
9823 
9824 		hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
9825 		    APPLE_KEXT_PREFIX);
9826 
9827 		infoString = OSDynamicCast(OSString,
9828 		    getPropertyForHostArch("CFBundleGetInfoString"));
9829 		if (infoString) {
9830 			infoCopyrightIsValid =
9831 			    kxld_validate_copyright_string(infoString->getCStringNoCopy());
9832 		}
9833 
9834 		readableString = OSDynamicCast(OSString,
9835 		    getPropertyForHostArch("NSHumanReadableCopyright"));
9836 		if (readableString) {
9837 			readableCopyrightIsValid =
9838 			    kxld_validate_copyright_string(readableString->getCStringNoCopy());
9839 		}
9840 
9841 		if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
9842 			OSKextLog(this,
9843 			    kOSKextLogErrorLevel |
9844 			    kOSKextLogDependenciesFlag,
9845 			    "Error - kext %s declares a dependency on %s. "
9846 			    "Only Apple kexts may declare a dependency on %s.",
9847 			    getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
9848 			goto finish;
9849 		}
9850 	}
9851 #endif // CONFIG_KXLD
9852 
9853 	result = true;
9854 	flags.hasAllDependencies = 1;
9855 
9856 finish:
9857 
9858 	if (addedToLoopStack) {
9859 		count = loopStack->getCount();
9860 		if (count > 0 && (this == loopStack->getObject(count - 1))) {
9861 			loopStack->removeObject(count - 1);
9862 		} else {
9863 			OSKextLog(this,
9864 			    kOSKextLogErrorLevel |
9865 			    kOSKextLogDependenciesFlag,
9866 			    "Kext %s - internal error resolving dependencies.",
9867 			    getIdentifierCString());
9868 		}
9869 	}
9870 
9871 	if (result && localLoopStack) {
9872 		OSKextLog(this,
9873 		    kOSKextLogStepLevel |
9874 		    kOSKextLogDependenciesFlag,
9875 		    "Kext %s successfully resolved dependencies.",
9876 		    getIdentifierCString());
9877 	}
9878 
9879 	return result;
9880 }
9881 
9882 /*********************************************************************
9883 *********************************************************************/
9884 bool
9885 OSKext::addBleedthroughDependencies(OSArray * anArray)
9886 {
9887 	bool result = false;
9888 	unsigned int dependencyIndex, dependencyCount;
9889 
9890 	dependencyCount = getNumDependencies();
9891 
9892 	for (dependencyIndex = 0;
9893 	    dependencyIndex < dependencyCount;
9894 	    dependencyIndex++) {
9895 		OSKext * dependency = OSDynamicCast(OSKext,
9896 		    dependencies->getObject(dependencyIndex));
9897 		if (!dependency) {
9898 			OSKextLog(this,
9899 			    kOSKextLogErrorLevel |
9900 			    kOSKextLogDependenciesFlag,
9901 			    "Kext %s - internal error propagating compatibility dependencies.",
9902 			    getIdentifierCString());
9903 			goto finish;
9904 		}
9905 		if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
9906 			anArray->setObject(dependency);
9907 		}
9908 		dependency->addBleedthroughDependencies(anArray);
9909 	}
9910 
9911 	result = true;
9912 
9913 finish:
9914 	return result;
9915 }
9916 
9917 /*********************************************************************
9918 *********************************************************************/
9919 bool
9920 OSKext::flushDependencies(bool forceFlag)
9921 {
9922 	bool result = false;
9923 
9924 	/* Only clear the dependencies if the kext isn't loaded;
9925 	 * we need the info for loaded kexts to track references.
9926 	 */
9927 	if (!isLoaded() || forceFlag) {
9928 		if (dependencies) {
9929 			// xxx - check level
9930 			OSKextLog(this,
9931 			    kOSKextLogProgressLevel |
9932 			    kOSKextLogDependenciesFlag,
9933 			    "Kext %s flushing dependencies.",
9934 			    getIdentifierCString());
9935 			dependencies.reset();
9936 		}
9937 		if (!isKernelComponent()) {
9938 			flags.hasAllDependencies = 0;
9939 		}
9940 		result = true;
9941 	}
9942 
9943 	return result;
9944 }
9945 
9946 /*********************************************************************
9947 *********************************************************************/
9948 uint32_t
9949 OSKext::getNumDependencies(void)
9950 {
9951 	if (!dependencies) {
9952 		return 0;
9953 	}
9954 	return dependencies->getCount();
9955 }
9956 
9957 /*********************************************************************
9958 *********************************************************************/
9959 OSArray *
9960 OSKext::getDependencies(void)
9961 {
9962 	return dependencies.get();
9963 }
9964 
9965 bool
9966 OSKext::hasDependency(const OSSymbol * depID)
9967 {
9968 	bool result __block;
9969 
9970 	if (depID == getIdentifier()) {
9971 		return true;
9972 	}
9973 	if (!dependencies) {
9974 		return false;
9975 	}
9976 	result = false;
9977 	dependencies->iterateObjects(^bool (OSObject * obj) {
9978 		OSKext * kext;
9979 		kext = OSDynamicCast(OSKext, obj);
9980 		if (!kext) {
9981 		        return false;
9982 		}
9983 		result = (depID == kext->getIdentifier());
9984 		return result;
9985 	});
9986 	return result;
9987 }
9988 
9989 #if PRAGMA_MARK
9990 #pragma mark OSMetaClass Support
9991 #endif
9992 /*********************************************************************
9993 *********************************************************************/
9994 OSReturn
9995 OSKext::addClass(
9996 	OSMetaClass * aClass,
9997 	uint32_t      numClasses)
9998 {
9999 	OSReturn result = kOSMetaClassNoInsKModSet;
10000 
10001 	if (!metaClasses) {
10002 		metaClasses = OSSet::withCapacity(numClasses);
10003 		if (!metaClasses) {
10004 			goto finish;
10005 		}
10006 	}
10007 
10008 	if (metaClasses->containsObject(aClass)) {
10009 		OSKextLog(this,
10010 		    kOSKextLogWarningLevel |
10011 		    kOSKextLogLoadFlag,
10012 		    "Notice - kext %s has already registered class %s.",
10013 		    getIdentifierCString(),
10014 		    aClass->getClassName());
10015 		result = kOSReturnSuccess;
10016 		goto finish;
10017 	}
10018 
10019 	if (!metaClasses->setObject(aClass)) {
10020 		goto finish;
10021 	} else {
10022 		OSKextLog(this,
10023 		    kOSKextLogDetailLevel |
10024 		    kOSKextLogLoadFlag,
10025 		    "Kext %s registered class %s.",
10026 		    getIdentifierCString(),
10027 		    aClass->getClassName());
10028 	}
10029 
10030 	if (!flags.autounloadEnabled) {
10031 		const OSMetaClass * metaScan  = NULL;        // do not release
10032 
10033 		for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
10034 			if (metaScan == OSTypeID(IOService)) {
10035 				OSKextLog(this,
10036 				    kOSKextLogProgressLevel |
10037 				    kOSKextLogLoadFlag,
10038 				    "Kext %s has IOService subclass %s; enabling autounload.",
10039 				    getIdentifierCString(),
10040 				    aClass->getClassName());
10041 
10042 				flags.autounloadEnabled = (0 == flags.unloadUnsupported);
10043 				break;
10044 			}
10045 		}
10046 	}
10047 
10048 	notifyAddClassObservers(this, aClass, flags);
10049 
10050 	result = kOSReturnSuccess;
10051 
10052 finish:
10053 	if (result != kOSReturnSuccess) {
10054 		OSKextLog(this,
10055 		    kOSKextLogErrorLevel |
10056 		    kOSKextLogLoadFlag,
10057 		    "Kext %s failed to register class %s.",
10058 		    getIdentifierCString(),
10059 		    aClass->getClassName());
10060 	}
10061 
10062 	return result;
10063 }
10064 
10065 /*********************************************************************
10066 *********************************************************************/
10067 OSReturn
10068 OSKext::removeClass(
10069 	OSMetaClass * aClass)
10070 {
10071 	OSReturn result = kOSMetaClassNoKModSet;
10072 
10073 	if (!metaClasses) {
10074 		goto finish;
10075 	}
10076 
10077 	if (!metaClasses->containsObject(aClass)) {
10078 		OSKextLog(this,
10079 		    kOSKextLogWarningLevel |
10080 		    kOSKextLogLoadFlag,
10081 		    "Notice - kext %s asked to unregister unknown class %s.",
10082 		    getIdentifierCString(),
10083 		    aClass->getClassName());
10084 		result = kOSReturnSuccess;
10085 		goto finish;
10086 	}
10087 
10088 	OSKextLog(this,
10089 	    kOSKextLogDetailLevel |
10090 	    kOSKextLogLoadFlag,
10091 	    "Kext %s unregistering class %s.",
10092 	    getIdentifierCString(),
10093 	    aClass->getClassName());
10094 
10095 	metaClasses->removeObject(aClass);
10096 
10097 	notifyRemoveClassObservers(this, aClass, flags);
10098 
10099 	result = kOSReturnSuccess;
10100 
10101 finish:
10102 	if (result != kOSReturnSuccess) {
10103 		OSKextLog(this,
10104 		    kOSKextLogErrorLevel |
10105 		    kOSKextLogLoadFlag,
10106 		    "Failed to unregister kext %s class %s.",
10107 		    getIdentifierCString(),
10108 		    aClass->getClassName());
10109 	}
10110 	return result;
10111 }
10112 
10113 /*********************************************************************
10114 *********************************************************************/
10115 OSSet *
10116 OSKext::getMetaClasses(void)
10117 {
10118 	return metaClasses.get();
10119 }
10120 
10121 /*********************************************************************
10122 *********************************************************************/
10123 bool
10124 OSKext::hasOSMetaClassInstances(void)
10125 {
10126 	bool                   result        = false;
10127 	OSSharedPtr<OSCollectionIterator> classIterator;
10128 	OSMetaClass          * checkClass    = NULL;        // do not release
10129 
10130 	if (!metaClasses) {
10131 		goto finish;
10132 	}
10133 
10134 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
10135 	if (!classIterator) {
10136 		// xxx - log alloc failure?
10137 		goto finish;
10138 	}
10139 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
10140 		if (checkClass->getInstanceCount()) {
10141 			result = true;
10142 			goto finish;
10143 		}
10144 	}
10145 
10146 finish:
10147 	return result;
10148 }
10149 
10150 /*********************************************************************
10151 *********************************************************************/
10152 /* static */
10153 void
10154 OSKext::reportOSMetaClassInstances(
10155 	const char     * kextIdentifier,
10156 	OSKextLogSpec    msgLogSpec)
10157 {
10158 	OSSharedPtr<OSKext> theKext;
10159 
10160 	theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
10161 	if (!theKext) {
10162 		goto finish;
10163 	}
10164 
10165 	theKext->reportOSMetaClassInstances(msgLogSpec);
10166 finish:
10167 	return;
10168 }
10169 
10170 /*********************************************************************
10171 *********************************************************************/
10172 void
10173 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
10174 {
10175 	OSSharedPtr<OSCollectionIterator> classIterator;
10176 	OSMetaClass          * checkClass    = NULL;        // do not release
10177 
10178 	if (!metaClasses) {
10179 		goto finish;
10180 	}
10181 
10182 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
10183 	if (!classIterator) {
10184 		goto finish;
10185 	}
10186 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
10187 		if (checkClass->getInstanceCount()) {
10188 			OSKextLog(this,
10189 			    msgLogSpec,
10190 			    "    Kext %s class %s has %d instance%s.",
10191 			    getIdentifierCString(),
10192 			    checkClass->getClassName(),
10193 			    checkClass->getInstanceCount(),
10194 			    checkClass->getInstanceCount() == 1 ? "" : "s");
10195 		}
10196 	}
10197 
10198 finish:
10199 	return;
10200 }
10201 
10202 #if PRAGMA_MARK
10203 #pragma mark User-Space Requests
10204 #endif
10205 
10206 static kern_return_t
10207 patchDextLaunchRequests(task_t calling_task, OSArray *requests)
10208 {
10209 	OSReturn result = kOSReturnSuccess;
10210 	for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) {
10211 		OSDictionary * request = NULL;         //do not release
10212 		IOUserServerCheckInToken * token = NULL;         //do not release
10213 		OSString * requestPredicate = NULL;         //do not release
10214 		OSSharedPtr<OSNumber> portNameNumber;
10215 		mach_port_name_t portName = 0;
10216 		request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex));
10217 		if (!request) {
10218 			OSKextLog(/* kext */ NULL,
10219 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10220 			    "Elements of request should be of type OSDictionary");
10221 			result = kOSKextReturnInternalError;
10222 			goto finish;
10223 		}
10224 		requestPredicate = _OSKextGetRequestPredicate(request);
10225 		if (!requestPredicate) {
10226 			OSKextLog(/* kext */ NULL,
10227 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10228 			    "Failed to get request predicate");
10229 			result = kOSKextReturnInternalError;
10230 			goto finish;
10231 		}
10232 		// is this a dext launch?
10233 		if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) {
10234 			token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken));
10235 			if (!token) {
10236 				OSKextLog(/* kext */ NULL,
10237 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10238 				    "Could not find a IOUserServerCheckInToken in daemon launch request.");
10239 				result = kOSKextReturnInternalError;
10240 				goto finish;
10241 			}
10242 			portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT);
10243 			if (portName == 0 || portName == MACH_PORT_DEAD) {
10244 				OSKextLog(/* kext */ NULL,
10245 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10246 				    "Could not create send right for object.");
10247 				result = kOSKextReturnInternalError;
10248 				goto finish;
10249 			}
10250 			// Store the mach port name as a OSNumber
10251 			portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName));
10252 			if (!portNameNumber) {
10253 				OSKextLog(/* kext */ NULL,
10254 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10255 				    "Could not create OSNumber object.");
10256 				result = kOSKextReturnNoMemory;
10257 				goto finish;
10258 			}
10259 			if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) {
10260 				OSKextLog(/* kext */ NULL,
10261 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10262 				    "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken);
10263 				result = kOSKextReturnNoMemory;
10264 				goto finish;
10265 			}
10266 		}
10267 finish:
10268 		if (result != kOSReturnSuccess) {
10269 			break;
10270 		}
10271 	}
10272 	return result;
10273 }
10274 
10275 bool
10276 OSKext::iokitDaemonActive()
10277 {
10278 	bool result;
10279 	IORecursiveLockLock(sKextLock);
10280 	result = sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot;
10281 	IORecursiveLockUnlock(sKextLock);
10282 	return result;
10283 }
10284 
10285 /*********************************************************************
10286 * XXX - this function is a big ugly mess
10287 *********************************************************************/
10288 /* static */
10289 OSReturn
10290 OSKext::handleRequest(
10291 	host_priv_t     hostPriv,
10292 	OSKextLogSpec   clientLogFilter,
10293 	char          * requestBuffer,
10294 	uint32_t        requestLength,
10295 	char         ** responseOut,
10296 	uint32_t      * responseLengthOut,
10297 	char         ** logInfoOut,
10298 	uint32_t      * logInfoLengthOut)
10299 {
10300 	OSReturn       result             = kOSReturnError;
10301 	kern_return_t  kmem_result        = KERN_FAILURE;
10302 
10303 	char         * response           = NULL;        // returned by reference
10304 	uint32_t       responseLength     = 0;
10305 
10306 	bool           taskCanManageAllKCs   = false;
10307 	bool           taskOnlyManagesBootKC = false;
10308 
10309 	OSSharedPtr<OSObject>     parsedXML;
10310 	OSDictionary            * requestDict    = NULL;        // do not release
10311 	OSSharedPtr<OSString>     errorString;
10312 
10313 	OSSharedPtr<OSObject>     responseObject;
10314 
10315 	OSSharedPtr<OSSerialize>  serializer;
10316 
10317 	OSSharedPtr<OSArray>      logInfoArray;
10318 
10319 	OSString     * predicate          = NULL;        // do not release
10320 	OSString     * kextIdentifier     = NULL;        // do not release
10321 	OSArray      * kextIdentifiers    = NULL;        // do not release
10322 	OSKext       * theKext            = NULL;        // do not release
10323 	OSBoolean    * boolArg            = NULL;        // do not release
10324 
10325 
10326 	IORecursiveLockLock(sKextLock);
10327 
10328 	if (responseOut) {
10329 		*responseOut = NULL;
10330 		*responseLengthOut = 0;
10331 	}
10332 	if (logInfoOut) {
10333 		*logInfoOut = NULL;
10334 		*logInfoLengthOut = 0;
10335 	}
10336 
10337 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
10338 
10339 	/* XML must be nul-terminated.
10340 	 */
10341 	if (requestBuffer[requestLength - 1] != '\0') {
10342 		OSKextLog(/* kext */ NULL,
10343 		    kOSKextLogErrorLevel |
10344 		    kOSKextLogIPCFlag,
10345 		    "Invalid request from user space (not nul-terminated).");
10346 		result = kOSKextReturnBadData;
10347 		goto finish;
10348 	}
10349 	parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString);
10350 	if (parsedXML) {
10351 		requestDict = OSDynamicCast(OSDictionary, parsedXML.get());
10352 	}
10353 	if (!requestDict) {
10354 		const char * errorCString = "(unknown error)";
10355 
10356 		if (errorString && errorString->getCStringNoCopy()) {
10357 			errorCString = errorString->getCStringNoCopy();
10358 		} else if (parsedXML) {
10359 			errorCString = "not a dictionary";
10360 		}
10361 		OSKextLog(/* kext */ NULL,
10362 		    kOSKextLogErrorLevel |
10363 		    kOSKextLogIPCFlag,
10364 		    "Error unserializing request from user space: %s.",
10365 		    errorCString);
10366 		result = kOSKextReturnSerialization;
10367 		goto finish;
10368 	}
10369 
10370 	predicate = _OSKextGetRequestPredicate(requestDict);
10371 	if (!predicate) {
10372 		OSKextLog(/* kext */ NULL,
10373 		    kOSKextLogErrorLevel |
10374 		    kOSKextLogIPCFlag,
10375 		    "Recieved kext request from user space with no predicate.");
10376 		result = kOSKextReturnInvalidArgument;
10377 		goto finish;
10378 	}
10379 	OSKextLog(/* kext */ NULL,
10380 	    kOSKextLogDebugLevel |
10381 	    kOSKextLogIPCFlag,
10382 	    "Received '%s' request from user space.",
10383 	    predicate->getCStringNoCopy());
10384 
10385 	/*
10386 	 * All management of file sets requires an entitlement
10387 	 */
10388 	result = kOSKextReturnNotPrivileged;
10389 	if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
10390 	    predicate->isEqualTo(kKextRequestPredicateStart) ||
10391 	    predicate->isEqualTo(kKextRequestPredicateStop) ||
10392 	    predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
10393 	    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
10394 	    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
10395 	    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
10396 	    predicate->isEqualTo(kKextRequestPredicateLoadFromKC) ||
10397 	    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
10398 	    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
10399 	    predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
10400 		if (!iokitDaemonAvailable()) {
10401 			panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable");
10402 		}
10403 		if (hostPriv == HOST_PRIV_NULL) {
10404 			OSKextLog(/* kext */ NULL,
10405 			    kOSKextLogErrorLevel |
10406 			    kOSKextLogIPCFlag,
10407 			    "Access Failure - must be root user.");
10408 			goto finish;
10409 		}
10410 		taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE;
10411 		taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE;
10412 
10413 		if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) {
10414 			OSKextLog(/* kext */ NULL,
10415 			    kOSKextLogErrorLevel |
10416 			    kOSKextLogIPCFlag,
10417 			    "Access Failure - client not entitled to manage file sets.");
10418 			goto finish;
10419 		}
10420 
10421 		/*
10422 		 * The OnlyBootKC entitlement restricts the
10423 		 * collection-management entitlement to only managing kexts in
10424 		 * the BootKC. All other predicates that alter global state or
10425 		 * add new KCs are disallowed.
10426 		 */
10427 		if (taskOnlyManagesBootKC &&
10428 		    (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
10429 		    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
10430 		    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
10431 		    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
10432 		    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
10433 		    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
10434 		    predicate->isEqualTo(kKextRequestPredicateDaemonReady))) {
10435 			OSKextLog(/* kext */ NULL,
10436 			    kOSKextLogErrorLevel |
10437 			    kOSKextLogIPCFlag,
10438 			    "Access Failure - client not entitled to manage non-primary KCs");
10439 			goto finish;
10440 		}
10441 
10442 		/*
10443 		 * If we get here, then the process either has the full KC
10444 		 * management entitlement, or it has the BootKC-only
10445 		 * entitlement and the request is about the BootKC.
10446 		 */
10447 	}
10448 
10449 	/* Get common args in anticipation of use.
10450 	 */
10451 	kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
10452 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
10453 	kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
10454 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
10455 	if (kextIdentifier) {
10456 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
10457 	}
10458 	boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
10459 		    requestDict, kKextRequestArgumentValueKey));
10460 
10461 	if (taskOnlyManagesBootKC &&
10462 	    theKext &&
10463 	    theKext->isInFileset() &&
10464 	    theKext->kc_type != KCKindPrimary) {
10465 		OSKextLog(/* kext */ NULL,
10466 		    kOSKextLogErrorLevel |
10467 		    kOSKextLogIPCFlag,
10468 		    "Access Failure - client not entitled to manage kext in non-primary KC");
10469 		result = kOSKextReturnNotPrivileged;
10470 		goto finish;
10471 	}
10472 	result = kOSKextReturnInvalidArgument;
10473 
10474 	if (predicate->isEqualTo(kKextRequestPredicateStart)) {
10475 		if (!kextIdentifier) {
10476 			OSKextLog(/* kext */ NULL,
10477 			    kOSKextLogErrorLevel |
10478 			    kOSKextLogIPCFlag,
10479 			    "Invalid arguments to kext start request.");
10480 		} else if (!theKext) {
10481 			OSKextLog(/* kext */ NULL,
10482 			    kOSKextLogErrorLevel |
10483 			    kOSKextLogIPCFlag,
10484 			    "Kext %s not found for start request.",
10485 			    kextIdentifier->getCStringNoCopy());
10486 			result = kOSKextReturnNotFound;
10487 		} else {
10488 			result = theKext->start();
10489 		}
10490 	} else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
10491 		if (!kextIdentifier) {
10492 			OSKextLog(/* kext */ NULL,
10493 			    kOSKextLogErrorLevel |
10494 			    kOSKextLogIPCFlag,
10495 			    "Invalid arguments to kext stop request.");
10496 		} else if (!theKext) {
10497 			OSKextLog(/* kext */ NULL,
10498 			    kOSKextLogErrorLevel |
10499 			    kOSKextLogIPCFlag,
10500 			    "Kext %s not found for stop request.",
10501 			    kextIdentifier->getCStringNoCopy());
10502 			result = kOSKextReturnNotFound;
10503 		} else {
10504 			result = theKext->stop();
10505 		}
10506 	} else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) {
10507 		result = OSKext::setMissingAuxKCBundles(requestDict);
10508 	} else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) {
10509 		if (!kextIdentifier) {
10510 			OSKextLog(/* kext */ NULL,
10511 			    kOSKextLogErrorLevel |
10512 			    kOSKextLogIPCFlag,
10513 			    "Invalid arguments to AuxKC Bundle Available request.");
10514 		} else {
10515 			result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict);
10516 		}
10517 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) {
10518 		if (!kextIdentifier) {
10519 			OSKextLog(/* kext */ NULL,
10520 			    kOSKextLogErrorLevel |
10521 			    kOSKextLogIPCFlag,
10522 			    "Invalid arguments to kext load from KC request.");
10523 		} else if (!theKext) {
10524 			OSKextLog(/* kext */ NULL,
10525 			    kOSKextLogErrorLevel |
10526 			    kOSKextLogIPCFlag,
10527 			    "Kext %s not found for load from KC request.",
10528 			    kextIdentifier->getCStringNoCopy());
10529 			result = kOSKextReturnNotFound;
10530 		} else if (!theKext->isInFileset()) {
10531 			OSKextLog(/* kext */ NULL,
10532 			    kOSKextLogErrorLevel |
10533 			    kOSKextLogIPCFlag,
10534 			    "Kext %s does not exist in a KC: refusing to load.",
10535 			    kextIdentifier->getCStringNoCopy());
10536 			result = kOSKextReturnNotLoadable;
10537 		} else {
10538 			result = OSKext::loadKextFromKC(theKext, requestDict);
10539 		}
10540 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) {
10541 		if (!kextIdentifier) {
10542 			OSKextLog(/* kext */ NULL,
10543 			    kOSKextLogErrorLevel |
10544 			    kOSKextLogIPCFlag,
10545 			    "Invalid arguments to codeless kext load interface (missing identifier).");
10546 		} else {
10547 			result = OSKext::loadCodelessKext(kextIdentifier, requestDict);
10548 		}
10549 	} else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
10550 		if (!kextIdentifier) {
10551 			OSKextLog(/* kext */ NULL,
10552 			    kOSKextLogErrorLevel |
10553 			    kOSKextLogIPCFlag,
10554 			    "Invalid arguments to kext unload request.");
10555 		} else if (!theKext) {
10556 			OSKextLog(/* kext */ NULL,
10557 			    kOSKextLogErrorLevel |
10558 			    kOSKextLogIPCFlag,
10559 			    "Kext %s not found for unload request.",
10560 			    kextIdentifier->getCStringNoCopy());
10561 			result = kOSKextReturnNotFound;
10562 		} else {
10563 			if (theKext->isDriverKit()) {
10564 				result = OSKext::removeDext(theKext);
10565 			} else {
10566 				OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
10567 				    _OSKextGetRequestArgument(requestDict,
10568 				    kKextRequestArgumentTerminateIOServicesKey));
10569 				result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
10570 			}
10571 		}
10572 	} else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
10573 		result = OSKext::dispatchResource(requestDict);
10574 	} else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
10575 		OSNumber     *lookupNum   = NULL;
10576 		lookupNum = OSDynamicCast(OSNumber,
10577 		    _OSKextGetRequestArgument(requestDict,
10578 		    kKextRequestArgumentLookupAddressKey));
10579 
10580 		responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
10581 		if (responseObject) {
10582 			result = kOSReturnSuccess;
10583 		} else {
10584 			goto finish;
10585 		}
10586 	} else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
10587 	    predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) ||
10588 	    predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection) ||
10589 	    predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
10590 		OSBoolean    * delayAutounloadBool = NULL;
10591 		OSObject     * infoKeysRaw         = NULL;
10592 		OSArray      * infoKeys            = NULL;
10593 		uint32_t       infoKeysCount       = 0;
10594 
10595 		delayAutounloadBool = OSDynamicCast(OSBoolean,
10596 		    _OSKextGetRequestArgument(requestDict,
10597 		    kKextRequestArgumentDelayAutounloadKey));
10598 
10599 		/* If asked to delay autounload, reset the timer if it's currently set.
10600 		 * (That is, don't schedule an unload if one isn't already pending.
10601 		 */
10602 		if (delayAutounloadBool == kOSBooleanTrue) {
10603 			OSKext::considerUnloads(/* rescheduleOnly? */ true);
10604 		}
10605 
10606 		infoKeysRaw = _OSKextGetRequestArgument(requestDict,
10607 		    kKextRequestArgumentInfoKeysKey);
10608 		infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
10609 		if (infoKeysRaw && !infoKeys) {
10610 			OSKextLog(/* kext */ NULL,
10611 			    kOSKextLogErrorLevel |
10612 			    kOSKextLogIPCFlag,
10613 			    "Invalid arguments to kext info request.");
10614 			goto finish;
10615 		}
10616 
10617 		if (infoKeys) {
10618 			infoKeysCount = infoKeys->getCount();
10619 			for (uint32_t i = 0; i < infoKeysCount; i++) {
10620 				if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
10621 					OSKextLog(/* kext */ NULL,
10622 					    kOSKextLogErrorLevel |
10623 					    kOSKextLogIPCFlag,
10624 					    "Invalid arguments to kext info request.");
10625 					goto finish;
10626 				}
10627 			}
10628 		}
10629 
10630 		if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
10631 			responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
10632 		} else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
10633 			responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
10634 		} else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
10635 			responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys);
10636 		} else if (predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
10637 			responseObject = OSKext::copyDextsInfo(kextIdentifiers, infoKeys);
10638 		}
10639 
10640 		if (!responseObject) {
10641 			result = kOSKextReturnInternalError;
10642 		} else {
10643 			OSKextLog(/* kext */ NULL,
10644 			    kOSKextLogDebugLevel |
10645 			    kOSKextLogIPCFlag,
10646 			    "Returning loaded kext info.");
10647 			result = kOSReturnSuccess;
10648 		}
10649 	} else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
10650 		/* Hand the current sKernelRequests array to the caller
10651 		 * (who must release it), and make a new one.
10652 		 */
10653 		responseObject = os::move(sKernelRequests);
10654 		sKernelRequests = OSArray::withCapacity(0);
10655 		sPostedKextLoadIdentifiers->flushCollection();
10656 		OSKextLog(/* kext */ NULL,
10657 		    kOSKextLogDebugLevel |
10658 		    kOSKextLogIPCFlag,
10659 		    "Returning kernel requests.");
10660 		result = kOSReturnSuccess;
10661 	} else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
10662 		/* Return the set of all requested bundle identifiers */
10663 		responseObject = sAllKextLoadIdentifiers;
10664 		OSKextLog(/* kext */ NULL,
10665 		    kOSKextLogDebugLevel |
10666 		    kOSKextLogIPCFlag,
10667 		    "Returning load requests.");
10668 		result = kOSReturnSuccess;
10669 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) {
10670 		printf("KextLog: Loading FileSet KC(s)\n");
10671 		result = OSKext::loadFileSetKexts(requestDict);
10672 	} else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
10673 		bool active = iokitDaemonActive();
10674 		printf("KextLog: " kIOKitDaemonName " is %s\n", active ? "active" : "not active");
10675 		if (sOSKextWasResetAfterUserspaceReboot) {
10676 			printf("KextLog: was reset after userspace reboot\n");
10677 		}
10678 		result = active ? kOSReturnSuccess : kIOReturnNotReady;
10679 	} else {
10680 		OSKextLog(/* kext */ NULL,
10681 		    kOSKextLogDebugLevel |
10682 		    kOSKextLogIPCFlag,
10683 		    "Received '%s' invalid request from user space.",
10684 		    predicate->getCStringNoCopy());
10685 		goto finish;
10686 	}
10687 
10688 	/**********
10689 	 * Now we have handle the request, or not. Gather up the response & logging
10690 	 * info to ship to user space.
10691 	 *********/
10692 
10693 	/* Note: Nothing in OSKext is supposed to retain requestDict,
10694 	 * but you never know....
10695 	 */
10696 	if (requestDict->getRetainCount() > 1) {
10697 		OSKextLog(/* kext */ NULL,
10698 		    kOSKextLogWarningLevel |
10699 		    kOSKextLogIPCFlag,
10700 		    "Request from user space still retained by a kext; "
10701 		    "probable memory leak.");
10702 	}
10703 
10704 	if (responseOut && responseObject) {
10705 		serializer = OSSerialize::withCapacity(0);
10706 		if (!serializer) {
10707 			result = kOSKextReturnNoMemory;
10708 			goto finish;
10709 		}
10710 		/*
10711 		 * Before serializing the kernel requests, patch the dext launch requests so
10712 		 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the
10713 		 * IOUserServerCheckInToken kernel object.
10714 		 */
10715 		if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
10716 			OSArray * requests = OSDynamicCast(OSArray, responseObject.get());
10717 			task_t calling_task = current_task();
10718 			if (!requests) {
10719 				OSKextLog(/* kext */ NULL,
10720 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10721 				    "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests);
10722 				result = kOSKextReturnInternalError;
10723 				goto finish;
10724 			}
10725 			result = patchDextLaunchRequests(calling_task, requests);
10726 			if (result != kOSReturnSuccess) {
10727 				OSKextLog(/* kext */ NULL,
10728 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10729 				    "Failed to patch dext launch requests.");
10730 				goto finish;
10731 			}
10732 		}
10733 
10734 		if (!responseObject->serialize(serializer.get())) {
10735 			OSKextLog(/* kext */ NULL,
10736 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10737 			    "Failed to serialize response to request from user space.");
10738 			result = kOSKextReturnSerialization;
10739 			goto finish;
10740 		}
10741 
10742 		response = (char *)serializer->text();
10743 		responseLength = serializer->getLength();
10744 	}
10745 
10746 	if (responseOut && response) {
10747 		char * buffer;
10748 
10749 		/* This kmem_alloc sets the return value of the function.
10750 		 */
10751 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
10752 		    round_page(responseLength), KMA_DATA_SHARED, VM_KERN_MEMORY_OSKEXT);
10753 		if (kmem_result != KERN_SUCCESS) {
10754 			OSKextLog(/* kext */ NULL,
10755 			    kOSKextLogErrorLevel |
10756 			    kOSKextLogIPCFlag,
10757 			    "Failed to copy response to request from user space.");
10758 			result = kmem_result;
10759 			goto finish;
10760 		} else {
10761 			/* 11981737 - clear uninitialized data in last page */
10762 			bzero((void *)(buffer + responseLength),
10763 			    (round_page(responseLength) - responseLength));
10764 			memcpy(buffer, response, responseLength);
10765 			*responseOut = buffer;
10766 			*responseLengthOut = responseLength;
10767 		}
10768 	}
10769 
10770 finish:
10771 
10772 	/* Gather up the collected log messages for user space. Any messages
10773 	 * messages past this call will not make it up as log messages but
10774 	 * will be in the system log. Note that we ignore the return of the
10775 	 * serialize; it has no bearing on the operation at hand even if we
10776 	 * fail to get the log messages.
10777 	 */
10778 	logInfoArray = OSKext::clearUserSpaceLogFilter();
10779 
10780 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
10781 		(void)OSKext::serializeLogInfo(logInfoArray.get(),
10782 		    logInfoOut, logInfoLengthOut);
10783 	}
10784 
10785 	IORecursiveLockUnlock(sKextLock);
10786 
10787 	return result;
10788 }
10789 
10790 #if PRAGMA_MARK
10791 #pragma mark Linked Kext Collection Support
10792 #endif
10793 
10794 static int
10795 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount)
10796 {
10797 	for (int i = 0; i < segCount; i++) {
10798 		vm_offset_t segStart = segAddrs[i];
10799 		vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i];
10800 
10801 		if (theAddr >= segStart && theAddr < segEnd) {
10802 			return i;
10803 		}
10804 	}
10805 	return -1;
10806 }
10807 
10808 static void
10809 __slideOldKaslrOffsets(kernel_mach_header_t *mh,
10810     kernel_segment_command_t *kextTextSeg,
10811     OSData *kaslrOffsets)
10812 {
10813 	static const char *plk_segNames[] = {
10814 		"__TEXT",
10815 		"__TEXT_EXEC",
10816 		"__DATA",
10817 		"__DATA_CONST",
10818 		"__LINKEDIT",
10819 		"__PRELINK_TEXT",
10820 		"__PLK_TEXT_EXEC",
10821 		"__PRELINK_DATA",
10822 		"__PLK_DATA_CONST",
10823 		"__PLK_LLVM_COV",
10824 		"__PLK_LINKEDIT",
10825 		"__PRELINK_INFO"
10826 	};
10827 	static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0]));
10828 
10829 	unsigned long plk_segSizes[num_plk_seg];
10830 	vm_offset_t   plk_segAddrs[num_plk_seg];
10831 
10832 	for (size_t i = 0; i < num_plk_seg; i++) {
10833 		plk_segSizes[i] = 0;
10834 		plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]);
10835 	}
10836 
10837 	uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr;
10838 
10839 	int slidKextAddrCount = 0;
10840 	int badSlideAddr = 0;
10841 	int badSlideTarget = 0;
10842 
10843 	struct kaslrPackedOffsets {
10844 		uint32_t    count;          /* number of offsets */
10845 		uint32_t    offsetsArray[];        /* offsets to slide */
10846 	};
10847 	const struct kaslrPackedOffsets *myOffsets = NULL;
10848 	myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy();
10849 
10850 	for (uint32_t j = 0; j < myOffsets->count; j++) {
10851 		uint64_t   slideOffset = (uint64_t)myOffsets->offsetsArray[j];
10852 		vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset);
10853 		int        slideAddrSegIndex = -1;
10854 		int        addrToSlideSegIndex = -1;
10855 
10856 		slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
10857 		if (slideAddrSegIndex >= 0) {
10858 			addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
10859 			if (addrToSlideSegIndex < 0) {
10860 				badSlideTarget++;
10861 				continue;
10862 			}
10863 		} else {
10864 			badSlideAddr++;
10865 			continue;
10866 		}
10867 
10868 		slidKextAddrCount++;
10869 		*slideAddr = ml_static_slide(*slideAddr);
10870 	}         // for ...
10871 }
10872 
10873 
10874 
10875 /********************************************************************
10876 * addKextsFromKextCollection
10877 *
10878 * Input: MachO header of kext collection. The MachO is assumed to
10879 *        have a section named 'info_seg_name,info_sect_name' that
10880 *        contains a serialized XML info dictionary. This dictionary
10881 *        contains a UUID, possibly a set of relocations (for older
10882 *        kxld-built binaries), and an array of kext personalities.
10883 *
10884 ********************************************************************/
10885 bool
10886 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10887     OSDictionary *infoDict, const char *text_seg_name,
10888     OSData **kcUUID, kc_kind_t type)
10889 {
10890 	bool result = false;
10891 
10892 	OSArray *kextArray     = NULL;        // do not release
10893 	OSData *infoDictKCUUID = NULL;         // do not release
10894 	OSData *kaslrOffsets   = NULL;        // do not release
10895 
10896 	IORegistryEntry *registryRoot = NULL;         // do not release
10897 	OSSharedPtr<OSNumber> kcKextCount;
10898 
10899 	/* extract the KC UUID from the dictionary */
10900 	infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
10901 	if (infoDictKCUUID) {
10902 		if (infoDictKCUUID->getLength() != sizeof(uuid_t)) {
10903 			panic("kcUUID length is %d, expected %lu",
10904 			    infoDictKCUUID->getLength(), sizeof(uuid_t));
10905 		}
10906 	}
10907 
10908 	/* locate the array of kext dictionaries */
10909 	kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey));
10910 	if (!kextArray) {
10911 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10912 		    "The given KC has no kext info dictionaries");
10913 		goto finish;
10914 	}
10915 
10916 	/*
10917 	 * old-style KASLR offsets may be present in the info dictionary. If
10918 	 * we find them, use them and eventually slide them.
10919 	 */
10920 	kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey));
10921 
10922 	/*
10923 	 * Before processing any kexts, locate the special kext bundle which
10924 	 * contains a list of kexts that we are to prevent from loading.
10925 	 */
10926 	createExcludeListFromPrelinkInfo(kextArray);
10927 
10928 	/*
10929 	 * Create OSKext objects for each kext we find in the array of kext
10930 	 * info plist dictionaries.
10931 	 */
10932 	for (int i = 0; i < (int)kextArray->getCount(); ++i) {
10933 		OSDictionary *kextDict = NULL;
10934 		kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i));
10935 		if (!kextDict) {
10936 			OSKextLog(/* kext */ NULL,
10937 			    kOSKextLogErrorLevel |
10938 			    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10939 			    "Kext info dictionary for kext #%d isn't a dictionary?", i);
10940 			continue;
10941 		}
10942 
10943 		/*
10944 		 * Create the kext for the entry, then release it, because the
10945 		 * kext system keeps a reference around until the kext is
10946 		 * explicitly removed.  Any creation/registration failures are
10947 		 * already logged for us.
10948 		 */
10949 		withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type);
10950 	}
10951 
10952 	/*
10953 	 * slide old-style kxld relocations
10954 	 * NOTE: this is still used on embedded KCs built with kcgen
10955 	 * TODO: Remove this once we use the new kext linker everywhere!
10956 	 */
10957 	if (kaslrOffsets && vm_kernel_slide > 0) {
10958 		kernel_segment_command_t *text_segment = NULL;
10959 		text_segment = getsegbynamefromheader(mh, text_seg_name);
10960 		if (!text_segment) {
10961 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10962 			    "Can't find a TEXT segment named '%s' in macho header", text_seg_name);
10963 			goto finish;
10964 		}
10965 
10966 		__slideOldKaslrOffsets(mh, text_segment, kaslrOffsets);
10967 		/* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */
10968 		setAllVMAttributes();
10969 	}
10970 
10971 	/* Store the number of prelinked kexts in the registry so we can tell
10972 	 * when the system has been started from a prelinked kernel.
10973 	 */
10974 	registryRoot = IORegistryEntry::getRegistryRoot();
10975 	assert(registryRoot);
10976 
10977 	kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t));
10978 	assert(kcKextCount);
10979 	if (kcKextCount) {
10980 		OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey);
10981 		OSNumber *num;
10982 		num = OSDynamicCast(OSNumber, prop.get());
10983 		if (num) {
10984 			kcKextCount->addValue(num->unsigned64BitValue());
10985 		}
10986 		registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get());
10987 	}
10988 
10989 	OSKextLog(/* kext */ NULL,
10990 	    kOSKextLogProgressLevel |
10991 	    kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
10992 	    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10993 	    "%u prelinked kexts", infoDict->getCount());
10994 
10995 
10996 	if (kcUUID && infoDictKCUUID) {
10997 		*kcUUID = OSData::withData(infoDictKCUUID).detach();
10998 	}
10999 
11000 	result = true;
11001 
11002 finish:
11003 	return result;
11004 }
11005 
11006 bool
11007 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
11008     OSDictionary *infoDict, const char *text_seg_name,
11009     OSSharedPtr<OSData> &kcUUID, kc_kind_t type)
11010 {
11011 	OSData  *result = NULL;
11012 	bool success = addKextsFromKextCollection(mh,
11013 	    infoDict,
11014 	    text_seg_name,
11015 	    &result,
11016 	    type);
11017 	if (success) {
11018 		kcUUID.reset(result, OSNoRetain);
11019 	}
11020 	return success;
11021 }
11022 
11023 static OSSharedPtr<OSObject> deferredAuxKCXML;
11024 bool
11025 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh,
11026     OSSharedPtr<OSObject> &parsedXML, kc_kind_t type)
11027 {
11028 	if (type != KCKindAuxiliary) {
11029 		return false;
11030 	}
11031 
11032 	kernel_mach_header_t *_mh;
11033 	_mh = (kernel_mach_header_t*)PE_get_kc_header(type);
11034 	if (!_mh || _mh != mh) {
11035 		return false;
11036 	}
11037 
11038 	if (deferredAuxKCXML) {
11039 		/* only allow this to be called once */
11040 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
11041 		    "An Aux KC has already been registered for deferred processing.");
11042 		return false;
11043 	}
11044 
11045 	OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
11046 	if (!infoDict) {
11047 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
11048 		    "The Aux KC has info dictionary");
11049 		return false;
11050 	}
11051 
11052 	OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
11053 	if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) {
11054 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
11055 		    "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey);
11056 		return false;
11057 	}
11058 
11059 	/*
11060 	 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid
11061 	 * sysctl can return the UUID to user space which will check this
11062 	 * value for errors.
11063 	 */
11064 	memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(),
11065 	    kcUUID->getLength());
11066 	uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
11067 	auxkc_uuid_valid = TRUE;
11068 
11069 	deferredAuxKCXML = parsedXML;
11070 
11071 	return true;
11072 }
11073 
11074 OSSharedPtr<OSObject>
11075 OSKext::consumeDeferredKextCollection(kc_kind_t type)
11076 {
11077 	if (type != KCKindAuxiliary || !deferredAuxKCXML) {
11078 		return NULL;
11079 	}
11080 
11081 	return os::move(deferredAuxKCXML);
11082 }
11083 
11084 #if PRAGMA_MARK
11085 #pragma mark Profile-Guided-Optimization Support
11086 #endif
11087 
11088 // #include <InstrProfiling.h>
11089 extern "C" {
11090 uint64_t __llvm_profile_get_size_for_buffer_internal(
11091 	const char *DataBegin,
11092 	const char *DataEnd,
11093 	const char *CountersBegin,
11094 	const char *CountersEnd,
11095 	const char *BitmapBegin,
11096 	const char *BitmapEnd,
11097 	const char *NamesBegin,
11098 	const char *NamesEnd,
11099 	const char *VTableBegin,
11100 	const char *VTableEnd,
11101 	const char *VNamesBegin,
11102 	const char *VNamesEnd);
11103 int __llvm_profile_write_buffer_internal(
11104 	char *Buffer,
11105 	const char *DataBegin,
11106 	const char *DataEnd,
11107 	const char *CountersBegin,
11108 	const char *CountersEnd,
11109 	const char *BitmapBegin,
11110 	const char *BitmapEnd,
11111 	const char *NamesBegin,
11112 	const char *NamesEnd);
11113 }
11114 
11115 static
11116 void
11117 OSKextPgoMetadataPut(char *pBuffer,
11118     size_t *position,
11119     size_t bufferSize,
11120     uint32_t *num_pairs,
11121     const char *key,
11122     const char *value)
11123 {
11124 	size_t strlen_key = strlen(key);
11125 	size_t strlen_value = strlen(value);
11126 	size_t len = strlen(key) + 1 + strlen(value) + 1;
11127 	char *pos = pBuffer + *position;
11128 	*position += len;
11129 	if (pBuffer && bufferSize && *position <= bufferSize) {
11130 		memcpy(pos, key, strlen_key); pos += strlen_key;
11131 		*(pos++) = '=';
11132 		memcpy(pos, value, strlen_value); pos += strlen_value;
11133 		*(pos++) = 0;
11134 		if (num_pairs) {
11135 			(*num_pairs)++;
11136 		}
11137 	}
11138 }
11139 
11140 
11141 static
11142 void
11143 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
11144 {
11145 	*position += strlen(key) + 1 + value_max + 1;
11146 }
11147 
11148 
11149 static
11150 void
11151 OSKextPgoMetadataPutAll(OSKext *kext,
11152     uuid_t instance_uuid,
11153     char *pBuffer,
11154     size_t *position,
11155     size_t bufferSize,
11156     uint32_t *num_pairs)
11157 {
11158 	_static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
11159 	//log_10 2^16 ≈ 4.82
11160 	const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
11161 	const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
11162 
11163 	if (!pBuffer) {
11164 		OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
11165 		OSKextPgoMetadataPutMax(position, "UUID", 36);
11166 		OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
11167 	} else {
11168 		uuid_string_t instance_uuid_string;
11169 		uuid_unparse(instance_uuid, instance_uuid_string);
11170 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11171 		    "INSTANCE", instance_uuid_string);
11172 
11173 		OSSharedPtr<OSData> uuid_data;
11174 		uuid_t uuid;
11175 		uuid_string_t uuid_string;
11176 		uuid_data = kext->copyUUID();
11177 		if (uuid_data) {
11178 			memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
11179 			uuid_unparse(uuid, uuid_string);
11180 			OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11181 			    "UUID", uuid_string);
11182 		}
11183 
11184 		clock_sec_t secs;
11185 		clock_usec_t usecs;
11186 		clock_get_calendar_microtime(&secs, &usecs);
11187 		assert(usecs < 1000000);
11188 		char timestamp[max_timestamp_string_size + 1];
11189 		_static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
11190 		snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
11191 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11192 		    "TIMESTAMP", timestamp);
11193 	}
11194 
11195 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11196 	    "NAME", kext->getIdentifierCString());
11197 
11198 	char versionCString[kOSKextVersionMaxLength];
11199 	OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
11200 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11201 	    "VERSION", versionCString);
11202 }
11203 
11204 static
11205 size_t
11206 OSKextPgoMetadataSize(OSKext *kext)
11207 {
11208 	size_t position = 0;
11209 	uuid_t fakeuuid = {};
11210 	OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
11211 	return position;
11212 }
11213 
11214 int
11215 OSKextGrabPgoDataLocked(OSKext *kext,
11216     bool metadata,
11217     uuid_t instance_uuid,
11218     uint64_t *pSize,
11219     char *pBuffer,
11220     uint64_t bufferSize)
11221 {
11222 	int err = 0;
11223 
11224 	kernel_section_t *sect_prf_data = NULL;
11225 	kernel_section_t *sect_prf_name = NULL;
11226 	kernel_section_t *sect_prf_cnts = NULL;
11227 	uint64_t size;
11228 	size_t metadata_size = 0;
11229 	size_t offset_to_pairs = 0;
11230 
11231 	sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
11232 	sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
11233 	if (!sect_prf_name) {
11234 		// kextcache sometimes truncates the section name to 15 chars
11235 		// <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache
11236 		sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
11237 	}
11238 	sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
11239 
11240 	// Ignore some sections used by optional PGO variants.
11241 	const char *unused_section = NULL;
11242 
11243 	if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
11244 		err = ENOTSUP;
11245 		goto out;
11246 	}
11247 
11248 	size = __llvm_profile_get_size_for_buffer_internal(
11249 		(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
11250 		(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
11251 		unused_section /* bits */, unused_section /* bits end */,
11252 		(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size,
11253 		unused_section /* vtab */, unused_section /* vtab end */,
11254 		unused_section /* vnam */, unused_section /* vnam end */);
11255 
11256 	if (metadata) {
11257 		metadata_size = OSKextPgoMetadataSize(kext);
11258 		size += metadata_size;
11259 		size += sizeof(pgo_metadata_footer);
11260 	}
11261 
11262 
11263 	if (pSize) {
11264 		*pSize = size;
11265 	}
11266 
11267 	if (pBuffer && bufferSize) {
11268 		if (bufferSize < size) {
11269 			err = ERANGE;
11270 			goto out;
11271 		}
11272 
11273 		err = __llvm_profile_write_buffer_internal(
11274 			pBuffer,
11275 			(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
11276 			(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
11277 			unused_section /* bits */, unused_section /* bits end */,
11278 			(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
11279 
11280 		if (err) {
11281 			err = EIO;
11282 			goto out;
11283 		}
11284 
11285 		if (metadata) {
11286 			offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size;
11287 			if (offset_to_pairs > UINT32_MAX) {
11288 				err = E2BIG;
11289 				goto out;
11290 			}
11291 
11292 			char *end_of_buffer = pBuffer + size;
11293 			struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
11294 			char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
11295 
11296 			size_t metadata_position = 0;
11297 			uint32_t num_pairs = 0;
11298 			OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
11299 			while (metadata_position < metadata_size) {
11300 				metadata_buffer[metadata_position++] = 0;
11301 			}
11302 
11303 			struct pgo_metadata_footer footer;
11304 			footer.magic = htonl(0x6d657461);
11305 			footer.number_of_pairs = htonl( num_pairs );
11306 			footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs );
11307 			memcpy(footerp, &footer, sizeof(footer));
11308 		}
11309 	}
11310 
11311 out:
11312 	return err;
11313 }
11314 
11315 
11316 int
11317 OSKextGrabPgoData(uuid_t uuid,
11318     uint64_t *pSize,
11319     char *pBuffer,
11320     uint64_t bufferSize,
11321     int wait_for_unload,
11322     int metadata)
11323 {
11324 	int err = 0;
11325 	OSSharedPtr<OSKext> kext;
11326 
11327 
11328 	IORecursiveLockLock(sKextLock);
11329 
11330 	kext = OSKext::lookupKextWithUUID(uuid);
11331 	if (!kext) {
11332 		err = ENOENT;
11333 		goto out;
11334 	}
11335 
11336 	if (wait_for_unload) {
11337 		OSKextGrabPgoStruct s;
11338 
11339 		s.metadata = metadata;
11340 		s.pSize = pSize;
11341 		s.pBuffer = pBuffer;
11342 		s.bufferSize = bufferSize;
11343 		s.err = EINTR;
11344 
11345 		struct list_head *prev = &kext->pendingPgoHead;
11346 		struct list_head *next = kext->pendingPgoHead.next;
11347 
11348 		s.list_head.prev = prev;
11349 		s.list_head.next = next;
11350 
11351 		prev->next = &s.list_head;
11352 		next->prev = &s.list_head;
11353 
11354 		kext.reset();
11355 
11356 		IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
11357 
11358 		prev = s.list_head.prev;
11359 		next = s.list_head.next;
11360 
11361 		prev->next = next;
11362 		next->prev = prev;
11363 
11364 		err = s.err;
11365 	} else {
11366 		err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
11367 	}
11368 
11369 out:
11370 
11371 	IORecursiveLockUnlock(sKextLock);
11372 
11373 	return err;
11374 }
11375 
11376 void
11377 OSKextResetPgoCountersLock()
11378 {
11379 	IORecursiveLockLock(sKextLock);
11380 }
11381 
11382 void
11383 OSKextResetPgoCountersUnlock()
11384 {
11385 	IORecursiveLockUnlock(sKextLock);
11386 }
11387 
11388 
11389 extern unsigned int not_in_kdp;
11390 
11391 void
11392 OSKextResetPgoCounters()
11393 {
11394 	assert(!not_in_kdp);
11395 	uint32_t count = sLoadedKexts->getCount();
11396 	for (uint32_t i = 0; i < count; i++) {
11397 		OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
11398 		kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
11399 		if (!sect_prf_cnts) {
11400 			continue;
11401 		}
11402 		memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
11403 	}
11404 }
11405 
11406 OSSharedPtr<OSDictionary>
11407 OSKext::copyLoadedKextInfoByUUID(
11408 	OSArray * kextIdentifiers,
11409 	OSArray * infoKeys)
11410 {
11411 	OSSharedPtr<OSDictionary> result;
11412 	OSSharedPtr<OSDictionary> kextInfo;
11413 	uint32_t       max_count, i, j;
11414 	uint32_t       idCount = 0;
11415 	uint32_t       idIndex = 0;
11416 	IORecursiveLockLock(sKextLock);
11417 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
11418 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
11419 
11420 #if CONFIG_MACF
11421 	/* Is the calling process allowed to query kext 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 	/* Empty list of UUIDs is equivalent to no list (get all).
11441 	 */
11442 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11443 		kextIdentifiers = NULL;
11444 	} else if (kextIdentifiers) {
11445 		idCount = kextIdentifiers->getCount();
11446 	}
11447 
11448 	/* Same for keys.
11449 	 */
11450 	if (infoKeys && !infoKeys->getCount()) {
11451 		infoKeys = NULL;
11452 	}
11453 
11454 	max_count = count[0] + count[1];
11455 	result = OSDictionary::withCapacity(max_count);
11456 	if (!result) {
11457 		goto finish;
11458 	}
11459 
11460 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
11461 		for (i = 0; i < count[j]; i++) {
11462 			OSKext       *thisKext     = NULL;        // do not release
11463 			Boolean       includeThis  = true;
11464 			uuid_t        thisKextUUID;
11465 			uuid_t        thisKextTextUUID;
11466 			OSSharedPtr<OSData> uuid_data;
11467 			uuid_string_t uuid_key;
11468 
11469 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
11470 			if (!thisKext) {
11471 				continue;
11472 			}
11473 
11474 			uuid_data = thisKext->copyUUID();
11475 			if (!uuid_data) {
11476 				continue;
11477 			}
11478 
11479 			memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
11480 
11481 			uuid_unparse(thisKextUUID, uuid_key);
11482 
11483 			uuid_data = thisKext->copyTextUUID();
11484 			if (!uuid_data) {
11485 				continue;
11486 			}
11487 			memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
11488 
11489 			/* Skip current kext if we have a list of UUIDs and
11490 			 * it isn't in the list.
11491 			 */
11492 			if (kextIdentifiers) {
11493 				includeThis = false;
11494 
11495 				for (idIndex = 0; idIndex < idCount; idIndex++) {
11496 					const OSString* wantedUUID = OSDynamicCast(OSString,
11497 					    kextIdentifiers->getObject(idIndex));
11498 
11499 					uuid_t uuid;
11500 					uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
11501 
11502 					if ((0 == uuid_compare(uuid, thisKextUUID))
11503 					    || (0 == uuid_compare(uuid, thisKextTextUUID))) {
11504 						includeThis = true;
11505 						/* Only need to find the first kext if multiple match,
11506 						 * ie. asking for the kernel uuid does not need to find
11507 						 * interface kexts or builtin static kexts.
11508 						 */
11509 						kextIdentifiers->removeObject(idIndex);
11510 						uuid_unparse(uuid, uuid_key);
11511 						break;
11512 					}
11513 				}
11514 			}
11515 
11516 			if (!includeThis) {
11517 				continue;
11518 			}
11519 
11520 			kextInfo = thisKext->copyInfo(infoKeys);
11521 			if (kextInfo) {
11522 				result->setObject(uuid_key, kextInfo.get());
11523 			}
11524 
11525 			if (kextIdentifiers && !kextIdentifiers->getCount()) {
11526 				goto finish;
11527 			}
11528 		}
11529 	}
11530 
11531 finish:
11532 	IORecursiveLockUnlock(sKextLock);
11533 
11534 	return result;
11535 }
11536 
11537 /*********************************************************************
11538 *********************************************************************/
11539 /* static */
11540 OSSharedPtr<OSDictionary>
11541 OSKext::copyKextCollectionInfo(
11542 	OSDictionary *requestDict,
11543 	OSArray  *infoKeys)
11544 {
11545 	OSSharedPtr<OSDictionary> result;
11546 	OSString *collectionType = NULL;
11547 	OSObject *rawLoadedState = NULL;
11548 	OSString *loadedState    = NULL;
11549 
11550 	kc_kind_t kc_request_kind = KCKindUnknown;
11551 	bool onlyLoaded = false;
11552 	bool onlyUnloaded = false;
11553 
11554 #if CONFIG_MACF
11555 	/* Is the calling process allowed to query kext info? */
11556 	if (current_task() != kernel_task) {
11557 		int                 macCheckResult      = 0;
11558 		kauth_cred_t        cred                = NULL;
11559 
11560 		cred = kauth_cred_get_with_ref();
11561 		macCheckResult = mac_kext_check_query(cred);
11562 		kauth_cred_unref(&cred);
11563 
11564 		if (macCheckResult != 0) {
11565 			OSKextLog(/* kext */ NULL,
11566 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11567 			    "Failed to query kext info (MAC policy error 0x%x).",
11568 			    macCheckResult);
11569 			goto finish;
11570 		}
11571 	}
11572 #endif
11573 
11574 	if (infoKeys && !infoKeys->getCount()) {
11575 		infoKeys = NULL;
11576 	}
11577 
11578 	collectionType = OSDynamicCast(OSString,
11579 	    _OSKextGetRequestArgument(requestDict,
11580 	    kKextRequestArgumentCollectionTypeKey));
11581 	if (!collectionType) {
11582 		OSKextLog(/* kext */ NULL,
11583 		    kOSKextLogErrorLevel |
11584 		    kOSKextLogIPCFlag,
11585 		    "Invalid '%s' argument to kext collection info request.",
11586 		    kKextRequestArgumentCollectionTypeKey);
11587 		goto finish;
11588 	}
11589 	if (collectionType->isEqualTo(kKCTypePrimary)) {
11590 		kc_request_kind = KCKindPrimary;
11591 	} else if (collectionType->isEqualTo(kKCTypeSystem)) {
11592 		kc_request_kind = KCKindPageable;
11593 	} else if (collectionType->isEqualTo(kKCTypeAuxiliary)) {
11594 		kc_request_kind = KCKindAuxiliary;
11595 	} else if (collectionType->isEqualTo(kKCTypeCodeless)) {
11596 		kc_request_kind = KCKindNone;
11597 	} else if (!collectionType->isEqualTo(kKCTypeAny)) {
11598 		OSKextLog(/* kext */ NULL,
11599 		    kOSKextLogErrorLevel |
11600 		    kOSKextLogIPCFlag,
11601 		    "Invalid '%s' argument value '%s' to kext collection info request.",
11602 		    kKextRequestArgumentCollectionTypeKey,
11603 		    collectionType->getCStringNoCopy());
11604 		goto finish;
11605 	}
11606 
11607 	rawLoadedState = _OSKextGetRequestArgument(requestDict,
11608 	    kKextRequestArgumentLoadedStateKey);
11609 	if (rawLoadedState) {
11610 		loadedState = OSDynamicCast(OSString, rawLoadedState);
11611 		if (!loadedState) {
11612 			OSKextLog(/* kext */ NULL,
11613 			    kOSKextLogErrorLevel |
11614 			    kOSKextLogIPCFlag,
11615 			    "Invalid '%s' argument to kext collection info request.",
11616 			    kKextRequestArgumentLoadedStateKey);
11617 			goto finish;
11618 		}
11619 	}
11620 	if (loadedState) {
11621 		if (loadedState->isEqualTo("Loaded")) {
11622 			onlyLoaded = true;
11623 		} else if (loadedState->isEqualTo("Unloaded")) {
11624 			onlyUnloaded = true;
11625 		} else if (!loadedState->isEqualTo("Any")) {
11626 			OSKextLog(/* kext */ NULL,
11627 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11628 			    "Invalid '%s' argument value '%s' for '%s' collection info",
11629 			    kKextRequestArgumentLoadedStateKey,
11630 			    loadedState->getCStringNoCopy(),
11631 			    collectionType->getCStringNoCopy());
11632 			goto finish;
11633 		}
11634 	}
11635 
11636 	result = OSDictionary::withCapacity(sKextsByID->getCount());
11637 	if (!result) {
11638 		goto finish;
11639 	}
11640 
11641 	IORecursiveLockLock(sKextLock);
11642 	{         // start block scope
11643 		sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11644 		{
11645 			OSKext       *thisKext    = NULL;  // do not release
11646 			OSSharedPtr<OSDictionary> kextInfo;
11647 
11648 			(void)thisKextID;
11649 
11650 			thisKext = OSDynamicCast(OSKext, obj);
11651 			if (!thisKext) {
11652 			        return false;
11653 			}
11654 
11655 			/*
11656 			 * skip the kext if it came from the wrong collection type
11657 			 * (and the caller requested a specific type)
11658 			 */
11659 			if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) {
11660 			        return false;
11661 			}
11662 
11663 			/*
11664 			 * respect the caller's desire to find only loaded or
11665 			 * unloaded kexts
11666 			 */
11667 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11668 			        return false;
11669 			}
11670 			if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11671 			        return false;
11672 			}
11673 
11674 			kextInfo = thisKext->copyInfo(infoKeys);
11675 			if (kextInfo) {
11676 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
11677 			}
11678 			return false;
11679 		});
11680 	} // end block scope
11681 	IORecursiveLockUnlock(sKextLock);
11682 
11683 finish:
11684 	return result;
11685 }
11686 
11687 /* static */
11688 OSSharedPtr<OSArray>
11689 OSKext::copyDextsInfo(
11690 	OSArray *kextIdentifiers,
11691 	OSArray *infoKeys)
11692 {
11693 	OSSharedPtr<OSArray> result = NULL;
11694 	uint32_t idCount = 0;
11695 	bool getActive = false;
11696 	bool getLoaded = false;
11697 	bool getUnloaded = false;
11698 	bool getPendingUpgrade = false;
11699 	unsigned int avgDextCount = 0;
11700 
11701 #if CONFIG_MACF
11702 	/* Is the calling process allowed to query dext info? */
11703 	if (current_task() != kernel_task) {
11704 		int                 macCheckResult      = 0;
11705 		kauth_cred_t        cred                = NULL;
11706 
11707 		cred = kauth_cred_get_with_ref();
11708 		macCheckResult = mac_kext_check_query(cred);
11709 		kauth_cred_unref(&cred);
11710 
11711 		if (macCheckResult != 0) {
11712 			OSKextLog(/* kext */ NULL,
11713 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11714 			    "Failed to query kext info (MAC policy error 0x%x).",
11715 			    macCheckResult);
11716 			goto finish;
11717 		}
11718 	}
11719 #endif
11720 	/*
11721 	 * No infoKeys means return everything we
11722 	 * know about the dexts.
11723 	 */
11724 	if (infoKeys && !infoKeys->getCount()) {
11725 		infoKeys = NULL;
11726 	}
11727 
11728 	/*
11729 	 * Empty list of bundle ids is equivalent to
11730 	 * no list (get all).
11731 	 */
11732 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11733 		kextIdentifiers = NULL;
11734 	} else if (kextIdentifiers) {
11735 		idCount = kextIdentifiers->getCount();
11736 	}
11737 
11738 	/*
11739 	 * Caller can specify which state of dexts to query.
11740 	 */
11741 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveKey)) {
11742 		getActive = true;
11743 	}
11744 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveLoadedKey)) {
11745 		getLoaded = true;
11746 	}
11747 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveUnloadedKey)) {
11748 		getUnloaded = true;
11749 	}
11750 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStatePendingUpgradeKey)) {
11751 		getPendingUpgrade = true;
11752 	}
11753 
11754 	/*
11755 	 * By default we are going to return all active and pendingUpgrade dexts
11756 	 * only.
11757 	 */
11758 	if (!(getActive || getLoaded || getUnloaded || getPendingUpgrade)) {
11759 		getActive = true;
11760 		getPendingUpgrade = true;
11761 	}
11762 
11763 	/*
11764 	 * We return a dictionary of dexts
11765 	 * for every group requested.
11766 	 */
11767 	avgDextCount = sLoadedDriverKitKexts->getCount() + sDriverKitToUpgradeByID->getCount();
11768 	result = OSArray::withCapacity(avgDextCount);
11769 	if (!result) {
11770 		goto finish;
11771 	}
11772 
11773 	IORecursiveLockLock(sKextLock);
11774 	{ // start block scope
11775 		if (getActive || getLoaded || getUnloaded) {
11776 			sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11777 			{
11778 				OSKext *thisKext = NULL;  // do not release
11779 				OSSharedPtr<OSDictionary> kextInfo;
11780 				Boolean includeThis = true;
11781 				(void)thisKextID;
11782 
11783 				thisKext = OSDynamicCast(OSKext, obj);
11784 				if (!thisKext || !thisKext->isDriverKit()) {
11785 				        return false;
11786 				}
11787 
11788 				/*
11789 				 * Skip current dext if we have a list of bundle IDs and
11790 				 * it isn't in the list.
11791 				 */
11792 				if (kextIdentifiers) {
11793 				        includeThis = false;
11794 
11795 				        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11796 				                const OSString * thisRequestID = OSDynamicCast(OSString,
11797 				                kextIdentifiers->getObject(idIndex));
11798 				                if (thisKextID->isEqualTo(thisRequestID)) {
11799 				                        includeThis = true;
11800 				                        break;
11801 						}
11802 					}
11803 				}
11804 
11805 				if (!includeThis) {
11806 				        return false;
11807 				}
11808 
11809 				OSSharedPtr<OSString> state;
11810 				if (sLoadedDriverKitKexts->getNextIndexOfObject(thisKext, 0) == -1U) {
11811 				        if (!(getActive || getUnloaded)) {
11812 				                return false;
11813 					}
11814 				        state = OSString::withCString(kOSBundleDextStateActiveUnloadedKey);
11815 				} else {
11816 				        if (!(getActive || getLoaded)) {
11817 				                return false;
11818 					}
11819 				        state = OSString::withCString(kOSBundleDextStateActiveLoadedKey);
11820 				}
11821 
11822 				kextInfo = thisKext->copyInfo(infoKeys);
11823 				if (kextInfo) {
11824 				        kextInfo->setObject(kOSBundleDextStateKey, state.get());
11825 				        result->setObject(kextInfo.get());
11826 				}
11827 
11828 				return false;
11829 			});
11830 		}
11831 
11832 		if (getPendingUpgrade) {
11833 			sDriverKitToUpgradeByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11834 			{
11835 				OSKext *thisKext = NULL;  // do not release
11836 				OSSharedPtr<OSDictionary> kextInfo;
11837 				Boolean includeThis = true;
11838 				(void)thisKextID;
11839 
11840 				thisKext = OSDynamicCast(OSKext, obj);
11841 				if (!thisKext) {
11842 				        return false;
11843 				}
11844 				__assert_only bool isDext = thisKext->isDriverKit();
11845 				assert(isDext == true);
11846 
11847 				/*
11848 				 * Skip current dext if we have a list of bundle IDs and
11849 				 * it isn't in the list.
11850 				 */
11851 				if (kextIdentifiers) {
11852 				        includeThis = false;
11853 
11854 				        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11855 				                const OSString * thisRequestID = OSDynamicCast(OSString,
11856 				                kextIdentifiers->getObject(idIndex));
11857 				                if (thisKextID->isEqualTo(thisRequestID)) {
11858 				                        includeThis = true;
11859 				                        break;
11860 						}
11861 					}
11862 				}
11863 
11864 				if (!includeThis) {
11865 				        return false;
11866 				}
11867 
11868 				kextInfo = thisKext->copyInfo(infoKeys);
11869 				if (kextInfo) {
11870 				        OSSharedPtr<OSString> state = OSString::withCString(kOSBundleDextStatePendingUpgradeKey);
11871 				        kextInfo->setObject(kOSBundleDextStateKey, state.get());
11872 				        result->setObject(kextInfo.get());
11873 				}
11874 				return false;
11875 			});
11876 		}
11877 	} // end block scope
11878 	IORecursiveLockUnlock(sKextLock);
11879 finish:
11880 	return result;
11881 }
11882 
11883 /*********************************************************************
11884 *********************************************************************/
11885 /* static */
11886 OSSharedPtr<OSDictionary>
11887 OSKext::copyLoadedKextInfo(
11888 	OSArray * kextIdentifiers,
11889 	OSArray * infoKeys)
11890 {
11891 	OSSharedPtr<OSDictionary> result;
11892 	uint32_t       idCount = 0;
11893 	bool           onlyLoaded;
11894 
11895 	IORecursiveLockLock(sKextLock);
11896 
11897 #if CONFIG_MACF
11898 	/* Is the calling process allowed to query kext info? */
11899 	if (current_task() != kernel_task) {
11900 		int                 macCheckResult      = 0;
11901 		kauth_cred_t        cred                = NULL;
11902 
11903 		cred = kauth_cred_get_with_ref();
11904 		macCheckResult = mac_kext_check_query(cred);
11905 		kauth_cred_unref(&cred);
11906 
11907 		if (macCheckResult != 0) {
11908 			OSKextLog(/* kext */ NULL,
11909 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11910 			    "Failed to query kext info (MAC policy error 0x%x).",
11911 			    macCheckResult);
11912 			goto finish;
11913 		}
11914 	}
11915 #endif
11916 
11917 	/* Empty list of bundle ids is equivalent to no list (get all).
11918 	 */
11919 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11920 		kextIdentifiers = NULL;
11921 	} else if (kextIdentifiers) {
11922 		idCount = kextIdentifiers->getCount();
11923 	}
11924 
11925 	/* Same for keys.
11926 	 */
11927 	if (infoKeys && !infoKeys->getCount()) {
11928 		infoKeys = NULL;
11929 	}
11930 
11931 	onlyLoaded =  (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
11932 
11933 	result = OSDictionary::withCapacity(128);
11934 	if (!result) {
11935 		goto finish;
11936 	}
11937 
11938 #if 0
11939 	OSKextLog(/* kext */ NULL,
11940 	    kOSKextLogErrorLevel |
11941 	    kOSKextLogGeneralFlag,
11942 	    "kaslr: vm_kernel_slide 0x%lx \n",
11943 	    vm_kernel_slide);
11944 	OSKextLog(/* kext */ NULL,
11945 	    kOSKextLogErrorLevel |
11946 	    kOSKextLogGeneralFlag,
11947 	    "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
11948 	    vm_kernel_stext, vm_kernel_etext);
11949 	OSKextLog(/* kext */ NULL,
11950 	    kOSKextLogErrorLevel |
11951 	    kOSKextLogGeneralFlag,
11952 	    "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
11953 	    vm_kernel_base, vm_kernel_top);
11954 	OSKextLog(/* kext */ NULL,
11955 	    kOSKextLogErrorLevel |
11956 	    kOSKextLogGeneralFlag,
11957 	    "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
11958 	    vm_kext_base, vm_kext_top);
11959 	OSKextLog(/* kext */ NULL,
11960 	    kOSKextLogErrorLevel |
11961 	    kOSKextLogGeneralFlag,
11962 	    "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
11963 	    vm_prelink_stext, vm_prelink_etext);
11964 	OSKextLog(/* kext */ NULL,
11965 	    kOSKextLogErrorLevel |
11966 	    kOSKextLogGeneralFlag,
11967 	    "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
11968 	    vm_prelink_sinfo, vm_prelink_einfo);
11969 	OSKextLog(/* kext */ NULL,
11970 	    kOSKextLogErrorLevel |
11971 	    kOSKextLogGeneralFlag,
11972 	    "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
11973 	    vm_slinkedit, vm_elinkedit);
11974 #endif
11975 	{         // start block scope
11976 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
11977 		{
11978 			OSKext       * thisKext     = NULL;        // do not release
11979 			Boolean        includeThis  = true;
11980 			OSSharedPtr<OSDictionary> kextInfo;
11981 
11982 			thisKext = OSDynamicCast(OSKext, obj);
11983 			if (!thisKext) {
11984 			        return false;
11985 			}
11986 
11987 			/* Skip current kext if not yet started and caller didn't request all.
11988 			 */
11989 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11990 			        return false;
11991 			}
11992 
11993 			/* Skip current kext if we have a list of bundle IDs and
11994 			 * it isn't in the list.
11995 			 */
11996 			if (kextIdentifiers) {
11997 			        includeThis = false;
11998 
11999 			        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
12000 			                const OSString * thisRequestID = OSDynamicCast(OSString,
12001 			                kextIdentifiers->getObject(idIndex));
12002 			                if (thisKextID->isEqualTo(thisRequestID)) {
12003 			                        includeThis = true;
12004 			                        break;
12005 					}
12006 				}
12007 			}
12008 
12009 			if (!includeThis) {
12010 			        return false;
12011 			}
12012 
12013 			kextInfo = thisKext->copyInfo(infoKeys);
12014 			if (kextInfo) {
12015 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
12016 			}
12017 			return false;
12018 		});
12019 	}         // end block scope
12020 
12021 finish:
12022 	IORecursiveLockUnlock(sKextLock);
12023 
12024 	return result;
12025 }
12026 
12027 /*********************************************************************
12028 * Any info that needs to do allocations must goto finish on alloc
12029 * failure. Info that is just a lookup should just not set the object
12030 * if the info does not exist.
12031 *********************************************************************/
12032 #define _OSKextLoadInfoDictCapacity   (12)
12033 
12034 OSSharedPtr<OSDictionary>
12035 OSKext::copyInfo(OSArray * infoKeys)
12036 {
12037 	OSSharedPtr<OSDictionary>  result;
12038 	bool                       success                     = false;
12039 	OSSharedPtr<OSData>        headerData;
12040 	OSSharedPtr<OSData>        logData;
12041 	OSSharedPtr<OSNumber>      cpuTypeNumber;
12042 	OSSharedPtr<OSNumber>      cpuSubtypeNumber;
12043 	OSString                 * versionString               = NULL;        // do not release
12044 	OSString                 * bundleType                  = NULL;        // do not release
12045 	uint32_t                   executablePathCStringSize   = 0;
12046 	char                     * executablePathCString       = NULL;        // must kfree
12047 	OSSharedPtr<OSString>      executablePathString;
12048 	OSSharedPtr<OSData>        uuid;
12049 	OSSharedPtr<OSArray>       dependencyLoadTags;
12050 	OSSharedPtr<OSCollectionIterator>      metaClassIterator;
12051 	OSSharedPtr<OSArray>       metaClassInfo;
12052 	OSSharedPtr<OSDictionary>  metaClassDict;
12053 	OSMetaClass              * thisMetaClass               = NULL;        // do not release
12054 	OSSharedPtr<OSString>      metaClassName;
12055 	OSSharedPtr<OSString>      superclassName;
12056 	kc_format_t                kcformat;
12057 	uint32_t                   count, i;
12058 
12059 	result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
12060 	if (!result) {
12061 		goto finish;
12062 	}
12063 
12064 
12065 	/* Empty keys means no keys, but NULL is quicker to check.
12066 	 */
12067 	if (infoKeys && !infoKeys->getCount()) {
12068 		infoKeys = NULL;
12069 	}
12070 
12071 	if (!PE_get_primary_kc_format(&kcformat)) {
12072 		goto finish;
12073 	}
12074 
12075 	/* Headers, CPU type, and CPU subtype.
12076 	 */
12077 	if (!infoKeys ||
12078 	    _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
12079 	    _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
12080 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
12081 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
12082 		if (linkedExecutable && !isInterface()) {
12083 			kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
12084 			    linkedExecutable->getBytesNoCopy();
12085 
12086 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX
12087 			// do not return macho header info on shipping embedded - 19095897
12088 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
12089 				kernel_mach_header_t *  temp_kext_mach_hdr;
12090 				struct load_command *   lcp;
12091 
12092 				headerData = OSData::withBytes(kext_mach_hdr,
12093 				    (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
12094 				if (!headerData) {
12095 					goto finish;
12096 				}
12097 
12098 				// unslide any vmaddrs we return to userspace - 10726716
12099 				temp_kext_mach_hdr = (kernel_mach_header_t *)
12100 				    headerData->getBytesNoCopy();
12101 				if (temp_kext_mach_hdr == NULL) {
12102 					goto finish;
12103 				}
12104 
12105 				lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
12106 				for (i = 0; (i < temp_kext_mach_hdr->ncmds) && !flags.unslidMachO; i++) {
12107 					if (lcp->cmd == LC_SEGMENT_KERNEL) {
12108 						kernel_segment_command_t *  segp;
12109 						kernel_section_t *          secp;
12110 
12111 						segp = (kernel_segment_command_t *) lcp;
12112 						// 10543468 - if we jettisoned __LINKEDIT clear size info
12113 						if (flags.jettisonLinkeditSeg) {
12114 							if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
12115 								segp->vmsize = 0;
12116 								segp->fileoff = 0;
12117 								segp->filesize = 0;
12118 							}
12119 						}
12120 
12121 #if __arm__ || __arm64__
12122 						// iBoot disregards zero-size segments, just set their addresses to gVirtBase
12123 						// and unslide them to avoid vm assertion failures / kernel logging breakage.
12124 						if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) {
12125 							segp->vmaddr = gVirtBase;
12126 							for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
12127 								secp->size = 0; // paranoia :)
12128 								secp->addr = gVirtBase;
12129 							}
12130 						}
12131 #endif
12132 
12133 #if 0
12134 						OSKextLog(/* kext */ NULL,
12135 						    kOSKextLogErrorLevel |
12136 						    kOSKextLogGeneralFlag,
12137 						    "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
12138 						    __FUNCTION__, segp->segname, segp->vmaddr,
12139 						    VM_KERNEL_UNSLIDE(segp->vmaddr),
12140 						    segp->vmsize, segp->nsects);
12141 						if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
12142 						    (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
12143 						    (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
12144 						    (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
12145 						    (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
12146 							OSKextLog(/* kext */ NULL,
12147 							    kOSKextLogErrorLevel |
12148 							    kOSKextLogGeneralFlag,
12149 							    "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
12150 							    __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
12151 						}
12152 #endif
12153 						segp->vmaddr = ml_static_unslide(segp->vmaddr);
12154 
12155 						for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
12156 							secp->addr = ml_static_unslide(secp->addr);
12157 						}
12158 					}
12159 					lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
12160 				}
12161 				result->setObject(kOSBundleMachOHeadersKey, headerData.get());
12162 			}
12163 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX
12164 
12165 			if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
12166 				osLogDataHeaderRef *header;
12167 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
12168 
12169 				void *os_log_data               = NULL;
12170 				void *cstring_data              = NULL;
12171 				void *asan_cstring_data         = NULL;
12172 				unsigned long os_log_size       = 0;
12173 				unsigned long cstring_size      = 0;
12174 				unsigned long asan_cstring_size = 0;
12175 				uint32_t os_log_offset          = 0;
12176 				uint32_t cstring_offset         = 0;
12177 				uint32_t asan_cstring_offset    = 0;
12178 				bool res;
12179 
12180 				os_log_data         = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
12181 				cstring_data        = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
12182 				asan_cstring_data   = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size);
12183 
12184 				/*
12185 				 * If the addresses in the Mach-O header are unslid, manually
12186 				 * slide them to allow for dereferencing.
12187 				 */
12188 				if (flags.unslidMachO) {
12189 					os_log_data = (os_log_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)os_log_data) : nullptr;
12190 					cstring_data = (cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)cstring_data) : nullptr;
12191 					asan_cstring_data = (asan_cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)asan_cstring_data) : nullptr;
12192 				}
12193 
12194 				os_log_offset       = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr;
12195 				cstring_offset      = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr;
12196 				asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr;
12197 
12198 				header             = (osLogDataHeaderRef *) headerBytes;
12199 				header->version    = OS_LOG_HDR_VERSION;
12200 				header->sect_count = NUM_OS_LOG_SECTIONS;
12201 				header->sections[OS_LOG_SECT_IDX].sect_offset       = os_log_offset;
12202 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) os_log_size;
12203 				header->sections[CSTRING_SECT_IDX].sect_offset      = cstring_offset;
12204 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) cstring_size;
12205 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset;
12206 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) asan_cstring_size;
12207 
12208 
12209 				logData = OSData::withValue(*header);
12210 				if (!logData) {
12211 					goto finish;
12212 				}
12213 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
12214 				if (!res) {
12215 					goto finish;
12216 				}
12217 				if (os_log_data) {
12218 					res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
12219 					if (!res) {
12220 						goto finish;
12221 					}
12222 				}
12223 				if (cstring_data) {
12224 					res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
12225 					if (!res) {
12226 						goto finish;
12227 					}
12228 				}
12229 				if (asan_cstring_data) {
12230 					res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size);
12231 					if (!res) {
12232 						goto finish;
12233 					}
12234 				}
12235 				result->setObject(kOSBundleLogStringsKey, logData.get());
12236 			}
12237 
12238 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
12239 				cpuTypeNumber = OSNumber::withNumber(
12240 					(uint64_t) kext_mach_hdr->cputype,
12241 					8 * sizeof(kext_mach_hdr->cputype));
12242 				if (!cpuTypeNumber) {
12243 					goto finish;
12244 				}
12245 				result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get());
12246 			}
12247 
12248 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
12249 				cpuSubtypeNumber = OSNumber::withNumber(
12250 					(uint64_t) kext_mach_hdr->cpusubtype,
12251 					8 * sizeof(kext_mach_hdr->cpusubtype));
12252 				if (!cpuSubtypeNumber) {
12253 					goto finish;
12254 				}
12255 				result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get());
12256 			}
12257 		} else {
12258 			if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
12259 				osLogDataHeaderRef *header;
12260 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
12261 				bool res;
12262 
12263 				header             = (osLogDataHeaderRef *) headerBytes;
12264 				header->version    = OS_LOG_HDR_VERSION;
12265 				header->sect_count = NUM_OS_LOG_SECTIONS;
12266 				header->sections[OS_LOG_SECT_IDX].sect_offset       = 0;
12267 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) 0;
12268 				header->sections[CSTRING_SECT_IDX].sect_offset      = 0;
12269 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) 0;
12270 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0;
12271 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) 0;
12272 
12273 				logData = OSData::withValue(*header);
12274 				if (!logData) {
12275 					goto finish;
12276 				}
12277 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
12278 				if (!res) {
12279 					goto finish;
12280 				}
12281 				result->setObject(kOSBundleLogStringsKey, logData.get());
12282 			}
12283 		}
12284 	}
12285 
12286 	/* CFBundleIdentifier. We set this regardless because it's just stupid not to.
12287 	 */
12288 	result->setObject(kCFBundleIdentifierKey, bundleID.get());
12289 
12290 	/* kOSBundleDextUniqueIdentifierKey if present.
12291 	 */
12292 	if (isDriverKit() && dextUniqueID != NULL) {
12293 		result->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID.get());
12294 	}
12295 
12296 	/* CFBundlePackageType
12297 	 */
12298 	bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL;
12299 	if (bundleType) {
12300 		result->setObject(kCFBundlePackageTypeKey, bundleType);
12301 	}
12302 
12303 	/* CFBundleVersion.
12304 	 */
12305 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
12306 		versionString = OSDynamicCast(OSString,
12307 		    getPropertyForHostArch(kCFBundleVersionKey));
12308 		if (versionString) {
12309 			result->setObject(kCFBundleVersionKey, versionString);
12310 		}
12311 	}
12312 
12313 	/* OSBundleCompatibleVersion.
12314 	 */
12315 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
12316 		versionString = OSDynamicCast(OSString,
12317 		    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
12318 		if (versionString) {
12319 			result->setObject(kOSBundleCompatibleVersionKey, versionString);
12320 		}
12321 	}
12322 
12323 	/* Path.
12324 	 */
12325 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
12326 		if (path) {
12327 			result->setObject(kOSBundlePathKey, path.get());
12328 		}
12329 	}
12330 
12331 
12332 	/* OSBundleExecutablePath.
12333 	 */
12334 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
12335 		if (path && executableRelPath) {
12336 			uint32_t pathLength = path->getLength();         // gets incremented below
12337 
12338 			// +1 for slash, +1 for \0
12339 			executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
12340 
12341 			executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
12342 			    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);         // +1 for \0
12343 			if (!executablePathCString) {
12344 				goto finish;
12345 			}
12346 			strlcpy(executablePathCString, path->getCStringNoCopy(),
12347 			    executablePathCStringSize);
12348 			executablePathCString[pathLength++] = '/';
12349 			executablePathCString[pathLength++] = '\0';
12350 			strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
12351 			    executablePathCStringSize);
12352 
12353 			executablePathString = OSString::withCString(executablePathCString);
12354 
12355 			if (!executablePathString) {
12356 				goto finish;
12357 			}
12358 
12359 			result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
12360 		} else if (flags.builtin) {
12361 			result->setObject(kOSBundleExecutablePathKey, bundleID.get());
12362 		} else if (isDriverKit()) {
12363 			if (path) {
12364 				// +1 for slash, +1 for \0
12365 				uint32_t pathLength = path->getLength();
12366 				executablePathCStringSize = pathLength + 2;
12367 
12368 				executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
12369 				    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
12370 				if (!executablePathCString) {
12371 					goto finish;
12372 				}
12373 				strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize);
12374 				executablePathCString[pathLength++] = '/';
12375 				executablePathCString[pathLength++] = '\0';
12376 
12377 				executablePathString = OSString::withCString(executablePathCString);
12378 
12379 				if (!executablePathString) {
12380 					goto finish;
12381 				}
12382 
12383 				result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
12384 			}
12385 		}
12386 	}
12387 
12388 	/* UUID, if the kext has one.
12389 	 */
12390 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
12391 		uuid = copyUUID();
12392 		if (uuid) {
12393 			result->setObject(kOSBundleUUIDKey, uuid.get());
12394 		}
12395 	}
12396 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
12397 		uuid = copyTextUUID();
12398 		if (uuid) {
12399 			result->setObject(kOSBundleTextUUIDKey, uuid.get());
12400 		}
12401 	}
12402 
12403 	/*
12404 	 * Info.plist digest
12405 	 */
12406 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) {
12407 		OSData *digest;
12408 		digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL;
12409 		if (digest) {
12410 			result->setObject(kOSKextInfoPlistDigestKey, digest);
12411 		}
12412 	}
12413 
12414 	/*
12415 	 * Collection type
12416 	 */
12417 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) {
12418 		result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString()));
12419 	}
12420 
12421 	/*
12422 	 * Collection availability
12423 	 */
12424 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) {
12425 		result->setObject(kOSKextAuxKCAvailabilityKey,
12426 		    isLoadable() ? kOSBooleanTrue : kOSBooleanFalse);
12427 	}
12428 
12429 	/*
12430 	 * Allows user load
12431 	 */
12432 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) {
12433 		OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey));
12434 		if (allowUserLoad) {
12435 			result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad);
12436 		}
12437 	}
12438 
12439 	/*
12440 	 * Bundle Dependencies (OSBundleLibraries)
12441 	 */
12442 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) {
12443 		OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey));
12444 		if (libraries) {
12445 			result->setObject(kOSBundleLibrariesKey, libraries);
12446 		}
12447 	}
12448 
12449 	/*****
12450 	 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
12451 	 */
12452 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
12453 		result->setObject(kOSKernelResourceKey,
12454 		    isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
12455 	}
12456 
12457 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
12458 		result->setObject(kOSBundleIsInterfaceKey,
12459 		    isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
12460 	}
12461 
12462 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
12463 		result->setObject(kOSBundlePrelinkedKey,
12464 		    isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
12465 	}
12466 
12467 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
12468 		result->setObject(kOSBundleStartedKey,
12469 		    isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
12470 	}
12471 
12472 	/* LoadTag (Index).
12473 	 */
12474 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
12475 		OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
12476 		    /* numBits */ 8 * sizeof(loadTag));
12477 		if (!scratchNumber) {
12478 			goto finish;
12479 		}
12480 		result->setObject(kOSBundleLoadTagKey, scratchNumber.get());
12481 	}
12482 
12483 	/* LoadAddress, LoadSize.
12484 	 */
12485 	if (!infoKeys ||
12486 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
12487 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
12488 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
12489 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
12490 	    _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
12491 		bool is_dext = isDriverKit();
12492 		if (isInterface() || flags.builtin || linkedExecutable || is_dext) {
12493 			/* These go to userspace via serialization, so we don't want any doubts
12494 			 * about their size.
12495 			 */
12496 			uint64_t    loadAddress     = 0;
12497 			uint32_t    loadSize        = 0;
12498 			uint32_t    wiredSize       = 0;
12499 			uint64_t    execLoadAddress = 0;
12500 			uint32_t    execLoadSize    = 0;
12501 
12502 			/* Interfaces always report 0 load address & size.
12503 			 * Just the way they roll.
12504 			 *
12505 			 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
12506 			 * xxx - shouldn't have one!
12507 			 */
12508 
12509 			if (flags.builtin || linkedExecutable) {
12510 				kernel_mach_header_t     *mh  = NULL;
12511 				kernel_segment_command_t *seg = NULL;
12512 
12513 				if (flags.builtin) {
12514 					loadAddress = kmod_info->address;
12515 					loadSize    = (uint32_t)kmod_info->size;
12516 				} else {
12517 					loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
12518 					loadSize = linkedExecutable->getLength();
12519 				}
12520 				mh = (kernel_mach_header_t *)loadAddress;
12521 				loadAddress = ml_static_unslide(loadAddress);
12522 
12523 				/* Walk through the kext, looking for the first executable
12524 				 * segment in case we were asked for its size/address.
12525 				 */
12526 				for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
12527 					if (seg->initprot & VM_PROT_EXECUTE) {
12528 						execLoadAddress = (flags.unslidMachO) ? seg->vmaddr : ml_static_unslide(seg->vmaddr);
12529 						execLoadSize = (uint32_t)seg->vmsize;
12530 						break;
12531 					}
12532 				}
12533 
12534 				/* If we have a kmod_info struct, calculated the wired size
12535 				 * from that. Otherwise it's the full load size.
12536 				 */
12537 				if (kmod_info) {
12538 					wiredSize = loadSize - (uint32_t)kmod_info->hdr_size;
12539 				} else {
12540 					wiredSize = loadSize;
12541 				}
12542 			} else if (is_dext) {
12543 				/*
12544 				 * DriverKit userspace executables do not have a kernel linkedExecutable,
12545 				 * so we "fake" their address range with the LoadTag.
12546 				 */
12547 				if (loadTag) {
12548 					loadAddress = execLoadAddress = loadTag;
12549 					loadSize = execLoadSize = 1;
12550 				}
12551 			}
12552 
12553 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
12554 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12555 					(unsigned long long)(loadAddress),
12556 					/* numBits */ 8 * sizeof(loadAddress));
12557 				if (!scratchNumber) {
12558 					goto finish;
12559 				}
12560 				result->setObject(kOSBundleLoadAddressKey, scratchNumber.get());
12561 			}
12562 			if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) {
12563 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
12564 				    && loadAddress && loadSize) {
12565 					void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary);
12566 					if (!baseAddress) {
12567 						goto finish;
12568 					}
12569 
12570 					OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12571 						(unsigned long long)ml_static_unslide((vm_offset_t)baseAddress),
12572 						/* numBits */ 8 * sizeof(loadAddress));
12573 					if (!scratchNumber) {
12574 						goto finish;
12575 					}
12576 					result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get());
12577 				}
12578 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
12579 				    && (this == sKernelKext) && gBuiltinKmodsCount) {
12580 					result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
12581 				}
12582 			}
12583 
12584 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
12585 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12586 					(unsigned long long)(execLoadAddress),
12587 					/* numBits */ 8 * sizeof(execLoadAddress));
12588 				if (!scratchNumber) {
12589 					goto finish;
12590 				}
12591 				result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get());
12592 			}
12593 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
12594 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12595 					(unsigned long long)(loadSize),
12596 					/* numBits */ 8 * sizeof(loadSize));
12597 				if (!scratchNumber) {
12598 					goto finish;
12599 				}
12600 				result->setObject(kOSBundleLoadSizeKey, scratchNumber.get());
12601 			}
12602 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
12603 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12604 					(unsigned long long)(execLoadSize),
12605 					/* numBits */ 8 * sizeof(execLoadSize));
12606 				if (!scratchNumber) {
12607 					goto finish;
12608 				}
12609 				result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get());
12610 			}
12611 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
12612 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12613 					(unsigned long long)(wiredSize),
12614 					/* numBits */ 8 * sizeof(wiredSize));
12615 				if (!scratchNumber) {
12616 					goto finish;
12617 				}
12618 				result->setObject(kOSBundleWiredSizeKey, scratchNumber.get());
12619 			}
12620 		}
12621 	}
12622 
12623 	/* OSBundleDependencies. In descending order for
12624 	 * easy compatibility with kextstat(8).
12625 	 */
12626 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
12627 		if ((count = getNumDependencies())) {
12628 			dependencyLoadTags = OSArray::withCapacity(count);
12629 			result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get());
12630 
12631 			i = count - 1;
12632 			do {
12633 				OSKext * dependency = OSDynamicCast(OSKext,
12634 				    dependencies->getObject(i));
12635 
12636 				if (!dependency) {
12637 					continue;
12638 				}
12639 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12640 					(unsigned long long)dependency->getLoadTag(),
12641 					/* numBits*/ 8 * sizeof(loadTag));
12642 				if (!scratchNumber) {
12643 					goto finish;
12644 				}
12645 				dependencyLoadTags->setObject(scratchNumber.get());
12646 			} while (i--);
12647 		}
12648 	}
12649 
12650 	/* OSBundleMetaClasses.
12651 	 */
12652 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
12653 		if (metaClasses && metaClasses->getCount()) {
12654 			metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get());
12655 			metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
12656 			if (!metaClassIterator || !metaClassInfo) {
12657 				goto finish;
12658 			}
12659 			result->setObject(kOSBundleClassesKey, metaClassInfo.get());
12660 
12661 			while ((thisMetaClass = OSDynamicCast(OSMetaClass,
12662 			    metaClassIterator->getNextObject()))) {
12663 				metaClassDict = OSDictionary::withCapacity(3);
12664 				if (!metaClassDict) {
12665 					goto finish;
12666 				}
12667 
12668 				metaClassName = OSString::withCString(thisMetaClass->getClassName());
12669 				if (thisMetaClass->getSuperClass()) {
12670 					superclassName = OSString::withCString(
12671 						thisMetaClass->getSuperClass()->getClassName());
12672 				}
12673 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
12674 				    8 * sizeof(unsigned int));
12675 
12676 				/* Bail if any of the essentials is missing. The root class lacks a superclass,
12677 				 * of course.
12678 				 */
12679 				if (!metaClassDict || !metaClassName || !scratchNumber) {
12680 					goto finish;
12681 				}
12682 
12683 				metaClassInfo->setObject(metaClassDict.get());
12684 				metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get());
12685 				if (superclassName) {
12686 					metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get());
12687 				}
12688 				metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get());
12689 			}
12690 		}
12691 	}
12692 
12693 	/* OSBundleRetainCount.
12694 	 */
12695 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
12696 		{
12697 			int kextRetainCount = getRetainCount() - 1;
12698 			if (isLoaded()) {
12699 				kextRetainCount--;
12700 			}
12701 			OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12702 				(int)kextRetainCount,
12703 				/* numBits*/ 8 * sizeof(int));
12704 			if (scratchNumber) {
12705 				result->setObject(kOSBundleRetainCountKey, scratchNumber.get());
12706 			}
12707 		}
12708 	}
12709 
12710 	success = true;
12711 
12712 finish:
12713 	if (executablePathCString) {
12714 		kfree_data(executablePathCString, executablePathCStringSize);
12715 	}
12716 	if (!success) {
12717 		result.reset();
12718 	}
12719 	return result;
12720 }
12721 
12722 /*********************************************************************
12723 *********************************************************************/
12724 /* static */
12725 bool
12726 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
12727 {
12728 	bool ok;
12729 	OSSharedPtr<OSKext> kext;
12730 
12731 	IORecursiveLockLock(sKextLock);
12732 	kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain);
12733 	IORecursiveLockUnlock(sKextLock);
12734 
12735 	if (!kext || !kext->path || !kext->userExecutableRelPath) {
12736 		return false;
12737 	}
12738 	snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
12739 	    kext->path->getCStringNoCopy(),
12740 	    kext->userExecutableRelPath->getCStringNoCopy());
12741 	ok = true;
12742 
12743 	return ok;
12744 }
12745 
12746 /*********************************************************************
12747 *********************************************************************/
12748 /* static */
12749 OSReturn
12750 OSKext::requestResource(
12751 	const char                    * kextIdentifierCString,
12752 	const char                    * resourceNameCString,
12753 	OSKextRequestResourceCallback   callback,
12754 	void                          * context,
12755 	OSKextRequestTag              * requestTagOut)
12756 {
12757 	OSReturn                        result = kOSReturnError;
12758 	OSSharedPtr<OSKext>             callbackKext;        // looked up
12759 
12760 	OSKextRequestTag   requestTag      = -1;
12761 	OSSharedPtr<OSNumber>           requestTagNum;
12762 	OSSharedPtr<OSDictionary>       requestDict;
12763 	OSSharedPtr<OSString>           kextIdentifier;
12764 	OSSharedPtr<OSString>           resourceName;
12765 
12766 	OSSharedPtr<OSDictionary>       callbackRecord;
12767 	OSSharedPtr<OSValueObject<OSKextRequestResourceCallback> > callbackWrapper;
12768 
12769 	OSSharedPtr<OSValueObject<void *> > contextWrapper;
12770 
12771 	IORecursiveLockLock(sKextLock);
12772 
12773 	if (requestTagOut) {
12774 		*requestTagOut = kOSKextRequestTagInvalid;
12775 	}
12776 
12777 	/* If requests to user space are disabled, don't go any further */
12778 	if (!sKernelRequestsEnabled) {
12779 		OSKextLog(/* kext */ NULL,
12780 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12781 		    "Can't request resource %s for %s - requests to user space are disabled.",
12782 		    resourceNameCString,
12783 		    kextIdentifierCString);
12784 		result = kOSKextReturnDisabled;
12785 		goto finish;
12786 	}
12787 
12788 	if (!kextIdentifierCString || !resourceNameCString || !callback) {
12789 		result = kOSKextReturnInvalidArgument;
12790 		goto finish;
12791 	}
12792 
12793 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
12794 	if (!callbackKext) {
12795 		OSKextLog(/* kext */ NULL,
12796 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12797 		    "Resource request has bad callback address.");
12798 		result = kOSKextReturnInvalidArgument;
12799 		goto finish;
12800 	}
12801 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
12802 		OSKextLog(/* kext */ NULL,
12803 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12804 		    "Resource request callback is in a kext that is not started.");
12805 		result = kOSKextReturnInvalidArgument;
12806 		goto finish;
12807 	}
12808 
12809 	/* Do not allow any new requests to be made on a kext that is unloading.
12810 	 */
12811 	if (callbackKext->flags.stopping) {
12812 		result = kOSKextReturnStopping;
12813 		goto finish;
12814 	}
12815 
12816 	/* If we're wrapped the next available request tag around to the negative
12817 	 * numbers, we can't service any more requests.
12818 	 */
12819 	if (sNextRequestTag == kOSKextRequestTagInvalid) {
12820 		OSKextLog(/* kext */ NULL,
12821 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12822 		    "No more request tags available; restart required.");
12823 		result = kOSKextReturnNoResources;
12824 		goto finish;
12825 	}
12826 	requestTag = sNextRequestTag++;
12827 
12828 	result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
12829 	    requestDict);
12830 	if (result != kOSReturnSuccess) {
12831 		goto finish;
12832 	}
12833 
12834 	kextIdentifier = OSString::withCString(kextIdentifierCString);
12835 	resourceName   = OSString::withCString(resourceNameCString);
12836 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
12837 	    8 * sizeof(requestTag));
12838 	if (!kextIdentifier ||
12839 	    !resourceName ||
12840 	    !requestTagNum ||
12841 	    !_OSKextSetRequestArgument(requestDict.get(),
12842 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) ||
12843 	    !_OSKextSetRequestArgument(requestDict.get(),
12844 	    kKextRequestArgumentNameKey, resourceName.get()) ||
12845 	    !_OSKextSetRequestArgument(requestDict.get(),
12846 	    kKextRequestArgumentRequestTagKey, requestTagNum.get())) {
12847 		result = kOSKextReturnNoMemory;
12848 		goto finish;
12849 	}
12850 
12851 	callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection());
12852 	if (!callbackRecord) {
12853 		result = kOSKextReturnNoMemory;
12854 		goto finish;
12855 	}
12856 	// we validate callback address at call time
12857 	callbackWrapper = OSValueObjectWithValue(callback);
12858 	if (context) {
12859 		contextWrapper = OSValueObjectWithValue(context);
12860 	}
12861 	if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
12862 	    kKextRequestArgumentCallbackKey, callbackWrapper.get())) {
12863 		result = kOSKextReturnNoMemory;
12864 		goto finish;
12865 	}
12866 
12867 	if (context) {
12868 		if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
12869 		    kKextRequestArgumentContextKey, contextWrapper.get())) {
12870 			result = kOSKextReturnNoMemory;
12871 			goto finish;
12872 		}
12873 	}
12874 
12875 	/* Only post the requests after all the other potential failure points
12876 	 * have been passed.
12877 	 */
12878 	if (!sKernelRequests->setObject(requestDict.get()) ||
12879 	    !sRequestCallbackRecords->setObject(callbackRecord.get())) {
12880 		result = kOSKextReturnNoMemory;
12881 		goto finish;
12882 	}
12883 
12884 	OSKext::pingIOKitDaemon();
12885 
12886 	result = kOSReturnSuccess;
12887 	if (requestTagOut) {
12888 		*requestTagOut = requestTag;
12889 	}
12890 
12891 finish:
12892 
12893 	/* If we didn't succeed, yank the request & callback
12894 	 * from their holding arrays.
12895 	 */
12896 	if (result != kOSReturnSuccess) {
12897 		unsigned int index;
12898 
12899 		index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0);
12900 		if (index != (unsigned int)-1) {
12901 			sKernelRequests->removeObject(index);
12902 		}
12903 		index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0);
12904 		if (index != (unsigned int)-1) {
12905 			sRequestCallbackRecords->removeObject(index);
12906 		}
12907 	}
12908 
12909 	OSKext::considerUnloads(/* rescheduleOnly? */ true);
12910 
12911 	IORecursiveLockUnlock(sKextLock);
12912 
12913 	return result;
12914 }
12915 
12916 OSReturn
12917 OSKext::requestDaemonLaunch(
12918 	OSString *kextIdentifier,
12919 	OSString *serverName,
12920 	OSNumber *serverTag,
12921 	OSBoolean *reslide,
12922 	IOUserServerCheckInToken * checkInToken,
12923 	OSData *serverDUI)
12924 {
12925 	OSReturn       result        = kOSReturnError;
12926 	OSSharedPtr<OSDictionary> requestDict;
12927 	unsigned int size = 0;
12928 	const char *dextUniqueIDCString = NULL;
12929 
12930 	if (!kextIdentifier || !serverName || !serverTag || !checkInToken) {
12931 		return kOSKextReturnInvalidArgument;
12932 	}
12933 	if (!iokitDaemonAvailable()) {
12934 		panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable");
12935 	}
12936 
12937 	if (serverDUI != NULL) {
12938 		dextUniqueIDCString = getDextUniqueIDCString(serverDUI, &size);
12939 	}
12940 
12941 	IORecursiveLockLock(sKextLock);
12942 
12943 	OSKextLog(/* kext */ NULL,
12944 	    kOSKextLogDebugLevel |
12945 	    kOSKextLogGeneralFlag,
12946 	    "Requesting daemon launch for %s %s with serverName %s and tag %llu%s",
12947 	    kextIdentifier->getCStringNoCopy(),
12948 	    (dextUniqueIDCString != NULL)?dextUniqueIDCString:"",
12949 	    serverName->getCStringNoCopy(),
12950 	    serverTag->unsigned64BitValue(),
12951 	    reslide == kOSBooleanTrue ? " with reslid shared cache" : ""
12952 	    );
12953 
12954 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict);
12955 	if (result != kOSReturnSuccess) {
12956 		goto finish;
12957 	}
12958 
12959 	if (!_OSKextSetRequestArgument(requestDict.get(),
12960 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
12961 	    !_OSKextSetRequestArgument(requestDict.get(),
12962 	    kKextRequestArgumentDriverExtensionServerName, serverName) ||
12963 	    !_OSKextSetRequestArgument(requestDict.get(),
12964 	    kKextRequestArgumentDriverExtensionServerTag, serverTag) ||
12965 	    !_OSKextSetRequestArgument(requestDict.get(),
12966 	    kKextRequestArgumentDriverExtensionReslideSharedCache, reslide) ||
12967 	    !_OSKextSetRequestArgument(requestDict.get(),
12968 	    kKextRequestArgumentCheckInToken, checkInToken)) {
12969 		result = kOSKextReturnNoMemory;
12970 		goto finish;
12971 	}
12972 
12973 	if (serverDUI) {
12974 		if (!_OSKextSetRequestArgument(requestDict.get(),
12975 		    kOSBundleDextUniqueIdentifierKey, serverDUI)) {
12976 			result = kOSKextReturnNoMemory;
12977 			goto finish;
12978 		}
12979 	}
12980 
12981 	/* Only post the requests after all the other potential failure points
12982 	 * have been passed.
12983 	 */
12984 	if (!sKernelRequests->setObject(requestDict.get())) {
12985 		result = kOSKextReturnNoMemory;
12986 		goto finish;
12987 	}
12988 	result = OSKext::pingIOKitDaemon();
12989 	if (result != kOSReturnSuccess) {
12990 		goto finish;
12991 	}
12992 
12993 	result = kOSReturnSuccess;
12994 finish:
12995 	IORecursiveLockUnlock(sKextLock);
12996 	if (dextUniqueIDCString) {
12997 		kfree_data(dextUniqueIDCString, size);
12998 	}
12999 	return result;
13000 }
13001 
13002 OSReturn
13003 OSKext::notifyDextUpgrade(
13004 	OSString *kextIdentifier,
13005 	OSData *dextUniqueIdentifier)
13006 {
13007 	OSReturn result = kOSReturnError;
13008 	OSSharedPtr<OSDictionary> requestDict;
13009 	unsigned int size = 0;
13010 	const char *dextUniqueIDCString = getDextUniqueIDCString(dextUniqueIdentifier, &size);
13011 	assert(dextUniqueIDCString != NULL);
13012 
13013 	IORecursiveLockLock(sKextLock);
13014 
13015 	OSKextLog(NULL,
13016 	    kOSKextLogDebugLevel |
13017 	    kOSKextLogGeneralFlag,
13018 	    "Notifying of dext upgrade for %s with UniqueID %s",
13019 	    kextIdentifier->getCStringNoCopy(), dextUniqueIDCString);
13020 
13021 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonUpgradeNotification, requestDict);
13022 	if (result != kOSReturnSuccess) {
13023 		goto finish;
13024 	}
13025 
13026 	if (!_OSKextSetRequestArgument(requestDict.get(),
13027 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
13028 	    !_OSKextSetRequestArgument(requestDict.get(),
13029 	    kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) {
13030 		result = kOSKextReturnNoMemory;
13031 		goto finish;
13032 	}
13033 
13034 	/* Only post the requests after all the other potential failure points
13035 	 * have been passed.
13036 	 */
13037 	if (!sKernelRequests->setObject(requestDict.get())) {
13038 		result = kOSKextReturnNoMemory;
13039 		goto finish;
13040 	}
13041 	OSKext::pingIOKitDaemon();
13042 
13043 	result = kOSReturnSuccess;
13044 finish:
13045 	IORecursiveLockUnlock(sKextLock);
13046 
13047 	if (dextUniqueIDCString != NULL) {
13048 		kfree_data(dextUniqueIDCString, size);
13049 	}
13050 	return result;
13051 }
13052 
13053 /*********************************************************************
13054 * Assumes sKextLock is held.
13055 *********************************************************************/
13056 /* static */
13057 OSReturn
13058 OSKext::dequeueCallbackForRequestTag(
13059 	OSKextRequestTag    requestTag,
13060 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
13061 {
13062 	OSDictionary * callbackRecordOutRaw = NULL;
13063 	OSReturn result;
13064 
13065 	result = dequeueCallbackForRequestTag(requestTag,
13066 	    &callbackRecordOutRaw);
13067 
13068 	if (kOSReturnSuccess == result) {
13069 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
13070 	}
13071 
13072 	return result;
13073 }
13074 OSReturn
13075 OSKext::dequeueCallbackForRequestTag(
13076 	OSKextRequestTag    requestTag,
13077 	OSDictionary     ** callbackRecordOut)
13078 {
13079 	OSReturn   result = kOSReturnError;
13080 	OSSharedPtr<OSNumber> requestTagNum;
13081 
13082 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
13083 	    8 * sizeof(requestTag));
13084 	if (!requestTagNum) {
13085 		goto finish;
13086 	}
13087 
13088 	result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(),
13089 	    callbackRecordOut);
13090 
13091 finish:
13092 	return result;
13093 }
13094 
13095 /*********************************************************************
13096 * Assumes sKextLock is held.
13097 *********************************************************************/
13098 /* static */
13099 OSReturn
13100 OSKext::dequeueCallbackForRequestTag(
13101 	OSNumber     *    requestTagNum,
13102 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
13103 {
13104 	OSDictionary * callbackRecordOutRaw = NULL;
13105 	OSReturn result;
13106 
13107 	result = dequeueCallbackForRequestTag(requestTagNum,
13108 	    &callbackRecordOutRaw);
13109 
13110 	if (kOSReturnSuccess == result) {
13111 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
13112 	}
13113 
13114 	return result;
13115 }
13116 OSReturn
13117 OSKext::dequeueCallbackForRequestTag(
13118 	OSNumber     *    requestTagNum,
13119 	OSDictionary ** callbackRecordOut)
13120 {
13121 	OSReturn        result          = kOSKextReturnInvalidArgument;
13122 	OSDictionary  * callbackRecord  = NULL;        // retain if matched!
13123 	OSNumber      * callbackTagNum  = NULL;        // do not release
13124 	unsigned int    count, i;
13125 
13126 	result = kOSReturnError;
13127 	count = sRequestCallbackRecords->getCount();
13128 	for (i = 0; i < count; i++) {
13129 		callbackRecord = OSDynamicCast(OSDictionary,
13130 		    sRequestCallbackRecords->getObject(i));
13131 		if (!callbackRecord) {
13132 			goto finish;
13133 		}
13134 
13135 		/* If we don't find a tag, we basically have a leak here. Maybe
13136 		 * we should just remove it.
13137 		 */
13138 		callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
13139 			    callbackRecord, kKextRequestArgumentRequestTagKey));
13140 		if (!callbackTagNum) {
13141 			goto finish;
13142 		}
13143 
13144 		/* We could be even more paranoid and check that all the incoming
13145 		 * args match what's in the callback record.
13146 		 */
13147 		if (callbackTagNum->isEqualTo(requestTagNum)) {
13148 			if (callbackRecordOut) {
13149 				*callbackRecordOut = callbackRecord;
13150 				callbackRecord->retain();
13151 			}
13152 			sRequestCallbackRecords->removeObject(i);
13153 			result = kOSReturnSuccess;
13154 			goto finish;
13155 		}
13156 	}
13157 	result = kOSKextReturnNotFound;
13158 
13159 finish:
13160 	return result;
13161 }
13162 
13163 
13164 /*********************************************************************
13165 * Busy timeout triage
13166 *********************************************************************/
13167 /* static */
13168 bool
13169 OSKext::pendingIOKitDaemonRequests(void)
13170 {
13171 	return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
13172 }
13173 
13174 /*********************************************************************
13175 * Acquires and releases sKextLock
13176 *
13177 * This function is designed to be called by kernelmanagerd and driverkitd
13178 * and it gathers all codeless kext and dext personalities, and then attempts
13179 * to map a System (pageable) KC and an Auxiliary (aux) KC.
13180 *
13181 * The pageable and aux KC can be loaded only once at boot time.
13182 * Even if the pageable or aux KC fail to load - this function will
13183 * not allow a new pageable or aux KC to be installed by subsequent calls.
13184 * This is done to avoid security issues where userspace has been compromised
13185 * or the pageable kc has been tampered with and the attacker
13186 * attempts to re-load a malicious variant.
13187 * However dexts can be dynamically loaded, so this function can be used
13188 * to request the installation of a new set of dexts even after boot time.
13189 *
13190 *
13191 *
13192 * Return: if a KC fails to load the return value will contain:
13193 *         kOSKextReturnKCLoadFailure. If the pageable KC fails,
13194 *         the return value will contain kOSKextReturnKCLoadFailureSystemKC.
13195 *         Similarly, if the aux kc load fails, the return value will
13196 *         contain kOSKextReturnKCLoadFailureAuxKC. The two values
13197 *         compose with each other and with kOSKextReturnKCLoadFailure.
13198 *********************************************************************/
13199 /* static */
13200 OSReturn
13201 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused)
13202 {
13203 	static bool daemon_ready = false;
13204 
13205 	OSReturn ret = kOSKextReturnInvalidArgument;
13206 	OSReturn kcerr = 0;
13207 	bool start_matching = false;
13208 
13209 	bool allow_fileset_load = !daemon_ready;
13210 #if !(defined(__x86_64__) || defined(__i386__))
13211 	/* never allow KCs full of kexts on non-x86 machines */
13212 	allow_fileset_load = false;
13213 #endif
13214 
13215 	/*
13216 	 * Change with 70582300
13217 	 */
13218 #if 0 || !defined(VM_MAPPED_KEXTS)
13219 	/*
13220 	 * On platforms that don't support the SystemKC or a file-backed
13221 	 * AuxKC, the kext receipt for 3rd party kexts loaded by the booter
13222 	 * needs to be queried before we load any codeless kexts or release
13223 	 * any 3rd party kexts to run. On platforms that support a file-backed
13224 	 * AuxKC, this process is done via the kext audit mechanism.
13225 	 */
13226 
13227 	printf("KextLog: waiting for kext receipt to be queried.\n");
13228 	while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) {
13229 		IOSleep(30);
13230 	}
13231 #endif /* !VM_MAPPED_KEXTS */
13232 
13233 	/*
13234 	 * Get the args from the request. Right now we need the file
13235 	 * name for the pageable and the aux kext collection file sets.
13236 	 */
13237 	OSDictionary * requestArgs                = NULL;        // do not release
13238 	OSString     * pageable_filepath          = NULL;        // do not release
13239 	OSString     * aux_filepath               = NULL;        // do not release
13240 	OSArray      * codeless_kexts             = NULL;        // do not release
13241 
13242 	kernel_mach_header_t *akc_mh              = NULL;
13243 
13244 	requestArgs = OSDynamicCast(OSDictionary,
13245 	    requestDict->getObject(kKextRequestArgumentsKey));
13246 
13247 	if (requestArgs == NULL) {
13248 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13249 		    "KextLog: No arguments in plist for loading fileset kext\n");
13250 		printf("KextLog: No arguments in plist for loading fileset kext\n");
13251 		return ret;
13252 	}
13253 
13254 	ret = kOSKextReturnDisabled;
13255 
13256 	IORecursiveLockLock(sKextLock);
13257 
13258 	if (!sLoadEnabled) {
13259 		OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13260 		    "KextLog: Kext loading is disabled (attempt to load KCs).");
13261 		IORecursiveLockUnlock(sKextLock);
13262 		return ret;
13263 	}
13264 
13265 	pageable_filepath = OSDynamicCast(OSString,
13266 	    requestArgs->getObject(kKextRequestArgumentPageableKCFilename));
13267 
13268 	if (allow_fileset_load && pageable_filepath != NULL) {
13269 		printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy());
13270 
13271 		ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable);
13272 		if (ret) {
13273 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13274 			    "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
13275 
13276 			printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
13277 			ret = kOSKextReturnKCLoadFailure;
13278 			kcerr |= kOSKextReturnKCLoadFailureSystemKC;
13279 			goto try_auxkc;
13280 		}
13281 		/*
13282 		 * Even if the AuxKC fails to load, we still want to send
13283 		 * the System KC personalities to the catalog for matching
13284 		 */
13285 		start_matching = true;
13286 	} else if (pageable_filepath != NULL) {
13287 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13288 		    "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy());
13289 		ret = kOSKextReturnUnsupported;
13290 	}
13291 
13292 try_auxkc:
13293 	akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
13294 	if (akc_mh) {
13295 		/*
13296 		 * If we try to load a deferred AuxKC, then don't ever attempt
13297 		 * a filesystem map of a file
13298 		 */
13299 		allow_fileset_load = false;
13300 
13301 		/*
13302 		 * This function is only called once per boot, so we haven't
13303 		 * yet loaded an AuxKC. If we have registered the AuxKC mach
13304 		 * header, that means that the kext collection has been placed
13305 		 * in memory for us by the booter, and is waiting for us to
13306 		 * process it.  Grab the deferred XML plist of info
13307 		 * dictionaries and add all the kexts.
13308 		 */
13309 		OSSharedPtr<OSObject>  parsedXML;
13310 		OSSharedPtr<OSData>    loaded_kcUUID;
13311 		OSDictionary          *infoDict;
13312 		parsedXML = consumeDeferredKextCollection(KCKindAuxiliary);
13313 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
13314 #if !defined(VM_MAPPED_KEXTS)
13315 		/*
13316 		 * On platforms where we don't dynamically wire-down / page-in
13317 		 * kext memory, we need to maintain the invariant that if the
13318 		 * AuxKC in memory does not contain a kext receipt, then we
13319 		 * should not load any of the kexts.
13320 		 */
13321 		size_t receipt_sz = 0;
13322 		if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) {
13323 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13324 			    "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt");
13325 			ret = kOSKextReturnKCLoadFailure;
13326 			goto try_codeless;
13327 		}
13328 #endif
13329 		if (infoDict) {
13330 			bool added;
13331 			printf("KextLog: Adding kexts from in-memory AuxKC\n");
13332 			added = OSKext::addKextsFromKextCollection(akc_mh, infoDict,
13333 			    kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary);
13334 			if (!loaded_kcUUID) {
13335 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13336 				    "KextLog: WARNING: did not find UUID in deferred Aux KC!");
13337 			} else if (!added) {
13338 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13339 				    "KextLog: WARNING: Failed to load AuxKC from memory.");
13340 			}
13341 			/* only return success if the pageable load (above) was successful */
13342 			if (ret != kOSKextReturnKCLoadFailure) {
13343 				ret = kOSReturnSuccess;
13344 			}
13345 			/* the registration of the AuxKC parsed out the KC's UUID already */
13346 		} else {
13347 			if (daemon_ready) {
13348 				/*
13349 				 * Complain, but don't return an error if this isn't the first time the
13350 				 * IOKit daemon is checking in. If the daemon ever restarts, we will
13351 				 * hit this case because we've already consumed the deferred personalities.
13352 				 * We return success here so that a call to this function from a restarted
13353 				 * daemon with no codeless kexts will succeed.
13354 				 */
13355 				OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13356 				    "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart");
13357 				if (ret != kOSKextReturnKCLoadFailure) {
13358 					ret = kOSReturnSuccess;
13359 				}
13360 			} else {
13361 				/* this is a real error case */
13362 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13363 				    "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary");
13364 				printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n");
13365 				ret = kOSKextReturnKCLoadFailure;
13366 				kcerr |= kOSKextReturnKCLoadFailureAuxKC;
13367 			}
13368 		}
13369 	}
13370 
13371 	aux_filepath = OSDynamicCast(OSString,
13372 	    requestArgs->getObject(kKextRequestArgumentAuxKCFilename));
13373 	if (allow_fileset_load && aux_filepath != NULL) {
13374 		printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy());
13375 
13376 		ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary);
13377 		if (ret) {
13378 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13379 			    "KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
13380 
13381 			printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
13382 			ret = kOSKextReturnKCLoadFailure;
13383 			kcerr |= kOSKextReturnKCLoadFailureAuxKC;
13384 			goto try_codeless;
13385 		}
13386 		start_matching = true;
13387 	} else if (aux_filepath != NULL) {
13388 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13389 		    "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy());
13390 		if (ret != kOSKextReturnKCLoadFailure) {
13391 			ret = kOSKextReturnUnsupported;
13392 		}
13393 	}
13394 
13395 try_codeless:
13396 	/*
13397 	 * Load codeless kexts last so that there is no possibilty of a
13398 	 * codeless kext bundle ID preventing a kext in the system KC from
13399 	 * loading
13400 	 */
13401 	codeless_kexts = OSDynamicCast(OSArray,
13402 	    requestArgs->getObject(kKextRequestArgumentCodelessPersonalities));
13403 	if (codeless_kexts != NULL) {
13404 		uint32_t count = codeless_kexts->getCount();
13405 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13406 		    "KextLog: loading %d codeless kexts/dexts", count);
13407 		for (uint32_t i = 0; i < count; i++) {
13408 			OSDictionary *infoDict;
13409 			infoDict = OSDynamicCast(OSDictionary,
13410 			    codeless_kexts->getObject(i));
13411 			if (!infoDict) {
13412 				continue;
13413 			}
13414 			// instantiate a new kext, and don't hold a reference
13415 			// (the kext subsystem will hold one implicitly)
13416 			OSKext::withCodelessInfo(infoDict, NULL);
13417 		}
13418 		/* ignore errors that are not KC load failures */
13419 		if (ret != kOSKextReturnKCLoadFailure) {
13420 			ret = kOSReturnSuccess;
13421 		}
13422 		start_matching = true;
13423 	}
13424 
13425 	/* send personalities to the IOCatalog once */
13426 	if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) {
13427 		OSKext::sendAllKextPersonalitiesToCatalog(true);
13428 		/*
13429 		 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark
13430 		 * things as active and start all the delayed matching: the
13431 		 * dext and codeless kext personalities should have all been
13432 		 * delivered via this one call.
13433 		 */
13434 		if (!daemon_ready) {
13435 			OSKext::setIOKitDaemonActive();
13436 			OSKext::setDeferredLoadSucceeded(TRUE);
13437 			IOService::iokitDaemonLaunched();
13438 		}
13439 		if (sOSKextWasResetAfterUserspaceReboot) {
13440 			sOSKextWasResetAfterUserspaceReboot = false;
13441 			OSKext::setIOKitDaemonActive();
13442 			IOService::startDeferredMatches();
13443 		}
13444 	}
13445 
13446 	if (ret == kOSKextReturnKCLoadFailure) {
13447 		ret |= kcerr;
13448 	}
13449 
13450 	/*
13451 	 * Only allow this function to attempt to load the pageable and
13452 	 * aux KCs once per boot.
13453 	 */
13454 	daemon_ready = true;
13455 
13456 	IORecursiveLockUnlock(sKextLock);
13457 
13458 	return ret;
13459 }
13460 
13461 OSReturn
13462 OSKext::resetMutableSegments(void)
13463 {
13464 	kernel_segment_command_t *seg = NULL;
13465 	kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
13466 	u_int index = 0;
13467 	OSKextSavedMutableSegment *savedSegment = NULL;
13468 	uintptr_t kext_slide = PE_get_kc_slide(kc_type);
13469 	OSReturn err;
13470 
13471 	if (!savedMutableSegments) {
13472 		OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
13473 		    "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString());
13474 		err = kOSKextReturnInternalError;
13475 		goto finish;
13476 	}
13477 
13478 	for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) {
13479 		if (!segmentIsMutable(seg)) {
13480 			continue;
13481 		}
13482 		uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
13483 		uint64_t vmsize = seg->vmsize;
13484 		err = kOSKextReturnInternalError;
13485 		for (index = 0; index < savedMutableSegments->getCount(); index++) {
13486 			savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index));
13487 			assert(savedSegment);
13488 			if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) {
13489 				OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
13490 				    "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13491 				err = savedSegment->restoreContents(seg);
13492 				if (err != kOSReturnSuccess) {
13493 					panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13494 				}
13495 			}
13496 		}
13497 		if (err != kOSReturnSuccess) {
13498 			panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13499 		}
13500 	}
13501 	err = kOSReturnSuccess;
13502 finish:
13503 	return err;
13504 }
13505 
13506 
13507 /*********************************************************************
13508 * Assumes sKextLock is held.
13509 *********************************************************************/
13510 /* static */
13511 OSReturn
13512 OSKext::loadKCFileSet(
13513 	const char *filepath,
13514 	kc_kind_t   type)
13515 {
13516 #if VM_MAPPED_KEXTS
13517 	/* we only need to load filesets on systems that support VM_MAPPED kexts */
13518 	OSReturn err;
13519 	struct vnode *vp = NULL;
13520 	void *fileset_control;
13521 	off_t fsize;
13522 	bool pageable = (type == KCKindPageable);
13523 
13524 	if ((pageable && pageableKCloaded) ||
13525 	    (!pageable && auxKCloaded)) {
13526 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13527 		    "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux"));
13528 
13529 		return kOSKextReturnInvalidArgument;
13530 	}
13531 
13532 	/* Do not allow AuxKC to load if Pageable KC is not loaded */
13533 	if (!pageable && !pageableKCloaded) {
13534 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13535 		    "Trying to load the Aux KC without loading the Pageable KC");
13536 		return kOSKextReturnInvalidArgument;
13537 	}
13538 
13539 	fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize);
13540 
13541 	if (fileset_control == NULL) {
13542 		printf("Could not get memory control object for file %s", filepath);
13543 
13544 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13545 		    "Could not get memory control object for file %s", filepath);
13546 		return kOSKextReturnInvalidArgument;
13547 	}
13548 	if (vp == NULL) {
13549 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13550 		    "Could not find vnode for file %s", filepath);
13551 		return kOSKextReturnInvalidArgument;
13552 	}
13553 
13554 	kernel_mach_header_t *mh = NULL;
13555 	uintptr_t slide = 0;
13556 
13557 #if CONFIG_CSR
13558 	/*
13559 	 * When SIP is enabled, the KC we map must be SIP-protected
13560 	 */
13561 	if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) {
13562 		struct vnode_attr va;
13563 		int error;
13564 		VATTR_INIT(&va);
13565 		VATTR_WANTED(&va, va_flags);
13566 		error = vnode_getattr(vp, &va, vfs_context_current());
13567 		if (error) {
13568 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13569 			    "vnode_getattr(%s) failed (error=%d)", filepath, error);
13570 			err = kOSKextReturnInternalError;
13571 			goto finish;
13572 		}
13573 		if (!(va.va_flags & SF_RESTRICTED)) {
13574 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13575 			    "Path to KC '%s' is not SIP-protected", filepath);
13576 			err = kOSKextReturnInvalidArgument;
13577 			goto finish;
13578 		}
13579 	}
13580 #endif
13581 
13582 	err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL);
13583 	if (err) {
13584 		printf("KextLog: mapKCFileSet returned %d\n", err);
13585 
13586 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13587 		    "mapKCFileSet returned %d\n", err);
13588 
13589 		err = kOSKextReturnInvalidArgument;
13590 	}
13591 
13592 #if CONFIG_CSR
13593 finish:
13594 #endif
13595 	/* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */
13596 	assert(vp != NULL);
13597 	if (err == kOSReturnSuccess) {
13598 		PE_set_kc_vp(type, vp);
13599 		if (pageable) {
13600 			pageableKCloaded = true;
13601 		} else {
13602 			auxKCloaded = true;
13603 		}
13604 	} else {
13605 		vnode_put(vp);
13606 	}
13607 
13608 	return err;
13609 #else
13610 	(void)filepath;
13611 	(void)type;
13612 	return kOSKextReturnUnsupported;
13613 #endif // VM_MAPPED_KEXTS
13614 }
13615 
13616 #if defined(__x86_64__) || defined(__i386__)
13617 /*********************************************************************
13618 * Assumes sKextLock is held.
13619 *********************************************************************/
13620 /* static */
13621 OSReturn
13622 OSKext::mapKCFileSet(
13623 	void                 *control,
13624 	vm_size_t            fsize,
13625 	kernel_mach_header_t **mhp,
13626 	off_t                file_offset,
13627 	uintptr_t            *slidep,
13628 	bool                 pageable,
13629 	void                 *map_entry_list)
13630 {
13631 	bool fileset_load = false;
13632 	kern_return_t ret;
13633 	OSReturn err;
13634 	kernel_section_t *infoPlistSection = NULL;
13635 	OSDictionary *infoDict = NULL;
13636 
13637 	OSSharedPtr<OSObject> parsedXML;
13638 	OSSharedPtr<OSString> errorString;
13639 	OSSharedPtr<OSData> loaded_kcUUID;
13640 
13641 	/* Check if initial load for file set */
13642 	if (*mhp == NULL) {
13643 		fileset_load = true;
13644 
13645 		/* Get a page aligned address from kext map to map the file */
13646 		vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize);
13647 		if (pagealigned_addr == 0) {
13648 			return kOSKextReturnNoMemory;
13649 		}
13650 
13651 		*mhp = (kernel_mach_header_t *)pagealigned_addr;
13652 
13653 		/* Allocate memory for bailout mechanism */
13654 		map_entry_list = allocate_kcfileset_map_entry_list();
13655 		if (map_entry_list == NULL) {
13656 			return kOSKextReturnNoMemory;
13657 		}
13658 	}
13659 
13660 	uintptr_t *slideptr = fileset_load ? slidep : NULL;
13661 	err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list);
13662 	/* mhp and slideptr are updated by mapKCTextSegment */
13663 	if (err) {
13664 		if (fileset_load) {
13665 			deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13666 		}
13667 		return err;
13668 	}
13669 
13670 	/* Initialize the kc header globals */
13671 	if (fileset_load) {
13672 		if (pageable) {
13673 			PE_set_kc_header(KCKindPageable, *mhp, *slidep);
13674 		} else {
13675 			PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep);
13676 		}
13677 	}
13678 
13679 	/* Iterate through all the segments and map necessary segments */
13680 	struct load_command *lcp = (struct load_command *) (*mhp + 1);
13681 	for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) {
13682 		vm_map_offset_t start;
13683 		kernel_mach_header_t *k_mh = NULL;
13684 		kernel_segment_command_t * seg = NULL;
13685 		struct fileset_entry_command *fse = NULL;
13686 
13687 		if (lcp->cmd == LC_SEGMENT_KERNEL) {
13688 			seg = (kernel_segment_command_t *)lcp;
13689 			start = ((uintptr_t)(seg->vmaddr)) + *slidep;
13690 		} else if (lcp->cmd == LC_FILESET_ENTRY) {
13691 			fse = (struct fileset_entry_command *)lcp;
13692 			k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep);
13693 
13694 			/* Map the segments of the mach-o binary */
13695 			err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list);
13696 			if (err) {
13697 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13698 				return kOSKextReturnInvalidArgument;
13699 			}
13700 			continue;
13701 		} else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) {
13702 			/* Check if the Aux KC is built pageable style */
13703 			if (!pageable && !fileset_load && !auxKCloaded) {
13704 				resetAuxKCSegmentOnUnload = true;
13705 			}
13706 			continue;
13707 		} else {
13708 			continue;
13709 		}
13710 
13711 		if (fileset_load) {
13712 			if (seg->vmsize == 0) {
13713 				continue;
13714 			}
13715 
13716 			/* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */
13717 			if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 &&
13718 			    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 &&
13719 			    strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 &&
13720 			    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) {
13721 				continue;
13722 			}
13723 		} else {
13724 			if (seg->vmsize == 0) {
13725 				continue;
13726 			}
13727 
13728 			/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
13729 			if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
13730 			    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
13731 			    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
13732 				continue;
13733 			}
13734 		}
13735 
13736 		ret = vm_map_kcfileset_segment(
13737 			&start, seg->vmsize,
13738 			(memory_object_control_t)control, seg->fileoff, seg->maxprot);
13739 
13740 		if (ret != KERN_SUCCESS) {
13741 			if (fileset_load) {
13742 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13743 			}
13744 			return kOSKextReturnInvalidArgument;
13745 		}
13746 		add_kcfileset_map_entry(map_entry_list, start, seg->vmsize);
13747 	}
13748 
13749 	/* Return if regular mach-o */
13750 	if (!fileset_load) {
13751 		return 0;
13752 	}
13753 
13754 	/*
13755 	 * Fixup for the Pageable KC and the Aux KC is done by
13756 	 * i386_slide_kext_collection_mh_addrs, but it differs in
13757 	 * following ways:
13758 	 *
13759 	 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands.
13760 	 * The fixup of kext segments and kext load commands are done at kext
13761 	 * load time by calling i386_slide_individual_kext.
13762 	 *
13763 	 * AuxKC old style: Fixup all the segments and all the load commands.
13764 	 *
13765 	 * AuxKC pageable style: Same as the Pageable KC.
13766 	 */
13767 	bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false));
13768 	ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header);
13769 	if (ret != KERN_SUCCESS) {
13770 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13771 		return kOSKextReturnInvalidArgument;
13772 	}
13773 
13774 	/* Get the prelink info dictionary */
13775 	infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection);
13776 	parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
13777 	if (parsedXML) {
13778 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
13779 	}
13780 
13781 	if (!infoDict) {
13782 		const char *errorCString = "(unknown error)";
13783 
13784 		if (errorString && errorString->getCStringNoCopy()) {
13785 			errorCString = errorString->getCStringNoCopy();
13786 		} else if (parsedXML) {
13787 			errorCString = "not a dictionary";
13788 		}
13789 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13790 		    "Error unserializing kext info plist section: %s.", errorCString);
13791 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13792 		return kOSKextReturnInvalidArgument;
13793 	}
13794 
13795 	/* Validate that the Kext Collection is prelinked to the loaded KC */
13796 	err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary);
13797 	if (err) {
13798 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13799 		return kOSKextReturnInvalidArgument;
13800 	}
13801 
13802 	/* Set Protection of Segments */
13803 	OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary);
13804 
13805 	OSKext::addKextsFromKextCollection(*mhp,
13806 	    infoDict, kPrelinkTextSegment,
13807 	    loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary);
13808 
13809 	/* Copy in the KC UUID */
13810 	if (!loaded_kcUUID) {
13811 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13812 		    "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux");
13813 	} else if (pageable) {
13814 		pageablekc_uuid_valid = TRUE;
13815 		memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
13816 		uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string);
13817 	} else {
13818 		auxkc_uuid_valid = TRUE;
13819 		memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
13820 		uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
13821 	}
13822 
13823 	deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable);
13824 
13825 	return 0;
13826 }
13827 
13828 /*********************************************************************
13829 * Assumes sKextLock is held.
13830 *********************************************************************/
13831 /* static */
13832 OSReturn
13833 OSKext::mapKCTextSegment(
13834 	void                 *control,
13835 	kernel_mach_header_t **mhp,
13836 	off_t                file_offset,
13837 	uintptr_t            *slidep,
13838 	void                 *map_entry_list)
13839 {
13840 	kern_return_t ret;
13841 	vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t),
13842 	    PAGE_MASK);
13843 	vm_map_offset_t load_command_map_size = 0;
13844 	kernel_mach_header_t *base_mh = *mhp;
13845 
13846 	/* Map the mach header at start of fileset for now (vmaddr = 0) */
13847 	ret = vm_map_kcfileset_segment(
13848 		(vm_map_offset_t *)&base_mh, mach_header_map_size,
13849 		(memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE));
13850 
13851 	if (ret != KERN_SUCCESS) {
13852 		printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret);
13853 
13854 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13855 		    "Failed to map mach header of kc fileset with error %d", ret);
13856 		return kOSKextReturnInvalidArgument;
13857 	}
13858 
13859 	if (slidep) {
13860 		/* Verify that it's an MH_FILESET */
13861 		if (base_mh->filetype != MH_FILESET) {
13862 			printf("Kext Log: mapKCTextSegment mach header filetype"
13863 			    " is not an MH_FILESET, it is %x", base_mh->filetype);
13864 
13865 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13866 			    "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype);
13867 
13868 			/* Unmap the mach header */
13869 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13870 			return kOSKextReturnInvalidArgument;
13871 		}
13872 	}
13873 
13874 	/* Map the remaining pages of load commands */
13875 	if (base_mh->sizeofcmds > mach_header_map_size) {
13876 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
13877 		load_command_map_size = base_mh->sizeofcmds - mach_header_map_size;
13878 
13879 		/* Map the load commands */
13880 		ret = vm_map_kcfileset_segment(
13881 			&load_command_addr, load_command_map_size,
13882 			(memory_object_control_t)control, file_offset + mach_header_map_size,
13883 			(VM_PROT_READ | VM_PROT_WRITE));
13884 
13885 		if (ret != KERN_SUCCESS) {
13886 			printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret);
13887 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13888 			    "Failed to map load commands of kc fileset with error %d", ret);
13889 
13890 			/* Unmap the mach header */
13891 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13892 			return kOSKextReturnInvalidArgument;
13893 		}
13894 	}
13895 
13896 	kernel_segment_command_t *text_seg;
13897 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT);
13898 
13899 	/* Calculate the slide and vm addr of mach header */
13900 	if (slidep) {
13901 		*mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr);
13902 		*slidep = ((uintptr_t)*mhp) - text_seg->vmaddr;
13903 	}
13904 
13905 	/* Cache the text segment size and file offset before unmapping */
13906 	vm_map_offset_t text_segment_size = text_seg->vmsize;
13907 	vm_object_offset_t text_segment_fileoff = text_seg->fileoff;
13908 	vm_prot_t text_maxprot = text_seg->maxprot;
13909 
13910 	/* Unmap the first page and loadcommands and map the text segment */
13911 	ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13912 	assert(ret == KERN_SUCCESS);
13913 
13914 	if (load_command_map_size) {
13915 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
13916 		ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size);
13917 		assert(ret == KERN_SUCCESS);
13918 	}
13919 
13920 	/* Map the text segment at actual vm addr specified in fileset */
13921 	ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size,
13922 	    (memory_object_control_t)control, text_segment_fileoff, text_maxprot);
13923 	if (ret != KERN_SUCCESS) {
13924 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13925 		    "Failed to map Text segment of kc fileset with error %d", ret);
13926 		return kOSKextReturnInvalidArgument;
13927 	}
13928 
13929 	add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size);
13930 	return 0;
13931 }
13932 
13933 /*********************************************************************
13934 * Assumes sKextLock is held.
13935 *********************************************************************/
13936 /* static */
13937 OSReturn
13938 OSKext::protectKCFileSet(
13939 	kernel_mach_header_t *mh,
13940 	kc_kind_t            type)
13941 {
13942 	vm_map_t                    kext_map        = g_kext_map;
13943 	kernel_segment_command_t  * seg             = NULL;
13944 	vm_map_offset_t             start           = 0;
13945 	vm_map_offset_t             end             = 0;
13946 	vm_map_size_t               size            = 0;
13947 	OSReturn                    ret             = 0;
13948 
13949 	/* Set VM permissions */
13950 	seg = firstsegfromheader((kernel_mach_header_t *)mh);
13951 	while (seg) {
13952 		start = round_page(seg->vmaddr);
13953 		end = trunc_page(seg->vmaddr + seg->vmsize);
13954 		size = end - start;
13955 
13956 		/*
13957 		 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS
13958 		 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT
13959 		 * for the Aux KC as well.
13960 		 */
13961 		if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 ||
13962 		    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 ||
13963 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 ||
13964 		    (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload &&
13965 		    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) {
13966 			ret = OSKext_protect((kernel_mach_header_t *)mh,
13967 			    kext_map, start, size, seg->maxprot, TRUE, type);
13968 			if (ret != KERN_SUCCESS) {
13969 				printf("OSKext protect failed with error %d", ret);
13970 				return kOSKextReturnInvalidArgument;
13971 			}
13972 
13973 			ret = OSKext_protect((kernel_mach_header_t *)mh,
13974 			    kext_map, start, size, seg->initprot, FALSE, type);
13975 			if (ret != KERN_SUCCESS) {
13976 				printf("OSKext protect failed with error %d", ret);
13977 				return kOSKextReturnInvalidArgument;
13978 			}
13979 
13980 			ret = OSKext_wire((kernel_mach_header_t *)mh,
13981 			    kext_map, start, end, seg->initprot, FALSE, type);
13982 			if (ret != KERN_SUCCESS) {
13983 				printf("OSKext wire failed with error %d", ret);
13984 				return kOSKextReturnInvalidArgument;
13985 			}
13986 		}
13987 
13988 		seg = nextsegfromheader((kernel_mach_header_t *) mh, seg);
13989 	}
13990 
13991 	return 0;
13992 }
13993 
13994 /*********************************************************************
13995 * Assumes sKextLock is held.
13996 *********************************************************************/
13997 /* static */
13998 void
13999 OSKext::freeKCFileSetcontrol(void)
14000 {
14001 	PE_reset_all_kc_vp();
14002 }
14003 
14004 /*********************************************************************
14005 * Assumes sKextLock is held.
14006 *
14007 * resetKCFileSetSegments: Kext start function expects data segment to
14008 * be pristine on every load, unmap the dirty segments on unload and
14009 * remap them from FileSet on disk. Remap all segments of kext since
14010 * fixups are done per kext and not per segment.
14011 *********************************************************************/
14012 OSReturn
14013 OSKext::resetKCFileSetSegments(void)
14014 {
14015 	kernel_segment_command_t *seg = NULL;
14016 	kernel_segment_command_t *text_seg;
14017 	uint32_t text_fileoff;
14018 	kernel_mach_header_t *k_mh = NULL;
14019 	uintptr_t slide;
14020 	struct vnode *vp = NULL;
14021 	void *fileset_control = NULL;
14022 	bool pageable = (kc_type == KCKindPageable);
14023 	OSReturn err;
14024 	kern_return_t kr;
14025 
14026 	/* Check the vnode reference is still available */
14027 	vp = (struct vnode *)PE_get_kc_vp(kc_type);
14028 	if (vp == NULL) {
14029 		OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
14030 		    "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString());
14031 		return kOSKextReturnInternalError;
14032 	}
14033 
14034 	fileset_control = ubc_getobject(vp, 0);
14035 	assert(fileset_control != NULL);
14036 
14037 	OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
14038 	    "Kext %s resetting all segments", getIdentifierCString());
14039 
14040 	k_mh = (kernel_mach_header_t *)kmod_info->address;
14041 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT);
14042 	text_fileoff = text_seg->fileoff;
14043 	slide = PE_get_kc_slide(kc_type);
14044 
14045 	seg = firstsegfromheader((kernel_mach_header_t *)k_mh);
14046 	while (seg) {
14047 		if (seg->vmsize == 0) {
14048 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
14049 			continue;
14050 		}
14051 
14052 		/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
14053 		if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
14054 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
14055 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
14056 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
14057 			continue;
14058 		}
14059 
14060 		kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize);
14061 		assert(kr == KERN_SUCCESS);
14062 		seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
14063 	}
14064 
14065 	/* Unmap the text segment */
14066 	kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize);
14067 	assert(kr == KERN_SUCCESS);
14068 
14069 	/* Map all the segments of the kext */
14070 	err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL);
14071 	if (err) {
14072 		panic("Could not reset segments of a mapped kext, error %x", err);
14073 	}
14074 
14075 	/* Update address in kmod_info, since it has been reset */
14076 	if (kmod_info->address) {
14077 		kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide);
14078 	}
14079 
14080 	return 0;
14081 }
14082 
14083 /*********************************************************************
14084 * Mechanism to track all segment mapping while mapping KC fileset.
14085 *********************************************************************/
14086 
14087 struct kcfileset_map_entry {
14088 	vm_map_offset_t me_start;
14089 	vm_map_offset_t me_size;
14090 };
14091 
14092 struct kcfileset_map_entry_list {
14093 	int                        kme_list_count;
14094 	int                        kme_list_index;
14095 	struct kcfileset_map_entry kme_list[];
14096 };
14097 
14098 #define KCFILESET_MAP_ENTRY_MAX (16380)
14099 
14100 static void *
14101 allocate_kcfileset_map_entry_list(void)
14102 {
14103 	struct kcfileset_map_entry_list *entry_list;
14104 
14105 	entry_list = kalloc_type(struct kcfileset_map_entry_list,
14106 	    struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO);
14107 
14108 	entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX;
14109 	entry_list->kme_list_index = 0;
14110 	return entry_list;
14111 }
14112 
14113 static void
14114 add_kcfileset_map_entry(
14115 	void            *map_entry_list,
14116 	vm_map_offset_t start,
14117 	vm_map_offset_t size)
14118 {
14119 	if (map_entry_list == NULL) {
14120 		return;
14121 	}
14122 
14123 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
14124 
14125 	if (entry_list->kme_list_index >= entry_list->kme_list_count) {
14126 		panic("Ran out of map kc fileset list");
14127 	}
14128 
14129 	entry_list->kme_list[entry_list->kme_list_index].me_start = start;
14130 	entry_list->kme_list[entry_list->kme_list_index].me_size = size;
14131 
14132 	entry_list->kme_list_index++;
14133 }
14134 
14135 static void
14136 deallocate_kcfileset_map_entry_list_and_unmap_entries(
14137 	void      *map_entry_list,
14138 	boolean_t unmap_entries,
14139 	bool      pageable)
14140 {
14141 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
14142 
14143 	if (unmap_entries) {
14144 		for (int i = 0; i < entry_list->kme_list_index; i++) {
14145 			kern_return_t ret;
14146 			ret = vm_unmap_kcfileset_segment(
14147 				&(entry_list->kme_list[i].me_start),
14148 				entry_list->kme_list[i].me_size);
14149 			assert(ret == KERN_SUCCESS);
14150 		}
14151 
14152 		PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary);
14153 	}
14154 
14155 	kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry,
14156 	    KCFILESET_MAP_ENTRY_MAX, entry_list);
14157 }
14158 
14159 /*********************************************************************
14160 * Mechanism to map kext segment.
14161 *********************************************************************/
14162 
14163 kern_return_t
14164 vm_map_kcfileset_segment(
14165 	vm_map_offset_t    *start,
14166 	vm_map_offset_t    size,
14167 	void               *control,
14168 	vm_object_offset_t fileoffset,
14169 	vm_prot_t          max_prot)
14170 {
14171 	vm_map_kernel_flags_t vmk_flags = {
14172 		.vmf_fixed = true,
14173 		.vmkf_no_copy_on_read = true,
14174 		.vmkf_cs_enforcement_override = true,
14175 		.vm_tag = VM_KERN_MEMORY_OSKEXT,
14176 	};
14177 	kern_return_t ret;
14178 
14179 	/* Add Write to max prot to allow fixups */
14180 	max_prot = max_prot | VM_PROT_WRITE;
14181 
14182 	/*
14183 	 * Map the segments from file as COPY mappings to
14184 	 * make sure changes on disk to the file does not affect
14185 	 * mapped segments.
14186 	 */
14187 	ret = vm_map_enter_mem_object_control(
14188 		g_kext_map,
14189 		start,
14190 		size,
14191 		(mach_vm_offset_t)0,
14192 		vmk_flags,
14193 		(memory_object_control_t)control,
14194 		fileoffset,
14195 		TRUE,         /* copy */
14196 		(VM_PROT_READ | VM_PROT_WRITE), max_prot,
14197 		VM_INHERIT_NONE);
14198 
14199 	return ret;
14200 }
14201 
14202 kern_return_t
14203 vm_unmap_kcfileset_segment(
14204 	vm_map_offset_t    *start,
14205 	vm_map_offset_t    size)
14206 {
14207 	return mach_vm_deallocate(g_kext_map, *start, size);
14208 }
14209 
14210 #endif //(__x86_64__) || defined(__i386__)
14211 
14212 /*********************************************************************
14213 * Assumes sKextLock is held.
14214 *********************************************************************/
14215 /* static */
14216 OSReturn
14217 OSKext::validateKCFileSetUUID(
14218 	OSDictionary         *infoDict,
14219 	kc_kind_t            type)
14220 {
14221 	OSReturn ret           = kOSReturnSuccess;
14222 
14223 	if (!kernelcache_uuid_valid) {
14224 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14225 		    "validateKCFileSetUUID Boot KC UUID was not set at boot.");
14226 		ret = kOSKextReturnInvalidArgument;
14227 		goto finish;
14228 	}
14229 	ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey);
14230 	if (ret != 0) {
14231 		goto finish;
14232 	}
14233 
14234 #if defined(__x86_64__) || defined(__i386__)
14235 	/* Check if the Aux KC is prelinked to correct Pageable KC */
14236 	if (type == KCKindAuxiliary) {
14237 		if (!pageablekc_uuid_valid) {
14238 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14239 			    "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC.");
14240 			ret = kOSKextReturnInvalidArgument;
14241 			goto finish;
14242 		}
14243 		ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey);
14244 		if (ret != 0) {
14245 			goto finish;
14246 		}
14247 	}
14248 #endif //(__x86_64__) || defined(__i386__)
14249 
14250 	printf("KextLog: Collection UUID matches with loaded KCs.\n");
14251 finish:
14252 	return ret;
14253 }
14254 
14255 /*********************************************************************
14256 * Assumes sKextLock is held.
14257 *********************************************************************/
14258 /* static */
14259 OSReturn
14260 OSKext::validateKCUUIDfromPrelinkInfo(
14261 	uuid_t               *loaded_kcuuid,
14262 	kc_kind_t             type,
14263 	OSDictionary         *infoDict,
14264 	const char           *uuid_key)
14265 {
14266 	/* extract the UUID from the dictionary */
14267 	OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key));
14268 	if (!prelinkinfoKCUUID) {
14269 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14270 		    "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key);
14271 		return kOSKextReturnInvalidArgument;
14272 	}
14273 
14274 	if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) {
14275 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14276 		    "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength());
14277 		return kOSKextReturnInvalidArgument;
14278 	}
14279 
14280 	if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(),
14281 	    prelinkinfoKCUUID->getLength())) {
14282 		OSData       *info_dict_uuid;
14283 		uuid_string_t info_dict_uuid_str = {};
14284 		uuid_string_t expected_uuid_str = {};
14285 		uuid_string_t given_uuid_str = {};
14286 		uuid_t        given_uuid;
14287 
14288 		/* extract the KC UUID from the dictionary */
14289 		info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
14290 		if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) {
14291 			uuid_t tmp_uuid;
14292 			memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid));
14293 			uuid_unparse(tmp_uuid, info_dict_uuid_str);
14294 		}
14295 
14296 		uuid_unparse(*loaded_kcuuid, expected_uuid_str);
14297 		memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid));
14298 		uuid_unparse(given_uuid, given_uuid_str);
14299 
14300 		printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
14301 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
14302 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14303 		    "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
14304 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
14305 		if (type == KCKindPageable && sPanicOnKCMismatch) {
14306 			panic("System KC UUID %s linked against %s, but %s is loaded",
14307 			    info_dict_uuid_str, given_uuid_str, expected_uuid_str);
14308 		}
14309 		return kOSKextReturnInvalidArgument;
14310 	}
14311 
14312 	return 0;
14313 }
14314 
14315 /*********************************************************************
14316 * Assumes sKextLock is held.
14317 *********************************************************************/
14318 /* static */
14319 OSReturn
14320 OSKext::dispatchResource(OSDictionary * requestDict)
14321 {
14322 	OSReturn                        result          = kOSReturnError;
14323 	OSSharedPtr<OSDictionary>       callbackRecord;
14324 	OSNumber                      * requestTag      = NULL;        // do not release
14325 	OSNumber                      * requestResult   = NULL;        // do not release
14326 	OSData                        * dataObj         = NULL;        // do not release
14327 	uint32_t                        dataLength      = 0;
14328 	const void                    * dataPtr         = NULL;        // do not free
14329 	OSValueObject<OSKextRequestResourceCallback> * callbackWrapper = nullptr; // do not release
14330 	OSKextRequestResourceCallback   callback        = NULL;
14331 	OSValueObject<void *>         * contextWrapper  = nullptr;     // do not release
14332 	void                          * context         = NULL;        // do not free
14333 	OSSharedPtr<OSKext>             callbackKext;
14334 
14335 	/* Get the args from the request. Right now we need the tag
14336 	 * to look up the callback record, and the result for invoking the callback.
14337 	 */
14338 	requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
14339 	    kKextRequestArgumentRequestTagKey));
14340 	requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
14341 	    kKextRequestArgumentResultKey));
14342 	if (!requestTag || !requestResult) {
14343 		result = kOSKextReturnInvalidArgument;
14344 		goto finish;
14345 	}
14346 
14347 	/* Look for a callback record matching this request's tag.
14348 	 */
14349 	result = dequeueCallbackForRequestTag(requestTag, callbackRecord);
14350 	if (result != kOSReturnSuccess) {
14351 		goto finish;
14352 	}
14353 
14354 	/*****
14355 	 * Get the context pointer of the callback record (if there is one).
14356 	 */
14357 	contextWrapper = OSDynamicCast(OSValueObject<void *>, _OSKextGetRequestArgument(
14358 		    callbackRecord.get(), kKextRequestArgumentContextKey));
14359 	context = _OSKextExtractPointer(contextWrapper);
14360 	if (contextWrapper && !context) {
14361 		goto finish;
14362 	}
14363 
14364 	callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14365 	    _OSKextGetRequestArgument(callbackRecord.get(),
14366 	    kKextRequestArgumentCallbackKey));
14367 	callback = _OSKextExtractCallbackPointer(callbackWrapper);
14368 	if (!callback) {
14369 		goto finish;
14370 	}
14371 
14372 	/* Check for a data obj. We might not have one and that's ok, that means
14373 	 * we didn't find the requested resource, and we still have to tell the
14374 	 * caller that via the callback.
14375 	 */
14376 	dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
14377 	    kKextRequestArgumentValueKey));
14378 	if (dataObj) {
14379 		dataPtr = dataObj->getBytesNoCopy();
14380 		dataLength = dataObj->getLength();
14381 	}
14382 
14383 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
14384 	if (!callbackKext) {
14385 		OSKextLog(/* kext */ NULL,
14386 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
14387 		    "Can't invoke callback for resource request; ");
14388 		goto finish;
14389 	}
14390 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
14391 		OSKextLog(/* kext */ NULL,
14392 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
14393 		    "Can't invoke kext resource callback; ");
14394 		goto finish;
14395 	}
14396 
14397 	(void)callback(requestTag->unsigned32BitValue(),
14398 	    (OSReturn)requestResult->unsigned32BitValue(),
14399 	    dataPtr, dataLength, context);
14400 
14401 	result = kOSReturnSuccess;
14402 
14403 finish:
14404 	return result;
14405 }
14406 
14407 /*********************************************************************
14408 * Assumes sKextLock is held.
14409 *********************************************************************/
14410 /* static */
14411 OSReturn
14412 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict)
14413 {
14414 	OSSharedPtr<OSDictionary> missingIDs;
14415 	OSArray *bundleIDList     = NULL; // do not release
14416 
14417 	bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
14418 		    requestDict, kKextRequestArgumentMissingBundleIDs));
14419 	if (!bundleIDList) {
14420 		return kOSKextReturnInvalidArgument;
14421 	}
14422 
14423 	missingIDs = OSDictionary::withCapacity(bundleIDList->getCount());
14424 	if (!missingIDs) {
14425 		return kOSKextReturnNoMemory;
14426 	}
14427 
14428 	uint32_t count, i;
14429 	count = bundleIDList->getCount();
14430 	for (i = 0; i < count; i++) {
14431 		OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i));
14432 		if (thisID) {
14433 			missingIDs->setObject(thisID, kOSBooleanFalse);
14434 		}
14435 	}
14436 
14437 	sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain);
14438 
14439 	return kOSReturnSuccess;
14440 }
14441 
14442 /*********************************************************************
14443 * Assumes sKextLock is held.
14444 *********************************************************************/
14445 /* static */
14446 OSReturn
14447 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict)
14448 {
14449 	bool loadable = true;
14450 	if (!kextIdentifier) {
14451 		return kOSKextReturnInvalidArgument;
14452 	}
14453 
14454 	if (requestDict) {
14455 		OSBoolean *loadableArg;
14456 		loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
14457 			    requestDict, kKextRequestArgumentBundleAvailability));
14458 		/* If we find the "Bundle Available" arg, and it's false, then
14459 		 * mark the bundle ID as _not_ loadable
14460 		 */
14461 		if (loadableArg && !loadableArg->getValue()) {
14462 			loadable = false;
14463 		}
14464 	}
14465 
14466 	if (!sNonLoadableKextsByID) {
14467 		sNonLoadableKextsByID = OSDictionary::withCapacity(1);
14468 	}
14469 
14470 	sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable));
14471 
14472 	OSKextLog(/* kext */ NULL,
14473 	    kOSKextLogBasicLevel | kOSKextLogIPCFlag,
14474 	    "KextLog: AuxKC bundle %s marked as %s",
14475 	    kextIdentifier->getCStringNoCopy(),
14476 	    (loadable ? "loadable" : "NOT loadable"));
14477 
14478 	return kOSReturnSuccess;
14479 }
14480 
14481 /*********************************************************************
14482 *********************************************************************/
14483 /* static */
14484 void
14485 OSKext::invokeRequestCallback(
14486 	OSDictionary * callbackRecord,
14487 	OSReturn       callbackResult)
14488 {
14489 	OSString * predicate  = _OSKextGetRequestPredicate(callbackRecord);
14490 	OSSharedPtr<OSNumber> resultNum;
14491 
14492 	if (!predicate) {
14493 		goto finish;
14494 	}
14495 
14496 	resultNum  = OSNumber::withNumber((long long unsigned int)callbackResult,
14497 	    8 * sizeof(callbackResult));
14498 	if (!resultNum) {
14499 		goto finish;
14500 	}
14501 
14502 	/* Insert the result into the callback record and dispatch it as if it
14503 	 * were the reply coming down from user space.
14504 	 */
14505 	_OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
14506 	    resultNum.get());
14507 
14508 	if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
14509 		/* This removes the pending callback record.
14510 		 */
14511 		OSKext::dispatchResource(callbackRecord);
14512 	}
14513 
14514 finish:
14515 	return;
14516 }
14517 
14518 /*********************************************************************
14519 * Assumes sKextLock is held.
14520 *********************************************************************/
14521 /* static */
14522 OSReturn
14523 OSKext::cancelRequest(
14524 	OSKextRequestTag    requestTag,
14525 	void             ** contextOut)
14526 {
14527 	OSReturn       result         = kOSKextReturnNoMemory;
14528 	OSSharedPtr<OSDictionary> callbackRecord;
14529 	OSValueObject<void *> * contextWrapper = nullptr; // do not release
14530 
14531 	IORecursiveLockLock(sKextLock);
14532 	result = OSKext::dequeueCallbackForRequestTag(requestTag,
14533 	    callbackRecord);
14534 	IORecursiveLockUnlock(sKextLock);
14535 
14536 	if (result == kOSReturnSuccess && contextOut) {
14537 		contextWrapper = OSDynamicCast(OSValueObject<void *>,
14538 		    _OSKextGetRequestArgument(callbackRecord.get(),
14539 		    kKextRequestArgumentContextKey));
14540 		*contextOut = _OSKextExtractPointer(contextWrapper);
14541 	}
14542 
14543 	return result;
14544 }
14545 
14546 /*********************************************************************
14547 * Assumes sKextLock is held.
14548 *********************************************************************/
14549 void
14550 OSKext::invokeOrCancelRequestCallbacks(
14551 	OSReturn callbackResult,
14552 	bool     invokeFlag)
14553 {
14554 	unsigned int count, i;
14555 
14556 	count = sRequestCallbackRecords->getCount();
14557 	if (!count) {
14558 		goto finish;
14559 	}
14560 
14561 	i = count - 1;
14562 	do {
14563 		OSDictionary * request = OSDynamicCast(OSDictionary,
14564 		    sRequestCallbackRecords->getObject(i));
14565 
14566 		if (!request) {
14567 			continue;
14568 		}
14569 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14570 		    _OSKextGetRequestArgument(request,
14571 		    kKextRequestArgumentCallbackKey));
14572 
14573 		if (!callbackWrapper) {
14574 			sRequestCallbackRecords->removeObject(i);
14575 			continue;
14576 		}
14577 
14578 		vm_address_t callbackAddress = (vm_address_t)
14579 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
14580 
14581 		if ((kmod_info->address <= callbackAddress) &&
14582 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
14583 			if (invokeFlag) {
14584 				/* This removes the callback record.
14585 				 */
14586 				invokeRequestCallback(request, callbackResult);
14587 			} else {
14588 				sRequestCallbackRecords->removeObject(i);
14589 			}
14590 		}
14591 	} while (i--);
14592 
14593 finish:
14594 	return;
14595 }
14596 
14597 /*********************************************************************
14598 * Assumes sKextLock is held.
14599 *********************************************************************/
14600 uint32_t
14601 OSKext::countRequestCallbacks(void)
14602 {
14603 	uint32_t     result = 0;
14604 	unsigned int count, i;
14605 
14606 	count = sRequestCallbackRecords->getCount();
14607 	if (!count) {
14608 		goto finish;
14609 	}
14610 
14611 	i = count - 1;
14612 	do {
14613 		OSDictionary * request = OSDynamicCast(OSDictionary,
14614 		    sRequestCallbackRecords->getObject(i));
14615 
14616 		if (!request) {
14617 			continue;
14618 		}
14619 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14620 		    _OSKextGetRequestArgument(request,
14621 		    kKextRequestArgumentCallbackKey));
14622 
14623 		if (!callbackWrapper) {
14624 			continue;
14625 		}
14626 
14627 		vm_address_t callbackAddress = (vm_address_t)
14628 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
14629 
14630 		if ((kmod_info->address <= callbackAddress) &&
14631 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
14632 			result++;
14633 		}
14634 	} while (i--);
14635 
14636 finish:
14637 	return result;
14638 }
14639 
14640 /*********************************************************************
14641 *********************************************************************/
14642 static OSReturn
14643 _OSKextCreateRequest(
14644 	const char    * predicate,
14645 	OSSharedPtr<OSDictionary> & requestR)
14646 {
14647 	OSReturn result = kOSKextReturnNoMemory;
14648 	OSSharedPtr<OSDictionary> request;
14649 
14650 	request = OSDictionary::withCapacity(2);
14651 	if (!request) {
14652 		goto finish;
14653 	}
14654 	result = _OSDictionarySetCStringValue(request.get(),
14655 	    kKextRequestPredicateKey, predicate);
14656 	if (result != kOSReturnSuccess) {
14657 		goto finish;
14658 	}
14659 	result = kOSReturnSuccess;
14660 
14661 finish:
14662 	if (result == kOSReturnSuccess) {
14663 		requestR = os::move(request);
14664 	}
14665 
14666 	return result;
14667 }
14668 
14669 /*********************************************************************
14670 *********************************************************************/
14671 static OSString *
14672 _OSKextGetRequestPredicate(OSDictionary * requestDict)
14673 {
14674 	return OSDynamicCast(OSString,
14675 	           requestDict->getObject(kKextRequestPredicateKey));
14676 }
14677 
14678 /*********************************************************************
14679 *********************************************************************/
14680 static OSObject *
14681 _OSKextGetRequestArgument(
14682 	OSDictionary * requestDict,
14683 	const char   * argName)
14684 {
14685 	OSDictionary * args = OSDynamicCast(OSDictionary,
14686 	    requestDict->getObject(kKextRequestArgumentsKey));
14687 	if (args) {
14688 		return args->getObject(argName);
14689 	}
14690 	return NULL;
14691 }
14692 
14693 /*********************************************************************
14694 *********************************************************************/
14695 static bool
14696 _OSKextSetRequestArgument(
14697 	OSDictionary    * requestDict,
14698 	const char      * argName,
14699 	OSMetaClassBase * value)
14700 {
14701 	OSDictionary * args = OSDynamicCast(OSDictionary,
14702 	    requestDict->getObject(kKextRequestArgumentsKey));
14703 	OSSharedPtr<OSDictionary> newArgs;
14704 	if (!args) {
14705 		newArgs = OSDictionary::withCapacity(2);
14706 		args = newArgs.get();
14707 		if (!args) {
14708 			goto finish;
14709 		}
14710 		requestDict->setObject(kKextRequestArgumentsKey, args);
14711 	}
14712 	if (args) {
14713 		return args->setObject(argName, value);
14714 	}
14715 finish:
14716 	return false;
14717 }
14718 
14719 /*********************************************************************
14720 *********************************************************************/
14721 template <typename T>
14722 static T *
14723 _OSKextExtractPointer(OSValueObject<T *> * wrapper)
14724 {
14725 	if (!wrapper) {
14726 		return nullptr;
14727 	}
14728 	return wrapper->getRef();
14729 }
14730 
14731 /*********************************************************************
14732 *********************************************************************/
14733 static OSKextRequestResourceCallback
14734 _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper)
14735 {
14736 	if (!wrapper) {
14737 		return nullptr;
14738 	}
14739 	return wrapper->getRef();
14740 }
14741 
14742 
14743 /*********************************************************************
14744 *********************************************************************/
14745 static OSReturn
14746 _OSDictionarySetCStringValue(
14747 	OSDictionary * dict,
14748 	const char   * cKey,
14749 	const char   * cValue)
14750 {
14751 	OSReturn result = kOSKextReturnNoMemory;
14752 	OSSharedPtr<const OSSymbol> key;
14753 	OSSharedPtr<OSString> value;
14754 
14755 	key = OSSymbol::withCString(cKey);
14756 	value = OSString::withCString(cValue);
14757 	if (!key || !value) {
14758 		goto finish;
14759 	}
14760 	if (dict->setObject(key.get(), value.get())) {
14761 		result = kOSReturnSuccess;
14762 	}
14763 
14764 finish:
14765 	return result;
14766 }
14767 
14768 /*********************************************************************
14769 *********************************************************************/
14770 static bool
14771 _OSArrayContainsCString(
14772 	OSArray    * array,
14773 	const char * cString)
14774 {
14775 	bool             result = false;
14776 	OSSharedPtr<const OSSymbol> symbol;
14777 	uint32_t         count, i;
14778 
14779 	if (!array || !cString) {
14780 		goto finish;
14781 	}
14782 
14783 	symbol = OSSymbol::withCStringNoCopy(cString);
14784 	if (!symbol) {
14785 		goto finish;
14786 	}
14787 
14788 	count = array->getCount();
14789 	for (i = 0; i < count; i++) {
14790 		OSObject * thisObject = array->getObject(i);
14791 		if (symbol->isEqualTo(thisObject)) {
14792 			result = true;
14793 			goto finish;
14794 		}
14795 	}
14796 
14797 finish:
14798 	return result;
14799 }
14800 
14801 #if CONFIG_KXLD
14802 /*********************************************************************
14803 * We really only care about boot / system start up related kexts.
14804 * We return true if we're less than REBUILD_MAX_TIME since start up,
14805 * otherwise return false.
14806 *********************************************************************/
14807 bool
14808 _OSKextInPrelinkRebuildWindow(void)
14809 {
14810 	static bool     outside_the_window = false;
14811 	AbsoluteTime    my_abstime;
14812 	UInt64          my_ns;
14813 	SInt32          my_secs;
14814 
14815 	if (outside_the_window) {
14816 		return false;
14817 	}
14818 	clock_get_uptime(&my_abstime);
14819 	absolutetime_to_nanoseconds(my_abstime, &my_ns);
14820 	my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
14821 	if (my_secs > REBUILD_MAX_TIME) {
14822 		outside_the_window = true;
14823 		return false;
14824 	}
14825 	return true;
14826 }
14827 #endif /* CONFIG_KXLD */
14828 
14829 /*********************************************************************
14830 *********************************************************************/
14831 bool
14832 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
14833 {
14834 	int unLoadedCount, i;
14835 	bool result = false;
14836 
14837 	IORecursiveLockLock(sKextLock);
14838 
14839 	if (sUnloadedPrelinkedKexts == NULL) {
14840 		goto finish;
14841 	}
14842 	unLoadedCount = sUnloadedPrelinkedKexts->getCount();
14843 	if (unLoadedCount == 0) {
14844 		goto finish;
14845 	}
14846 
14847 	for (i = 0; i < unLoadedCount; i++) {
14848 		const OSSymbol *    myBundleID;        // do not release
14849 
14850 		myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
14851 		if (!myBundleID) {
14852 			continue;
14853 		}
14854 		if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
14855 			result = true;
14856 			break;
14857 		}
14858 	}
14859 finish:
14860 	IORecursiveLockUnlock(sKextLock);
14861 	return result;
14862 }
14863 
14864 #if PRAGMA_MARK
14865 #pragma mark Personalities (IOKit Drivers)
14866 #endif
14867 /*********************************************************************
14868 *********************************************************************/
14869 /* static */
14870 OSSharedPtr<OSArray>
14871 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
14872 {
14873 	OSSharedPtr<OSArray>              result;
14874 	OSSharedPtr<OSCollectionIterator> kextIterator;
14875 	OSSharedPtr<OSArray>              personalities;
14876 
14877 	OSString             * kextID                = NULL;        // do not release
14878 	OSKext               * theKext               = NULL;        // do not release
14879 
14880 	IORecursiveLockLock(sKextLock);
14881 
14882 	/* Let's conservatively guess that any given kext has around 3
14883 	 * personalities for now.
14884 	 */
14885 	result = OSArray::withCapacity(sKextsByID->getCount() * 3);
14886 	if (!result) {
14887 		goto finish;
14888 	}
14889 
14890 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
14891 	if (!kextIterator) {
14892 		goto finish;
14893 	}
14894 
14895 	while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
14896 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
14897 		if (theKext->flags.requireExplicitLoad) {
14898 			OSKextLog(theKext,
14899 			    kOSKextLogDebugLevel |
14900 			    kOSKextLogLoadFlag,
14901 			    "Kext %s requires an explicit kextload; "
14902 			    "omitting its personalities.",
14903 			    theKext->getIdentifierCString());
14904 		} else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
14905 			personalities = theKext->copyPersonalitiesArray();
14906 			if (!personalities) {
14907 				continue;
14908 			}
14909 			result->merge(personalities.get());
14910 		} else {
14911 			// xxx - check for better place to put this log msg
14912 			OSKextLog(theKext,
14913 			    kOSKextLogWarningLevel |
14914 			    kOSKextLogLoadFlag,
14915 			    "Kext %s is not loadable during safe boot; "
14916 			    "omitting its personalities.",
14917 			    theKext->getIdentifierCString());
14918 		}
14919 	}
14920 
14921 finish:
14922 	IORecursiveLockUnlock(sKextLock);
14923 
14924 	return result;
14925 }
14926 
14927 /*********************************************************************
14928 *********************************************************************/
14929 /* static */
14930 void
14931 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
14932 {
14933 	int numPersonalities = 0;
14934 
14935 	OSKextLog(/* kext */ NULL,
14936 	    kOSKextLogStepLevel |
14937 	    kOSKextLogLoadFlag,
14938 	    "Sending all eligible registered kexts' personalities "
14939 	    "to the IOCatalogue %s.",
14940 	    startMatching ? "and starting matching" : "but not starting matching");
14941 
14942 	OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities(
14943 		/* filterSafeBootFlag */ true);
14944 
14945 	if (personalities) {
14946 		gIOCatalogue->addDrivers(personalities.get(), startMatching);
14947 		numPersonalities = personalities->getCount();
14948 	}
14949 
14950 	OSKextLog(/* kext */ NULL,
14951 	    kOSKextLogStepLevel |
14952 	    kOSKextLogLoadFlag,
14953 	    "%d kext personalit%s sent to the IOCatalogue; %s.",
14954 	    numPersonalities, numPersonalities > 0 ? "ies" : "y",
14955 	    startMatching ? "matching started" : "matching not started");
14956 	return;
14957 }
14958 
14959 /*********************************************************************
14960 * Do not make a deep copy, just convert the IOKitPersonalities dict
14961 * to an array for sending to the IOCatalogue.
14962 *********************************************************************/
14963 OSSharedPtr<OSArray>
14964 OSKext::copyPersonalitiesArray(void)
14965 {
14966 	OSSharedPtr<OSArray>              result;
14967 	OSDictionary         * personalities               = NULL;        // do not release
14968 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
14969 
14970 	OSString             * personalityName             = NULL;        // do not release
14971 	OSString             * personalityBundleIdentifier = NULL;        // do not release
14972 
14973 	personalities = OSDynamicCast(OSDictionary,
14974 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
14975 	if (!personalities) {
14976 		goto finish;
14977 	}
14978 
14979 	result = OSArray::withCapacity(personalities->getCount());
14980 	if (!result) {
14981 		goto finish;
14982 	}
14983 
14984 	personalitiesIterator =
14985 	    OSCollectionIterator::withCollection(personalities);
14986 	if (!personalitiesIterator) {
14987 		goto finish;
14988 	}
14989 	while ((personalityName = OSDynamicCast(OSString,
14990 	    personalitiesIterator->getNextObject()))) {
14991 		OSDictionary * personality = OSDynamicCast(OSDictionary,
14992 		    personalities->getObject(personalityName));
14993 
14994 		if (personality) {
14995 			/******
14996 			 * If the personality doesn't have a CFBundleIdentifier, or if it
14997 			 * differs from the kext's, insert the kext's ID so we can find it.
14998 			 * The publisher ID is used to remove personalities from bundles
14999 			 * correctly.
15000 			 */
15001 			personalityBundleIdentifier = OSDynamicCast(OSString,
15002 			    personality->getObject(kCFBundleIdentifierKey));
15003 
15004 			if (!personalityBundleIdentifier) {
15005 				personality->setObject(kCFBundleIdentifierKey, bundleID.get());
15006 			} else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) {
15007 				personality->setObject(kIOPersonalityPublisherKey, bundleID.get());
15008 			}
15009 		}
15010 
15011 		result->setObject(personality);
15012 	}
15013 
15014 finish:
15015 	return result;
15016 }
15017 
15018 /*********************************************************************
15019 *   Might want to change this to a bool return?
15020 *********************************************************************/
15021 OSReturn
15022 OSKext::sendPersonalitiesToCatalog(
15023 	bool      startMatching,
15024 	OSArray * personalityNames)
15025 {
15026 	OSReturn       result              = kOSReturnSuccess;
15027 	OSSharedPtr<OSArray> personalitiesToSend;
15028 	OSDictionary * kextPersonalities   = NULL;        // do not release
15029 	int            count, i;
15030 
15031 	if (!sLoadEnabled) {
15032 		OSKextLog(this,
15033 		    kOSKextLogErrorLevel |
15034 		    kOSKextLogLoadFlag,
15035 		    "Kext loading is disabled (attempt to start matching for kext %s).",
15036 		    getIdentifierCString());
15037 		result = kOSKextReturnDisabled;
15038 		goto finish;
15039 	}
15040 
15041 	if (sSafeBoot && !isLoadableInSafeBoot()) {
15042 		OSKextLog(this,
15043 		    kOSKextLogErrorLevel |
15044 		    kOSKextLogLoadFlag,
15045 		    "Kext %s is not loadable during safe boot; "
15046 		    "not sending personalities to the IOCatalogue.",
15047 		    getIdentifierCString());
15048 		result = kOSKextReturnNotLoadable;
15049 		goto finish;
15050 	}
15051 
15052 	if (!personalityNames || !personalityNames->getCount()) {
15053 		personalitiesToSend = copyPersonalitiesArray();
15054 	} else {
15055 		kextPersonalities = OSDynamicCast(OSDictionary,
15056 		    getPropertyForHostArch(kIOKitPersonalitiesKey));
15057 		if (!kextPersonalities || !kextPersonalities->getCount()) {
15058 			// not an error
15059 			goto finish;
15060 		}
15061 		personalitiesToSend = OSArray::withCapacity(0);
15062 		if (!personalitiesToSend) {
15063 			result = kOSKextReturnNoMemory;
15064 			goto finish;
15065 		}
15066 		count = personalityNames->getCount();
15067 		for (i = 0; i < count; i++) {
15068 			OSString * name = OSDynamicCast(OSString,
15069 			    personalityNames->getObject(i));
15070 			if (!name) {
15071 				continue;
15072 			}
15073 			OSDictionary * personality = OSDynamicCast(OSDictionary,
15074 			    kextPersonalities->getObject(name));
15075 			if (personality) {
15076 				personalitiesToSend->setObject(personality);
15077 			}
15078 		}
15079 	}
15080 	if (personalitiesToSend) {
15081 		unsigned numPersonalities = personalitiesToSend->getCount();
15082 		OSKextLog(this,
15083 		    kOSKextLogStepLevel |
15084 		    kOSKextLogLoadFlag,
15085 		    "Kext %s sending %d personalit%s to the IOCatalogue%s.",
15086 		    getIdentifierCString(),
15087 		    numPersonalities,
15088 		    numPersonalities > 1 ? "ies" : "y",
15089 		    startMatching ? " and starting matching" : " but not starting matching");
15090 		gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching);
15091 	}
15092 finish:
15093 	return result;
15094 }
15095 
15096 /*********************************************************************
15097 * xxx - We should allow removing the kext's declared personalities,
15098 * xxx - even with other bundle identifiers.
15099 *********************************************************************/
15100 void
15101 OSKext::removePersonalitiesFromCatalog(void)
15102 {
15103 	OSSharedPtr<OSDictionary> personality;
15104 
15105 	personality = OSDictionary::withCapacity(1);
15106 	if (!personality) {
15107 		goto finish;
15108 	}
15109 	personality->setObject(kCFBundleIdentifierKey, getIdentifier());
15110 
15111 	OSKextLog(this,
15112 	    kOSKextLogStepLevel |
15113 	    kOSKextLogLoadFlag,
15114 	    "Kext %s removing all personalities naming it from the IOCatalogue.",
15115 	    getIdentifierCString());
15116 
15117 	/* Have the IOCatalog remove all personalities matching this kext's
15118 	 * bundle ID and trigger matching anew.
15119 	 */
15120 	gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true);
15121 
15122 finish:
15123 	return;
15124 }
15125 
15126 void
15127 OSKext::updatePersonalitiesInCatalog(OSArray *upgradedPersonalities)
15128 {
15129 	if (!upgradedPersonalities || upgradedPersonalities->getCount() == 0) {
15130 		return;
15131 	}
15132 
15133 	OSSharedPtr<OSDictionary> personalityToRemove = OSDictionary::withCapacity(1);
15134 	if (!personalityToRemove) {
15135 		return;
15136 	}
15137 
15138 	/*
15139 	 * Create a personality dictionary with just the bundleID.
15140 	 * We will remove any personality that has a matching bundleID,
15141 	 * irrespective of which other keys are present on the dictionary.
15142 	 */
15143 	personalityToRemove->setObject(kCFBundleIdentifierKey, getIdentifier());
15144 	gIOCatalogue->exchangeDrivers(personalityToRemove.get(), upgradedPersonalities, true);
15145 }
15146 
15147 #if PRAGMA_MARK
15148 #pragma mark Logging
15149 #endif
15150 /*********************************************************************
15151 * Do not call any function that takes sKextLock here!
15152 *********************************************************************/
15153 /* static */
15154 OSKextLogSpec
15155 OSKext::setUserSpaceLogFilter(
15156 	OSKextLogSpec   newUserLogFilter,
15157 	bool            captureFlag)
15158 {
15159 	OSKextLogSpec result;
15160 	bool          allocError = false;
15161 
15162 	/* Do not call any function that takes sKextLoggingLock during
15163 	 * this critical block. That means do logging after.
15164 	 */
15165 	IOLockLock(sKextLoggingLock);
15166 
15167 	result = sUserSpaceKextLogFilter;
15168 	sUserSpaceKextLogFilter = newUserLogFilter;
15169 
15170 	if (newUserLogFilter && captureFlag &&
15171 	    !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
15172 		// xxx - do some measurements for a good initial capacity?
15173 		sUserSpaceLogSpecArray = OSArray::withCapacity(0);
15174 		sUserSpaceLogMessageArray = OSArray::withCapacity(0);
15175 
15176 		if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
15177 			allocError = true;
15178 		}
15179 	}
15180 
15181 	IOLockUnlock(sKextLoggingLock);
15182 
15183 	/* If the config flag itself is changing, log the state change
15184 	 * going both ways, before setting up the user-space log arrays,
15185 	 * so that this is only logged in the kernel.
15186 	 */
15187 	if (result != newUserLogFilter) {
15188 		OSKextLog(/* kext */ NULL,
15189 		    kOSKextLogDebugLevel |
15190 		    kOSKextLogGeneralFlag,
15191 		    "User-space log flags changed from 0x%x to 0x%x.",
15192 		    result, newUserLogFilter);
15193 	}
15194 	if (allocError) {
15195 		OSKextLog(/* kext */ NULL,
15196 		    kOSKextLogErrorLevel |
15197 		    kOSKextLogGeneralFlag,
15198 		    "Failed to allocate user-space log message arrays.");
15199 	}
15200 
15201 	return result;
15202 }
15203 
15204 /*********************************************************************
15205 * Do not call any function that takes sKextLock here!
15206 *********************************************************************/
15207 /* static */
15208 OSSharedPtr<OSArray>
15209 OSKext::clearUserSpaceLogFilter(void)
15210 {
15211 	OSSharedPtr<OSArray>       result;
15212 	OSKextLogSpec   oldLogFilter;
15213 	OSKextLogSpec   newLogFilter = kOSKextLogSilentFilter;
15214 
15215 	/* Do not call any function that takes sKextLoggingLock during
15216 	 * this critical block. That means do logging after.
15217 	 */
15218 	IOLockLock(sKextLoggingLock);
15219 
15220 	result = OSArray::withCapacity(2);
15221 	if (result) {
15222 		result->setObject(sUserSpaceLogSpecArray.get());
15223 		result->setObject(sUserSpaceLogMessageArray.get());
15224 	}
15225 	sUserSpaceLogSpecArray.reset();
15226 	sUserSpaceLogMessageArray.reset();
15227 
15228 	oldLogFilter = sUserSpaceKextLogFilter;
15229 	sUserSpaceKextLogFilter = newLogFilter;
15230 
15231 	IOLockUnlock(sKextLoggingLock);
15232 
15233 	/* If the config flag itself is changing, log the state change
15234 	 * going both ways, after tearing down the user-space log
15235 	 * arrays, so this is only logged within the kernel.
15236 	 */
15237 	if (oldLogFilter != newLogFilter) {
15238 		OSKextLog(/* kext */ NULL,
15239 		    kOSKextLogDebugLevel |
15240 		    kOSKextLogGeneralFlag,
15241 		    "User-space log flags changed from 0x%x to 0x%x.",
15242 		    oldLogFilter, newLogFilter);
15243 	}
15244 
15245 	return result;
15246 }
15247 
15248 
15249 /*********************************************************************
15250 * Do not call any function that takes sKextLock here!
15251 *********************************************************************/
15252 /* static */
15253 OSKextLogSpec
15254 OSKext::getUserSpaceLogFilter(void)
15255 {
15256 	OSKextLogSpec result;
15257 
15258 	IOLockLock(sKextLoggingLock);
15259 	result = sUserSpaceKextLogFilter;
15260 	IOLockUnlock(sKextLoggingLock);
15261 
15262 	return result;
15263 }
15264 
15265 /*********************************************************************
15266 * This function is called by OSMetaClass during kernel C++ setup.
15267 * Be careful what you access here; assume only OSKext::initialize()
15268 * has been called.
15269 *
15270 * Do not call any function that takes sKextLock here!
15271 *********************************************************************/
15272 #define VTRESET   "\033[0m"
15273 
15274 #define VTBOLD    "\033[1m"
15275 #define VTUNDER   "\033[4m"
15276 
15277 #define VTRED     "\033[31m"
15278 #define VTGREEN   "\033[32m"
15279 #define VTYELLOW  "\033[33m"
15280 #define VTBLUE    "\033[34m"
15281 #define VTMAGENTA "\033[35m"
15282 #define VTCYAN    "\033[36m"
15283 
15284 inline const char *
15285 colorForFlags(OSKextLogSpec flags)
15286 {
15287 	OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
15288 
15289 	switch (logLevel) {
15290 	case kOSKextLogErrorLevel:
15291 		return VTRED VTBOLD;
15292 	case kOSKextLogWarningLevel:
15293 		return VTRED;
15294 	case kOSKextLogBasicLevel:
15295 		return VTYELLOW VTUNDER;
15296 	case kOSKextLogProgressLevel:
15297 		return VTYELLOW;
15298 	case kOSKextLogStepLevel:
15299 		return VTGREEN;
15300 	case kOSKextLogDetailLevel:
15301 		return VTCYAN;
15302 	case kOSKextLogDebugLevel:
15303 		return VTMAGENTA;
15304 	default:
15305 		return "";         // white
15306 	}
15307 }
15308 
15309 inline bool
15310 logSpecMatch(
15311 	OSKextLogSpec msgLogSpec,
15312 	OSKextLogSpec logFilter)
15313 {
15314 	OSKextLogSpec filterKextGlobal  = logFilter & kOSKextLogKextOrGlobalMask;
15315 	OSKextLogSpec filterLevel       = logFilter & kOSKextLogLevelMask;
15316 	OSKextLogSpec filterFlags       = logFilter & kOSKextLogFlagsMask;
15317 
15318 	OSKextLogSpec msgKextGlobal    = msgLogSpec & kOSKextLogKextOrGlobalMask;
15319 	OSKextLogSpec msgLevel         = msgLogSpec & kOSKextLogLevelMask;
15320 	OSKextLogSpec msgFlags         = msgLogSpec & kOSKextLogFlagsMask;
15321 
15322 	/* Explicit messages always get logged.
15323 	 */
15324 	if (msgLevel == kOSKextLogExplicitLevel) {
15325 		return true;
15326 	}
15327 
15328 	/* Warnings and errors are logged regardless of the flags.
15329 	 */
15330 	if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
15331 		return true;
15332 	}
15333 
15334 	/* A verbose message that isn't for a logging-enabled kext and isn't global
15335 	 * does *not* get logged.
15336 	 */
15337 	if (!msgKextGlobal && !filterKextGlobal) {
15338 		return false;
15339 	}
15340 
15341 	/* Warnings and errors are logged regardless of the flags.
15342 	 * All other messages must fit the flags and
15343 	 * have a level at or below the filter.
15344 	 *
15345 	 */
15346 	if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
15347 		return true;
15348 	}
15349 	return false;
15350 }
15351 
15352 extern "C" {
15353 void
15354 OSKextLog(
15355 	OSKext         * aKext,
15356 	OSKextLogSpec    msgLogSpec,
15357 	const char     * format, ...)
15358 {
15359 	va_list argList;
15360 
15361 	va_start(argList, format);
15362 	OSKextVLog(aKext, msgLogSpec, format, argList);
15363 	va_end(argList);
15364 }
15365 
15366 void
15367 OSKextVLog(
15368 	OSKext         * aKext,
15369 	OSKextLogSpec    msgLogSpec,
15370 	const char     * format,
15371 	va_list          srcArgList)
15372 {
15373 	bool             logForKernel       = false;
15374 	bool             logForUser         = false;
15375 	va_list          argList;
15376 	char             stackBuffer[120];
15377 	uint32_t         length            = 0;
15378 	char           * allocBuffer       = NULL;        // must kfree
15379 	OSSharedPtr<OSNumber> logSpecNum;
15380 	OSSharedPtr<OSString> logString;
15381 	char           * buffer            = stackBuffer;        // do not free
15382 
15383 	IOLockLock(sKextLoggingLock);
15384 
15385 	/* Set the kext/global bit in the message spec if we have no
15386 	 * kext or if the kext requests logging.
15387 	 */
15388 	if (!aKext || aKext->flags.loggingEnabled) {
15389 		msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
15390 	}
15391 
15392 	logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
15393 	if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
15394 		logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
15395 	}
15396 
15397 	if (!(logForKernel || logForUser)) {
15398 		goto finish;
15399 	}
15400 
15401 	/* No goto from here until past va_end()!
15402 	 */
15403 	va_copy(argList, srcArgList);
15404 	length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
15405 	va_end(argList);
15406 
15407 	if (length + 1 >= sizeof(stackBuffer)) {
15408 		allocBuffer = (char *)kalloc_data_tag(length + 1,
15409 		    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
15410 		if (!allocBuffer) {
15411 			goto finish;
15412 		}
15413 
15414 		/* No goto from here until past va_end()!
15415 		 */
15416 		va_copy(argList, srcArgList);
15417 		vsnprintf(allocBuffer, length + 1, format, argList);
15418 		va_end(argList);
15419 
15420 		buffer = allocBuffer;
15421 	}
15422 
15423 	/* If user space wants the log message, queue it up.
15424 	 */
15425 	if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
15426 		logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
15427 		logString = OSString::withCString(buffer);
15428 		if (logSpecNum && logString) {
15429 			sUserSpaceLogSpecArray->setObject(logSpecNum.get());
15430 			sUserSpaceLogMessageArray->setObject(logString.get());
15431 		}
15432 	}
15433 
15434 	/* Always log messages from the kernel according to the kernel's
15435 	 * log flags.
15436 	 */
15437 	if (logForKernel) {
15438 		/* If we are in console mode and have a custom log filter,
15439 		 * colorize the log message.
15440 		 */
15441 		if (sBootArgLogFilterFound) {
15442 			const char * color = "";         // do not free
15443 			color = colorForFlags(msgLogSpec);
15444 			printf("%s%s%s\n", colorForFlags(msgLogSpec),
15445 			    buffer, color[0] ? VTRESET : "");
15446 		} else {
15447 			printf("%s\n", buffer);
15448 		}
15449 	}
15450 
15451 finish:
15452 	IOLockUnlock(sKextLoggingLock);
15453 
15454 	if (allocBuffer) {
15455 		kfree_data(allocBuffer, length + 1);
15456 	}
15457 	return;
15458 }
15459 
15460 #if KASLR_IOREG_DEBUG
15461 
15462 #define IOLOG_INDENT( the_indention ) \
15463 { \
15464     int     i; \
15465     for ( i = 0; i < (the_indention); i++ ) { \
15466 	IOLog(" "); \
15467     } \
15468 }
15469 
15470 extern vm_offset_t       vm_kernel_stext;
15471 extern vm_offset_t       vm_kernel_etext;
15472 extern mach_vm_offset_t kext_alloc_base;
15473 extern mach_vm_offset_t kext_alloc_max;
15474 
15475 bool ScanForAddrInObject(OSObject * theObject,
15476     int indent );
15477 
15478 bool
15479 ScanForAddrInObject(OSObject * theObject,
15480     int indent)
15481 {
15482 	const OSMetaClass *     myTypeID;
15483 	OSSharedPtr<OSCollectionIterator>  myIter;
15484 	OSSymbol *              myKey;
15485 	OSObject *              myValue;
15486 	bool                    myResult = false;
15487 
15488 	if (theObject == NULL) {
15489 		IOLog("%s: theObject is NULL \n",
15490 		    __FUNCTION__);
15491 		return myResult;
15492 	}
15493 
15494 	myTypeID = OSTypeIDInst(theObject);
15495 
15496 	if (myTypeID == OSTypeID(OSDictionary)) {
15497 		OSDictionary *      myDictionary;
15498 
15499 		myDictionary = OSDynamicCast(OSDictionary, theObject);
15500 		myIter = OSCollectionIterator::withCollection( myDictionary );
15501 		if (myIter == NULL) {
15502 			return myResult;
15503 		}
15504 
15505 		// !! reset the iterator
15506 		myIter->reset();
15507 
15508 		while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
15509 			bool    myTempResult;
15510 
15511 			myValue = myDictionary->getObject(myKey);
15512 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
15513 			if (myTempResult) {
15514 				// if we ever get a true result return true
15515 				myResult = true;
15516 				IOLOG_INDENT(indent);
15517 				IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
15518 			}
15519 		}
15520 
15521 		// !! release the iterator
15522 		myIter.reset();
15523 	} else if (myTypeID == OSTypeID(OSArray)) {
15524 		OSArray *   myArray;
15525 
15526 		myArray = OSDynamicCast(OSArray, theObject);
15527 		myIter = OSCollectionIterator::withCollection(myArray);
15528 		if (myIter == NULL) {
15529 			return myResult;
15530 		}
15531 		// !! reset the iterator
15532 		myIter->reset();
15533 
15534 		while ((myValue = myIter->getNextObject())) {
15535 			bool        myTempResult;
15536 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
15537 			if (myTempResult) {
15538 				// if we ever get a true result return true
15539 				myResult = true;
15540 				IOLOG_INDENT(indent);
15541 				IOLog("OSArray: \n");
15542 			}
15543 		}
15544 		// !! release the iterator
15545 		myIter.reset();
15546 	} else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
15547 		// should we look for addresses in strings?
15548 	} else if (myTypeID == OSTypeID(OSData)) {
15549 		void * *        myPtrPtr;
15550 		unsigned int    myLen;
15551 		OSData *        myDataObj;
15552 
15553 		myDataObj =    OSDynamicCast(OSData, theObject);
15554 		myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
15555 		myLen = myDataObj->getLength();
15556 
15557 		if (myPtrPtr && myLen && myLen > 7) {
15558 			int     i;
15559 			int     myPtrCount = (myLen / sizeof(void *));
15560 
15561 			for (i = 0; i < myPtrCount; i++) {
15562 				UInt64 numberValue = (UInt64) * (myPtrPtr);
15563 
15564 				if (kext_alloc_max != 0 &&
15565 				    numberValue >= kext_alloc_base &&
15566 				    numberValue < kext_alloc_max) {
15567 					OSSharedPtr<OSKext> myKext;
15568 					// IOLog("found OSData %p in kext map %p to %p  \n",
15569 					//       *(myPtrPtr),
15570 					//       (void *) kext_alloc_base,
15571 					//       (void *) kext_alloc_max);
15572 
15573 					myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
15574 					if (myKext) {
15575 						IOLog("found addr %p from an OSData obj within kext \"%s\"  \n",
15576 						    *(myPtrPtr),
15577 						    myKext->getIdentifierCString());
15578 					}
15579 					myResult = true;
15580 				}
15581 				if (vm_kernel_etext != 0 &&
15582 				    numberValue >= vm_kernel_stext &&
15583 				    numberValue < vm_kernel_etext) {
15584 					IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n",
15585 					    *(myPtrPtr),
15586 					    (void *) vm_kernel_stext,
15587 					    (void *) vm_kernel_etext);
15588 					myResult = true;
15589 				}
15590 				myPtrPtr++;
15591 			}
15592 		}
15593 	} else if (myTypeID == OSTypeID(OSBoolean)) {
15594 		// do nothing here...
15595 	} else if (myTypeID == OSTypeID(OSNumber)) {
15596 		OSNumber * number = OSDynamicCast(OSNumber, theObject);
15597 
15598 		UInt64 numberValue = number->unsigned64BitValue();
15599 
15600 		if (kext_alloc_max != 0 &&
15601 		    numberValue >= kext_alloc_base &&
15602 		    numberValue < kext_alloc_max) {
15603 			OSSharedPtr<OSKext> myKext;
15604 			IOLog("found OSNumber in kext map %p to %p  \n",
15605 			    (void *) kext_alloc_base,
15606 			    (void *) kext_alloc_max);
15607 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
15608 
15609 			myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
15610 			if (myKext) {
15611 				IOLog("found in kext \"%s\"  \n",
15612 				    myKext->getIdentifierCString());
15613 			}
15614 
15615 			myResult = true;
15616 		}
15617 		if (vm_kernel_etext != 0 &&
15618 		    numberValue >= vm_kernel_stext &&
15619 		    numberValue < vm_kernel_etext) {
15620 			IOLog("found OSNumber in kernel text segment %p to %p  \n",
15621 			    (void *) vm_kernel_stext,
15622 			    (void *) vm_kernel_etext);
15623 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
15624 			myResult = true;
15625 		}
15626 	}
15627 #if 0
15628 	else {
15629 		const OSMetaClass* myMetaClass = NULL;
15630 
15631 		myMetaClass = theObject->getMetaClass();
15632 		if (myMetaClass) {
15633 			IOLog("class %s \n", myMetaClass->getClassName());
15634 		} else {
15635 			IOLog("Unknown object \n" );
15636 		}
15637 	}
15638 #endif
15639 
15640 	return myResult;
15641 }
15642 #endif // KASLR_KEXT_DEBUG
15643 };         /* extern "C" */
15644 
15645 #if PRAGMA_MARK
15646 #pragma mark Backtrace Dump & kmod_get_info() support
15647 #endif
15648 /*********************************************************************
15649 * This function must be safe to call in panic context.
15650 *********************************************************************/
15651 /* static */
15652 void
15653 OSKext::printKextsInBacktrace(
15654 	vm_offset_t  * addr __unused,
15655 	unsigned int   cnt __unused,
15656 	int         (* printf_func)(const char *fmt, ...) __unused,
15657 	uint32_t       flags __unused)
15658 {
15659 	addr64_t    summary_page = 0;
15660 	addr64_t    last_summary_page = 0;
15661 
15662 	if (kPrintKextsLock & flags) {
15663 		if (!sKextSummariesLock) {
15664 			return;
15665 		}
15666 		IOLockLock(sKextSummariesLock);
15667 	}
15668 
15669 	if (!gLoadedKextSummaries) {
15670 		(*printf_func)("         can't perform kext scan: no kext summary");
15671 		goto finish;
15672 	}
15673 
15674 	summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
15675 	last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
15676 	for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
15677 		if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
15678 			(*printf_func)("         can't perform kext scan: "
15679 			    "missing kext summary page %p", summary_page);
15680 			goto finish;
15681 		}
15682 	}
15683 
15684 	foreachKextInBacktrace(addr, cnt, 0, ^(OSKextLoadedKextSummary *summary, uint32_t index) {
15685 		if (index == 0 && !(kPrintKextsTerse & flags)) {
15686 		        (*printf_func)("      Kernel Extensions in backtrace:\n");
15687 		}
15688 
15689 		printSummary(summary, printf_func, flags);
15690 	});
15691 
15692 finish:
15693 	if (kPrintKextsLock & flags) {
15694 		IOLockUnlock(sKextSummariesLock);
15695 	}
15696 
15697 	return;
15698 }
15699 
15700 void
15701 OSKext::foreachKextInBacktrace(
15702 	vm_offset_t   * addr,
15703 	uint32_t        cnt,
15704 	uint32_t        flags,
15705 	void         (^ handler)(OSKextLoadedKextSummary *summary, uint32_t index))
15706 {
15707 	uint32_t n = 0;
15708 
15709 	if (kPrintKextsLock & flags) {
15710 		if (!sKextSummariesLock) {
15711 			return;
15712 		}
15713 		IOLockLock(sKextSummariesLock);
15714 	}
15715 
15716 	for (uint32_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15717 		OSKextLoadedKextSummary * summary;
15718 
15719 		summary = gLoadedKextSummaries->summaries + i;
15720 		if (!summary->address) {
15721 			continue;
15722 		}
15723 
15724 		if (!summaryIsInBacktrace(summary, addr, cnt)) {
15725 			continue;
15726 		}
15727 
15728 		handler(summary, n++);
15729 	}
15730 
15731 	if (kPrintKextsLock & flags) {
15732 		IOLockUnlock(sKextSummariesLock);
15733 	}
15734 }
15735 
15736 /*********************************************************************
15737 * This function must be safe to call in panic context.
15738 *********************************************************************/
15739 /* static */
15740 boolean_t
15741 OSKext::summaryIsInBacktrace(
15742 	OSKextLoadedKextSummary   * summary,
15743 	vm_offset_t               * addr,
15744 	unsigned int                cnt)
15745 {
15746 	u_int i = 0;
15747 
15748 	for (i = 0; i < cnt; i++) {
15749 		vm_offset_t kscan_addr = addr[i];
15750 #if  __has_feature(ptrauth_calls)
15751 		kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr);
15752 #endif /*  __has_feature(ptrauth_calls) */
15753 		if ((kscan_addr >= summary->text_exec_address) &&
15754 		    (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) {
15755 			return TRUE;
15756 		}
15757 	}
15758 
15759 	return FALSE;
15760 }
15761 
15762 /*
15763  * Get the kext summary object for the kext where 'addr' lies. Must be called with
15764  * sKextSummariesLock held.
15765  */
15766 OSKextLoadedKextSummary *
15767 OSKext::summaryForAddress(uintptr_t addr)
15768 {
15769 #if  __has_feature(ptrauth_calls)
15770 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
15771 #endif /*  __has_feature(ptrauth_calls) */
15772 	for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15773 		OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
15774 		if (!summary->address) {
15775 			continue;
15776 		}
15777 
15778 #if VM_MAPPED_KEXTS
15779 		/* On our platforms that use VM_MAPPED_KEXTS, we currently do not
15780 		 * support split kexts, but we also may unmap the kexts, which can
15781 		 * race with the above codepath (see OSKext::unload).  As such,
15782 		 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
15783 		 */
15784 		if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
15785 			return summary;
15786 		}
15787 #else
15788 		kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
15789 		kernel_segment_command_t *seg;
15790 
15791 		for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
15792 			if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
15793 				return summary;
15794 			}
15795 		}
15796 #endif
15797 	}
15798 
15799 	/* addr did not map to any kext */
15800 	return NULL;
15801 }
15802 
15803 /* static */
15804 void *
15805 OSKext::kextForAddress(const void *address)
15806 {
15807 	OSKextActiveAccount * active;
15808 	OSKext              * kext = NULL;
15809 	uint32_t              baseIdx;
15810 	uint32_t              lim;
15811 	uintptr_t             addr = (uintptr_t) address;
15812 	size_t                i;
15813 
15814 	if (!addr) {
15815 		return NULL;
15816 	}
15817 #if  __has_feature(ptrauth_calls)
15818 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
15819 #endif /*  __has_feature(ptrauth_calls) */
15820 
15821 	if (sKextAccountsCount) {
15822 		lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
15823 		// bsearch sKextAccounts list
15824 		for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15825 			active = &sKextAccounts[baseIdx + (lim >> 1)];
15826 			if ((addr >= active->address) && (addr < active->address_end)) {
15827 				if (active->account &&
15828 				    (kext = active->account->kext) &&
15829 				    kext->kmod_info) {
15830 					lck_ticket_unlock(sKextAccountsLock);
15831 					return (void *)kext->kmod_info->address;
15832 				}
15833 				break;
15834 			} else if (addr > active->address) {
15835 				// move right
15836 				baseIdx += (lim >> 1) + 1;
15837 				lim--;
15838 			}
15839 			// else move left
15840 		}
15841 		lck_ticket_unlock(sKextAccountsLock);
15842 	}
15843 	if (kernel_text_contains(addr)) {
15844 		return (void *)&_mh_execute_header;
15845 	}
15846 	if (gLoadedKextSummaries) {
15847 		IOLockLock(sKextSummariesLock);
15848 		for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) {
15849 			OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
15850 			if (addr >= summary->address && addr < summary->address + summary->size) {
15851 				void *kextAddress = (void *)summary->address;
15852 				IOLockUnlock(sKextSummariesLock);
15853 				return kextAddress;
15854 			}
15855 		}
15856 		IOLockUnlock(sKextSummariesLock);
15857 	}
15858 
15859 	return NULL;
15860 }
15861 
15862 /* static */
15863 kern_return_t
15864 OSKext::summaryForAddressExt(
15865 	const void              * address,
15866 	OSKextLoadedKextSummary * summary)
15867 {
15868 	kern_return_t                   result = KERN_FAILURE;
15869 	const OSKextLoadedKextSummary * foundSummary = NULL;
15870 
15871 	/*
15872 	 * This needs to be safe to call even before the lock has been initialized
15873 	 * in OSKext::initialize(), as we might get here from the ksancov runtime
15874 	 * when instrumenting XNU itself with sanitizer coverage.
15875 	 */
15876 	if (!sKextSummariesLock) {
15877 		return result;
15878 	}
15879 
15880 	IOLockLock(sKextSummariesLock);
15881 	if (gLoadedKextSummaries) {
15882 		foundSummary = summaryForAddress((uintptr_t)address);
15883 		if (foundSummary) {
15884 			memcpy(summary, foundSummary, sizeof(*summary));
15885 			result = KERN_SUCCESS;
15886 		} else {
15887 			result = KERN_NOT_FOUND;
15888 		}
15889 	}
15890 	IOLockUnlock(sKextSummariesLock);
15891 
15892 	return result;
15893 }
15894 
15895 /*
15896  * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t *
15897  * Safe to call in panic context.
15898  */
15899 static OSKextLoadedKextSummary *
15900 findSummary(uint32_t tagID)
15901 {
15902 	OSKextLoadedKextSummary * summary;
15903 	for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15904 		summary = gLoadedKextSummaries->summaries + i;
15905 		if (summary->loadTag == tagID) {
15906 			return summary;
15907 		}
15908 	}
15909 	return NULL;
15910 }
15911 
15912 /*********************************************************************
15913 * This function must be safe to call in panic context.
15914 *********************************************************************/
15915 void
15916 OSKext::printSummary(
15917 	OSKextLoadedKextSummary * summary,
15918 	int                    (* printf_func)(const char *fmt, ...),
15919 	uint32_t                  flags)
15920 {
15921 	kmod_reference_t * kmod_ref = NULL;
15922 	uuid_string_t uuid;
15923 	char version[kOSKextVersionMaxLength];
15924 	uint64_t tmpAddr;
15925 	uint64_t tmpSize;
15926 	OSKextLoadedKextSummary *dependencySummary;
15927 
15928 	if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
15929 		strlcpy(version, "unknown version", sizeof(version));
15930 	}
15931 	(void) uuid_unparse(summary->uuid, uuid);
15932 
15933 #if defined(__arm__) || defined(__arm64__)
15934 	tmpAddr = summary->text_exec_address;
15935 	tmpSize = summary->text_exec_size;
15936 #else
15937 	tmpAddr = summary->address;
15938 	tmpSize = summary->size;
15939 #endif
15940 	if (kPrintKextsUnslide & flags) {
15941 		tmpAddr = ml_static_unslide(tmpAddr);
15942 	}
15943 	(*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
15944 	    (kPrintKextsTerse & flags) ? "" : "         ",
15945 	    summary->name, version, uuid,
15946 	    tmpAddr, tmpAddr + tmpSize - 1);
15947 
15948 	if (kPrintKextsTerse & flags) {
15949 		return;
15950 	}
15951 
15952 	/* print dependency info */
15953 	for (kmod_ref = (kmod_reference_t *) summary->reference_list;
15954 	    kmod_ref;
15955 	    kmod_ref = kmod_ref->next) {
15956 		kmod_info_t * rinfo;
15957 
15958 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
15959 			(*printf_func)("            kmod dependency scan stopped "
15960 			    "due to missing dependency page: %p\n",
15961 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
15962 			break;
15963 		}
15964 		rinfo = kmod_ref->info;
15965 
15966 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
15967 			(*printf_func)("            kmod dependency scan stopped "
15968 			    "due to missing kmod page: %p\n",
15969 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
15970 			break;
15971 		}
15972 
15973 		if (!rinfo->address) {
15974 			continue;         // skip fake entries for built-ins
15975 		}
15976 
15977 		dependencySummary = findSummary(rinfo->id);
15978 		uuid[0] = 0x00;
15979 		tmpAddr = rinfo->address;
15980 		tmpSize = rinfo->size;
15981 		if (dependencySummary) {
15982 			(void) uuid_unparse(dependencySummary->uuid, uuid);
15983 #if defined(__arm__) || defined(__arm64__)
15984 			tmpAddr = dependencySummary->text_exec_address;
15985 			tmpSize = dependencySummary->text_exec_size;
15986 #endif
15987 		}
15988 
15989 		if (kPrintKextsUnslide & flags) {
15990 			tmpAddr = ml_static_unslide(tmpAddr);
15991 		}
15992 		(*printf_func)("            dependency: %s(%s)[%s]@%p->%p\n",
15993 		    rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1);
15994 	}
15995 	return;
15996 }
15997 
15998 
15999 #if !defined(__arm__) && !defined(__arm64__)
16000 /*******************************************************************************
16001 * substitute() looks at an input string (a pointer within a larger buffer)
16002 * for a match to a substring, and on match it writes the marker & substitution
16003 * character to an output string, updating the scan (from) and
16004 * output (to) indexes as appropriate.
16005 *******************************************************************************/
16006 static int substitute(
16007 	const char * scan_string,
16008 	char       * string_out,
16009 	uint32_t   * to_index,
16010 	uint32_t   * from_index,
16011 	const char * substring,
16012 	char         marker,
16013 	char         substitution);
16014 
16015 /* string_out must be at least KMOD_MAX_NAME bytes.
16016  */
16017 static int
16018 substitute(
16019 	const char * scan_string,
16020 	char       * string_out,
16021 	uint32_t   * to_index,
16022 	uint32_t   * from_index,
16023 	const char * substring,
16024 	char         marker,
16025 	char         substitution)
16026 {
16027 	size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
16028 
16029 	/* On a substring match, append the marker (if there is one) and then
16030 	 * the substitution character, updating the output (to) index accordingly.
16031 	 * Then update the input (from) length by the length of the substring
16032 	 * that got replaced.
16033 	 */
16034 	if (!strncmp(scan_string, substring, substring_length)) {
16035 		if (marker) {
16036 			string_out[(*to_index)++] = marker;
16037 		}
16038 		string_out[(*to_index)++] = substitution;
16039 		(*from_index) += substring_length;
16040 		return 1;
16041 	}
16042 	return 0;
16043 }
16044 
16045 /*******************************************************************************
16046 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
16047 * KMOD_MAX_NAME characters and performs various substitutions of common
16048 * prefixes & substrings as defined by tables in kext_panic_report.h.
16049 *******************************************************************************/
16050 static void compactIdentifier(
16051 	const char * identifier,
16052 	char       * identifier_out,
16053 	char      ** identifier_out_end);
16054 
16055 static void
16056 compactIdentifier(
16057 	const char * identifier,
16058 	char       * identifier_out,
16059 	char      ** identifier_out_end)
16060 {
16061 	uint32_t       from_index, to_index;
16062 	uint32_t       scan_from_index = 0;
16063 	uint32_t       scan_to_index   = 0;
16064 	subs_entry_t * subs_entry    = NULL;
16065 	int            did_sub       = 0;
16066 
16067 	from_index = to_index = 0;
16068 	identifier_out[0] = '\0';
16069 
16070 	/* Replace certain identifier prefixes with shorter @+character sequences.
16071 	 * Check the return value of substitute() so we only replace the prefix.
16072 	 */
16073 	for (subs_entry = &kext_identifier_prefix_subs[0];
16074 	    subs_entry->substring && !did_sub;
16075 	    subs_entry++) {
16076 		did_sub = substitute(identifier, identifier_out,
16077 		    &scan_to_index, &scan_from_index,
16078 		    subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
16079 	}
16080 	did_sub = 0;
16081 
16082 	/* Now scan through the identifier looking for the common substrings
16083 	 * and replacing them with shorter !+character sequences via substitute().
16084 	 */
16085 	for (/* see above */;
16086 	    scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
16087 	    /* see loop */) {
16088 		const char   * scan_string = &identifier[scan_from_index];
16089 
16090 		did_sub = 0;
16091 
16092 		if (scan_from_index) {
16093 			for (subs_entry = &kext_identifier_substring_subs[0];
16094 			    subs_entry->substring && !did_sub;
16095 			    subs_entry++) {
16096 				did_sub = substitute(scan_string, identifier_out,
16097 				    &scan_to_index, &scan_from_index,
16098 				    subs_entry->substring, '!', subs_entry->substitute);
16099 			}
16100 		}
16101 
16102 		/* If we didn't substitute, copy the input character to the output.
16103 		 */
16104 		if (!did_sub) {
16105 			identifier_out[scan_to_index++] = identifier[scan_from_index++];
16106 		}
16107 	}
16108 
16109 	identifier_out[scan_to_index] = '\0';
16110 	if (identifier_out_end) {
16111 		*identifier_out_end = &identifier_out[scan_to_index];
16112 	}
16113 
16114 	return;
16115 }
16116 #endif /* !defined(__arm__) && !defined(__arm64__) */
16117 
16118 /*******************************************************************************
16119 * assemble_identifier_and_version() adds to a string buffer a compacted
16120 * bundle identifier followed by a version string.
16121 *******************************************************************************/
16122 
16123 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
16124  */
16125 static size_t assemble_identifier_and_version(
16126 	kmod_info_t * kmod_info,
16127 	char        * identPlusVers,
16128 	size_t        bufSize);
16129 
16130 static size_t
16131 assemble_identifier_and_version(
16132 	kmod_info_t * kmod_info,
16133 	char        * identPlusVers,
16134 	size_t        bufSize)
16135 {
16136 	size_t result = 0;
16137 
16138 #if defined(__arm__) || defined(__arm64__)
16139 	result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME);
16140 #else
16141 	compactIdentifier(kmod_info->name, identPlusVers, NULL);
16142 	result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
16143 #endif
16144 	identPlusVers[result++] = '\t';         // increment for real char
16145 	identPlusVers[result] = '\0';         // don't increment for nul char
16146 	result = strlcat(identPlusVers, kmod_info->version, bufSize);
16147 	if (result >= bufSize) {
16148 		identPlusVers[bufSize - 1] = '\0';
16149 		result = bufSize - 1;
16150 	}
16151 
16152 	return result;
16153 }
16154 
16155 /*******************************************************************************
16156 * Assumes sKextLock is held.
16157 *******************************************************************************/
16158 /* static */
16159 int
16160 OSKext::saveLoadedKextPanicListTyped(
16161 	const char * prefix,
16162 	int          invertFlag,
16163 	int          libsFlag,
16164 	char       * paniclist,
16165 	uint32_t     list_size)
16166 {
16167 	int             result = -1;
16168 	unsigned int    count, i;
16169 
16170 	count = sLoadedKexts->getCount();
16171 	if (!count) {
16172 		goto finish;
16173 	}
16174 
16175 	i = count - 1;
16176 	do {
16177 		OSObject    * rawKext = sLoadedKexts->getObject(i);
16178 		OSKext      * theKext = OSDynamicCast(OSKext, rawKext);
16179 		int           match;
16180 		size_t        identPlusVersLength;
16181 		size_t        tempLen;
16182 		char          identPlusVers[2 * KMOD_MAX_NAME];
16183 
16184 		if (!rawKext) {
16185 			printf("OSKext::saveLoadedKextPanicListTyped - "
16186 			    "NULL kext in loaded kext list; continuing\n");
16187 			continue;
16188 		}
16189 
16190 		if (!theKext) {
16191 			printf("OSKext::saveLoadedKextPanicListTyped - "
16192 			    "Kext type cast failed in loaded kext list; continuing\n");
16193 			continue;
16194 		}
16195 
16196 		/* Skip all built-in kexts.
16197 		 */
16198 		if (theKext->isKernelComponent()) {
16199 			continue;
16200 		}
16201 
16202 		kmod_info_t * kmod_info = theKext->kmod_info;
16203 
16204 		/* Filter for kmod name (bundle identifier).
16205 		 */
16206 		match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
16207 		if ((match && invertFlag) || (!match && !invertFlag)) {
16208 			continue;
16209 		}
16210 
16211 		/* Filter for libraries (kexts that have a compatible version).
16212 		 */
16213 		if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
16214 		    (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
16215 			continue;
16216 		}
16217 
16218 		if (!kmod_info ||
16219 		    !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
16220 			printf("kext scan stopped due to missing kmod_info page: %p\n",
16221 			    kmod_info);
16222 			goto finish;
16223 		}
16224 
16225 		identPlusVersLength = assemble_identifier_and_version(kmod_info,
16226 		    identPlusVers,
16227 		    sizeof(identPlusVers));
16228 		if (!identPlusVersLength) {
16229 			printf("error saving loaded kext info\n");
16230 			goto finish;
16231 		}
16232 
16233 		/* make sure everything fits and we null terminate.
16234 		 */
16235 		tempLen = strlcat(paniclist, identPlusVers, list_size);
16236 		if (tempLen >= list_size) {
16237 			// panic list is full, keep it and null terminate
16238 			paniclist[list_size - 1] = 0x00;
16239 			result = 0;
16240 			goto finish;
16241 		}
16242 		tempLen = strlcat(paniclist, "\n", list_size);
16243 		if (tempLen >= list_size) {
16244 			// panic list is full, keep it and null terminate
16245 			paniclist[list_size - 1] = 0x00;
16246 			result = 0;
16247 			goto finish;
16248 		}
16249 	} while (i--);
16250 
16251 	result = 0;
16252 finish:
16253 
16254 	return result;
16255 }
16256 
16257 /*********************************************************************
16258 *********************************************************************/
16259 /* static */
16260 void
16261 OSKext::saveLoadedKextPanicList(void)
16262 {
16263 	char     * newlist        = NULL;
16264 	uint32_t   newlist_size   = 0;
16265 
16266 	newlist_size = KEXT_PANICLIST_SIZE;
16267 	newlist = (char *)kalloc_data_tag(newlist_size,
16268 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
16269 
16270 	if (!newlist) {
16271 		OSKextLog(/* kext */ NULL,
16272 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
16273 		    "Couldn't allocate kext panic log buffer.");
16274 		goto finish;
16275 	}
16276 
16277 	newlist[0] = '\0';
16278 
16279 	// non-"com.apple." kexts
16280 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
16281 	    /* libs? */ -1, newlist, newlist_size) != 0) {
16282 		goto finish;
16283 	}
16284 	// "com.apple." nonlibrary kexts
16285 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
16286 	    /* libs? */ 0, newlist, newlist_size) != 0) {
16287 		goto finish;
16288 	}
16289 	// "com.apple." library kexts
16290 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
16291 	    /* libs? */ 1, newlist, newlist_size) != 0) {
16292 		goto finish;
16293 	}
16294 
16295 	if (loaded_kext_paniclist) {
16296 		kfree_data(loaded_kext_paniclist, loaded_kext_paniclist_size);
16297 	}
16298 	loaded_kext_paniclist = newlist;
16299 	newlist = NULL;
16300 	loaded_kext_paniclist_size = newlist_size;
16301 
16302 finish:
16303 	if (newlist) {
16304 		kfree_data(newlist, newlist_size);
16305 	}
16306 	return;
16307 }
16308 
16309 /*********************************************************************
16310 * Assumes sKextLock is held.
16311 *********************************************************************/
16312 void
16313 OSKext::savePanicString(bool isLoading)
16314 {
16315 	u_long len;
16316 
16317 	if (!kmod_info) {
16318 		return;         // do not goto finish here b/c of lock
16319 	}
16320 
16321 	len = assemble_identifier_and_version( kmod_info,
16322 	    (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
16323 	    (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
16324 	if (!len) {
16325 		printf("error saving unloaded kext info\n");
16326 		goto finish;
16327 	}
16328 
16329 	if (isLoading) {
16330 		last_loaded_strlen = len;
16331 		last_loaded_address = (void *)kmod_info->address;
16332 		last_loaded_size = kmod_info->size;
16333 		clock_get_uptime(&last_loaded_timestamp);
16334 	} else {
16335 		last_unloaded_strlen = len;
16336 		last_unloaded_address = (void *)kmod_info->address;
16337 		last_unloaded_size = kmod_info->size;
16338 		clock_get_uptime(&last_unloaded_timestamp);
16339 	}
16340 
16341 finish:
16342 	return;
16343 }
16344 
16345 /*********************************************************************
16346 *********************************************************************/
16347 /* static */
16348 void
16349 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
16350 {
16351 	if (last_loaded_strlen) {
16352 		printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n",
16353 		    AbsoluteTime_to_scalar(&last_loaded_timestamp),
16354 		    last_loaded_strlen, last_loaded_str_buf,
16355 		    last_loaded_address, last_loaded_size);
16356 	}
16357 
16358 	if (last_unloaded_strlen) {
16359 		printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n",
16360 		    AbsoluteTime_to_scalar(&last_unloaded_timestamp),
16361 		    last_unloaded_strlen, last_unloaded_str_buf,
16362 		    last_unloaded_address, last_unloaded_size);
16363 	}
16364 
16365 	printf_func("loaded kexts:\n");
16366 	if (loaded_kext_paniclist &&
16367 	    pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
16368 	    loaded_kext_paniclist[0]) {
16369 		printf_func("%.*s",
16370 		    strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
16371 		    loaded_kext_paniclist);
16372 	} else {
16373 		printf_func("(none)\n");
16374 	}
16375 	return;
16376 }
16377 
16378 /*********************************************************************
16379 * Assumes sKextLock is held.
16380 *********************************************************************/
16381 /* static */
16382 void
16383 OSKext::updateLoadedKextSummaries(void)
16384 {
16385 	kern_return_t result = KERN_FAILURE;
16386 	OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
16387 	OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
16388 	OSKext *aKext;
16389 	vm_map_offset_t start;
16390 	size_t summarySize = 0;
16391 	size_t size;
16392 	u_int count;
16393 	u_int maxKexts;
16394 	u_int i, j;
16395 	OSKextActiveAccount * accountingList;
16396 	OSKextActiveAccount * prevAccountingList;
16397 	uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
16398 
16399 	prevAccountingList = NULL;
16400 	prevAccountingListCount = 0;
16401 
16402 #if DEVELOPMENT || DEBUG
16403 	if (IORecursiveLockHaveLock(sKextLock) == false) {
16404 		panic("sKextLock must be held");
16405 	}
16406 #endif
16407 
16408 	IOLockLock(sKextSummariesLock);
16409 
16410 	count = sLoadedKexts->getCount();
16411 	for (i = 0, maxKexts = 0; i < count; ++i) {
16412 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16413 		maxKexts += (aKext && (aKext->isExecutable() || aKext->isSpecialKernelBinary()));
16414 	}
16415 
16416 	if (!maxKexts) {
16417 		goto finish;
16418 	}
16419 	if (maxKexts < kOSKextTypicalLoadCount) {
16420 		maxKexts = kOSKextTypicalLoadCount;
16421 	}
16422 
16423 	/* Calculate the size needed for the new summary headers.
16424 	 */
16425 
16426 	size = sizeof(*gLoadedKextSummaries);
16427 	size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
16428 	size = round_page(size);
16429 
16430 	if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
16431 		if (gLoadedKextSummaries) {
16432 			kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
16433 			gLoadedKextSummaries = NULL;
16434 			gLoadedKextSummariesTimestamp = mach_absolute_time();
16435 			sLoadedKextSummariesAllocSize = 0;
16436 		}
16437 		result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size,
16438 		    KMA_NONE, VM_KERN_MEMORY_OSKEXT);
16439 		if (result != KERN_SUCCESS) {
16440 			goto finish;
16441 		}
16442 		summaryHeader = summaryHeaderAlloc;
16443 		summarySize = size;
16444 	} else {
16445 		summaryHeader = gLoadedKextSummaries;
16446 		summarySize = sLoadedKextSummariesAllocSize;
16447 
16448 		start = (vm_map_offset_t) summaryHeader;
16449 		result = mach_vm_protect(kernel_map,
16450 		    start,
16451 		    summarySize,
16452 		    false,
16453 		    VM_PROT_DEFAULT);
16454 		if (result != KERN_SUCCESS) {
16455 			goto finish;
16456 		}
16457 	}
16458 
16459 	/* Populate the summary header.
16460 	 */
16461 
16462 	bzero(summaryHeader, summarySize);
16463 	summaryHeader->version = kOSKextLoadedKextSummaryVersion;
16464 	summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
16465 
16466 	/* Populate each kext summary.
16467 	 */
16468 
16469 	count = sLoadedKexts->getCount();
16470 	accountingListAlloc = 0;
16471 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
16472 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16473 		if (!aKext || (!aKext->isExecutable() && !aKext->isSpecialKernelBinary())) {
16474 			continue;
16475 		}
16476 
16477 		aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
16478 		summaryHeader->numSummaries++;
16479 		accountingListAlloc++;
16480 	}
16481 
16482 	accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
16483 	accountingListCount = 0;
16484 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
16485 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16486 		if (!aKext || (!aKext->isExecutable() && !aKext->isSpecialKernelBinary())) {
16487 			continue;
16488 		}
16489 
16490 		OSKextActiveAccount activeAccount;
16491 		aKext->updateActiveAccount(&activeAccount);
16492 		// order by address
16493 		for (idx = 0; idx < accountingListCount; idx++) {
16494 			if (activeAccount.address < accountingList[idx].address) {
16495 				break;
16496 			}
16497 		}
16498 		bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
16499 		accountingList[idx] = activeAccount;
16500 		accountingListCount++;
16501 	}
16502 	assert(accountingListCount == accountingListAlloc);
16503 	/* Write protect the buffer and move it into place.
16504 	 */
16505 
16506 	start = (vm_map_offset_t) summaryHeader;
16507 
16508 	result = mach_vm_protect(kernel_map, start, summarySize, false, VM_PROT_READ);
16509 	if (result != KERN_SUCCESS) {
16510 		goto finish;
16511 	}
16512 
16513 	gLoadedKextSummaries = summaryHeader;
16514 	gLoadedKextSummariesTimestamp = mach_absolute_time();
16515 	sLoadedKextSummariesAllocSize = summarySize;
16516 	summaryHeaderAlloc = NULL;
16517 
16518 	/* Call the magic breakpoint function through a static function pointer so
16519 	 * the compiler can't optimize the function away.
16520 	 */
16521 	if (sLoadedKextSummariesUpdated) {
16522 		(*sLoadedKextSummariesUpdated)();
16523 	}
16524 
16525 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16526 	prevAccountingList      = sKextAccounts;
16527 	prevAccountingListCount = sKextAccountsCount;
16528 	sKextAccounts           = accountingList;
16529 	sKextAccountsCount      = accountingListCount;
16530 	lck_ticket_unlock(sKextAccountsLock);
16531 
16532 finish:
16533 	IOLockUnlock(sKextSummariesLock);
16534 
16535 	/* If we had to allocate a new buffer but failed to generate the summaries,
16536 	 * free that now.
16537 	 */
16538 	if (summaryHeaderAlloc) {
16539 		kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
16540 	}
16541 	if (prevAccountingList) {
16542 		IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
16543 	}
16544 
16545 	return;
16546 }
16547 
16548 /*********************************************************************
16549 *********************************************************************/
16550 void
16551 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
16552 {
16553 	OSSharedPtr<OSData> uuid;
16554 
16555 	strlcpy(summary->name, getIdentifierCString(),
16556 	    sizeof(summary->name));
16557 
16558 	uuid = copyUUID();
16559 	if (uuid) {
16560 		memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
16561 	}
16562 
16563 	if (flags.builtin) {
16564 //      this value will stop lldb from parsing the mach-o header
16565 //      summary->address = UINT64_MAX;
16566 //      summary->size = 0;
16567 		summary->address = kmod_info->address;
16568 		summary->size = kmod_info->size;
16569 	} else {
16570 		summary->address = kmod_info->address;
16571 		summary->size = kmod_info->size;
16572 	}
16573 	summary->version = getVersion();
16574 	summary->loadTag = kmod_info->id;
16575 	summary->flags = 0;
16576 	summary->reference_list = (uint64_t) kmod_info->reference_list;
16577 
16578 	summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size);
16579 	if (summary->text_exec_address == 0) {
16580 		// Fallback to __TEXT
16581 		summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size);
16582 	}
16583 
16584 	/**
16585 	 * If the addresses within the Mach-O are unslid, then manually slide any
16586 	 * addresses coming from the Mach-O as higher layer software using these
16587 	 * summaries expects a slid address here.
16588 	 */
16589 	if (flags.unslidMachO) {
16590 		summary->text_exec_address = (uint64_t) ml_static_slide((vm_offset_t) summary->text_exec_address);
16591 	}
16592 
16593 	return;
16594 }
16595 
16596 /*********************************************************************
16597 *********************************************************************/
16598 
16599 void
16600 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
16601 {
16602 	kernel_mach_header_t     *hdr = NULL;
16603 	kernel_segment_command_t *seg = NULL;
16604 
16605 	bzero(accountp, sizeof(*accountp));
16606 
16607 	hdr = (kernel_mach_header_t *)kmod_info->address;
16608 	if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) {
16609 		/*
16610 		 * If this kext supports split segments (or is in a new
16611 		 * MH_FILESET kext collection), use the first
16612 		 * executable segment as the range for instructions
16613 		 * (and thus for backtracing.
16614 		 */
16615 		for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
16616 			if (seg->initprot & VM_PROT_EXECUTE) {
16617 				break;
16618 			}
16619 		}
16620 	}
16621 	if (seg) {
16622 		accountp->address = seg->vmaddr;
16623 		if (accountp->address) {
16624 			accountp->address_end = seg->vmaddr + seg->vmsize;
16625 		}
16626 	} else {
16627 		/* For non-split kexts and for kexts without executable
16628 		 * segments, just use the kmod_info range (as the kext
16629 		 * is either all in one range or should not show up in
16630 		 * instruction backtraces).
16631 		 */
16632 		accountp->address = kmod_info->address;
16633 		if (accountp->address) {
16634 			accountp->address_end = kmod_info->address + kmod_info->size;
16635 		}
16636 	}
16637 
16638 	accountp->account = this->account;
16639 }
16640 
16641 bool
16642 OSKext::isDriverKit(void)
16643 {
16644 	OSString *bundleType;
16645 
16646 	if (infoDict) {
16647 		bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey));
16648 		if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) {
16649 			return TRUE;
16650 		}
16651 	}
16652 	return FALSE;
16653 }
16654 
16655 bool
16656 OSKext::isInFileset(void)
16657 {
16658 	if (!kmod_info) {
16659 		goto check_prelinked;
16660 	}
16661 
16662 	if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) {
16663 		return true;
16664 	}
16665 
16666 check_prelinked:
16667 	if (isPrelinked()) {
16668 		/*
16669 		 * If we haven't setup kmod_info yet, but we know
16670 		 * we're loading a prelinked kext in an MH_FILESET KC,
16671 		 * then return true
16672 		 */
16673 		kc_format_t kc_format;
16674 		if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
16675 			return true;
16676 		}
16677 	}
16678 	return false;
16679 }
16680 
16681 OSSharedPtr<OSDextStatistics>
16682 OSKext::copyDextStatistics(void)
16683 {
16684 	return dextStatistics;
16685 }
16686 
16687 bool
16688 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg)
16689 {
16690 	kern_return_t result;
16691 	if (!super::init()) {
16692 		return false;
16693 	}
16694 	if (seg == nullptr) {
16695 		return false;
16696 	}
16697 	result = kmem_alloc(kernel_map, (vm_offset_t *)&data, seg->vmsize,
16698 	    KMA_PAGEABLE, VM_KERN_MEMORY_KEXT);
16699 	if (result != KERN_SUCCESS) {
16700 		return false;
16701 	}
16702 	memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize);
16703 	savedSegment = seg;
16704 	vmsize = seg->vmsize;
16705 	vmaddr = seg->vmaddr;
16706 	return true;
16707 }
16708 
16709 OSSharedPtr<OSKextSavedMutableSegment>
16710 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg)
16711 {
16712 	OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>();
16713 	if (me && !me->initWithSegment(seg)) {
16714 		return nullptr;
16715 	}
16716 	return me;
16717 }
16718 
16719 void
16720 OSKextSavedMutableSegment::free(void)
16721 {
16722 	if (data) {
16723 		kmem_free(kernel_map, (vm_offset_t)data, vmsize);
16724 	}
16725 }
16726 
16727 vm_offset_t
16728 OSKextSavedMutableSegment::getVMAddr() const
16729 {
16730 	return vmaddr;
16731 }
16732 
16733 vm_offset_t
16734 OSKextSavedMutableSegment::getVMSize() const
16735 {
16736 	return vmsize;
16737 }
16738 
16739 OSReturn
16740 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg)
16741 {
16742 	if (seg != savedSegment) {
16743 		return kOSKextReturnInvalidArgument;
16744 	}
16745 	if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) {
16746 		return kOSKextReturnInvalidArgument;
16747 	}
16748 	memcpy((void *)seg->vmaddr, data, vmsize);
16749 	return kOSReturnSuccess;
16750 }
16751 
16752 extern "C" kern_return_t
16753 OSKextSetReceiptQueried(void)
16754 {
16755 	OSKextLog(/* kext */ NULL,
16756 	    kOSKextLogStepLevel | kOSKextLogGeneralFlag,
16757 	    "Setting kext receipt as queried");
16758 
16759 	IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue);
16760 	return KERN_SUCCESS;
16761 }
16762 
16763 extern "C" const vm_allocation_site_t *
16764 OSKextGetAllocationSiteForCaller(uintptr_t address)
16765 {
16766 	OSKextActiveAccount *  active;
16767 	vm_allocation_site_t * site;
16768 	vm_allocation_site_t * releasesite;
16769 
16770 	uint32_t baseIdx;
16771 	uint32_t lim;
16772 #if  __has_feature(ptrauth_calls)
16773 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
16774 #endif /*  __has_feature(ptrauth_calls) */
16775 
16776 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16777 	site = releasesite = NULL;
16778 
16779 	// bsearch sKextAccounts list
16780 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
16781 		active = &sKextAccounts[baseIdx + (lim >> 1)];
16782 		if ((address >= active->address) && (address < active->address_end)) {
16783 			site = &active->account->site;
16784 			if (!site->tag) {
16785 				vm_tag_alloc_locked(site, &releasesite);
16786 			}
16787 			break;
16788 		} else if (address > active->address) {
16789 			// move right
16790 			baseIdx += (lim >> 1) + 1;
16791 			lim--;
16792 		}
16793 		// else move left
16794 	}
16795 	lck_ticket_unlock(sKextAccountsLock);
16796 	if (releasesite) {
16797 		kern_allocation_name_release(releasesite);
16798 	}
16799 
16800 	return site;
16801 }
16802 
16803 #if DEVELOPMENT || DEBUG
16804 extern "C" void
16805 OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *))
16806 {
16807 	OSKextActiveAccount *  active;
16808 
16809 	uint32_t baseIdx;
16810 	uint32_t lim;
16811 #if  __has_feature(ptrauth_calls)
16812 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
16813 #endif /*  __has_feature(ptrauth_calls) */
16814 
16815 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16816 
16817 	// bsearch sKextAccounts list
16818 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
16819 		active = &sKextAccounts[baseIdx + (lim >> 1)];
16820 		if ((address >= active->address) && (address < active->address_end)) {
16821 			cb(&active->account->task_refgrp);
16822 			break;
16823 		} else if (address > active->address) {
16824 			// move right
16825 			baseIdx += (lim >> 1) + 1;
16826 			lim--;
16827 		}
16828 		// else move left
16829 	}
16830 	lck_ticket_unlock(sKextAccountsLock);
16831 }
16832 #endif /* DEVELOPMENT || DEBUG */
16833 
16834 extern "C" uint32_t
16835 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
16836 {
16837 	OSKextAccount * account = (typeof(account))site;
16838 	const char    * kname;
16839 
16840 	if (name) {
16841 		if (account->kext) {
16842 			kname = account->kext->getIdentifierCString();
16843 		} else {
16844 			kname = "<>";
16845 		}
16846 		strlcpy(name, kname, namelen);
16847 	}
16848 
16849 	return account->loadTag;
16850 }
16851 
16852 extern "C" void
16853 OSKextFreeSite(vm_allocation_site_t * site)
16854 {
16855 	OSKextAccount * freeAccount = (typeof(freeAccount))site;
16856 	IOFreeType(freeAccount, OSKextAccount);
16857 }
16858 
16859 /*********************************************************************
16860 *********************************************************************/
16861 
16862 #if CONFIG_IMAGEBOOT
16863 int
16864 OSKextGetUUIDForName(const char *name, uuid_t uuid)
16865 {
16866 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name);
16867 	if (!kext) {
16868 		return 1;
16869 	}
16870 
16871 	OSSharedPtr<OSData> uuid_data = kext->copyUUID();
16872 	if (uuid_data) {
16873 		memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
16874 		return 0;
16875 	}
16876 
16877 	return 1;
16878 }
16879 #endif
16880 
16881 
16882 
16883 class OSDextCrash : public OSObject {
16884 	OSDeclareDefaultStructors(OSDextCrash);
16885 public:
16886 	static OSPtr<OSDextCrash> withTimestamp(uint64_t timestamp);
16887 	uint64_t getTimestamp();
16888 
16889 private:
16890 	virtual bool initWithTimestamp(uint64_t timestamp);
16891 	uint64_t fTimestamp;
16892 };
16893 
16894 OSDefineMetaClassAndStructors(OSDextCrash, OSObject);
16895 
16896 OSSharedPtr<OSDextCrash>
16897 OSDextCrash::withTimestamp(uint64_t timestamp)
16898 {
16899 	OSSharedPtr<OSDextCrash> result = OSMakeShared<OSDextCrash>();
16900 	if (!result->initWithTimestamp(timestamp)) {
16901 		return NULL;
16902 	}
16903 	return result;
16904 }
16905 
16906 bool
16907 OSDextCrash::initWithTimestamp(uint64_t timestamp)
16908 {
16909 	if (!OSObject::init()) {
16910 		return false;
16911 	}
16912 	fTimestamp = timestamp;
16913 	return true;
16914 }
16915 
16916 uint64_t
16917 OSDextCrash::getTimestamp()
16918 {
16919 	return fTimestamp;
16920 }
16921 
16922 OSSharedPtr<OSDextStatistics>
16923 OSDextStatistics::create()
16924 {
16925 	OSSharedPtr<OSDextStatistics> result = OSMakeShared<OSDextStatistics>();
16926 	if (!result->init()) {
16927 		return NULL;
16928 	}
16929 	return result;
16930 }
16931 
16932 bool
16933 OSDextStatistics::init()
16934 {
16935 	if (!OSObject::init()) {
16936 		return false;
16937 	}
16938 
16939 	lock = IOLockAlloc();
16940 	crashes = OSArray::withCapacity(kMaxDextCrashesInOneDay);
16941 	return true;
16942 }
16943 
16944 void
16945 OSDextStatistics::free()
16946 {
16947 	if (lock) {
16948 		IOLockFree(lock);
16949 	}
16950 	crashes.reset();
16951 	OSObject::free();
16952 }
16953 
16954 OSDextCrashPolicy
16955 OSDextStatistics::recordCrash()
16956 {
16957 	size_t i = 0;
16958 	uint64_t timestamp = mach_continuous_time();
16959 	uint64_t interval;
16960 	nanoseconds_to_absolutetime(86400 * NSEC_PER_SEC /* 1 day */, &interval);
16961 	uint64_t lastTimestamp = timestamp > interval ? timestamp - interval : 0;
16962 	OSDextCrashPolicy policy;
16963 
16964 	IOLockLock(lock);
16965 	OSSharedPtr<OSDextCrash> crash = OSDextCrash::withTimestamp(timestamp);
16966 	for (i = 0; i < crashes->getCount();) {
16967 		OSDextCrash * current = OSDynamicCast(OSDextCrash, crashes->getObject(i));
16968 		assert(current != NULL);
16969 		if (current->getTimestamp() < lastTimestamp) {
16970 			crashes->removeObject(i);
16971 		} else {
16972 			i++;
16973 		}
16974 	}
16975 
16976 	crashes->setObject(crash);
16977 
16978 	if (crashes->getCount() > kMaxDextCrashesInOneDay) {
16979 		policy = kOSDextCrashPolicyReboot;
16980 	} else {
16981 		policy = kOSDextCrashPolicyNone;
16982 	}
16983 
16984 	IOLockUnlock(lock);
16985 
16986 	return policy;
16987 }
16988 
16989 size_t
16990 OSDextStatistics::getCrashCount()
16991 {
16992 	size_t result = 0;
16993 	IOLockLock(lock);
16994 	result = crashes->getCount();
16995 	IOLockUnlock(lock);
16996 	return result;
16997 }
16998 
16999 static int
17000 sysctl_willuserspacereboot
17001 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
17002 {
17003 	int new_value = 0, old_value = get_system_inuserspacereboot(), changed = 0;
17004 	int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
17005 	if (error) {
17006 		return error;
17007 	}
17008 	if (changed) {
17009 		OSKext::setWillUserspaceReboot();
17010 	}
17011 	return 0;
17012 }
17013 
17014 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot,
17015     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
17016     NULL, 0, sysctl_willuserspacereboot, "I", "");
17017