xref: /xnu-11417.140.69/libkern/c++/OSKext.cpp (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
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 <pexpert/pexpert.h>
54 
55 #include <sys/pgo.h>
56 
57 #if CONFIG_CSR
58 #include <sys/csr.h>
59 #include <sys/stat.h>
60 #include <sys/vnode.h>
61 #endif /* CONFIG_CSR */
62 };
63 
64 #if CONFIG_MACF
65 #include <sys/kauth.h>
66 #include <security/mac_framework.h>
67 #endif
68 
69 #include <vm/vm_kern_xnu.h>
70 #include <sys/sysctl.h>
71 #include <kern/task.h>
72 #include <os/cpp_util.h>
73 
74 #include <libkern/OSKextLibPrivate.h>
75 #include <libkern/c++/OSKext.h>
76 #include <libkern/c++/OSLib.h>
77 
78 #include <IOKit/IOLib.h>
79 #include <IOKit/IOCatalogue.h>
80 #include <IOKit/IORegistryEntry.h>
81 #include <IOKit/IOService.h>
82 #include <IOKit/IOUserServer.h>
83 
84 #include <IOKit/IOStatisticsPrivate.h>
85 #include <IOKit/IOBSD.h>
86 #include <IOKit/IOPlatformExpert.h>
87 
88 #include <san/kasan.h>
89 
90 #if CONFIG_SPTM
91 #include <arm64/sptm/sptm.h>
92 #endif
93 
94 #if PRAGMA_MARK
95 #pragma mark External & Internal Function Protos
96 #endif
97 /*********************************************************************
98 *********************************************************************/
99 extern "C" {
100 extern int  IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
101 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
102 
103 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
104 extern int dtrace_keep_kernel_symbols(void);
105 
106 #if defined(__x86_64__) || defined(__i386__)
107 extern kern_return_t i386_slide_individual_kext(kernel_mach_header_t *mh, uintptr_t slide);
108 extern kern_return_t i386_slide_kext_collection_mh_addrs(kernel_mach_header_t *mh, uintptr_t slide, bool adjust_mach_headers);
109 extern void *ubc_getobject_from_filename(const char *filename, struct vnode **, off_t *file_size);
110 static void *allocate_kcfileset_map_entry_list(void);
111 static void add_kcfileset_map_entry(void *map_entry_list, vm_map_offset_t start, vm_map_offset_t size);
112 static void deallocate_kcfileset_map_entry_list_and_unmap_entries(void *map_entry_list, boolean_t unmap_entries, bool pageable);
113 int vnode_put(struct vnode *vp);
114 kern_return_t vm_map_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size,
115     void *control, vm_object_offset_t fileoffset, vm_prot_t max_prot);
116 kern_return_t vm_unmap_kcfileset_segment(vm_map_offset_t *start, vm_map_offset_t size);
117 void * ubc_getobject(struct vnode *vp, __unused int flags);
118 #endif //(__x86_64__) || defined(__i386__)
119 }
120 
121 extern unsigned long gVirtBase;
122 extern unsigned long gPhysBase;
123 
124 bool pageableKCloaded = false;
125 bool auxKCloaded = false;
126 bool resetAuxKCSegmentOnUnload = false;
127 
128 extern boolean_t pageablekc_uuid_valid;
129 extern uuid_t pageablekc_uuid;
130 extern uuid_string_t pageablekc_uuid_string;
131 
132 extern boolean_t auxkc_uuid_valid;
133 extern uuid_t auxkc_uuid;
134 extern uuid_string_t auxkc_uuid_string;
135 
136 static OSReturn _OSKextCreateRequest(
137 	const char    * predicate,
138 	OSSharedPtr<OSDictionary> & requestP);
139 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
140 static OSObject * _OSKextGetRequestArgument(
141 	OSDictionary * requestDict,
142 	const char   * argName);
143 static bool _OSKextSetRequestArgument(
144 	OSDictionary    * requestDict,
145 	const char      * argName,
146 	OSMetaClassBase * value);
147 template <typename T>
148 static T * _OSKextExtractPointer(OSValueObject<T *> * wrapper);
149 static OSKextRequestResourceCallback _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper);
150 static OSReturn _OSDictionarySetCStringValue(
151 	OSDictionary * dict,
152 	const char   * key,
153 	const char   * value);
154 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
155 #if CONFIG_KXLD
156 static bool _OSKextInPrelinkRebuildWindow(void);
157 #endif
158 
159 // We really should add containsObject() & containsCString to OSCollection & subclasses.
160 // So few pad slots, though....
161 static bool _OSArrayContainsCString(OSArray * array, const char * cString);
162 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code);
163 
164 static const char *getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size);
165 
166 /* Prelinked arm kexts do not have VM entries because the method we use to
167  * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
168  * not work on ARM.  To get around that, we must free prelinked kext
169  * executables with ml_static_mfree() instead of kext_free().
170  */
171 #if __i386__ || __x86_64__
172 #define VM_MAPPED_KEXTS 1
173 #define KASLR_KEXT_DEBUG 0
174 #define KASLR_IOREG_DEBUG 0
175 #elif __arm__ || __arm64__
176 #define VM_MAPPED_KEXTS 0
177 #define KASLR_KEXT_DEBUG 0
178 #else
179 #error Unsupported architecture
180 #endif
181 
182 #if PRAGMA_MARK
183 #pragma mark Constants & Macros
184 #endif
185 /*********************************************************************
186 * Constants & Macros
187 *********************************************************************/
188 
189 /* Use this number to create containers.
190  */
191 #define kOSKextTypicalLoadCount      (150)
192 #define kOSKextTypicalUpgradeCount     (5)
193 
194 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
195  * A loaded kext will no dependents or external retains will have 2 retains.
196  */
197 #define kOSKextMinRetainCount        (1)
198 #define kOSKextMinLoadedRetainCount  (2)
199 
200 #define kOSKextMaxDextLaunchedCount  (~((uint32_t)0))
201 #define KOSBundleDextUniqueIdentifierMaxStringLength (KOSBundleDextUniqueIdentifierMaxLength * 2 +1)
202 
203 /**********
204  * Strings and substrings used in dependency resolution.
205  */
206 #define APPLE_KEXT_PREFIX            "com.apple."
207 #define KERNEL_LIB                   "com.apple.kernel"
208 
209 #define PRIVATE_KPI                  "com.apple.kpi.private"
210 
211 /* Version for compatbility pseudokexts (com.apple.kernel.*),
212  * compatible back to v6.0.
213  */
214 #define KERNEL6_LIB                  "com.apple.kernel.6.0"
215 #define KERNEL6_VERSION              "7.9.9"
216 
217 #define KERNEL_LIB_PREFIX            "com.apple.kernel."
218 #define KPI_LIB_PREFIX               "com.apple.kpi."
219 
220 #define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0)
221 
222 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
223 #define MINIMUM_WAKEUP_SECONDS (30)
224 
225 /*********************************************************************
226 * infoDict keys for internally-stored data. Saves on ivar slots for
227 * objects we don't keep around past boot time or during active load.
228 *********************************************************************/
229 
230 /* A usable, uncompressed file is stored under this key.
231  */
232 #define _kOSKextExecutableKey                "_OSKextExecutable"
233 
234 /* An indirect reference to the executable file from an mkext
235  * is stored under this key.
236  */
237 #define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference"
238 
239 /* If the file is contained in a larger buffer laid down by the booter or
240  * sent from user space, the OSKext stores that OSData under this key so that
241  * references are properly tracked. This is always an mkext, right now.
242  */
243 #define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData"
244 
245 #define OS_LOG_HDR_VERSION  1
246 #define NUM_OS_LOG_SECTIONS 3
247 
248 #define OS_LOG_SECT_IDX         0
249 #define CSTRING_SECT_IDX        1
250 #define ASAN_CSTRING_SECT_IDX   2
251 
252 #if PRAGMA_MARK
253 #pragma mark Typedefs
254 #endif
255 /*********************************************************************
256 * Typedefs
257 *********************************************************************/
258 
259 /*********************************************************************
260 * osLogDataHeaderRef describes the header information of an OSData
261 * object that is returned when querying for kOSBundleLogStringsKey.
262 * We currently return information regarding 2 sections - os_log and
263 * cstring. In the case that the os_log section doesn't exist, we just
264 * return an offset and length of 0 for that section.
265 *********************************************************************/
266 typedef struct osLogDataHeader {
267 	uint32_t version;
268 	uint32_t sect_count;
269 	struct {
270 		uint32_t sect_offset;
271 		uint32_t sect_size;
272 	} sections[0];
273 } osLogDataHeaderRef;
274 
275 /*********************************************************************
276 * MkextEntryRef describes the contents of an OSData object
277 * referencing a file entry from an mkext so that we can uncompress
278 * (if necessary) and extract it on demand.
279 *
280 * It contains the mkextVersion in case we ever wind up supporting
281 * multiple mkext formats. Mkext format 1 is officially retired as of
282 * Snow Leopard.
283 *********************************************************************/
284 typedef struct MkextEntryRef {
285 	mkext_basic_header * mkext; // beginning of whole mkext file
286 	void               * fileinfo;// mkext2_file_entry or equiv; see mkext.h
287 } MkextEntryRef;
288 
289 #if PRAGMA_MARK
290 #pragma mark Global and static Module Variables
291 #endif
292 /*********************************************************************
293 * Global & static variables, used to keep track of kexts.
294 *********************************************************************/
295 
296 static  bool                sPrelinkBoot               = false;
297 static  bool                sSafeBoot                  = false;
298 static  bool                sKeepSymbols               = false;
299 static  bool                sPanicOnKCMismatch         = false;
300 static  bool                sOSKextWasResetAfterUserspaceReboot = false;
301 
302 /*********************************************************************
303  * sKextLock is the principal lock for OSKext, and guards all static
304  * and global variables not owned by other locks (declared further
305  * below). It must be taken by any entry-point method or function,
306  * including internal functions called on scheduled threads.
307  *
308  * sKextLock and sKextInnerLock are recursive due to multiple functions
309  * that are called both externally and internally. The other locks are
310  * nonrecursive.
311  *
312  * Which locks are taken depends on what they protect, but if more than
313  * one must be taken, they must always be locked in this order
314  * (and unlocked in reverse order) to prevent deadlocks:
315  *
316  *    1. sKextLock
317  *    2. sKextInnerLock
318  *    3. sKextSummariesLock
319  *    4. sKextLoggingLock
320  */
321 static IORecursiveLock    * sKextLock                  = NULL;
322 
323 static OSSharedPtr<OSDictionary>   sKextsByID;
324 static OSSharedPtr<OSDictionary>   sExcludeListByID;
325 static OSKextVersion               sExcludeListVersion        = 0;
326 static OSSharedPtr<OSArray>        sLoadedKexts;
327 static OSSharedPtr<OSDictionary>   sNonLoadableKextsByID;
328 static OSSharedPtr<OSArray>        sUnloadedPrelinkedKexts;
329 static OSSharedPtr<OSArray>        sLoadedDriverKitKexts;
330 static OSSharedPtr<OSDictionary>   sDriverKitToUpgradeByID;
331 
332 // Requests to the IOKit daemon waiting to be picked up.
333 static OSSharedPtr<OSArray>        sKernelRequests;
334 // Identifier of kext load requests in sKernelRequests
335 static OSSharedPtr<OSSet>          sPostedKextLoadIdentifiers;
336 static OSSharedPtr<OSArray>        sRequestCallbackRecords;
337 
338 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
339 static OSSharedPtr<OSSet>          sAllKextLoadIdentifiers;
340 #if CONFIG_KXLD
341 static KXLDContext        * sKxldContext               = NULL;
342 #endif
343 static uint32_t             sNextLoadTag               = 0;
344 static uint32_t             sNextRequestTag            = 0;
345 
346 static bool                 sUserLoadsActive           = false;
347 static bool                 sIOKitDaemonActive         = false;
348 static bool                 sDeferredLoadSucceeded     = false;
349 static bool                 sConsiderUnloadsExecuted   = false;
350 
351 #if NO_KEXTD
352 static bool                 sKernelRequestsEnabled     = false;
353 #else
354 static bool                 sKernelRequestsEnabled     = true;
355 #endif
356 static bool                 sLoadEnabled               = true;
357 static bool                 sUnloadEnabled             = true;
358 
359 /*********************************************************************
360  * Stuff for the OSKext representing the kernel itself.
361  **********/
362 static OSKext          * sKernelKext             = NULL;
363 
364 /* Load Tag IDs used by statically loaded binaries (e.g, the kernel itself). */
365 enum : uint32_t {
366 	kOSKextKernelLoadTag = 0,
367 #if CONFIG_SPTM
368 	kOSKextSPTMLoadTag   = 1,
369 	kOSKextTXMLoadTag    = 2,
370 #endif /* CONFIG_SPTM */
371 	kOSKextLoadTagCount
372 };
373 
374 /* Set up a fake kmod_info struct for the kernel.
375  * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
376  * before OSKext is initialized; that call only needs the name
377  * and address to be set correctly.
378  *
379  * We don't do much else with the kerne's kmod_info; we never
380  * put it into the kmod list, never adjust the reference count,
381  * and never have kernel components reference it.
382  * For that matter, we don't do much with kmod_info structs
383  * at all anymore! We just keep them filled in for gdb and
384  * binary compability.
385  */
386 kmod_info_t g_kernel_kmod_info = {
387 	.next =            NULL,
388 	.info_version =    KMOD_INFO_VERSION,
389 	.id =              kOSKextKernelLoadTag,   // loadTag: kernel is always 0
390 	.name =            kOSKextKernelIdentifier,// bundle identifier
391 	.version =         "0",           // filled in in OSKext::initialize()
392 	.reference_count = -1,            // never adjusted; kernel never unloads
393 	.reference_list =  NULL,
394 	.address =         0,
395 	.size =            0,             // filled in in OSKext::initialize()
396 	.hdr_size =        0,
397 	.start =           NULL,
398 	.stop =            NULL
399 };
400 
401 #if CONFIG_SPTM
402 /* The SPTM and TXM need fake kmod structures just like the kernel. */
403 kmod_info_t g_sptm_kmod_info = {
404 	.next =            NULL,
405 	.info_version =    KMOD_INFO_VERSION,
406 	.id =              kOSKextSPTMLoadTag,   // Always one after the kernel
407 	.name =            kOSKextSPTMIdentifier,// bundle identifier
408 	.version =         "0",           // filled in by OSKext::initialize()
409 	.reference_count = -1,            // never adjusted; SPTM never unloads
410 	.reference_list =  NULL,
411 	.address =         0,
412 	.size =            0,             // filled in by OSKext::initialize()
413 	.hdr_size =        0,
414 	.start =           NULL,
415 	.stop =            NULL
416 };
417 
418 kmod_info_t g_txm_kmod_info = {
419 	.next =            NULL,
420 	.info_version =    KMOD_INFO_VERSION,
421 	.id =              kOSKextTXMLoadTag,   // Always one after the SPTM
422 	.name =            kOSKextTXMIdentifier,// bundle identifier
423 	.version =         "0",           // filled in by OSKext::initialize()
424 	.reference_count = -1,            // never adjusted; TXM never unloads
425 	.reference_list =  NULL,
426 	.address =         0,
427 	.size =            0,             // filled in by OSKext::initialize()
428 	.hdr_size =        0,
429 	.start =           NULL,
430 	.stop =            NULL
431 };
432 #endif /* CONFIG_SPTM */
433 
434 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
435 
436 kmod_info_t invalid_kmod_info = {
437 	.next =            NULL,
438 	.info_version =    KMOD_INFO_VERSION,
439 	.id =              UINT32_MAX,
440 	.name =            "invalid",
441 	.version =         "0",
442 	.reference_count = -1,
443 	.reference_list =  NULL,
444 	.address =         0,
445 	.size =            0,
446 	.hdr_size =        0,
447 	.start =           NULL,
448 	.stop =            NULL
449 };
450 
451 extern "C" {
452 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
453 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
454 // misc_protos.h, db_low_trace.c, kgmacros
455 // 'kmod' is a holdover from the old kmod system, we can't rename it.
456 kmod_info_t * kmod = NULL;
457 
458 #define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE)
459 
460 
461 static char     * loaded_kext_paniclist         = NULL;
462 static uint32_t   loaded_kext_paniclist_size    = 0;
463 
464 AbsoluteTime      last_loaded_timestamp;
465 static char       last_loaded_str_buf[2 * KMOD_MAX_NAME];
466 static u_long     last_loaded_strlen            = 0;
467 static void     * last_loaded_address           = NULL;
468 static u_long     last_loaded_size              = 0;
469 
470 AbsoluteTime      last_unloaded_timestamp;
471 static char       last_unloaded_str_buf[2 * KMOD_MAX_NAME];
472 static u_long     last_unloaded_strlen          = 0;
473 static void     * last_unloaded_address         = NULL;
474 static u_long     last_unloaded_size            = 0;
475 
476 // Statically linked kmods described by several mach-o sections:
477 //
478 // kPrelinkInfoSegment:kBuiltinInfoSection
479 // Array of pointers to kmod_info_t structs.
480 //
481 // kPrelinkInfoSegment:kBuiltinInfoSection
482 // Array of pointers to an embedded mach-o header.
483 //
484 // __DATA:kBuiltinInitSection, kBuiltinTermSection
485 // Structors for all kmods. Has to be filtered by proc address.
486 //
487 
488 static uint32_t gBuiltinKmodsCount;
489 static kernel_section_t * gBuiltinKmodsSectionInfo;
490 static kernel_section_t * gBuiltinKmodsSectionStart;
491 
492 const OSSymbol              * gIOSurfaceIdentifier;
493 vm_tag_t                      gIOSurfaceTag;
494 
495 /*********************************************************************
496  * sKextInnerLock protects against cross-calls with IOService and
497  * IOCatalogue, and owns the variables declared immediately below.
498  *
499  * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
500  *
501  * When both sKextLock and sKextInnerLock need to be taken,
502  * always lock sKextLock first and unlock it second. Never take both
503  * locks in an entry point to OSKext; if you need to do so, you must
504  * spawn an independent thread to avoid potential deadlocks for threads
505  * calling into OSKext.
506  **********/
507 static IORecursiveLock *    sKextInnerLock             = NULL;
508 
509 #if XNU_TARGET_OS_OSX
510 static bool                 sAutounloadEnabled         = true;
511 #endif
512 static bool                 sConsiderUnloadsCalled     = false;
513 static bool                 sConsiderUnloadsPending    = false;
514 
515 static unsigned int         sConsiderUnloadDelay       = 60;     // seconds
516 static thread_call_t        sUnloadCallout             = NULL;
517 #if CONFIG_KXLD
518 static thread_call_t        sDestroyLinkContextThread  = NULL;   // one-shot, one-at-a-time thread
519 #endif // CONFIG_KXLD
520 static bool                 sSystemSleep               = false;  // true when system going to sleep
521 static AbsoluteTime         sLastWakeTime;                       // last time we woke up
522 
523 /*********************************************************************
524  * Backtraces can be printed at various times so we need a tight lock
525  * on data used for that. sKextSummariesLock protects the variables
526  * declared immediately below.
527  *
528  * gLoadedKextSummaries is accessed by other modules, but only during
529  * a panic so the lock isn't needed then.
530  *
531  * gLoadedKextSummaries has the "used" attribute in order to ensure
532  * that it remains visible even when we are performing extremely
533  * aggressive optimizations, as it is needed to allow the debugger
534  * to automatically parse the list of loaded kexts.
535  **********/
536 static IOLock                 * sKextSummariesLock                = NULL;
537 extern "C" lck_grp_t            vm_page_lck_grp_bucket;
538 static lck_grp_t              * sKextAccountsLockGrp = &vm_page_lck_grp_bucket;
539 #define sKextAccountsLock       (&vm_allocation_sites_lock)
540 
541 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
542 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
543 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
544 static size_t sLoadedKextSummariesAllocSize = 0;
545 
546 static OSKextActiveAccount    * sKextAccounts;
547 static uint32_t                 sKextAccountsCount;
548 };
549 
550 /*********************************************************************
551  * sKextLoggingLock protects the logging variables declared immediately below.
552  **********/
553 static IOLock                 * sKextLoggingLock           = NULL;
554 
555 static  const OSKextLogSpec     kDefaultKernelLogFilter    = kOSKextLogBasicLevel |
556     kOSKextLogVerboseFlagsMask;
557 static  OSKextLogSpec           sKernelLogFilter           = kDefaultKernelLogFilter;
558 static  bool                    sBootArgLogFilterFound     = false;
559 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
560     0, "kernel kext logging");
561 
562 static  OSKextLogSpec           sUserSpaceKextLogFilter    = kOSKextLogSilentFilter;
563 static  OSSharedPtr<OSArray>    sUserSpaceLogSpecArray;
564 static  OSSharedPtr<OSArray>    sUserSpaceLogMessageArray;
565 
566 /*********
567  * End scope for sKextInnerLock-protected variables.
568  *********************************************************************/
569 
570 /*********************************************************************
571  * OSValueObject concrete type instantiations
572  **********/
573 OSDefineValueObjectForDependentType(void*)
574 OSDefineValueObjectForDependentType(OSKextRequestResourceCallback)
575 
576 
577 /**********************************************************************/
578 
579 TUNABLE(uint32_t, kMaxDextCrashesInOneDay, "daily_max_dext_crashes", kMaxDextCrashesInOneDayDefault);
580 
581 /*********************************************************************
582  *  helper function used for collecting PGO data upon unload of a kext
583  */
584 
585 static int OSKextGrabPgoDataLocked(OSKext *kext,
586     bool metadata,
587     uuid_t instance_uuid,
588     uint64_t *pSize,
589     char *pBuffer,
590     uint64_t bufferSize);
591 
592 /**********************************************************************/
593 
594 
595 
596 #if PRAGMA_MARK
597 #pragma mark OSData callbacks (need to move to OSData)
598 #endif
599 /*********************************************************************
600 * C functions used for callbacks.
601 *********************************************************************/
602 extern "C" {
603 void
osdata_kmem_free(void * ptr,unsigned int length)604 osdata_kmem_free(void * ptr, unsigned int length)
605 {
606 	kmem_free(kernel_map, (vm_address_t)ptr, length);
607 	return;
608 }
609 
610 void
osdata_phys_free(void * ptr,unsigned int length)611 osdata_phys_free(void * ptr, unsigned int length)
612 {
613 	ml_static_mfree((vm_offset_t)ptr, length);
614 	return;
615 }
616 
617 void
osdata_vm_deallocate(void * ptr,unsigned int length)618 osdata_vm_deallocate(void * ptr, unsigned int length)
619 {
620 	(void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
621 	return;
622 }
623 
624 void
osdata_kext_free(void * ptr,unsigned int length)625 osdata_kext_free(void * ptr, unsigned int length)
626 {
627 	(void)kext_free((vm_offset_t)ptr, length);
628 }
629 };
630 
631 #if PRAGMA_MARK
632 #pragma mark KXLD Allocation Callback
633 #endif
634 #if CONFIG_KXLD
635 /*********************************************************************
636 * KXLD Allocation Callback
637 *********************************************************************/
638 kxld_addr_t
kern_allocate(u_long size,KXLDAllocateFlags * flags,void * user_data)639 kern_allocate(
640 	u_long              size,
641 	KXLDAllocateFlags * flags,
642 	void              * user_data)
643 {
644 	vm_address_t  result       = 0; // returned
645 	kern_return_t mach_result  = KERN_FAILURE;
646 	bool          success      = false;
647 	OSKext      * theKext      = (OSKext *)user_data;
648 	unsigned int  roundSize    = 0;
649 	OSSharedPtr<OSData>      linkBuffer;
650 
651 	if (round_page(size) > UINT_MAX) {
652 		OSKextLog(theKext,
653 		    kOSKextLogErrorLevel |
654 		    kOSKextLogGeneralFlag,
655 		    "%s: Requested memory size is greater than UINT_MAX.",
656 		    theKext->getIdentifierCString());
657 		goto finish;
658 	}
659 
660 	roundSize = (unsigned int)round_page(size);
661 
662 	mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
663 	if (mach_result != KERN_SUCCESS) {
664 		OSKextLog(theKext,
665 		    kOSKextLogErrorLevel |
666 		    kOSKextLogGeneralFlag,
667 		    "Can't allocate kernel memory to link %s.",
668 		    theKext->getIdentifierCString());
669 		goto finish;
670 	}
671 
672 	/* Create an OSData wrapper for the allocated buffer.
673 	 */
674 	linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
675 	if (!linkBuffer) {
676 		OSKextLog(theKext,
677 		    kOSKextLogErrorLevel |
678 		    kOSKextLogGeneralFlag,
679 		    "Can't allocate linked executable wrapper for %s.",
680 		    theKext->getIdentifierCString());
681 		goto finish;
682 	}
683 	linkBuffer->setDeallocFunction(osdata_kext_free);
684 	OSKextLog(theKext,
685 	    kOSKextLogProgressLevel |
686 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
687 	    "Allocated link buffer for kext %s at %p (%lu bytes).",
688 	    theKext->getIdentifierCString(),
689 	    (void *)result, (unsigned long)roundSize);
690 
691 	theKext->setLinkedExecutable(linkBuffer.get());
692 
693 	*flags = kKxldAllocateWritable;
694 	success = true;
695 
696 finish:
697 	if (!success && result) {
698 		kext_free(result, roundSize);
699 		result = 0;
700 	}
701 
702 	return (kxld_addr_t)result;
703 }
704 
705 /*********************************************************************
706 *********************************************************************/
707 void
kxld_log_callback(KXLDLogSubsystem subsystem,KXLDLogLevel level,const char * format,va_list argList,void * user_data)708 kxld_log_callback(
709 	KXLDLogSubsystem    subsystem,
710 	KXLDLogLevel        level,
711 	const char        * format,
712 	va_list             argList,
713 	void              * user_data)
714 {
715 	OSKext *theKext = (OSKext *) user_data;
716 	OSKextLogSpec logSpec = 0;
717 
718 	switch (subsystem) {
719 	case kKxldLogLinking:
720 		logSpec |= kOSKextLogLinkFlag;
721 		break;
722 	case kKxldLogPatching:
723 		logSpec |= kOSKextLogPatchFlag;
724 		break;
725 	}
726 
727 	switch (level) {
728 	case kKxldLogExplicit:
729 		logSpec |= kOSKextLogExplicitLevel;
730 		break;
731 	case kKxldLogErr:
732 		logSpec |= kOSKextLogErrorLevel;
733 		break;
734 	case kKxldLogWarn:
735 		logSpec |= kOSKextLogWarningLevel;
736 		break;
737 	case kKxldLogBasic:
738 		logSpec |= kOSKextLogProgressLevel;
739 		break;
740 	case kKxldLogDetail:
741 		logSpec |= kOSKextLogDetailLevel;
742 		break;
743 	case kKxldLogDebug:
744 		logSpec |= kOSKextLogDebugLevel;
745 		break;
746 	}
747 
748 	OSKextVLog(theKext, logSpec, format, argList);
749 }
750 #endif // CONFIG_KXLD
751 
752 #if PRAGMA_MARK
753 #pragma mark IOStatistics defines
754 #endif
755 
756 #if IOKITSTATS
757 
758 #define notifyKextLoadObservers(kext, kmod_info) \
759 do { \
760     IOStatistics::onKextLoad(kext, kmod_info); \
761 } while (0)
762 
763 #define notifyKextUnloadObservers(kext) \
764 do { \
765     IOStatistics::onKextUnload(kext); \
766 } while (0)
767 
768 #define notifyAddClassObservers(kext, addedClass, flags) \
769 do { \
770     IOStatistics::onClassAdded(kext, addedClass); \
771 } while (0)
772 
773 #define notifyRemoveClassObservers(kext, removedClass, flags) \
774 do { \
775     IOStatistics::onClassRemoved(kext, removedClass); \
776 } while (0)
777 
778 #else
779 
780 #define notifyKextLoadObservers(kext, kmod_info)
781 #define notifyKextUnloadObservers(kext)
782 #define notifyAddClassObservers(kext, addedClass, flags)
783 #define notifyRemoveClassObservers(kext, removedClass, flags)
784 
785 #endif /* IOKITSTATS */
786 
787 #if PRAGMA_MARK
788 #pragma mark Module Config (Startup & Shutdown)
789 #endif
790 /*********************************************************************
791 * Module Config (Class Definition & Class Methods)
792 *********************************************************************/
793 #define super OSObject
794 OSDefineMetaClassAndStructors(OSKext, OSObject)
795 
796 OSDefineMetaClassAndStructors(OSKextSavedMutableSegment, OSObject);
797 
798 OSDefineMetaClassAndStructors(OSDextStatistics, OSObject);
799 
800 /*********************************************************************
801 *********************************************************************/
802 /**
803  * Allocate and intialize a fake/representative OSKext object for a statically
804  * loaded (by iBoot) binary (e.g., the XNU kernel itself).
805  *
806  * @param kmod_info Pointer to the kmod_info structure for the binary being
807  *                  setup. At least the "name" and "id" fields needs to already
808  *                  be set correctly.
809  *
810  * @return The allocated and initialized OSKext object.
811  */
812 /* static */
813 OSKext *
allocAndInitFakeKext(kmod_info_t * kmod_info)814 OSKext::allocAndInitFakeKext(kmod_info_t *kmod_info)
815 {
816 	vm_offset_t load_address = 0;
817 	const char *bundle_name = NULL;
818 	bool macho_is_unslid = false;
819 	bool set_custom_path = false;
820 	const char *executable_fallback_name = NULL;
821 
822 	if (kmod_info->id == kOSKextKernelLoadTag) {
823 		load_address = (vm_offset_t)&_mh_execute_header;
824 		bundle_name = "mach_kernel";
825 
826 		/* The kernel Mach-O header is fixed up to slide all of its addresses. */
827 		macho_is_unslid = false;
828 
829 		/**
830 		 * No path to the binary is set for the kernel in its OSKext object. The
831 		 * kernel binary is located in fixed directories depending on the OS.
832 		 */
833 		set_custom_path = false;
834 		executable_fallback_name = NULL;
835 #if CONFIG_SPTM
836 	} else if (kmod_info->id == kOSKextSPTMLoadTag) {
837 		load_address = (vm_offset_t)SPTMArgs->debug_header->image[DEBUG_HEADER_ENTRY_SPTM];
838 		bundle_name = "sptm";
839 
840 		/* The addresses in the SPTM Mach-O header are all unslid. */
841 		macho_is_unslid = true;
842 
843 		set_custom_path = true;
844 		executable_fallback_name = "sptm.no.binname.in.macho";
845 	} else if (kmod_info->id == kOSKextTXMLoadTag) {
846 		load_address = (vm_offset_t)SPTMArgs->debug_header->image[DEBUG_HEADER_ENTRY_TXM];
847 		bundle_name = "txm";
848 
849 		/* The addresses in the TXM Mach-O header are all unslid. */
850 		macho_is_unslid = true;
851 
852 		set_custom_path = true;
853 		executable_fallback_name = "txm.no.binname.in.macho";
854 #endif /* CONFIG_SPTM */
855 	} else {
856 		panic("%s: Unsupported kmod_info->id (%d)", __func__, kmod_info->id);
857 	}
858 
859 	/* Set up an OSKext instance to represent the statically loaded binary. */
860 	OSKext *fakeKext = new OSKext;
861 	assert(fakeKext);
862 	assert(load_address != 0);
863 
864 	/*
865 	 * The start address is always a slid address whereas the last VA returned
866 	 * by getlastaddr() might be unslid depending on the Mach-O. If the address
867 	 * coming from the Mach-O is unslid, then unslide the start address before
868 	 * computing the length of the executable.
869 	 */
870 	size_t binaryLength = getlastaddr((kernel_mach_header_t*)load_address);
871 	binaryLength -= (macho_is_unslid) ? ml_static_unslide(load_address) : load_address;
872 	assert(binaryLength <= UINT_MAX);
873 
874 	/**
875 	 * The load address is always slid. That value will be unslid before being
876 	 * exposed to userspace.
877 	 */
878 	OSSharedPtr<OSData> executable = OSData::withBytesNoCopy(
879 		(void*)load_address, (unsigned int)binaryLength);
880 	assert(executable);
881 
882 	fakeKext->loadTag = sNextLoadTag++;
883 	fakeKext->bundleID = OSSymbol::withCString(kmod_info->name);
884 
885 	fakeKext->version = OSKextParseVersionString(osrelease);
886 	fakeKext->compatibleVersion = fakeKext->version;
887 	fakeKext->linkedExecutable = os::move(executable);
888 	fakeKext->interfaceUUID = fakeKext->copyUUID();
889 
890 	fakeKext->flags.hasAllDependencies = 1;
891 	fakeKext->flags.kernelComponent = 1;
892 	fakeKext->flags.prelinked = 0;
893 	fakeKext->flags.loaded = 1;
894 	fakeKext->flags.started = 1;
895 	fakeKext->flags.CPPInitialized = 0;
896 	fakeKext->flags.jettisonLinkeditSeg = 0;
897 	fakeKext->flags.unslidMachO = macho_is_unslid;
898 
899 #if CONFIG_SPTM
900 	if (set_custom_path) {
901 		/* Only SPTM/TXM should have custom paths to their executables set. */
902 		assert((kmod_info->id == kOSKextSPTMLoadTag) ||
903 		    (kmod_info->id == kOSKextTXMLoadTag));
904 
905 		/* All SPTM/TXM binaries are placed into the same path on internal systems. */
906 		fakeKext->path = OSString::withCStringNoCopy("/usr/appleinternal/standalone/platform");
907 
908 		/**
909 		 * Each SPTM/TXM Mach-O should contain a __TEXT,__binname section which contains
910 		 * a character array representing the name of the Mach-O executable.
911 		 */
912 		kernel_section_t *binname_sect =
913 		    getsectbynamefromheader((kernel_mach_header_t*)load_address, "__TEXT", "__binname");
914 
915 		if (binname_sect != NULL) {
916 			const char *binname = (const char *)ml_static_slide(binname_sect->addr);
917 			fakeKext->executableRelPath = OSString::withCStringNoCopy(binname);
918 		} else {
919 			fakeKext->executableRelPath = OSString::withCStringNoCopy(executable_fallback_name);
920 		}
921 	}
922 #endif /* CONFIG_SPTM */
923 
924 	fakeKext->kmod_info = kmod_info;
925 	strlcpy(kmod_info->version, osrelease,
926 	    sizeof(kmod_info->version));
927 	kmod_info->size = binaryLength;
928 	assert(kmod_info->id == fakeKext->loadTag);
929 
930 	/*
931 	 * Con up an info dict, so we don't have to have special-case checking all
932 	 * over.
933 	 */
934 	fakeKext->infoDict = OSDictionary::withCapacity(5);
935 	assert(fakeKext->infoDict);
936 	bool setResult = fakeKext->infoDict->setObject(kCFBundleIdentifierKey,
937 	    fakeKext->bundleID.get());
938 	assert(setResult);
939 	setResult = fakeKext->infoDict->setObject(kOSKernelResourceKey,
940 	    kOSBooleanTrue);
941 	assert(setResult);
942 
943 	{
944 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(osrelease));
945 		assert(scratchString);
946 		setResult = fakeKext->infoDict->setObject(kCFBundleVersionKey,
947 		    scratchString.get());
948 		assert(setResult);
949 	}
950 
951 	{
952 		OSSharedPtr<OSString> scratchString(OSString::withCStringNoCopy(bundle_name));
953 		assert(scratchString);
954 		setResult = fakeKext->infoDict->setObject(kCFBundleNameKey,
955 		    scratchString.get());
956 		assert(setResult);
957 	}
958 
959 	return fakeKext;
960 }
961 
962 /* static */
963 void
initialize(void)964 OSKext::initialize(void)
965 {
966 	OSSharedPtr<OSData>     kernelExecutable   = NULL;// do not release
967 	IORegistryEntry * registryRoot       = NULL;// do not release
968 	OSSharedPtr<OSNumber> kernelCPUType;
969 	OSSharedPtr<OSNumber> kernelCPUSubtype;
970 	OSKextLogSpec     bootLogFilter      = kOSKextLogSilentFilter;
971 	bool              setResult          = false;
972 	uint64_t        * timestamp          = NULL;
973 	__unused char     bootArgBuffer[16];// for PE_parse_boot_argn w/strings
974 
975 	/* This must be the first thing allocated. Everything else grabs this lock.
976 	 */
977 	sKextLock = IORecursiveLockAlloc();
978 	sKextInnerLock = IORecursiveLockAlloc();
979 	sKextSummariesLock = IOLockAlloc();
980 	sKextLoggingLock = IOLockAlloc();
981 	assert(sKextLock);
982 	assert(sKextInnerLock);
983 	assert(sKextSummariesLock);
984 	assert(sKextLoggingLock);
985 
986 	sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
987 	sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
988 	sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
989 	sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
990 	sKernelRequests = OSArray::withCapacity(0);
991 	sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
992 	sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
993 	sRequestCallbackRecords = OSArray::withCapacity(0);
994 	sDriverKitToUpgradeByID = OSDictionary::withCapacity(kOSKextTypicalUpgradeCount);
995 
996 	assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests &&
997 	    sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
998 	    sRequestCallbackRecords && sUnloadedPrelinkedKexts && sDriverKitToUpgradeByID);
999 
1000 	/* Read the log flag boot-args and set the log flags.
1001 	 */
1002 	if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
1003 		sBootArgLogFilterFound = true;
1004 		sKernelLogFilter = bootLogFilter;
1005 		// log this if any flags are set
1006 		OSKextLog(/* kext */ NULL,
1007 		    kOSKextLogBasicLevel |
1008 		    kOSKextLogFlagsMask,
1009 		    "Kernel kext log filter 0x%x per kextlog boot arg.",
1010 		    (unsigned)sKernelLogFilter);
1011 	}
1012 
1013 #if !defined(__arm__) && !defined(__arm64__)
1014 	/*
1015 	 * On our ARM targets, the kernelcache/boot kernel collection contains
1016 	 * the set of kexts required to boot, as specified by KCB.  Safeboot is
1017 	 * either unsupported, or is supported by the bootloader only loading
1018 	 * the boot kernel collection; as a result OSKext has no role to play
1019 	 * in safeboot policy on ARM.
1020 	 */
1021 	sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
1022 	    sizeof(bootArgBuffer)) ? true : false;
1023 #endif /* defined(__arm__) && defined(__arm64__) */
1024 
1025 	if (sSafeBoot) {
1026 		OSKextLog(/* kext */ NULL,
1027 		    kOSKextLogWarningLevel |
1028 		    kOSKextLogGeneralFlag,
1029 		    "SAFE BOOT DETECTED - "
1030 		    "only valid OSBundleRequired kexts will be loaded.");
1031 	}
1032 
1033 	PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
1034 #if CONFIG_DTRACE
1035 	if (dtrace_keep_kernel_symbols()) {
1036 		sKeepSymbols = true;
1037 	}
1038 #endif /* CONFIG_DTRACE */
1039 #if KASAN_DYNAMIC_DENYLIST
1040 	/* needed for function lookup */
1041 	sKeepSymbols = true;
1042 #endif /* KASAN_DYNAMIC_DENYLIST */
1043 
1044 	/*
1045 	 * Should we panic when the SystemKC is not linked against the
1046 	 * BootKC that was loaded by the booter? By default: yes, if the
1047 	 * "-nokcmismatchpanic" boot-arg is passed, then we _don't_ panic
1048 	 * on mis-match and instead just print an error and continue.
1049 	 */
1050 	sPanicOnKCMismatch = PE_parse_boot_argn("-nokcmismatchpanic", bootArgBuffer,
1051 	    sizeof(bootArgBuffer)) ? false : true;
1052 
1053 	/* Set up an OSKext instance to represent the kernel itself. */
1054 	sKernelKext = allocAndInitFakeKext(&g_kernel_kmod_info);
1055 	assert(sKernelKext);
1056 
1057 #if CONFIG_SPTM
1058 	/* Set up OSKext instances to represent the SPTM/TXM. */
1059 	OSKext *SPTMKext = allocAndInitFakeKext(&g_sptm_kmod_info);
1060 	OSKext *TXMKext = allocAndInitFakeKext(&g_txm_kmod_info);
1061 #endif
1062 
1063 	/* Add the kernel kext to the bookkeeping dictionaries. Note that
1064 	 * the kernel kext doesn't have a kmod_info struct. copyInfo()
1065 	 * gathers info from other places anyhow.
1066 	 */
1067 	setResult = sKextsByID->setObject(sKernelKext->bundleID.get(), sKernelKext);
1068 	assert(setResult);
1069 	setResult = sLoadedKexts->setObject(sKernelKext);
1070 	assert(setResult);
1071 
1072 #if CONFIG_SPTM
1073 	setResult = sKextsByID->setObject(SPTMKext->bundleID.get(), SPTMKext);
1074 	assert(setResult);
1075 	setResult = sLoadedKexts->setObject(SPTMKext);
1076 	assert(setResult);
1077 
1078 	setResult = sKextsByID->setObject(TXMKext->bundleID.get(), TXMKext);
1079 	assert(setResult);
1080 	setResult = sLoadedKexts->setObject(TXMKext);
1081 	assert(setResult);
1082 #endif /* CONFIG_SPTM */
1083 
1084 	// XXX: better way with OSSharedPtr?
1085 	// sKernelKext remains a valid pointer even after the decref
1086 	sKernelKext->release();
1087 #if CONFIG_SPTM
1088 	SPTMKext->release();
1089 	TXMKext->release();
1090 #endif /* CONFIG_SPTM */
1091 
1092 	registryRoot = IORegistryEntry::getRegistryRoot();
1093 	kernelCPUType = OSNumber::withNumber(
1094 		(long long unsigned int)_mh_execute_header.cputype,
1095 		8 * sizeof(_mh_execute_header.cputype));
1096 	kernelCPUSubtype = OSNumber::withNumber(
1097 		(long long unsigned int)_mh_execute_header.cpusubtype,
1098 		8 * sizeof(_mh_execute_header.cpusubtype));
1099 	assert(registryRoot && kernelCPUSubtype && kernelCPUType);
1100 
1101 	registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType.get());
1102 	registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype.get());
1103 
1104 	gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
1105 	if (gBuiltinKmodsSectionInfo) {
1106 		uint32_t count;
1107 
1108 		assert(gBuiltinKmodsSectionInfo->addr);
1109 		assert(gBuiltinKmodsSectionInfo->size);
1110 		assert(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *) <= UINT_MAX);
1111 		gBuiltinKmodsCount = (unsigned int)(gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
1112 
1113 		gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
1114 		assert(gBuiltinKmodsSectionStart);
1115 		assert(gBuiltinKmodsSectionStart->addr);
1116 		assert(gBuiltinKmodsSectionStart->size);
1117 		assert(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t) <= UINT_MAX);
1118 		count = (unsigned int)(gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
1119 		// one extra pointer for the end of last kmod
1120 		assert(count == (gBuiltinKmodsCount + 1));
1121 
1122 		vm_kernel_builtinkmod_text     = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
1123 		vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
1124 	}
1125 
1126 	// Don't track this object -- it's never released
1127 	gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface").detach();
1128 
1129 	timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
1130 	*timestamp = 0;
1131 	timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
1132 	*timestamp = 0;
1133 	timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
1134 	*timestamp = 0;
1135 
1136 	OSKextLog(/* kext */ NULL,
1137 	    kOSKextLogProgressLevel |
1138 	    kOSKextLogGeneralFlag,
1139 	    "Kext system initialized.");
1140 
1141 	notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
1142 #if CONFIG_SPTM
1143 	notifyKextLoadObservers(SPTMKext, SPTMKext->kmod_info);
1144 	notifyKextLoadObservers(TXMKext, TXMKext->kmod_info);
1145 #endif
1146 
1147 	return;
1148 }
1149 
1150 /*********************************************************************
1151 * This is expected to be called exactly once, from exactly one thread
1152 * context, during kernel bootstrap.
1153 *********************************************************************/
1154 /* static */
1155 OSReturn
removeKextBootstrap(void)1156 OSKext::removeKextBootstrap(void)
1157 {
1158 	OSReturn                   result                = kOSReturnError;
1159 
1160 	const char               * dt_kernel_header_name = "Kernel-__HEADER";
1161 	const char               * dt_kernel_symtab_name = "Kernel-__SYMTAB";
1162 	kernel_mach_header_t     * dt_mach_header        = NULL;
1163 	int                        dt_mach_header_size   = 0;
1164 	struct symtab_command    * dt_symtab             = NULL;
1165 	int                        dt_symtab_size        = 0;
1166 	int                        dt_result             = 0;
1167 
1168 	kernel_segment_command_t * seg_kld               = NULL;
1169 	kernel_segment_command_t * seg_klddata           = NULL;
1170 	kernel_segment_command_t * seg_linkedit          = NULL;
1171 
1172 	const char __unused      * dt_segment_name       = NULL;
1173 	void       __unused      * segment_paddress      = NULL;
1174 	int        __unused        segment_size          = 0;
1175 
1176 	OSKextLog(/* kext */ NULL,
1177 	    kOSKextLogProgressLevel |
1178 	    kOSKextLogGeneralFlag,
1179 	    "Jettisoning kext bootstrap segments.");
1180 
1181 	/*
1182 	 * keep the linkedit segment around when booted from a new MH_FILESET
1183 	 * KC because all the kexts shared a linkedit segment.
1184 	 */
1185 	kc_format_t kc_format;
1186 	if (!PE_get_primary_kc_format(&kc_format)) {
1187 		OSKextLog(/* kext */ NULL,
1188 		    kOSKextLogErrorLevel |
1189 		    kOSKextLogGeneralFlag,
1190 		    "Unable to determine primary KC format");
1191 	}
1192 
1193 	/*****
1194 	 * Dispose of unnecessary stuff that the booter didn't need to load.
1195 	 */
1196 	dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
1197 	    (void **)&dt_mach_header, &dt_mach_header_size);
1198 	if (dt_result == 0 && dt_mach_header) {
1199 		IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
1200 		    round_page_32(dt_mach_header_size));
1201 	}
1202 	dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
1203 	    (void **)&dt_symtab, &dt_symtab_size);
1204 	if (dt_result == 0 && dt_symtab) {
1205 		IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
1206 		    round_page_32(dt_symtab_size));
1207 	}
1208 
1209 	/*****
1210 	 * KLD & KLDDATA bootstrap segments.
1211 	 */
1212 	// xxx - should rename KLD segment
1213 	seg_kld = getsegbyname("__KLD");
1214 	seg_klddata = getsegbyname("__KLDDATA");
1215 	if (seg_klddata) {
1216 		// __mod_term_func is part of __KLDDATA
1217 		OSRuntimeUnloadCPPForSegment(seg_klddata);
1218 	}
1219 
1220 #if __arm__ || __arm64__
1221 	/* Free the memory that was set up by iBoot.
1222 	 */
1223 #if !defined(KERNEL_INTEGRITY_KTRR) && !defined(KERNEL_INTEGRITY_CTRR)
1224 	/* We cannot free the KLD segment with CTRR enabled as it contains text and
1225 	 * is covered by the contiguous rorgn.
1226 	 */
1227 	dt_segment_name = "Kernel-__KLD";
1228 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1229 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1230 		    (int)segment_size); // calls ml_static_mfree
1231 	} else if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1232 		/* With fileset KCs, the Kernel KLD segment is not recorded in the DT. */
1233 #if !CONFIG_SPTM
1234 		ml_static_mfree(ml_static_ptovirt(seg_kld->vmaddr - gVirtBase + gPhysBase),
1235 		    seg_kld->vmsize);
1236 #else
1237 		ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize);
1238 #endif
1239 	}
1240 #endif
1241 	dt_segment_name = "Kernel-__KLDDATA";
1242 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1243 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1244 		    (int)segment_size);  // calls ml_static_mfree
1245 	} else if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1246 		/* With fileset KCs, the Kernel KLDDATA segment is not recorded in the DT. */
1247 #if !CONFIG_SPTM
1248 		ml_static_mfree(ml_static_ptovirt(seg_klddata->vmaddr - gVirtBase + gPhysBase),
1249 		    seg_klddata->vmsize);
1250 #else
1251 		ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize);
1252 #endif
1253 	}
1254 #elif __i386__ || __x86_64__
1255 	/* On x86, use the mapping data from the segment load command to
1256 	 * unload KLD & KLDDATA directly.
1257 	 * This may invalidate any assumptions about  "avail_start"
1258 	 * defining the lower bound for valid physical addresses.
1259 	 */
1260 	if (seg_kld && seg_kld->vmaddr && seg_kld->vmsize) {
1261 		bzero((void *)seg_kld->vmaddr, seg_kld->vmsize);
1262 		ml_static_mfree(seg_kld->vmaddr, seg_kld->vmsize);
1263 	}
1264 	if (seg_klddata && seg_klddata->vmaddr && seg_klddata->vmsize) {
1265 		bzero((void *)seg_klddata->vmaddr, seg_klddata->vmsize);
1266 		ml_static_mfree(seg_klddata->vmaddr, seg_klddata->vmsize);
1267 	}
1268 #else
1269 #error arch
1270 #endif
1271 
1272 	/*****
1273 	 * Prelinked kernel's symtab (if there is one).
1274 	 */
1275 	if (kc_format != KCFormatFileset) {
1276 		kernel_section_t * sect;
1277 		sect = getsectbyname("__PRELINK", "__symtab");
1278 		if (sect && sect->addr && sect->size) {
1279 			ml_static_mfree(sect->addr, sect->size);
1280 		}
1281 	}
1282 
1283 	seg_linkedit = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
1284 
1285 	/* kxld always needs the kernel's __LINKEDIT segment, but we can make it
1286 	 * pageable, unless keepsyms is set.  To do that, we have to copy it from
1287 	 * its booter-allocated memory, free the booter memory, reallocate proper
1288 	 * managed memory, then copy the segment back in.
1289 	 *
1290 	 * NOTE: This optimization is not valid for fileset KCs because each
1291 	 * fileset entry (kext or xnu) in an MH_FILESET has a LINKEDIT segment
1292 	 * that points to one fileset-global LINKEDIT segment. This
1293 	 * optimization is also only valid for platforms that support vm
1294 	 * mapped kexts or mapped kext collections (pageable KCs)
1295 	 */
1296 #if VM_MAPPED_KEXTS
1297 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1298 		kern_return_t mem_result;
1299 		void *seg_copy = NULL;
1300 		void *seg_data = NULL;
1301 		vm_map_offset_t seg_offset = 0;
1302 		vm_map_offset_t seg_copy_offset = 0;
1303 		vm_map_size_t seg_length = 0;
1304 
1305 		seg_data = (void *) seg_linkedit->vmaddr;
1306 		seg_offset = (vm_map_offset_t) seg_linkedit->vmaddr;
1307 		seg_length = (vm_map_size_t) seg_linkedit->vmsize;
1308 
1309 		/* Allocate space for the LINKEDIT copy.
1310 		 */
1311 		mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
1312 		    seg_length, KMA_ZERO, VM_KERN_MEMORY_KEXT);
1313 		if (mem_result != KERN_SUCCESS) {
1314 			OSKextLog(/* kext */ NULL,
1315 			    kOSKextLogErrorLevel |
1316 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1317 			    "Can't copy __LINKEDIT segment for VM reassign.");
1318 			return result;
1319 		}
1320 		seg_copy_offset = (vm_map_offset_t) seg_copy;
1321 
1322 		/* Copy it out.
1323 		 */
1324 		memcpy(seg_copy, seg_data, seg_length);
1325 
1326 		/* Dump the booter memory.
1327 		 */
1328 		ml_static_mfree(seg_offset, seg_length);
1329 
1330 		/* Set up the VM region.
1331 		 */
1332 		mem_result = mach_vm_map_kernel(
1333 			kernel_map,
1334 			&seg_offset,
1335 			seg_length, /* mask */ 0,
1336 			VM_MAP_KERNEL_FLAGS_FIXED(.vmf_overwrite = true),
1337 			(ipc_port_t)NULL,
1338 			(vm_object_offset_t) 0,
1339 			/* copy */ FALSE,
1340 			/* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
1341 			/* max_protection */ VM_PROT_ALL,
1342 			/* inheritance */ VM_INHERIT_DEFAULT);
1343 		if ((mem_result != KERN_SUCCESS) ||
1344 		    (seg_offset != (vm_map_offset_t) seg_data)) {
1345 			OSKextLog(/* kext */ NULL,
1346 			    kOSKextLogErrorLevel |
1347 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1348 			    "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1349 			    seg_data, seg_length, mem_result);
1350 			return result;
1351 		}
1352 
1353 		/* And copy it back.
1354 		 */
1355 		memcpy(seg_data, seg_copy, seg_length);
1356 
1357 		/* Free the copy.
1358 		 */
1359 		kmem_free(kernel_map, seg_copy_offset, seg_length);
1360 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1361 		/* Remove the linkedit segment of the Boot KC */
1362 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1363 		OSKext::jettisonFileSetLinkeditSegment(mh);
1364 	}
1365 #else // !VM_MAPPED_KEXTS
1366 	/*****
1367 	 * Dump the LINKEDIT segment, unless keepsyms is set.
1368 	 */
1369 	if (!sKeepSymbols && kc_format != KCFormatFileset) {
1370 		dt_segment_name = "Kernel-__LINKEDIT";
1371 		if (0 == IODTGetLoaderInfo(dt_segment_name,
1372 		    &segment_paddress, &segment_size)) {
1373 #ifdef SECURE_KERNEL
1374 			vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
1375 			bzero((void*)vmaddr, segment_size);
1376 #endif
1377 			IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1378 			    (int)segment_size);
1379 		}
1380 	} else if (!sKeepSymbols && kc_format == KCFormatFileset) {
1381 		/* Remove the linkedit segment of the Boot KC */
1382 		kernel_mach_header_t *mh = (kernel_mach_header_t *)PE_get_kc_header(KCKindPrimary);
1383 		OSKext::jettisonFileSetLinkeditSegment(mh);
1384 	} else {
1385 		OSKextLog(/* kext */ NULL,
1386 		    kOSKextLogBasicLevel |
1387 		    kOSKextLogGeneralFlag,
1388 		    "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1389 	}
1390 #endif // VM_MAPPED_KEXTS
1391 
1392 	result = kOSReturnSuccess;
1393 
1394 	return result;
1395 }
1396 
1397 #if CONFIG_KXLD
1398 /*********************************************************************
1399 *********************************************************************/
1400 void
flushNonloadedKexts(Boolean flushPrelinkedKexts)1401 OSKext::flushNonloadedKexts(
1402 	Boolean flushPrelinkedKexts)
1403 {
1404 	OSSharedPtr<OSSet>                keepKexts;
1405 
1406 	/* TODO: make this more efficient with MH_FILESET kexts */
1407 
1408 	// Do not unload prelinked kexts on arm because the kernelcache is not
1409 	// structured in a way that allows them to be unmapped
1410 #if !defined(__x86_64__)
1411 	flushPrelinkedKexts = false;
1412 #endif /* defined(__x86_64__) */
1413 
1414 	IORecursiveLockLock(sKextLock);
1415 
1416 	OSKextLog(/* kext */ NULL,
1417 	    kOSKextLogProgressLevel |
1418 	    kOSKextLogKextBookkeepingFlag,
1419 	    "Flushing nonloaded kexts and other unused data.");
1420 
1421 	OSKext::considerDestroyingLinkContext();
1422 
1423 	/* If we aren't flushing unused prelinked kexts, we have to put them
1424 	 * aside while we flush everything else so make a container for them.
1425 	 */
1426 	keepKexts = OSSet::withCapacity(16);
1427 	if (!keepKexts) {
1428 		goto finish;
1429 	}
1430 
1431 	/* Set aside prelinked kexts (in-use or not) and break
1432 	 * any lingering inter-kext references for nonloaded kexts
1433 	 * so they have min. retain counts.
1434 	 */
1435 	{
1436 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1437 			OSKext * thisKext = OSDynamicCast(OSKext, obj);
1438 			if (!thisKext) {
1439 			        return false;
1440 			}
1441 			if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
1442 			        keepKexts->setObject(thisKext);
1443 			} else if (!thisKext->declaresExecutable()) {
1444 			        /*
1445 			         * Don't unload codeless kexts, because they never appear in the loadedKexts array.
1446 			         * Requesting one from the IOKit daemon will load it and then immediately remove it by calling
1447 			         * flushNonloadedKexts().
1448 			         * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
1449 			         */
1450 			        keepKexts->setObject(thisKext);
1451 			} else if (thisKext->isInFileset()) {
1452 			        /* keep all kexts in the new MH_FILESET KC */
1453 			        keepKexts->setObject(thisKext);
1454 			}
1455 
1456 			thisKext->flushDependencies(/* forceIfLoaded */ false);
1457 			return false;
1458 		});
1459 	}
1460 	/* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1461 	 */
1462 	sKextsByID->flushCollection();
1463 
1464 	/* Now put the loaded kexts back into the ID dictionary.
1465 	 */
1466 	sLoadedKexts->iterateObjects(^bool (OSObject * obj) {
1467 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1468 		if (!thisKext) {
1469 		        return false;
1470 		}
1471 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1472 		return false;
1473 	});
1474 
1475 	/* Finally, put back the kept kexts if we saved any.
1476 	 */
1477 	keepKexts->iterateObjects(^bool (OSObject * obj) {
1478 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1479 		if (!thisKext) {
1480 		        return false;
1481 		}
1482 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1483 		return false;
1484 	});
1485 
1486 finish:
1487 	IORecursiveLockUnlock(sKextLock);
1488 	return;
1489 }
1490 #else /* !CONFIG_KXLD */
1491 
1492 void
flushNonloadedKexts(Boolean flushPrelinkedKexts __unused)1493 OSKext::flushNonloadedKexts(
1494 	Boolean flushPrelinkedKexts __unused)
1495 {
1496 	IORecursiveLockLock(sKextLock);
1497 
1498 	OSKextLog(/* kext */ NULL,
1499 	    kOSKextLogProgressLevel |
1500 	    kOSKextLogKextBookkeepingFlag,
1501 	    "Flushing dependency info for non-loaded kexts.");
1502 
1503 	/*
1504 	 * In a world where we don't dynamically link kexts, they all come
1505 	 * from a kext collection that's either in wired memory, or
1506 	 * wire-on-demand. We don't need to mess around with moving kexts in
1507 	 * and out of the sKextsByID array - they can all just stay there.
1508 	 * Here we just flush the dependency list for kexts that are not
1509 	 * loaded.
1510 	 */
1511 	sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1512 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1513 		if (!thisKext) {
1514 		        return false;
1515 		}
1516 		thisKext->flushDependencies(/* forceIfLoaded */ false);
1517 		return false;
1518 	});
1519 
1520 	IORecursiveLockUnlock(sKextLock);
1521 	return;
1522 }
1523 
1524 #endif /* CONFIG_KXLD */
1525 
1526 /*********************************************************************
1527 *********************************************************************/
1528 /* static */
1529 void
setIOKitDaemonActive(bool active)1530 OSKext::setIOKitDaemonActive(bool active)
1531 {
1532 	IOServiceTrace(IOSERVICE_KEXTD_ALIVE, 0, 0, 0, 0);
1533 	IORecursiveLockLock(sKextLock);
1534 	sIOKitDaemonActive = active;
1535 	if (sKernelRequests->getCount()) {
1536 		OSKext::pingIOKitDaemon();
1537 	}
1538 	IORecursiveLockUnlock(sKextLock);
1539 
1540 	return;
1541 }
1542 
1543 /*********************************************************************
1544 * OSKextLib.cpp might need access to this someday but for now it's
1545 * private.
1546 *********************************************************************/
1547 extern "C" {
1548 extern void ipc_port_release_send(ipc_port_t);
1549 };
1550 
1551 /* static */
1552 OSReturn
pingIOKitDaemon(void)1553 OSKext::pingIOKitDaemon(void)
1554 {
1555 	OSReturn    result     = kOSReturnError;
1556 #if !NO_KEXTD
1557 	mach_port_t kextd_port = IPC_PORT_NULL;
1558 
1559 	if (!sIOKitDaemonActive) {
1560 		result = kOSKextReturnDisabled; // basically unavailable
1561 		goto finish;
1562 	}
1563 
1564 	result = host_get_kextd_port(host_priv_self(), &kextd_port);
1565 	if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1566 		OSKextLog(/* kext */ NULL,
1567 		    kOSKextLogErrorLevel |
1568 		    kOSKextLogIPCFlag,
1569 		    "Can't get " kIOKitDaemonName " port.");
1570 		goto finish;
1571 	}
1572 
1573 	result = kextd_ping(kextd_port);
1574 	if (result != KERN_SUCCESS) {
1575 		OSKextLog(/* kext */ NULL,
1576 		    kOSKextLogErrorLevel |
1577 		    kOSKextLogIPCFlag,
1578 		    kIOKitDaemonName " ping failed (0x%x).", (int)result);
1579 		goto finish;
1580 	}
1581 
1582 finish:
1583 	if (IPC_PORT_VALID(kextd_port)) {
1584 		ipc_port_release_send(kextd_port);
1585 	}
1586 #endif
1587 
1588 	return result;
1589 }
1590 
1591 /*********************************************************************
1592 *********************************************************************/
1593 /* static */
1594 bool
driverkitEnabled(void)1595 OSKext::driverkitEnabled(void)
1596 {
1597 #if XNU_TARGET_OS_WATCH
1598 	return false;
1599 #else //!XNU_TARGET_OS_WATCH
1600 	return true;
1601 #endif //XNU_TARGET_OS_WATCH
1602 }
1603 
1604 /*********************************************************************
1605 *********************************************************************/
1606 /* static */
1607 bool
iokitDaemonAvailable(void)1608 OSKext::iokitDaemonAvailable(void)
1609 {
1610 #if !XNU_TARGET_OS_IOS && !XNU_TARGET_OS_OSX
1611 	int notused;
1612 	if (PE_parse_boot_argn("-restore", &notused, sizeof(notused))) {
1613 		return false;
1614 	}
1615 #endif //!XNU_TARGET_OS_IOS && !XNU_TARGET_OS_OSX
1616 	return driverkitEnabled();
1617 }
1618 
1619 /*********************************************************************
1620 *********************************************************************/
1621 /* static */
1622 void
setDeferredLoadSucceeded(Boolean succeeded)1623 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1624 {
1625 	IORecursiveLockLock(sKextLock);
1626 	sDeferredLoadSucceeded = succeeded;
1627 	IORecursiveLockUnlock(sKextLock);
1628 
1629 	return;
1630 }
1631 
1632 /*********************************************************************
1633 * Called from IOSystemShutdownNotification.
1634 *********************************************************************/
1635 /* static */
1636 void
willShutdown(void)1637 OSKext::willShutdown(void)
1638 {
1639 #if !NO_KEXTD
1640 	OSReturn       checkResult = kOSReturnError;
1641 #endif
1642 	OSSharedPtr<OSDictionary> exitRequest;
1643 
1644 	IORecursiveLockLock(sKextLock);
1645 
1646 	OSKext::setLoadEnabled(false);
1647 	OSKext::setUnloadEnabled(false);
1648 	OSKext::setAutounloadsEnabled(false);
1649 	OSKext::setKernelRequestsEnabled(false);
1650 
1651 #if defined(__x86_64__) || defined(__i386__)
1652 	if (IOPMRootDomainGetWillShutdown()) {
1653 		OSKext::freeKCFileSetcontrol();
1654 	}
1655 #endif // (__x86_64__) || defined(__i386__)
1656 
1657 #if !NO_KEXTD
1658 	OSKextLog(/* kext */ NULL,
1659 	    kOSKextLogProgressLevel |
1660 	    kOSKextLogGeneralFlag,
1661 	    "System shutdown; requesting immediate " kIOKitDaemonName " exit.");
1662 
1663 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonExit,
1664 	    exitRequest);
1665 	if (checkResult != kOSReturnSuccess) {
1666 		goto finish;
1667 	}
1668 	if (!sKernelRequests->setObject(exitRequest.get())) {
1669 		goto finish;
1670 	}
1671 
1672 	OSKext::pingIOKitDaemon();
1673 
1674 finish:
1675 #endif
1676 
1677 	IORecursiveLockUnlock(sKextLock);
1678 	return;
1679 }
1680 
1681 void
willUserspaceReboot(void)1682 OSKext::willUserspaceReboot(void)
1683 {
1684 	OSKext::willShutdown();
1685 	IOService::userSpaceWillReboot();
1686 	gIOCatalogue->terminateDriversForUserspaceReboot();
1687 }
1688 
1689 void
resetAfterUserspaceReboot(void)1690 OSKext::resetAfterUserspaceReboot(void)
1691 {
1692 	OSSharedPtr<OSArray> arr = OSArray::withCapacity(1);
1693 	IOService::updateConsoleUsers(arr.get(), 0, true /* after_userspace_reboot */);
1694 
1695 	IORecursiveLockLock(sKextLock);
1696 	gIOCatalogue->resetAfterUserspaceReboot();
1697 	IOService::userSpaceDidReboot();
1698 	OSKext::removeDaemonExitRequests();
1699 	OSKext::setLoadEnabled(true);
1700 	OSKext::setUnloadEnabled(true);
1701 	OSKext::setAutounloadsEnabled(true);
1702 	OSKext::setKernelRequestsEnabled(true);
1703 	sOSKextWasResetAfterUserspaceReboot = true;
1704 	IORecursiveLockUnlock(sKextLock);
1705 }
1706 
1707 extern "C" void
OSKextResetAfterUserspaceReboot(void)1708 OSKextResetAfterUserspaceReboot(void)
1709 {
1710 	OSKext::resetAfterUserspaceReboot();
1711 }
1712 
1713 /*
1714  * Remove daemon exit requests from sKernelRequests
1715  *
1716  * If we sent a daemon exit request during a userspace reboot and launchd
1717  * killed the IOKit daemon before it was able to dequeue the exit request, the
1718  * next time the daemon starts up it will immediately exit as it gets the old exit request.
1719  *
1720  * This removes exit requests so that this does not happen.
1721  */
1722 void
removeDaemonExitRequests(void)1723 OSKext::removeDaemonExitRequests(void)
1724 {
1725 	OSDictionary * current = NULL;
1726 	OSString     * predicate = NULL;
1727 	size_t         index     = 0;
1728 	OSSharedPtr<const OSSymbol> predicateKey = OSSymbol::withCString(kKextRequestPredicateKey);
1729 
1730 	while (index < sKernelRequests->getCount()) {
1731 		current = OSDynamicCast(OSDictionary, sKernelRequests->getObject(index));
1732 		if (current) {
1733 			predicate = OSDynamicCast(OSString, current->getObject(predicateKey.get()));
1734 			if (predicate && predicate->isEqualTo(kKextRequestPredicateRequestDaemonExit)) {
1735 				sKernelRequests->removeObject(index);
1736 				continue;
1737 			}
1738 		}
1739 		index++;
1740 	}
1741 }
1742 
1743 /*********************************************************************
1744 *********************************************************************/
1745 /* static */
1746 bool
getLoadEnabled(void)1747 OSKext::getLoadEnabled(void)
1748 {
1749 	bool result;
1750 
1751 	IORecursiveLockLock(sKextLock);
1752 	result = sLoadEnabled;
1753 	IORecursiveLockUnlock(sKextLock);
1754 	return result;
1755 }
1756 
1757 /*********************************************************************
1758 *********************************************************************/
1759 /* static */
1760 bool
setLoadEnabled(bool flag)1761 OSKext::setLoadEnabled(bool flag)
1762 {
1763 	bool result;
1764 
1765 	IORecursiveLockLock(sKextLock);
1766 	result = sLoadEnabled;
1767 	sLoadEnabled = (flag ? true : false);
1768 
1769 	if (sLoadEnabled != result) {
1770 		OSKextLog(/* kext */ NULL,
1771 		    kOSKextLogBasicLevel |
1772 		    kOSKextLogLoadFlag,
1773 		    "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1774 	}
1775 
1776 	IORecursiveLockUnlock(sKextLock);
1777 
1778 	return result;
1779 }
1780 
1781 /*********************************************************************
1782 *********************************************************************/
1783 /* static */
1784 bool
getUnloadEnabled(void)1785 OSKext::getUnloadEnabled(void)
1786 {
1787 	bool result;
1788 
1789 	IORecursiveLockLock(sKextLock);
1790 	result = sUnloadEnabled;
1791 	IORecursiveLockUnlock(sKextLock);
1792 	return result;
1793 }
1794 
1795 /*********************************************************************
1796 *********************************************************************/
1797 /* static */
1798 bool
setUnloadEnabled(bool flag)1799 OSKext::setUnloadEnabled(bool flag)
1800 {
1801 	bool result;
1802 
1803 	IORecursiveLockLock(sKextLock);
1804 	result = sUnloadEnabled;
1805 	sUnloadEnabled = (flag ? true : false);
1806 	IORecursiveLockUnlock(sKextLock);
1807 
1808 	if (sUnloadEnabled != result) {
1809 		OSKextLog(/* kext */ NULL,
1810 		    kOSKextLogBasicLevel |
1811 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1812 		    "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1813 	}
1814 
1815 	return result;
1816 }
1817 
1818 /*********************************************************************
1819 * Do not call any function that takes sKextLock here!
1820 *********************************************************************/
1821 /* static */
1822 bool
getAutounloadEnabled(void)1823 OSKext::getAutounloadEnabled(void)
1824 {
1825 #if XNU_TARGET_OS_OSX
1826 	bool result;
1827 
1828 	IORecursiveLockLock(sKextInnerLock);
1829 	result = sAutounloadEnabled ? true : false;
1830 	IORecursiveLockUnlock(sKextInnerLock);
1831 	return result;
1832 #else
1833 	return false;
1834 #endif /* XNU_TARGET_OS_OSX */
1835 }
1836 
1837 /*********************************************************************
1838 * Do not call any function that takes sKextLock here!
1839 *********************************************************************/
1840 /* static */
1841 bool
setAutounloadsEnabled(bool flag)1842 OSKext::setAutounloadsEnabled(bool flag)
1843 {
1844 #if XNU_TARGET_OS_OSX
1845 	bool result;
1846 
1847 	IORecursiveLockLock(sKextInnerLock);
1848 
1849 	result = sAutounloadEnabled;
1850 	sAutounloadEnabled = (flag ? true : false);
1851 	if (!sAutounloadEnabled && sUnloadCallout) {
1852 		thread_call_cancel(sUnloadCallout);
1853 	}
1854 
1855 	if (sAutounloadEnabled != result) {
1856 		OSKextLog(/* kext */ NULL,
1857 		    kOSKextLogBasicLevel |
1858 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1859 		    "Kext autounloading now %sabled.",
1860 		    sAutounloadEnabled ? "en" : "dis");
1861 	}
1862 
1863 	IORecursiveLockUnlock(sKextInnerLock);
1864 
1865 	return result;
1866 #else
1867 	(void)flag;
1868 	return false;
1869 #endif /* XNU_TARGET_OS_OSX */
1870 }
1871 
1872 /*********************************************************************
1873 *********************************************************************/
1874 /* instance method operating on OSKext field */
1875 bool
setAutounloadEnabled(bool flag)1876 OSKext::setAutounloadEnabled(bool flag)
1877 {
1878 	bool result = flags.autounloadEnabled ? true : false;
1879 	flags.autounloadEnabled = flag ? (0 == flags.unloadUnsupported) : 0;
1880 
1881 	if (result != (flag ? true : false)) {
1882 		OSKextLog(this,
1883 		    kOSKextLogProgressLevel |
1884 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1885 		    "Autounloading for kext %s now %sabled.",
1886 		    getIdentifierCString(),
1887 		    flags.autounloadEnabled ? "en" : "dis");
1888 	}
1889 	return result;
1890 }
1891 
1892 /*********************************************************************
1893 *********************************************************************/
1894 /* static */
1895 bool
setKernelRequestsEnabled(bool flag)1896 OSKext::setKernelRequestsEnabled(bool flag)
1897 {
1898 	bool result;
1899 
1900 	IORecursiveLockLock(sKextLock);
1901 	result = sKernelRequestsEnabled;
1902 	sKernelRequestsEnabled = flag ? true : false;
1903 
1904 	if (sKernelRequestsEnabled != result) {
1905 		OSKextLog(/* kext */ NULL,
1906 		    kOSKextLogBasicLevel |
1907 		    kOSKextLogGeneralFlag,
1908 		    "Kernel requests now %sabled.",
1909 		    sKernelRequestsEnabled ? "en" : "dis");
1910 	}
1911 	IORecursiveLockUnlock(sKextLock);
1912 	return result;
1913 }
1914 
1915 /*********************************************************************
1916 *********************************************************************/
1917 /* static */
1918 bool
getKernelRequestsEnabled(void)1919 OSKext::getKernelRequestsEnabled(void)
1920 {
1921 	bool result;
1922 
1923 	IORecursiveLockLock(sKextLock);
1924 	result = sKernelRequestsEnabled;
1925 	IORecursiveLockUnlock(sKextLock);
1926 	return result;
1927 }
1928 
1929 static bool
segmentIsMutable(kernel_segment_command_t * seg)1930 segmentIsMutable(kernel_segment_command_t *seg)
1931 {
1932 	/* Mutable segments have to have VM_PROT_WRITE */
1933 	if ((seg->maxprot & VM_PROT_WRITE) == 0) {
1934 		return false;
1935 	}
1936 	/* Exclude the __DATA_CONST segment */
1937 	if (strncmp(seg->segname, "__DATA_CONST", sizeof(seg->segname)) == 0) {
1938 		return false;
1939 	}
1940 	/* Exclude __LINKEDIT */
1941 	if (strncmp(seg->segname, "__LINKEDIT", sizeof(seg->segname)) == 0) {
1942 		return false;
1943 	}
1944 	return true;
1945 }
1946 
1947 #if PRAGMA_MARK
1948 #pragma mark Kext Life Cycle
1949 #endif
1950 /*********************************************************************
1951 *********************************************************************/
1952 OSSharedPtr<OSKext>
withPrelinkedInfoDict(OSDictionary * anInfoDict,bool doCoalescedSlides,kc_kind_t type)1953 OSKext::withPrelinkedInfoDict(
1954 	OSDictionary * anInfoDict,
1955 	bool doCoalescedSlides,
1956 	kc_kind_t type)
1957 {
1958 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
1959 
1960 	if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalescedSlides, type)) {
1961 		return NULL;
1962 	}
1963 
1964 	return newKext;
1965 }
1966 
1967 OSData *
parseDextUniqueID(OSDictionary * anInfoDict,const char * dextIDCS)1968 OSKext::parseDextUniqueID(
1969 	OSDictionary * anInfoDict,
1970 	const char *dextIDCS)
1971 {
1972 	OSData *ret = NULL;
1973 	OSData *data_duid = OSDynamicCast(OSData, anInfoDict->getObject(kOSBundleDextUniqueIdentifierKey));
1974 	if (data_duid != NULL) {
1975 		if (data_duid->getLength() > KOSBundleDextUniqueIdentifierMaxLength) {
1976 			OSKextLog(NULL,
1977 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
1978 			    "Dext %s DextUniqueIdentifier too long.",
1979 			    dextIDCS);
1980 		} else {
1981 			/*
1982 			 * If the DextUniqueID exists it should be
1983 			 * present also into the personalities.
1984 			 */
1985 			setDextUniqueIDInPersonalities(anInfoDict, data_duid);
1986 			ret = data_duid;
1987 		}
1988 	} else {
1989 		OSKextLog(NULL,
1990 		    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
1991 		    "Dext %s does not have a DextUniqueIdentifier",
1992 		    dextIDCS);
1993 	}
1994 	return ret;
1995 }
1996 
1997 void
setDextUniqueIDInPersonalities(OSDictionary * anInfoDict,OSData * dextUniqueID)1998 OSKext::setDextUniqueIDInPersonalities(
1999 	OSDictionary * anInfoDict,
2000 	OSData * dextUniqueID)
2001 {
2002 	OSDictionary * dextPersonalities = NULL;
2003 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
2004 	OSString * personalityName = NULL;
2005 
2006 	dextPersonalities = OSDynamicCast(OSDictionary,
2007 	    anInfoDict->getObject(kIOKitPersonalitiesKey));
2008 	if (!dextPersonalities || !dextPersonalities->getCount()) {
2009 		return;
2010 	}
2011 
2012 	personalitiesIterator =
2013 	    OSCollectionIterator::withCollection(dextPersonalities);
2014 	if (!personalitiesIterator) {
2015 		return;
2016 	}
2017 	while ((personalityName = OSDynamicCast(OSString,
2018 	    personalitiesIterator->getNextObject()))) {
2019 		OSDictionary * personality = OSDynamicCast(OSDictionary,
2020 		    dextPersonalities->getObject(personalityName));
2021 		if (personality) {
2022 			OSObject *duid = personality->getObject(kOSBundleDextUniqueIdentifierKey);
2023 			if (duid == NULL) {
2024 				personality->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID);
2025 			}
2026 		}
2027 	}
2028 }
2029 /*********************************************************************
2030 *********************************************************************/
2031 bool
initWithPrelinkedInfoDict(OSDictionary * anInfoDict,bool doCoalescedSlides,kc_kind_t type)2032 OSKext::initWithPrelinkedInfoDict(
2033 	OSDictionary * anInfoDict,
2034 	bool doCoalescedSlides,
2035 	kc_kind_t type)
2036 {
2037 	bool            result              = false;
2038 	OSString      * kextPath            = NULL;                // do not release
2039 	OSNumber      * addressNum          = NULL;                // reused; do not release
2040 	OSNumber      * lengthNum           = NULL;                // reused; do not release
2041 	OSBoolean     * scratchBool         = NULL;                // do not release
2042 	void          * data                = NULL;                // do not free
2043 	void          * srcData             = NULL;                // do not free
2044 	OSSharedPtr<OSData>        prelinkedExecutable;
2045 	uint32_t        length              = 0;                // reused
2046 	uintptr_t       kext_slide          = PE_get_kc_slide(type);
2047 	bool            shouldSaveSegments  = false;
2048 	kc_format     format                = KCFormatUnknown;
2049 
2050 	if (!super::init()) {
2051 		goto finish;
2052 	}
2053 
2054 	/* Get the path. Don't look for an arch-specific path property.
2055 	 */
2056 	kextPath = OSDynamicCast(OSString,
2057 	    anInfoDict->getObject(kPrelinkBundlePathKey));
2058 
2059 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2060 		goto finish;
2061 	}
2062 
2063 #if KASLR_KEXT_DEBUG
2064 	IOLog("kaslr: doCoalescedSlides %d kext %s \n", doCoalescedSlides, getIdentifierCString());
2065 #endif
2066 
2067 	/* Also get the executable's bundle-relative path if present.
2068 	 * Don't look for an arch-specific path property.
2069 	 */
2070 	executableRelPath.reset(OSDynamicCast(OSString,
2071 	    anInfoDict->getObject(kPrelinkExecutableRelativePathKey)), OSRetain);
2072 	userExecutableRelPath.reset(OSDynamicCast(OSString,
2073 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
2074 
2075 	/* Don't need the paths to be in the info dictionary any more.
2076 	 */
2077 	anInfoDict->removeObject(kPrelinkBundlePathKey);
2078 	anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
2079 
2080 	scratchBool = OSDynamicCast(OSBoolean,
2081 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
2082 	if (scratchBool == kOSBooleanTrue) {
2083 		flags.requireExplicitLoad = 1;
2084 	}
2085 
2086 	/* Create an OSData wrapper around the linked executable.
2087 	 */
2088 	addressNum = OSDynamicCast(OSNumber,
2089 	    anInfoDict->getObject(kPrelinkExecutableLoadKey));
2090 	if (addressNum && addressNum->unsigned64BitValue() != kOSKextCodelessKextLoadAddr) {
2091 		lengthNum = OSDynamicCast(OSNumber,
2092 		    anInfoDict->getObject(kPrelinkExecutableSizeKey));
2093 		if (!lengthNum) {
2094 			OSKextLog(this,
2095 			    kOSKextLogErrorLevel |
2096 			    kOSKextLogArchiveFlag,
2097 			    "Kext %s can't find prelinked kext executable size.",
2098 			    getIdentifierCString());
2099 			return result;
2100 		}
2101 
2102 		data = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
2103 		length = (uint32_t) (lengthNum->unsigned32BitValue());
2104 
2105 #if KASLR_KEXT_DEBUG
2106 		IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
2107 		    (unsigned long)ml_static_unslide((vm_offset_t)data),
2108 		    (unsigned long)data,
2109 		    length);
2110 #endif
2111 
2112 		anInfoDict->removeObject(kPrelinkExecutableLoadKey);
2113 		anInfoDict->removeObject(kPrelinkExecutableSizeKey);
2114 
2115 		/* If the kext's load address differs from its source address, allocate
2116 		 * space in the kext map at the load address and copy the kext over.
2117 		 */
2118 		addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
2119 		if (addressNum) {
2120 			srcData = (void *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
2121 
2122 #if KASLR_KEXT_DEBUG
2123 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
2124 			    (unsigned long)ml_static_unslide((vm_offset_t)srcData),
2125 			    (unsigned long)srcData);
2126 #endif
2127 
2128 			if (data != srcData) {
2129 #if __LP64__
2130 				kern_return_t alloc_result;
2131 
2132 				alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
2133 				if (alloc_result != KERN_SUCCESS) {
2134 					OSKextLog(this,
2135 					    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2136 					    "Failed to allocate space for prelinked kext %s.",
2137 					    getIdentifierCString());
2138 					goto finish;
2139 				}
2140 				memcpy(data, srcData, length);
2141 #else
2142 				OSKextLog(this,
2143 				    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2144 				    "Error: prelinked kext %s - source and load addresses "
2145 				    "differ on ILP32 architecture.",
2146 				    getIdentifierCString());
2147 				goto finish;
2148 #endif /* __LP64__ */
2149 			}
2150 
2151 			anInfoDict->removeObject(kPrelinkExecutableSourceKey);
2152 		}
2153 
2154 		prelinkedExecutable = OSData::withBytesNoCopy(data, length);
2155 		if (!prelinkedExecutable) {
2156 			OSKextLog(this,
2157 			    kOSKextLogErrorLevel |
2158 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
2159 			    "Kext %s failed to create executable wrapper.",
2160 			    getIdentifierCString());
2161 			goto finish;
2162 		}
2163 
2164 		/*
2165 		 * Fileset KCs are mapped as a whole by iBoot.
2166 		 * Individual kext executables should not be unmapped
2167 		 * by xnu.
2168 		 * Doing so may result in panics like rdar://85419651
2169 		 */
2170 		if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
2171 			prelinkedExecutable->setDeallocFunction(NULL);
2172 		} else { // Not from a Fileset KC
2173 #if VM_MAPPED_KEXTS
2174 			prelinkedExecutable->setDeallocFunction(osdata_kext_free);
2175 #else
2176 			prelinkedExecutable->setDeallocFunction(osdata_phys_free);
2177 #endif
2178 		}
2179 		setLinkedExecutable(prelinkedExecutable.get());
2180 		addressNum = OSDynamicCast(OSNumber,
2181 		    anInfoDict->getObject(kPrelinkKmodInfoKey));
2182 		if (!addressNum) {
2183 			OSKextLog(this,
2184 			    kOSKextLogErrorLevel |
2185 			    kOSKextLogArchiveFlag,
2186 			    "Kext %s can't find prelinked kext kmod_info address.",
2187 			    getIdentifierCString());
2188 			goto finish;
2189 		}
2190 
2191 		if (addressNum->unsigned64BitValue() != 0) {
2192 			kmod_info = (kmod_info_t *) (((uintptr_t) (addressNum->unsigned64BitValue())) + kext_slide);
2193 			if (kmod_info->address) {
2194 				kmod_info->address = (((uintptr_t)(kmod_info->address)) + kext_slide);
2195 			} else {
2196 				kmod_info->address = (uintptr_t)data;
2197 				kmod_info->size = length;
2198 			}
2199 #if KASLR_KEXT_DEBUG
2200 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
2201 			    (unsigned long)((vm_offset_t)kmod_info) - kext_slide,
2202 			    (unsigned long)kmod_info);
2203 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
2204 			    (unsigned long)((vm_offset_t)kmod_info->address) - kext_slide,
2205 			    (unsigned long)kmod_info->address);
2206  #endif
2207 		}
2208 
2209 		anInfoDict->removeObject(kPrelinkKmodInfoKey);
2210 	}
2211 
2212 	if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) {
2213 		uintptr_t builtinTextStart;
2214 		uintptr_t builtinTextEnd;
2215 
2216 		flags.builtin = true;
2217 		builtinKmodIdx = addressNum->unsigned32BitValue();
2218 		assert(builtinKmodIdx < gBuiltinKmodsCount);
2219 
2220 		builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx];
2221 		builtinTextEnd   = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1];
2222 
2223 		kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx];
2224 		kmod_info->address = builtinTextStart;
2225 		kmod_info->size    = builtinTextEnd - builtinTextStart;
2226 	}
2227 
2228 	/* If the plist has a UUID for an interface, save that off.
2229 	 */
2230 	if (isInterface()) {
2231 		interfaceUUID.reset(OSDynamicCast(OSData,
2232 		    anInfoDict->getObject(kPrelinkInterfaceUUIDKey)), OSRetain);
2233 		if (interfaceUUID) {
2234 			anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
2235 		}
2236 	}
2237 
2238 	result = (kOSReturnSuccess == slidePrelinkedExecutable(doCoalescedSlides));
2239 	if (!result) {
2240 		goto finish;
2241 	}
2242 
2243 	kc_type = type;
2244 	/* Exclude builtin and codeless kexts */
2245 	if (prelinkedExecutable && kmod_info) {
2246 		switch (kc_type) {
2247 		case KCKindPrimary:
2248 			shouldSaveSegments = (
2249 				getPropertyForHostArch(kOSMutableSegmentCopy) == kOSBooleanTrue ||
2250 				getPropertyForHostArch(kOSBundleAllowUserLoadKey) == kOSBooleanTrue);
2251 			if (shouldSaveSegments) {
2252 				flags.resetSegmentsFromImmutableCopy = 1;
2253 			} else {
2254 				flags.unloadUnsupported = 1;
2255 			}
2256 			break;
2257 		case KCKindPageable:
2258 			flags.resetSegmentsFromVnode = 1;
2259 			break;
2260 		case KCKindAuxiliary:
2261 			if (!pageableKCloaded) {
2262 				flags.resetSegmentsFromImmutableCopy = 1;
2263 			} else if (resetAuxKCSegmentOnUnload) {
2264 				flags.resetSegmentsFromVnode = 1;
2265 			} else {
2266 				flags.unloadUnsupported = 1;
2267 			}
2268 			break;
2269 		default:
2270 			break;
2271 		}
2272 	}
2273 
2274 	if (flags.resetSegmentsFromImmutableCopy) {
2275 		/* Save a pristine copy of the mutable segments */
2276 		kernel_segment_command_t *seg = NULL;
2277 		kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
2278 
2279 		savedMutableSegments = OSArray::withCapacity(0);
2280 
2281 		for (seg = firstsegfromheader(k_mh); seg; seg = nextsegfromheader(k_mh, seg)) {
2282 			if (!segmentIsMutable(seg)) {
2283 				continue;
2284 			}
2285 			uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
2286 			uint64_t vmsize = seg->vmsize;
2287 			OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2288 			    "Saving kext %s mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2289 			OSSharedPtr<OSKextSavedMutableSegment> savedSegment = OSKextSavedMutableSegment::withSegment(seg);
2290 			if (!savedSegment) {
2291 				OSKextLog(this,
2292 				    kOSKextLogErrorLevel |
2293 				    kOSKextLogGeneralFlag,
2294 				    "Kext %s failed to save mutable segment %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
2295 				result = false;
2296 				goto finish;
2297 			}
2298 			savedMutableSegments->setObject(savedSegment);
2299 		}
2300 	}
2301 
2302 	if (doCoalescedSlides == false && !flags.resetSegmentsFromVnode) {
2303 		/*
2304 		 * set VM protections now, wire pages for the old style Aux KC now,
2305 		 * wire pages for the rest of the KC types at load time.
2306 		 */
2307 		result = (kOSReturnSuccess == setVMAttributes(true, (type == KCKindAuxiliary) ? true : false));
2308 		if (!result) {
2309 			goto finish;
2310 		}
2311 	}
2312 
2313 	flags.prelinked = true;
2314 
2315 	if (isDriverKit()) {
2316 		dextStatistics = OSDextStatistics::create();
2317 		dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
2318 		dextLaunchedCount = 0;
2319 	}
2320 
2321 	/* If we created a kext from prelink info,
2322 	 * we must be booting from a prelinked kernel.
2323 	 */
2324 	sPrelinkBoot = true;
2325 
2326 	result = (registerIdentifier() == kOSKextInitialized);
2327 finish:
2328 	return result;
2329 }
2330 
2331 /*********************************************************************
2332 *********************************************************************/
2333 /* static */
2334 OSSharedPtr<OSKext>
withCodelessInfo(OSDictionary * anInfoDict,OSKextInitResult * result)2335 OSKext::withCodelessInfo(OSDictionary * anInfoDict, OSKextInitResult *result)
2336 {
2337 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
2338 	if (!newKext) {
2339 		return NULL;
2340 	}
2341 
2342 	OSKextInitResult ret = newKext->initWithCodelessInfo(anInfoDict);
2343 	if (result != NULL) {
2344 		*result = ret;
2345 	}
2346 	if (ret != kOSKextInitialized) {
2347 		return NULL;
2348 	}
2349 
2350 	return newKext;
2351 }
2352 
2353 /*********************************************************************
2354 *********************************************************************/
2355 OSKextInitResult
initWithCodelessInfo(OSDictionary * anInfoDict)2356 OSKext::initWithCodelessInfo(OSDictionary * anInfoDict)
2357 {
2358 	OSKextInitResult result          = kOSKextInitFailure;
2359 	OSString  * kextPath             = NULL;        // do not release
2360 	OSBoolean * scratchBool          = NULL;        // do not release
2361 
2362 	if (anInfoDict == NULL || !super::init()) {
2363 		goto finish;
2364 	}
2365 
2366 	/*
2367 	 * Get the path. Don't look for an arch-specific path property.
2368 	 */
2369 	kextPath = OSDynamicCast(OSString,
2370 	    anInfoDict->getObject(kKextRequestArgumentCodelessInfoBundlePathKey));
2371 	if (!kextPath) {
2372 		OSKextLog(NULL,
2373 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2374 		    "Requested codeless kext dictionary does not contain the '%s' key",
2375 		    kKextRequestArgumentCodelessInfoBundlePathKey);
2376 		goto finish;
2377 	}
2378 
2379 	uniquePersonalityProperties(anInfoDict);
2380 
2381 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2382 		goto finish;
2383 	}
2384 
2385 	/*
2386 	 * This path is meant to initialize codeless kexts only. Refuse
2387 	 * anything that looks like it has an executable and/or declares
2388 	 * itself as a kernel component.
2389 	 */
2390 	if (declaresExecutable() || isKernelComponent()) {
2391 		OSKextLog(NULL,
2392 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
2393 		    "Refusing to register codeless kext that declares an executable/kernel component: %s",
2394 		    getIdentifierCString());
2395 		goto finish;
2396 	}
2397 
2398 	if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
2399 		boolean_t updated = updateExcludeList(infoDict.get());
2400 		if (updated) {
2401 			OSKextLog(this,
2402 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2403 			    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
2404 		}
2405 	}
2406 
2407 	kc_type = KCKindNone;
2408 
2409 	scratchBool = OSDynamicCast(OSBoolean,
2410 	    getPropertyForHostArch(kOSBundleRequireExplicitLoadKey));
2411 	if (scratchBool == kOSBooleanTrue) {
2412 		flags.requireExplicitLoad = 1;
2413 	}
2414 
2415 	/* Also get the executable's bundle-relative path if present.
2416 	 * Don't look for an arch-specific path property.
2417 	 */
2418 	userExecutableRelPath.reset(OSDynamicCast(OSString,
2419 	    anInfoDict->getObject(kCFBundleDriverKitExecutableKey)), OSRetain);
2420 
2421 	/* remove unnecessary paths from the info dict */
2422 	anInfoDict->removeObject(kKextRequestArgumentCodelessInfoBundlePathKey);
2423 
2424 	if (isDriverKit()) {
2425 		dextStatistics = OSDextStatistics::create();
2426 		dextUniqueID.reset(parseDextUniqueID(anInfoDict, getIdentifierCString()), OSRetain);
2427 		dextLaunchedCount = 0;
2428 	}
2429 
2430 	result = registerIdentifier();
2431 
2432 finish:
2433 	return result;
2434 }
2435 
2436 /*********************************************************************
2437 *********************************************************************/
2438 /* static */
2439 void
setAllVMAttributes(void)2440 OSKext::setAllVMAttributes(void)
2441 {
2442 	OSSharedPtr<OSCollectionIterator> kextIterator;
2443 	const OSSymbol * thisID                 = NULL;        // do not release
2444 
2445 	IORecursiveLockLock(sKextLock);
2446 
2447 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
2448 	if (!kextIterator) {
2449 		goto finish;
2450 	}
2451 
2452 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
2453 		OSKext *    thisKext;        // do not release
2454 
2455 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
2456 		if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
2457 			continue;
2458 		}
2459 
2460 		if (!thisKext->flags.resetSegmentsFromVnode) {
2461 			/*
2462 			 * set VM protections now, wire pages for the old style Aux KC now,
2463 			 * wire pages for the rest of the KC types at load time.
2464 			 */
2465 			thisKext->setVMAttributes(true, (thisKext->kc_type == KCKindAuxiliary) ? true : false);
2466 		}
2467 	}
2468 
2469 finish:
2470 	IORecursiveLockUnlock(sKextLock);
2471 
2472 	return;
2473 }
2474 
2475 /*********************************************************************
2476 *********************************************************************/
2477 OSSharedPtr<OSKext>
withBooterData(OSString * deviceTreeName,OSData * booterData)2478 OSKext::withBooterData(
2479 	OSString * deviceTreeName,
2480 	OSData   * booterData)
2481 {
2482 	OSSharedPtr<OSKext> newKext(OSMakeShared<OSKext>());
2483 
2484 	if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
2485 		return NULL;
2486 	}
2487 
2488 	return newKext;
2489 }
2490 
2491 /*********************************************************************
2492 *********************************************************************/
2493 typedef struct _BooterKextFileInfo {
2494 	uint32_t  infoDictPhysAddr;
2495 	uint32_t  infoDictLength;
2496 	uint32_t  executablePhysAddr;
2497 	uint32_t  executableLength;
2498 	uint32_t  bundlePathPhysAddr;
2499 	uint32_t  bundlePathLength;
2500 } _BooterKextFileInfo;
2501 
2502 bool
initWithBooterData(OSString * deviceTreeName,OSData * booterData)2503 OSKext::initWithBooterData(
2504 	OSString * deviceTreeName,
2505 	OSData   * booterData)
2506 {
2507 	bool                  result         = false;
2508 	_BooterKextFileInfo * kextFileInfo   = NULL;        // do not free
2509 	char                * infoDictAddr   = NULL;        // do not free
2510 	void                * executableAddr = NULL;        // do not free
2511 	char                * bundlePathAddr = NULL;        // do not free
2512 
2513 	OSDictionary        * theInfoDict    = NULL;        // do not release
2514 	OSSharedPtr<OSObject> parsedXML;
2515 	OSSharedPtr<OSString> kextPath;
2516 
2517 	OSSharedPtr<OSString> errorString;
2518 	OSSharedPtr<OSData>   executable;
2519 
2520 	if (!super::init()) {
2521 		goto finish;
2522 	}
2523 
2524 	kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
2525 	if (!kextFileInfo) {
2526 		OSKextLog(this,
2527 		    kOSKextLogErrorLevel |
2528 		    kOSKextLogGeneralFlag,
2529 		    "No booter-provided data for kext device tree entry %s.",
2530 		    deviceTreeName->getCStringNoCopy());
2531 		goto finish;
2532 	}
2533 
2534 	/* The info plist must exist or we can't read the kext.
2535 	 */
2536 	if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
2537 		OSKextLog(this,
2538 		    kOSKextLogErrorLevel |
2539 		    kOSKextLogGeneralFlag,
2540 		    "No kext info dictionary for booter device tree entry %s.",
2541 		    deviceTreeName->getCStringNoCopy());
2542 		goto finish;
2543 	}
2544 
2545 	infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
2546 	if (!infoDictAddr) {
2547 		OSKextLog(this,
2548 		    kOSKextLogErrorLevel |
2549 		    kOSKextLogGeneralFlag,
2550 		    "Can't translate physical address 0x%x of kext info dictionary "
2551 		    "for device tree entry %s.",
2552 		    (int)kextFileInfo->infoDictPhysAddr,
2553 		    deviceTreeName->getCStringNoCopy());
2554 		goto finish;
2555 	}
2556 
2557 	parsedXML = OSUnserializeXML(infoDictAddr, errorString);
2558 	if (parsedXML) {
2559 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
2560 	}
2561 	if (!theInfoDict) {
2562 		const char * errorCString = "(unknown error)";
2563 
2564 		if (errorString && errorString->getCStringNoCopy()) {
2565 			errorCString = errorString->getCStringNoCopy();
2566 		} else if (parsedXML) {
2567 			errorCString = "not a dictionary";
2568 		}
2569 		OSKextLog(this,
2570 		    kOSKextLogErrorLevel |
2571 		    kOSKextLogGeneralFlag,
2572 		    "Error unserializing info dictionary for device tree entry %s: %s.",
2573 		    deviceTreeName->getCStringNoCopy(), errorCString);
2574 		goto finish;
2575 	}
2576 
2577 	/* A bundle path is not mandatory.
2578 	 */
2579 	if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
2580 		bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
2581 		if (!bundlePathAddr) {
2582 			OSKextLog(this,
2583 			    kOSKextLogErrorLevel |
2584 			    kOSKextLogGeneralFlag,
2585 			    "Can't translate physical address 0x%x of kext bundle path "
2586 			    "for device tree entry %s.",
2587 			    (int)kextFileInfo->bundlePathPhysAddr,
2588 			    deviceTreeName->getCStringNoCopy());
2589 			goto finish;
2590 		}
2591 		bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0';         // just in case!
2592 
2593 		kextPath = OSString::withCString(bundlePathAddr);
2594 		if (!kextPath) {
2595 			OSKextLog(this,
2596 			    kOSKextLogErrorLevel |
2597 			    kOSKextLogGeneralFlag,
2598 			    "Failed to create wrapper for device tree entry %s kext path %s.",
2599 			    deviceTreeName->getCStringNoCopy(), bundlePathAddr);
2600 			goto finish;
2601 		}
2602 	}
2603 
2604 	if (!setInfoDictionaryAndPath(theInfoDict, kextPath.get())) {
2605 		goto finish;
2606 	}
2607 
2608 	/* An executable is not mandatory.
2609 	 */
2610 	if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
2611 		executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
2612 		if (!executableAddr) {
2613 			OSKextLog(this,
2614 			    kOSKextLogErrorLevel |
2615 			    kOSKextLogGeneralFlag,
2616 			    "Can't translate physical address 0x%x of kext executable "
2617 			    "for device tree entry %s.",
2618 			    (int)kextFileInfo->executablePhysAddr,
2619 			    deviceTreeName->getCStringNoCopy());
2620 			goto finish;
2621 		}
2622 
2623 		executable = OSData::withBytesNoCopy(executableAddr,
2624 		    kextFileInfo->executableLength);
2625 		if (!executable) {
2626 			OSKextLog(this,
2627 			    kOSKextLogErrorLevel |
2628 			    kOSKextLogGeneralFlag,
2629 			    "Failed to create executable wrapper for device tree entry %s.",
2630 			    deviceTreeName->getCStringNoCopy());
2631 			goto finish;
2632 		}
2633 
2634 		/* A kext with an executable needs to retain the whole booterData
2635 		 * object to keep the executable in memory.
2636 		 */
2637 		if (!setExecutable(executable.get(), booterData)) {
2638 			OSKextLog(this,
2639 			    kOSKextLogErrorLevel |
2640 			    kOSKextLogGeneralFlag,
2641 			    "Failed to set kext executable for device tree entry %s.",
2642 			    deviceTreeName->getCStringNoCopy());
2643 			goto finish;
2644 		}
2645 	}
2646 
2647 	if (isDriverKit()) {
2648 		dextStatistics = OSDextStatistics::create();
2649 		dextUniqueID.reset(parseDextUniqueID(theInfoDict, getIdentifierCString()), OSRetain);
2650 		dextLaunchedCount = 0;
2651 	}
2652 
2653 	result = (registerIdentifier() == kOSKextInitialized);
2654 
2655 finish:
2656 	return result;
2657 }
2658 
2659 /*********************************************************************
2660 *********************************************************************/
2661 OSKextInitResult
registerIdentifier(void)2662 OSKext::registerIdentifier(void)
2663 {
2664 	OSKextInitResult  result                  = kOSKextInitFailure;
2665 	OSKext        * existingKext              = NULL;        // do not release
2666 	bool            existingIsLoaded          = false;
2667 	bool            existingIsPrelinked       = false;
2668 	bool            existingIsCodeless        = false;
2669 	bool            existingIsDext            = false;
2670 	OSKextVersion   newVersion                = -1;
2671 	OSKextVersion   existingVersion           = -1;
2672 	char            newVersionCString[kOSKextVersionMaxLength];
2673 	char            existingVersionCString[kOSKextVersionMaxLength];
2674 	OSSharedPtr<OSData> newUUID;
2675 	OSSharedPtr<OSData> existingUUID;
2676 	const char *newDextUniqueIDCString = NULL;
2677 	const char *existingDextUniqueIDCString = NULL;
2678 	unsigned int newDextUniqueIDCStringSize = 0;
2679 	unsigned int existingDextUniqueIDCStringSize = 0;
2680 
2681 	IORecursiveLockLock(sKextLock);
2682 
2683 	/* Get the new kext's version for checks & log messages.
2684 	 */
2685 	newVersion = getVersion();
2686 	OSKextVersionGetString(newVersion, newVersionCString,
2687 	    kOSKextVersionMaxLength);
2688 
2689 	/* If we don't have an existing kext with this identifier,
2690 	 * just record the new kext and we're done!
2691 	 */
2692 	existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID.get()));
2693 	if (!existingKext) {
2694 		sKextsByID->setObject(bundleID.get(), this);
2695 		result = kOSKextInitialized;
2696 		goto finish;
2697 	}
2698 
2699 	/* Get the existing kext's version for checks & log messages.
2700 	 */
2701 	existingVersion = existingKext->getVersion();
2702 	OSKextVersionGetString(existingVersion,
2703 	    existingVersionCString, kOSKextVersionMaxLength);
2704 
2705 	existingIsLoaded = existingKext->isLoaded();
2706 	existingIsPrelinked = existingKext->isPrelinked();
2707 	existingIsDext = existingKext->isDriverKit();
2708 	existingIsCodeless = !existingKext->declaresExecutable() && !existingIsDext;
2709 
2710 	/*
2711 	 * Check if we are trying to upgrade a dext
2712 	 * with another dext.
2713 	 */
2714 	if (isDriverKit() && existingIsDext) {
2715 		OSData *newDextUID = getDextUniqueID();
2716 		if (!newDextUID) {
2717 			OSKextLog(this,
2718 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2719 			    "New dext %s, v%s requested does not have a unique dext identifier\n",
2720 			    getIdentifierCString(), newVersionCString);
2721 			goto finish;
2722 		}
2723 		newDextUniqueIDCString = getDextUniqueIDCString(newDextUID, &newDextUniqueIDCStringSize);
2724 		assert(newDextUniqueIDCString != NULL);
2725 
2726 		OSData *existingDextUID = existingKext->getDextUniqueID();
2727 		if (!existingDextUID) {
2728 			OSKextLog(this,
2729 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2730 			    "Found a dext %s, v%s: with no unique dext identifier\n",
2731 			    existingKext->getIdentifierCString(), existingVersionCString);
2732 			goto finish;
2733 		}
2734 		existingDextUniqueIDCString = getDextUniqueIDCString(existingDextUID, &existingDextUniqueIDCStringSize);
2735 		assert(existingDextUniqueIDCString != NULL);
2736 
2737 		/*
2738 		 * We might get multiple requests to save the same dext.
2739 		 * Check if we already have saved it or if this is an upgrade
2740 		 * for a dext with the same BundleID.
2741 		 * Dexts are uniquely identified by DextUniqueID, if a new DextUniqueID
2742 		 * is requested for a BundleID we are going to upgrade to the newest
2743 		 * received irrespective from the dext version.
2744 		 */
2745 		if (newDextUID->isEqualTo(existingDextUID) && existingKext->flags.dextToReplace == 0) {
2746 			OSKextLog(this,
2747 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2748 			    "Refusing new dext %s, v%s:"
2749 			    "a dext v %s with the same unique dext identifier (%s) already exists\n",
2750 			    getIdentifierCString(), newVersionCString,
2751 			    existingVersionCString, newDextUniqueIDCString);
2752 			result = kOSKextAlreadyExist;
2753 			goto finish;
2754 		}
2755 
2756 		bool upgraded = upgradeDext(existingKext, this);
2757 		if (upgraded) {
2758 			/* If the dext was upgraded existingKext might have been deallocated */
2759 			existingKext = NULL;
2760 			OSKextLog(this,
2761 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2762 			    "Dext %s, v%s , unique dext identifier %s "
2763 			    "Upgraded to v%s, unique dext identifier %s \n",
2764 			    getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
2765 			    newVersionCString, newDextUniqueIDCString);
2766 			result = kOSKextInitialized;
2767 		} else {
2768 			OSKextLog(this,
2769 			    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
2770 			    "Upgrade delayed for %s v%s, unique dext identifier %s "
2771 			    "with v%s, unique dext identifier %s.\n",
2772 			    getIdentifierCString(), existingVersionCString, existingDextUniqueIDCString,
2773 			    newVersionCString, newDextUniqueIDCString);
2774 			result = kOSKextAlreadyExist;
2775 		}
2776 
2777 		goto finish;
2778 	}
2779 
2780 	/* If we have a non-codeless kext with this identifier that's already
2781 	 * loaded/prelinked, we can't use the new one, but let's be really
2782 	 * thorough and check how the two are related for a precise diagnostic
2783 	 * log message.
2784 	 *
2785 	 * This check is valid for kexts that declare an executable and for
2786 	 * dexts, but not for codeless kexts - we can just replace those.
2787 	 */
2788 	if ((!existingIsCodeless || existingIsDext) &&
2789 	    (existingIsLoaded || existingIsPrelinked)) {
2790 		bool sameVersion = (newVersion == existingVersion);
2791 		bool sameExecutable = true;         // assume true unless we have UUIDs
2792 
2793 		/* Only get the UUID if the existing kext is loaded. Doing so
2794 		 * might have to uncompress an mkext executable and we shouldn't
2795 		 * take that hit when neither kext is loaded.
2796 		 *
2797 		 * Note: there is no decompression that happens when all kexts
2798 		 * are loaded from kext collecitons.
2799 		 */
2800 		newUUID = copyUUID();
2801 		existingUUID = existingKext->copyUUID();
2802 
2803 		if (existingIsDext && !isDriverKit()) {
2804 			OSKextLog(this,
2805 			    kOSKextLogWarningLevel |
2806 			    kOSKextLogKextBookkeepingFlag,
2807 			    "Notice - new kext %s, v%s matches a %s dext"
2808 			    "with the same bundle ID, v%s.",
2809 			    getIdentifierCString(), newVersionCString,
2810 			    (existingIsLoaded ? "loaded" : "prelinked"),
2811 			    existingVersionCString);
2812 			goto finish;
2813 		}
2814 
2815 		/* I'm entirely too paranoid about checking equivalence of executables,
2816 		 * but I remember nasty problems with it in the past.
2817 		 *
2818 		 * - If we have UUIDs for both kexts, compare them.
2819 		 * - If only one kext has a UUID, they're definitely different.
2820 		 */
2821 		if (newUUID && existingUUID) {
2822 			sameExecutable = newUUID->isEqualTo(existingUUID.get());
2823 		} else if (newUUID || existingUUID) {
2824 			sameExecutable = false;
2825 		}
2826 
2827 		if (!newUUID && !existingUUID) {
2828 			/* If there are no UUIDs, we can't really tell that the executables
2829 			 * are *different* without a lot of work; the loaded kext's
2830 			 * unrelocated executable is no longer around (and we never had it
2831 			 * in-kernel for a prelinked kext). We certainly don't want to do
2832 			 * a whole fake link for the new kext just to compare, either.
2833 			 */
2834 			OSKextLog(this,
2835 			    kOSKextLogWarningLevel |
2836 			    kOSKextLogKextBookkeepingFlag,
2837 			    "Notice - new kext %s, v%s matches %s kext "
2838 			    "but can't determine if executables are the same (no UUIDs).",
2839 			    getIdentifierCString(),
2840 			    newVersionCString,
2841 			    (existingIsLoaded ? "loaded" : "prelinked"));
2842 		}
2843 
2844 		if (sameVersion && sameExecutable) {
2845 			OSKextLog(this,
2846 			    (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
2847 			    kOSKextLogKextBookkeepingFlag,
2848 			    "Refusing new kext %s, v%s: a %s copy is already present "
2849 			    "(same version and executable).",
2850 			    getIdentifierCString(), newVersionCString,
2851 			    (existingIsLoaded ? "loaded" : "prelinked"));
2852 		} else {
2853 			if (!sameVersion) {
2854 				/* This condition is significant so log it under warnings.
2855 				 */
2856 				OSKextLog(this,
2857 				    kOSKextLogWarningLevel |
2858 				    kOSKextLogKextBookkeepingFlag,
2859 				    "Refusing new kext %s, v%s: already have %s v%s.",
2860 				    getIdentifierCString(),
2861 				    newVersionCString,
2862 				    (existingIsLoaded ? "loaded" : "prelinked"),
2863 				    existingVersionCString);
2864 			} else {
2865 				/* This condition is significant so log it under warnings.
2866 				 */
2867 				OSKextLog(this,
2868 				    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2869 				    "Refusing new kext %s, v%s: a %s copy with a different "
2870 				    "executable UUID is already present.",
2871 				    getIdentifierCString(), newVersionCString,
2872 				    (existingIsLoaded ? "loaded" : "prelinked"));
2873 			}
2874 		}
2875 		goto finish;
2876 	} /* if ((!existingIsCodeless || existingIsDext) && (existingIsLoaded || existingIsPrelinked)) */
2877 
2878 	/* Refuse to allow an existing loaded codeless kext be replaced by a
2879 	 * normal kext with the same bundle ID.
2880 	 */
2881 	if (existingIsCodeless && declaresExecutable()) {
2882 		OSKextLog(this,
2883 		    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2884 		    "Refusing new kext %s, v%s: a codeless copy is already %s",
2885 		    getIdentifierCString(), newVersionCString,
2886 		    (existingIsLoaded ? "loaded" : "prelinked"));
2887 		goto finish;
2888 	}
2889 
2890 	/* Dexts packaged in the BootKC will be protected against replacement
2891 	 * by non-dexts by the logic above which checks if they are prelinked.
2892 	 * Dexts which are prelinked into the System KC will be registered
2893 	 * before any other kexts in the AuxKC are registered, and we never
2894 	 * put dexts in the AuxKC. Therefore, there is no need to check if an
2895 	 * existing object is a dext and is being replaced by a non-dext.
2896 	 * The scenario cannot happen by construction.
2897 	 *
2898 	 * See: OSKext::loadFileSetKexts()
2899 	 */
2900 
2901 
2902 	/* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2903 	 * user loads are happening or if we're still in early boot. User agents are
2904 	 * supposed to resolve dependencies topside and include only the exact
2905 	 * kexts needed; so we always accept the new kext (in fact we should never
2906 	 * see an older unloaded copy hanging around).
2907 	 */
2908 	if (sUserLoadsActive) {
2909 		sKextsByID->setObject(bundleID.get(), this);
2910 		result = kOSKextInitialized;
2911 
2912 		OSKextLog(this,
2913 		    kOSKextLogStepLevel |
2914 		    kOSKextLogKextBookkeepingFlag,
2915 		    "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2916 		    getIdentifierCString(),
2917 		    existingVersionCString,
2918 		    newVersionCString);
2919 
2920 		goto finish;
2921 	}
2922 
2923 	/* During early boot, the kext with the highest version always wins out.
2924 	 * Prelinked kernels will never hit this, but mkexts and booter-read
2925 	 * kexts might have duplicates.
2926 	 */
2927 	if (newVersion > existingVersion) {
2928 		sKextsByID->setObject(bundleID.get(), this);
2929 		result = kOSKextInitialized;
2930 
2931 		OSKextLog(this,
2932 		    kOSKextLogStepLevel |
2933 		    kOSKextLogKextBookkeepingFlag,
2934 		    "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2935 		    existingVersionCString,
2936 		    getIdentifierCString(),
2937 		    newVersionCString);
2938 	} else {
2939 		OSKextLog(this,
2940 		    kOSKextLogStepLevel |
2941 		    kOSKextLogKextBookkeepingFlag,
2942 		    "Kext %s is already registered with a higher/same version (v%s); "
2943 		    "dropping newly-added (v%s).",
2944 		    getIdentifierCString(),
2945 		    existingVersionCString,
2946 		    newVersionCString);
2947 	}
2948 
2949 	/* result has been set appropriately by now. */
2950 
2951 finish:
2952 
2953 	IORecursiveLockUnlock(sKextLock);
2954 
2955 	if (newDextUniqueIDCString != NULL) {
2956 		kfree_data(newDextUniqueIDCString, newDextUniqueIDCStringSize);
2957 	}
2958 	if (existingDextUniqueIDCString != NULL) {
2959 		kfree_data(existingDextUniqueIDCString, existingDextUniqueIDCStringSize);
2960 	}
2961 
2962 	if (result == kOSKextInitialized) {
2963 		OSKextLog(this,
2964 		    kOSKextLogStepLevel |
2965 		    kOSKextLogKextBookkeepingFlag,
2966 		    "Kext %s, v%s registered and available for loading.",
2967 		    getIdentifierCString(), newVersionCString);
2968 	}
2969 
2970 	return result;
2971 }
2972 
2973 /*********************************************************************
2974  * Does the bare minimum validation to look up a kext.
2975  * All other validation is done on the spot as needed.
2976  **********************************************************************/
2977 bool
setInfoDictionaryAndPath(OSDictionary * aDictionary,OSString * aPath)2978 OSKext::setInfoDictionaryAndPath(
2979 	OSDictionary * aDictionary,
2980 	OSString     * aPath)
2981 {
2982 	bool           result                   = false;
2983 	OSString     * bundleIDString           = NULL;        // do not release
2984 	OSString     * versionString            = NULL;        // do not release
2985 	OSString     * compatibleVersionString  = NULL;        // do not release
2986 	const char   * versionCString           = NULL;        // do not free
2987 	const char   * compatibleVersionCString = NULL;        // do not free
2988 	OSBoolean    * scratchBool              = NULL;        // do not release
2989 	OSDictionary * scratchDict              = NULL;        // do not release
2990 
2991 	if (infoDict) {
2992 		panic("Attempt to set info dictionary on a kext "
2993 		    "that already has one (%s).",
2994 		    getIdentifierCString());
2995 	}
2996 
2997 	if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
2998 		goto finish;
2999 	}
3000 
3001 	infoDict.reset(aDictionary, OSRetain);
3002 
3003 	/* Check right away if the info dictionary has any log flags.
3004 	 */
3005 	scratchBool = OSDynamicCast(OSBoolean,
3006 	    getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
3007 	if (scratchBool == kOSBooleanTrue) {
3008 		flags.loggingEnabled = 1;
3009 	}
3010 
3011 	/* The very next thing to get is the bundle identifier. Unlike
3012 	 * in user space, a kext with no bundle identifier gets axed
3013 	 * immediately.
3014 	 */
3015 	bundleIDString = OSDynamicCast(OSString,
3016 	    getPropertyForHostArch(kCFBundleIdentifierKey));
3017 	if (!bundleIDString) {
3018 		OSKextLog(this,
3019 		    kOSKextLogErrorLevel |
3020 		    kOSKextLogValidationFlag,
3021 		    "CFBundleIdentifier missing/invalid type in kext %s.",
3022 		    aPath ? aPath->getCStringNoCopy() : "(unknown)");
3023 		goto finish;
3024 	}
3025 	bundleID = OSSymbol::withString(bundleIDString);
3026 	if (!bundleID) {
3027 		OSKextLog(this,
3028 		    kOSKextLogErrorLevel |
3029 		    kOSKextLogValidationFlag,
3030 		    "Can't copy bundle identifier as symbol for kext %s.",
3031 		    bundleIDString->getCStringNoCopy());
3032 		goto finish;
3033 	}
3034 
3035 	/* Save the path if we got one (it should always be available but it's
3036 	 * just something nice to have for bookkeeping).
3037 	 */
3038 	if (aPath) {
3039 		path.reset(aPath, OSRetain);
3040 	}
3041 
3042 	/*****
3043 	 * Minimal validation to initialize. We'll do other validation on the spot.
3044 	 */
3045 	if (bundleID->getLength() >= KMOD_MAX_NAME) {
3046 		OSKextLog(this,
3047 		    kOSKextLogErrorLevel |
3048 		    kOSKextLogValidationFlag,
3049 		    "Kext %s error - CFBundleIdentifier over max length %d.",
3050 		    getIdentifierCString(), KMOD_MAX_NAME - 1);
3051 		goto finish;
3052 	}
3053 
3054 	version = compatibleVersion = -1;
3055 
3056 	versionString = OSDynamicCast(OSString,
3057 	    getPropertyForHostArch(kCFBundleVersionKey));
3058 	if (!versionString) {
3059 		OSKextLog(this,
3060 		    kOSKextLogErrorLevel |
3061 		    kOSKextLogValidationFlag,
3062 		    "Kext %s error - CFBundleVersion missing/invalid type.",
3063 		    getIdentifierCString());
3064 		goto finish;
3065 	}
3066 	versionCString = versionString->getCStringNoCopy();
3067 	version = OSKextParseVersionString(versionCString);
3068 	if (version < 0) {
3069 		OSKextLog(this,
3070 		    kOSKextLogErrorLevel |
3071 		    kOSKextLogValidationFlag,
3072 		    "Kext %s error - CFBundleVersion bad value '%s'.",
3073 		    getIdentifierCString(), versionCString);
3074 		goto finish;
3075 	}
3076 
3077 	compatibleVersion = -1;         // set to illegal value for kexts that don't have
3078 
3079 	compatibleVersionString = OSDynamicCast(OSString,
3080 	    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
3081 	if (compatibleVersionString) {
3082 		compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
3083 		compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
3084 		if (compatibleVersion < 0) {
3085 			OSKextLog(this,
3086 			    kOSKextLogErrorLevel |
3087 			    kOSKextLogValidationFlag,
3088 			    "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
3089 			    getIdentifierCString(), compatibleVersionCString);
3090 			goto finish;
3091 		}
3092 
3093 		if (compatibleVersion > version) {
3094 			OSKextLog(this,
3095 			    kOSKextLogErrorLevel |
3096 			    kOSKextLogValidationFlag,
3097 			    "Kext %s error - %s %s > %s %s (must be <=).",
3098 			    getIdentifierCString(),
3099 			    kOSBundleCompatibleVersionKey, compatibleVersionCString,
3100 			    kCFBundleVersionKey, versionCString);
3101 			goto finish;
3102 		}
3103 	}
3104 
3105 	/* Check to see if this kext is in exclude list */
3106 	if (isInExcludeList()) {
3107 		OSKextLog(this,
3108 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3109 		    "Kext %s is in exclude list, not loadable",
3110 		    getIdentifierCString());
3111 		goto finish;
3112 	}
3113 
3114 	/* Set flags for later use if the infoDict gets flushed. We only
3115 	 * check for true values, not false ones(!)
3116 	 */
3117 	scratchBool = OSDynamicCast(OSBoolean,
3118 	    getPropertyForHostArch(kOSBundleIsInterfaceKey));
3119 	if (scratchBool == kOSBooleanTrue) {
3120 		flags.interface = 1;
3121 	}
3122 
3123 	scratchBool = OSDynamicCast(OSBoolean,
3124 	    getPropertyForHostArch(kOSKernelResourceKey));
3125 	if (scratchBool == kOSBooleanTrue) {
3126 		flags.kernelComponent = 1;
3127 		flags.interface = 1;         // xxx - hm. the kernel itself isn't an interface...
3128 		flags.started = 1;
3129 
3130 		/* A kernel component has one implicit dependency on the kernel.
3131 		 */
3132 		flags.hasAllDependencies = 1;
3133 	}
3134 
3135 	/* Make sure common string values in personalities are uniqued to OSSymbols.
3136 	 */
3137 	scratchDict = OSDynamicCast(OSDictionary,
3138 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
3139 	if (scratchDict) {
3140 		uniquePersonalityProperties(scratchDict);
3141 	}
3142 
3143 	result = true;
3144 
3145 finish:
3146 
3147 	return result;
3148 }
3149 
3150 /*********************************************************************
3151 * Not used for prelinked kernel boot as there is no unrelocated
3152 * executable.
3153 *********************************************************************/
3154 bool
setExecutable(OSData * anExecutable,OSData * externalData,bool externalDataIsMkext)3155 OSKext::setExecutable(
3156 	OSData * anExecutable,
3157 	OSData * externalData,
3158 	bool     externalDataIsMkext)
3159 {
3160 	bool         result        = false;
3161 	const char * executableKey = NULL;         // do not free
3162 
3163 	if (!anExecutable) {
3164 		infoDict->removeObject(_kOSKextExecutableKey);
3165 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
3166 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
3167 		result = true;
3168 		goto finish;
3169 	}
3170 
3171 	if (infoDict->getObject(_kOSKextExecutableKey) ||
3172 	    infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
3173 		panic("Attempt to set an executable on a kext "
3174 		    "that already has one (%s).",
3175 		    getIdentifierCString());
3176 		goto finish;
3177 	}
3178 
3179 	if (externalDataIsMkext) {
3180 		executableKey = _kOSKextMkextExecutableReferenceKey;
3181 	} else {
3182 		executableKey = _kOSKextExecutableKey;
3183 	}
3184 
3185 	if (anExecutable) {
3186 		infoDict->setObject(executableKey, anExecutable);
3187 		if (externalData) {
3188 			infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
3189 		}
3190 	}
3191 
3192 	result = true;
3193 
3194 finish:
3195 	return result;
3196 }
3197 
3198 /*********************************************************************
3199 *********************************************************************/
3200 static void
uniqueStringPlistProperty(OSDictionary * dict,const char * key)3201 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
3202 {
3203 	OSObject       * value       = NULL;        // do not release
3204 	OSString       * stringValue = NULL;        // do not release
3205 	OSSharedPtr<const OSSymbol> symbolValue;
3206 
3207 	value = dict->getObject(key);
3208 	if (!value) {
3209 		goto finish;
3210 	}
3211 	if (OSDynamicCast(OSSymbol, value)) {
3212 		/* this is already an OSSymbol: we're good */
3213 		goto finish;
3214 	}
3215 
3216 	stringValue = OSDynamicCast(OSString, value);
3217 	if (!stringValue) {
3218 		goto finish;
3219 	}
3220 
3221 	symbolValue = OSSymbol::withString(stringValue);
3222 	if (!symbolValue) {
3223 		goto finish;
3224 	}
3225 
3226 	dict->setObject(key, symbolValue.get());
3227 
3228 finish:
3229 	return;
3230 }
3231 
3232 /*********************************************************************
3233 *********************************************************************/
3234 static void
uniqueStringPlistProperty(OSDictionary * dict,const OSString * key)3235 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
3236 {
3237 	OSObject       * value       = NULL;        // do not release
3238 	OSString       * stringValue = NULL;        // do not release
3239 	OSSharedPtr<const OSSymbol> symbolValue;
3240 
3241 	value = dict->getObject(key);
3242 	if (!value) {
3243 		goto finish;
3244 	}
3245 	if (OSDynamicCast(OSSymbol, value)) {
3246 		/* this is already an OSSymbol: we're good */
3247 		goto finish;
3248 	}
3249 
3250 	stringValue = OSDynamicCast(OSString, value);
3251 	if (!stringValue) {
3252 		goto finish;
3253 	}
3254 
3255 	symbolValue = OSSymbol::withString(stringValue);
3256 	if (!symbolValue) {
3257 		goto finish;
3258 	}
3259 
3260 	dict->setObject(key, symbolValue.get());
3261 
3262 finish:
3263 	return;
3264 }
3265 
3266 void
uniquePersonalityProperties(OSDictionary * personalityDict)3267 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
3268 {
3269 	OSKext::uniquePersonalityProperties(personalityDict, true);
3270 }
3271 
3272 /*********************************************************************
3273 * Replace common personality property values with uniqued instances
3274 * to save on wired memory.
3275 *********************************************************************/
3276 /* static */
3277 void
uniquePersonalityProperties(OSDictionary * personalityDict,bool defaultAddKernelBundleIdentifier)3278 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict, bool defaultAddKernelBundleIdentifier)
3279 {
3280 	/* Properties every personality has.
3281 	 */
3282 	uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
3283 	uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
3284 	uniqueStringPlistProperty(personalityDict, gIOClassKey.get());
3285 	if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) {
3286 		uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey);
3287 	} else if (defaultAddKernelBundleIdentifier) {
3288 		personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey));
3289 	}
3290 
3291 	/* Other commonly used properties.
3292 	 */
3293 	uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
3294 	uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
3295 	uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
3296 
3297 	uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
3298 	uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
3299 	uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
3300 	uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
3301 	uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
3302 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
3303 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
3304 	uniqueStringPlistProperty(personalityDict, "Vendor");
3305 	uniqueStringPlistProperty(personalityDict, "Vendor Identification");
3306 	uniqueStringPlistProperty(personalityDict, "Vendor Name");
3307 	uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
3308 	uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
3309 	uniqueStringPlistProperty(personalityDict, "idProduct");
3310 
3311 	return;
3312 }
3313 
3314 /*********************************************************************
3315 *********************************************************************/
3316 void
free(void)3317 OSKext::free(void)
3318 {
3319 	if (isLoaded()) {
3320 		panic("Attempt to free loaded kext %s.", getIdentifierCString());
3321 	}
3322 
3323 	if (isDriverKit()) {
3324 		if (dextLaunchedCount > 0) {
3325 			panic("Freeing dext %s but dextLaunchedCount is %d\n", getIdentifierCString(), dextLaunchedCount);
3326 		}
3327 	}
3328 
3329 	infoDict.reset();
3330 	bundleID.reset();
3331 	path.reset();
3332 	executableRelPath.reset();
3333 	userExecutableRelPath.reset();
3334 	dependencies.reset();
3335 	linkedExecutable.reset();
3336 	metaClasses.reset();
3337 	interfaceUUID.reset();
3338 	driverKitUUID.reset();
3339 	dextStatistics.reset();
3340 	dextUniqueID.reset();
3341 
3342 	if (isInterface() && kmod_info) {
3343 		kfree_type(kmod_info_t, kmod_info);
3344 	}
3345 
3346 	super::free();
3347 	return;
3348 }
3349 
3350 #if PRAGMA_MARK
3351 #pragma mark Mkext files
3352 #endif
3353 
3354 #if CONFIG_KXLD
3355 /*
3356  * mkext archives are really only relevant on kxld-enabled kernels.
3357  * Without a dynamic kernel linker, we don't need to support any mkexts.
3358  */
3359 
3360 /*********************************************************************
3361 *********************************************************************/
3362 OSReturn
readMkextArchive(OSData * mkextData,uint32_t * checksumPtr)3363 OSKext::readMkextArchive(OSData * mkextData,
3364     uint32_t * checksumPtr)
3365 {
3366 	OSReturn       result       = kOSKextReturnBadData;
3367 	uint32_t       mkextLength  = 0;
3368 	mkext_header * mkextHeader  = NULL;        // do not free
3369 	uint32_t       mkextVersion = 0;
3370 
3371 	/* Note default return of kOSKextReturnBadData above.
3372 	 */
3373 	mkextLength = mkextData->getLength();
3374 	if (mkextLength < sizeof(mkext_basic_header)) {
3375 		OSKextLog(/* kext */ NULL,
3376 		    kOSKextLogErrorLevel |
3377 		    kOSKextLogArchiveFlag,
3378 		    "Mkext archive too small to be valid.");
3379 		goto finish;
3380 	}
3381 
3382 	mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
3383 
3384 	if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
3385 	    MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
3386 		OSKextLog(/* kext */ NULL,
3387 		    kOSKextLogErrorLevel |
3388 		    kOSKextLogArchiveFlag,
3389 		    "Mkext archive has invalid magic or signature.");
3390 		goto finish;
3391 	}
3392 
3393 	if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
3394 		OSKextLog(/* kext */ NULL,
3395 		    kOSKextLogErrorLevel |
3396 		    kOSKextLogArchiveFlag,
3397 		    "Mkext archive recorded length doesn't match actual file length.");
3398 		goto finish;
3399 	}
3400 
3401 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3402 
3403 	if (mkextVersion == MKEXT_VERS_2) {
3404 		result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
3405 	} else {
3406 		OSKextLog(/* kext */ NULL,
3407 		    kOSKextLogErrorLevel |
3408 		    kOSKextLogArchiveFlag,
3409 		    "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
3410 		result = kOSKextReturnUnsupported;
3411 	}
3412 
3413 finish:
3414 	return result;
3415 }
3416 
3417 /*********************************************************************
3418 * Assumes magic, signature, version, length have been checked.
3419 * xxx - need to add further bounds checking for each file entry
3420 *
3421 * Should keep track of all kexts created so far, and if we hit a
3422 * fatal error halfway through, remove those kexts. If we've dropped
3423 * an older version that had already been read, whoops! Might want to
3424 * add a level of buffering?
3425 *********************************************************************/
3426 /* static */
3427 OSReturn
readMkext2Archive(OSData * mkextData,OSDictionary ** mkextPlistOut,uint32_t * checksumPtr)3428 OSKext::readMkext2Archive(
3429 	OSData        * mkextData,
3430 	OSDictionary ** mkextPlistOut,
3431 	uint32_t      * checksumPtr)
3432 {
3433 	OSReturn        result                     = kOSReturnError;
3434 	uint32_t        mkextLength;
3435 	mkext2_header * mkextHeader                = NULL;        // do not free
3436 	void          * mkextEnd                   = NULL;        // do not free
3437 	uint32_t        mkextVersion;
3438 	uint8_t       * crc_address                = NULL;
3439 	size_t          crc_buffer_size            = 0;
3440 	uint32_t        checksum;
3441 	uint32_t        mkextPlistOffset;
3442 	uint32_t        mkextPlistCompressedSize;
3443 	char          * mkextPlistEnd              = NULL;        // do not free
3444 	uint32_t        mkextPlistFullSize;
3445 	OSSharedPtr<OSString>     errorString;
3446 	OSSharedPtr<OSData>       mkextPlistUncompressedData;
3447 	const char    * mkextPlistDataBuffer       = NULL;        // do not free
3448 	OSSharedPtr<OSObject>      parsedXML;
3449 	OSDictionary  * mkextPlist                 = NULL;        // do not release
3450 	OSArray       * mkextInfoDictArray         = NULL;        // do not release
3451 	uint32_t        count, i;
3452 	kc_format_t kc_format;
3453 
3454 	if (!PE_get_primary_kc_format(&kc_format)) {
3455 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3456 		    "Unable to determine primary KC format");
3457 		goto finish;
3458 	}
3459 
3460 	mkextLength = mkextData->getLength();
3461 	mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
3462 	mkextEnd = (char *)mkextHeader + mkextLength;
3463 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
3464 
3465 	crc_address = (u_int8_t *)&mkextHeader->version;
3466 	crc_buffer_size = (uintptr_t)mkextHeader +
3467 	    MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address;
3468 	if (crc_buffer_size > INT32_MAX) {
3469 		OSKextLog(/* kext */ NULL,
3470 		    kOSKextLogErrorLevel |
3471 		    kOSKextLogArchiveFlag,
3472 		    "Mkext archive size is too large (%lu > INT32_MAX).",
3473 		    crc_buffer_size);
3474 		result = kOSKextReturnBadData;
3475 		goto finish;
3476 	}
3477 	checksum = mkext_adler32(crc_address, (int32_t)crc_buffer_size);
3478 
3479 	if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
3480 		OSKextLog(/* kext */ NULL,
3481 		    kOSKextLogErrorLevel |
3482 		    kOSKextLogArchiveFlag,
3483 		    "Mkext archive has bad checksum.");
3484 		result = kOSKextReturnBadData;
3485 		goto finish;
3486 	}
3487 
3488 	if (checksumPtr) {
3489 		*checksumPtr = checksum;
3490 	}
3491 
3492 	/* Check that the CPU type & subtype match that of the running kernel. */
3493 	if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
3494 		OSKextLog(/* kext */ NULL,
3495 		    kOSKextLogErrorLevel |
3496 		    kOSKextLogArchiveFlag,
3497 		    "Mkext archive must have a specific CPU type.");
3498 		result = kOSKextReturnBadData;
3499 		goto finish;
3500 	} else {
3501 		if ((UInt32)_mh_execute_header.cputype !=
3502 		    MKEXT_GET_CPUTYPE(mkextHeader)) {
3503 			OSKextLog(/* kext */ NULL,
3504 			    kOSKextLogErrorLevel |
3505 			    kOSKextLogArchiveFlag,
3506 			    "Mkext archive does not match the running kernel's CPU type.");
3507 			result = kOSKextReturnArchNotFound;
3508 			goto finish;
3509 		}
3510 	}
3511 
3512 	mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
3513 	mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
3514 	mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
3515 	    mkextPlistCompressedSize;
3516 	if (mkextPlistEnd > mkextEnd) {
3517 		OSKextLog(/* kext */ NULL,
3518 		    kOSKextLogErrorLevel |
3519 		    kOSKextLogArchiveFlag,
3520 		    "Mkext archive file overrun.");
3521 		result = kOSKextReturnBadData;
3522 	}
3523 
3524 	mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
3525 	if (mkextPlistCompressedSize) {
3526 		mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
3527 			(UInt8 *)mkextHeader + mkextPlistOffset,
3528 			"plist",
3529 			mkextPlistCompressedSize, mkextPlistFullSize);
3530 		if (!mkextPlistUncompressedData) {
3531 			goto finish;
3532 		}
3533 		mkextPlistDataBuffer = (const char *)
3534 		    mkextPlistUncompressedData->getBytesNoCopy();
3535 	} else {
3536 		mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
3537 	}
3538 
3539 	/* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
3540 	 */
3541 	parsedXML = OSUnserializeXML(mkextPlistDataBuffer, errorString);
3542 	if (parsedXML) {
3543 		mkextPlist = OSDynamicCast(OSDictionary, parsedXML.get());
3544 	}
3545 	if (!mkextPlist) {
3546 		const char * errorCString = "(unknown error)";
3547 
3548 		if (errorString && errorString->getCStringNoCopy()) {
3549 			errorCString = errorString->getCStringNoCopy();
3550 		} else if (parsedXML) {
3551 			errorCString = "not a dictionary";
3552 		}
3553 		OSKextLog(/* kext */ NULL,
3554 		    kOSKextLogErrorLevel |
3555 		    kOSKextLogArchiveFlag,
3556 		    "Error unserializing mkext plist: %s.", errorCString);
3557 		goto finish;
3558 	}
3559 
3560 	mkextInfoDictArray = OSDynamicCast(OSArray,
3561 	    mkextPlist->getObject(kMKEXTInfoDictionariesKey));
3562 	if (!mkextInfoDictArray) {
3563 		OSKextLog(/* kext */ NULL,
3564 		    kOSKextLogErrorLevel |
3565 		    kOSKextLogArchiveFlag,
3566 		    "Mkext archive contains no kext info dictionaries.");
3567 		goto finish;
3568 	}
3569 
3570 	count = mkextInfoDictArray->getCount();
3571 	for (i = 0; i < count; i++) {
3572 		OSDictionary * infoDict;
3573 
3574 
3575 		infoDict = OSDynamicCast(OSDictionary,
3576 		    mkextInfoDictArray->getObject(i));
3577 
3578 		/* Create the kext for the entry, then release it, because the
3579 		 * kext system keeps them around until explicitly removed.
3580 		 * Any creation/registration failures are already logged for us.
3581 		 */
3582 		if (infoDict) {
3583 			OSSharedPtr<OSKext> newKext = OSKext::withMkext2Info(infoDict, mkextData);
3584 
3585 			/* Fail dynamic loading of a kext when booted from MH_FILESET */
3586 			if (kc_format == KCFormatFileset &&
3587 			    newKext &&
3588 			    !(newKext->isPrelinked()) &&
3589 			    newKext->declaresExecutable()) {
3590 				result = kOSReturnError;
3591 				printf("Kext LOG: Dynamic loading of kext denied for kext %s\n",
3592 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3593 
3594 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
3595 				    "Dynamic loading of kext denied for kext %s\n",
3596 				    newKext->getIdentifier() ? newKext->getIdentifierCString() : "unknown kext");
3597 				goto finish;
3598 			}
3599 		}
3600 	}
3601 
3602 	/* If the caller needs the plist, hand them back our copy
3603 	 */
3604 	if (mkextPlistOut) {
3605 		*mkextPlistOut = mkextPlist;
3606 		parsedXML.detach();
3607 	}
3608 
3609 	/* Even if we didn't keep any kexts from the mkext, we may have a load
3610 	 * request to process, so we are successful (no errors occurred).
3611 	 */
3612 	result = kOSReturnSuccess;
3613 
3614 finish:
3615 	return result;
3616 }
3617 
3618 /* static */
3619 OSReturn
readMkext2Archive(OSData * mkextData,OSSharedPtr<OSDictionary> & mkextPlistOut,uint32_t * checksumPtr)3620 OSKext::readMkext2Archive(
3621 	OSData        * mkextData,
3622 	OSSharedPtr<OSDictionary> &mkextPlistOut,
3623 	uint32_t      * checksumPtr)
3624 {
3625 	OSDictionary * mkextPlist = NULL;
3626 	OSReturn ret;
3627 
3628 	if (kOSReturnSuccess == (ret = readMkext2Archive(mkextData,
3629 	    &mkextPlist,
3630 	    checksumPtr))) {
3631 		mkextPlistOut.reset(mkextPlist, OSNoRetain);
3632 	}
3633 	return ret;
3634 }
3635 
3636 /*********************************************************************
3637 *********************************************************************/
3638 /* static */
3639 OSSharedPtr<OSKext>
withMkext2Info(OSDictionary * anInfoDict,OSData * mkextData)3640 OSKext::withMkext2Info(
3641 	OSDictionary * anInfoDict,
3642 	OSData       * mkextData)
3643 {
3644 	OSSharedPtr<OSKext> newKext = OSMakeShared<OSKext>();
3645 
3646 	if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
3647 		return NULL;
3648 	}
3649 
3650 	return newKext;
3651 }
3652 
3653 /*********************************************************************
3654 *********************************************************************/
3655 bool
initWithMkext2Info(OSDictionary * anInfoDict,OSData * mkextData)3656 OSKext::initWithMkext2Info(
3657 	OSDictionary * anInfoDict,
3658 	OSData       * mkextData)
3659 {
3660 	bool                   result              = false;
3661 	OSString             * kextPath            = NULL;        // do not release
3662 	OSNumber             * executableOffsetNum = NULL;        // do not release
3663 	OSSharedPtr<OSData>               executable;
3664 
3665 	if (anInfoDict == NULL || !super::init()) {
3666 		goto finish;
3667 	}
3668 
3669 	/* Get the path. Don't look for an arch-specific path property.
3670 	 */
3671 	kextPath = OSDynamicCast(OSString,
3672 	    anInfoDict->getObject(kMKEXTBundlePathKey));
3673 
3674 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
3675 		goto finish;
3676 	}
3677 
3678 	/* If we have a path to the executable, save it.
3679 	 */
3680 	executableRelPath.reset(OSDynamicCast(OSString,
3681 	    anInfoDict->getObject(kMKEXTExecutableRelativePathKey)), OSRetain);
3682 
3683 	/* Don't need the paths to be in the info dictionary any more.
3684 	 */
3685 	anInfoDict->removeObject(kMKEXTBundlePathKey);
3686 	anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
3687 
3688 	executableOffsetNum = OSDynamicCast(OSNumber,
3689 	    infoDict->getObject(kMKEXTExecutableKey));
3690 	if (executableOffsetNum) {
3691 		executable = createMkext2FileEntry(mkextData,
3692 		    executableOffsetNum, "executable");
3693 		infoDict->removeObject(kMKEXTExecutableKey);
3694 		if (!executable) {
3695 			goto finish;
3696 		}
3697 		if (!setExecutable(executable.get(), mkextData, true)) {
3698 			goto finish;
3699 		}
3700 	}
3701 
3702 	result = (registerIdentifier() == kOSKextInitialized);
3703 finish:
3704 	return result;
3705 }
3706 
3707 /*********************************************************************
3708 *********************************************************************/
3709 OSSharedPtr<OSData>
createMkext2FileEntry(OSData * mkextData,OSNumber * offsetNum,const char * name)3710 OSKext::createMkext2FileEntry(
3711 	OSData     * mkextData,
3712 	OSNumber   * offsetNum,
3713 	const char * name)
3714 {
3715 	OSSharedPtr<OSData> result;
3716 	MkextEntryRef   entryRef;
3717 	uint8_t       * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
3718 	uint32_t        entryOffset = offsetNum->unsigned32BitValue();
3719 
3720 	result = OSData::withCapacity(sizeof(entryRef));
3721 	if (!result) {
3722 		goto finish;
3723 	}
3724 
3725 	entryRef.mkext = (mkext_basic_header *)mkextBuffer;
3726 	entryRef.fileinfo = mkextBuffer + entryOffset;
3727 	if (!result->appendValue(entryRef)) {
3728 		result.reset();
3729 		goto finish;
3730 	}
3731 
3732 finish:
3733 	if (!result) {
3734 		OSKextLog(this,
3735 		    kOSKextLogErrorLevel |
3736 		    kOSKextLogArchiveFlag,
3737 		    "Can't create wrapper for mkext file entry '%s' of kext %s.",
3738 		    name, getIdentifierCString());
3739 	}
3740 	return result;
3741 }
3742 
3743 /*********************************************************************
3744 *********************************************************************/
3745 extern "C" {
3746 static void * z_alloc(void *, u_int items, u_int size);
3747 static void   z_free(void *, void *ptr);
3748 
3749 typedef struct z_mem {
3750 	uint32_t alloc_size;
3751 	uint8_t  data[0];
3752 } z_mem;
3753 
3754 /*
3755  * Space allocation and freeing routines for use by zlib routines.
3756  */
3757 void *
z_alloc(void * notused __unused,u_int num_items,u_int size)3758 z_alloc(void * notused __unused, u_int num_items, u_int size)
3759 {
3760 	void     * result = NULL;
3761 	z_mem    * zmem = NULL;
3762 
3763 	uint64_t   total = ((uint64_t)num_items) * ((uint64_t)size);
3764 	//Check for overflow due to multiplication
3765 	if (total > UINT32_MAX) {
3766 		panic("z_alloc(%p, %x, %x): overflow caused by %x * %x",
3767 		    notused, num_items, size, num_items, size);
3768 	}
3769 
3770 	uint64_t   allocSize64 =  total + ((uint64_t)sizeof(zmem));
3771 	//Check for overflow due to addition
3772 	if (allocSize64 > UINT32_MAX) {
3773 		panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx",
3774 		    notused, num_items, size, (uint32_t)total, sizeof(zmem));
3775 	}
3776 	uint32_t allocSize = (uint32_t)allocSize64;
3777 
3778 	zmem = (z_mem *)kalloc_data_tag(allocSize, Z_WAITOK,
3779 	    VM_KERN_MEMORY_OSKEXT);
3780 	if (!zmem) {
3781 		goto finish;
3782 	}
3783 	zmem->alloc_size = allocSize;
3784 	result = (void *)&(zmem->data);
3785 finish:
3786 	return result;
3787 }
3788 
3789 void
z_free(void * notused __unused,void * ptr)3790 z_free(void * notused __unused, void * ptr)
3791 {
3792 	uint32_t * skipper = (uint32_t *)ptr - 1;
3793 	z_mem    * zmem = (z_mem *)skipper;
3794 	kfree_data(zmem, zmem->alloc_size);
3795 }
3796 };
3797 
3798 OSSharedPtr<OSData>
extractMkext2FileData(UInt8 * data,const char * name,uint32_t compressedSize,uint32_t fullSize)3799 OSKext::extractMkext2FileData(
3800 	UInt8      * data,
3801 	const char * name,
3802 	uint32_t     compressedSize,
3803 	uint32_t     fullSize)
3804 {
3805 	OSSharedPtr<OSData>      result;
3806 	OSSharedPtr<OSData>      uncompressedData;        // release on error
3807 
3808 	uint8_t     * uncompressedDataBuffer = NULL;        // do not free
3809 	unsigned long uncompressedSize;
3810 	z_stream      zstream;
3811 	bool          zstream_inited = false;
3812 	int           zlib_result;
3813 
3814 	/* If the file isn't compressed, we want to make a copy
3815 	 * so that we don't have the tie to the larger mkext file buffer any more.
3816 	 */
3817 	if (!compressedSize) {
3818 		uncompressedData = OSData::withBytes(data, fullSize);
3819 		// xxx - no check for failure?
3820 		result = uncompressedData;
3821 		goto finish;
3822 	}
3823 
3824 	if (KERN_SUCCESS != kmem_alloc(kernel_map,
3825 	    (vm_offset_t*)&uncompressedDataBuffer, fullSize,
3826 	    KMA_DATA, VM_KERN_MEMORY_OSKEXT)) {
3827 		/* How's this for cheesy? The kernel is only asked to extract
3828 		 * kext plists so we tailor the log messages.
3829 		 */
3830 		if (isKernel()) {
3831 			OSKextLog(this,
3832 			    kOSKextLogErrorLevel |
3833 			    kOSKextLogArchiveFlag,
3834 			    "Allocation failure extracting %s from mkext.", name);
3835 		} else {
3836 			OSKextLog(this,
3837 			    kOSKextLogErrorLevel |
3838 			    kOSKextLogArchiveFlag,
3839 			    "Allocation failure extracting %s from mkext for kext %s.",
3840 			    name, getIdentifierCString());
3841 		}
3842 
3843 		goto finish;
3844 	}
3845 	uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
3846 	if (!uncompressedData) {
3847 		if (isKernel()) {
3848 			OSKextLog(this,
3849 			    kOSKextLogErrorLevel |
3850 			    kOSKextLogArchiveFlag,
3851 			    "Allocation failure extracting %s from mkext.", name);
3852 		} else {
3853 			OSKextLog(this,
3854 			    kOSKextLogErrorLevel |
3855 			    kOSKextLogArchiveFlag,
3856 			    "Allocation failure extracting %s from mkext for kext %s.",
3857 			    name, getIdentifierCString());
3858 		}
3859 		goto finish;
3860 	}
3861 	uncompressedData->setDeallocFunction(&osdata_kmem_free);
3862 
3863 	if (isKernel()) {
3864 		OSKextLog(this,
3865 		    kOSKextLogDetailLevel |
3866 		    kOSKextLogArchiveFlag,
3867 		    "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3868 		    name, compressedSize, fullSize);
3869 	} else {
3870 		OSKextLog(this,
3871 		    kOSKextLogDetailLevel |
3872 		    kOSKextLogArchiveFlag,
3873 		    "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3874 		    getIdentifierCString(), name, compressedSize, fullSize);
3875 	}
3876 
3877 	bzero(&zstream, sizeof(zstream));
3878 	zstream.next_in   = (UInt8 *)data;
3879 	zstream.avail_in  = compressedSize;
3880 
3881 	zstream.next_out  = uncompressedDataBuffer;
3882 	zstream.avail_out = fullSize;
3883 
3884 	zstream.zalloc    = z_alloc;
3885 	zstream.zfree     = z_free;
3886 
3887 	zlib_result = inflateInit(&zstream);
3888 	if (Z_OK != zlib_result) {
3889 		if (isKernel()) {
3890 			OSKextLog(this,
3891 			    kOSKextLogErrorLevel |
3892 			    kOSKextLogArchiveFlag,
3893 			    "Mkext error; zlib inflateInit failed (%d) for %s.",
3894 			    zlib_result, name);
3895 		} else {
3896 			OSKextLog(this,
3897 			    kOSKextLogErrorLevel |
3898 			    kOSKextLogArchiveFlag,
3899 			    "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3900 			    getIdentifierCString(), zlib_result, name);
3901 		}
3902 		goto finish;
3903 	} else {
3904 		zstream_inited = true;
3905 	}
3906 
3907 	zlib_result = inflate(&zstream, Z_FINISH);
3908 
3909 	if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
3910 		uncompressedSize = zstream.total_out;
3911 	} else {
3912 		if (isKernel()) {
3913 			OSKextLog(this,
3914 			    kOSKextLogErrorLevel |
3915 			    kOSKextLogArchiveFlag,
3916 			    "Mkext error; zlib inflate failed (%d) for %s.",
3917 			    zlib_result, name);
3918 		} else {
3919 			OSKextLog(this,
3920 			    kOSKextLogErrorLevel |
3921 			    kOSKextLogArchiveFlag,
3922 			    "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3923 			    getIdentifierCString(), zlib_result, name);
3924 		}
3925 		if (zstream.msg) {
3926 			OSKextLog(this,
3927 			    kOSKextLogErrorLevel |
3928 			    kOSKextLogArchiveFlag,
3929 			    "zlib error: %s.", zstream.msg);
3930 		}
3931 		goto finish;
3932 	}
3933 
3934 	if (uncompressedSize != fullSize) {
3935 		if (isKernel()) {
3936 			OSKextLog(this,
3937 			    kOSKextLogErrorLevel |
3938 			    kOSKextLogArchiveFlag,
3939 			    "Mkext error; zlib inflate discrepancy for %s, "
3940 			    "uncompressed size != original size.", name);
3941 		} else {
3942 			OSKextLog(this,
3943 			    kOSKextLogErrorLevel |
3944 			    kOSKextLogArchiveFlag,
3945 			    "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3946 			    "uncompressed size != original size.",
3947 			    getIdentifierCString(), name);
3948 		}
3949 		goto finish;
3950 	}
3951 
3952 	result = os::move(uncompressedData);
3953 
3954 finish:
3955 	/* Don't bother checking return, nothing we can do on fail.
3956 	 */
3957 	if (zstream_inited) {
3958 		inflateEnd(&zstream);
3959 	}
3960 
3961 	return result;
3962 }
3963 
3964 /*********************************************************************
3965 *********************************************************************/
3966 /* static */
3967 OSReturn
loadFromMkext(OSKextLogSpec clientLogFilter,char * mkextBuffer,uint32_t mkextBufferLength,char ** logInfoOut,uint32_t * logInfoLengthOut)3968 OSKext::loadFromMkext(
3969 	OSKextLogSpec   clientLogFilter,
3970 	char          * mkextBuffer,
3971 	uint32_t        mkextBufferLength,
3972 	char         ** logInfoOut,
3973 	uint32_t      * logInfoLengthOut)
3974 {
3975 	OSReturn         result                      = kOSReturnError;
3976 	OSReturn         tempResult                  = kOSReturnError;
3977 
3978 	OSSharedPtr<OSData>        mkextData;
3979 	OSSharedPtr<OSDictionary>  mkextPlist;
3980 
3981 	OSSharedPtr<OSArray>       logInfoArray;
3982 	OSSharedPtr<OSSerialize>   serializer;
3983 
3984 	OSString       * predicate                   = NULL;        // do not release
3985 	OSDictionary   * requestArgs                 = NULL;        // do not release
3986 
3987 	OSString       * kextIdentifier              = NULL;        // do not release
3988 	OSNumber       * startKextExcludeNum         = NULL;        // do not release
3989 	OSNumber       * startMatchingExcludeNum     = NULL;        // do not release
3990 	OSBoolean      * delayAutounloadBool         = NULL;        // do not release
3991 	OSArray        * personalityNames            = NULL;        // do not release
3992 
3993 	/* Default values for these two options: regular autounload behavior,
3994 	 * load all kexts, send no personalities.
3995 	 */
3996 	Boolean            delayAutounload           = false;
3997 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
3998 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3999 
4000 	IORecursiveLockLock(sKextLock);
4001 
4002 	if (logInfoOut) {
4003 		*logInfoOut = NULL;
4004 		*logInfoLengthOut = 0;
4005 	}
4006 
4007 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
4008 
4009 	OSKextLog(/* kext */ NULL,
4010 	    kOSKextLogDebugLevel |
4011 	    kOSKextLogIPCFlag,
4012 	    "Received kext load request from user space.");
4013 
4014 	/* Regardless of processing, the fact that we have gotten here means some
4015 	 * user-space program is up and talking to us, so we'll switch our kext
4016 	 * registration to reflect that.
4017 	 */
4018 	if (!sUserLoadsActive) {
4019 		OSKextLog(/* kext */ NULL,
4020 		    kOSKextLogProgressLevel |
4021 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
4022 		    "Switching to late startup (user-space) kext loading policy.");
4023 
4024 		sUserLoadsActive = true;
4025 	}
4026 
4027 	if (!sLoadEnabled) {
4028 		OSKextLog(/* kext */ NULL,
4029 		    kOSKextLogErrorLevel |
4030 		    kOSKextLogLoadFlag,
4031 		    "Kext loading is disabled.");
4032 		result = kOSKextReturnDisabled;
4033 		goto finish;
4034 	}
4035 
4036 	/* Note that we do not set a dealloc function on this OSData
4037 	 * object! No references to it can remain after the loadFromMkext()
4038 	 * call since we are in a MIG function, and will vm_deallocate()
4039 	 * the buffer.
4040 	 */
4041 	mkextData = OSData::withBytesNoCopy(mkextBuffer,
4042 	    mkextBufferLength);
4043 	if (!mkextData) {
4044 		OSKextLog(/* kext */ NULL,
4045 		    kOSKextLogErrorLevel |
4046 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
4047 		    "Failed to create wrapper for kext load request.");
4048 		result = kOSKextReturnNoMemory;
4049 		goto finish;
4050 	}
4051 
4052 	result = readMkext2Archive(mkextData.get(), mkextPlist, NULL);
4053 	if (result != kOSReturnSuccess) {
4054 		OSKextLog(/* kext */ NULL,
4055 		    kOSKextLogErrorLevel |
4056 		    kOSKextLogLoadFlag,
4057 		    "Failed to read kext load request.");
4058 		goto finish;
4059 	}
4060 
4061 	predicate = _OSKextGetRequestPredicate(mkextPlist.get());
4062 	if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
4063 		OSKextLog(/* kext */ NULL,
4064 		    kOSKextLogErrorLevel |
4065 		    kOSKextLogLoadFlag,
4066 		    "Received kext load request with no predicate; skipping.");
4067 		result = kOSKextReturnInvalidArgument;
4068 		goto finish;
4069 	}
4070 
4071 	requestArgs = OSDynamicCast(OSDictionary,
4072 	    mkextPlist->getObject(kKextRequestArgumentsKey));
4073 	if (!requestArgs || !requestArgs->getCount()) {
4074 		OSKextLog(/* kext */ NULL,
4075 		    kOSKextLogErrorLevel |
4076 		    kOSKextLogLoadFlag,
4077 		    "Received kext load request with no arguments.");
4078 		result = kOSKextReturnInvalidArgument;
4079 		goto finish;
4080 	}
4081 
4082 	kextIdentifier = OSDynamicCast(OSString,
4083 	    requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
4084 
4085 	if (!kextIdentifier) {
4086 		OSKextLog(/* kext */ NULL,
4087 		    kOSKextLogErrorLevel |
4088 		    kOSKextLogLoadFlag,
4089 		    "Received kext load request with no kext identifier.");
4090 		result = kOSKextReturnInvalidArgument;
4091 		goto finish;
4092 	}
4093 
4094 	startKextExcludeNum = OSDynamicCast(OSNumber,
4095 	    requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
4096 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
4097 	    requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
4098 	delayAutounloadBool = OSDynamicCast(OSBoolean,
4099 	    requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
4100 	personalityNames = OSDynamicCast(OSArray,
4101 	    requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
4102 
4103 	if (delayAutounloadBool) {
4104 		delayAutounload = delayAutounloadBool->getValue();
4105 	}
4106 	if (startKextExcludeNum) {
4107 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
4108 	}
4109 	if (startMatchingExcludeNum) {
4110 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
4111 	}
4112 
4113 	OSKextLog(/* kext */ NULL,
4114 	    kOSKextLogProgressLevel |
4115 	    kOSKextLogIPCFlag,
4116 	    "Received request from user space to load kext %s.",
4117 	    kextIdentifier->getCStringNoCopy());
4118 
4119 	/* Load the kext, with no deferral, since this is a load from outside
4120 	 * the kernel.
4121 	 * xxx - Would like a better way to handle the default values for the
4122 	 * xxx - start/match opt args.
4123 	 */
4124 	result = OSKext::loadKextWithIdentifier(
4125 		kextIdentifier,
4126 		/* kextRef */ NULL,
4127 		/* allowDefer */ false,
4128 		delayAutounload,
4129 		startKextExcludeLevel,
4130 		startMatchingExcludeLevel,
4131 		personalityNames);
4132 	if (result != kOSReturnSuccess) {
4133 		goto finish;
4134 	}
4135 	/* If the load came down from the IOKit daemon, it will shortly inform IOCatalogue
4136 	 * for matching via a separate IOKit calldown.
4137 	 */
4138 
4139 finish:
4140 
4141 	/* Gather up the collected log messages for user space. Any
4142 	 * error messages past this call will not make it up as log messages
4143 	 * but will be in the system log.
4144 	 */
4145 	logInfoArray = OSKext::clearUserSpaceLogFilter();
4146 
4147 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
4148 		tempResult = OSKext::serializeLogInfo(logInfoArray.get(),
4149 		    logInfoOut, logInfoLengthOut);
4150 		if (tempResult != kOSReturnSuccess) {
4151 			result = tempResult;
4152 		}
4153 	}
4154 
4155 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
4156 
4157 	IORecursiveLockUnlock(sKextLock);
4158 
4159 	/* Note: mkextDataObject will have been retained by every kext w/an
4160 	 * executable in it. That should all have been flushed out at the
4161 	 * and of the load operation, but you never know....
4162 	 */
4163 	if (mkextData && mkextData->getRetainCount() > 1) {
4164 		OSKextLog(/* kext */ NULL,
4165 		    kOSKextLogErrorLevel |
4166 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
4167 		    "Kext load request buffer from user space still retained by a kext; "
4168 		    "probable memory leak.");
4169 	}
4170 
4171 	return result;
4172 }
4173 
4174 #endif // CONFIG_KXLD
4175 
4176 /*********************************************************************
4177 *********************************************************************/
4178 /* static */
4179 OSReturn
serializeLogInfo(OSArray * logInfoArray,char ** logInfoOut,uint32_t * logInfoLengthOut)4180 OSKext::serializeLogInfo(
4181 	OSArray   * logInfoArray,
4182 	char     ** logInfoOut,
4183 	uint32_t  * logInfoLengthOut)
4184 {
4185 	OSReturn        result      = kOSReturnError;
4186 	char          * buffer      = NULL;
4187 	kern_return_t   kmem_result = KERN_FAILURE;
4188 	OSSharedPtr<OSSerialize>  serializer;
4189 	char         * logInfo            = NULL;        // returned by reference
4190 	uint32_t       logInfoLength      = 0;
4191 
4192 	if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
4193 		OSKextLog(/* kext */ NULL,
4194 		    kOSKextLogErrorLevel |
4195 		    kOSKextLogIPCFlag,
4196 		    "Internal error; invalid arguments to OSKext::serializeLogInfo().");
4197 		/* Bad programmer. */
4198 		result = kOSKextReturnInvalidArgument;
4199 		goto finish;
4200 	}
4201 
4202 	serializer = OSSerialize::withCapacity(0);
4203 	if (!serializer) {
4204 		OSKextLog(/* kext */ NULL,
4205 		    kOSKextLogErrorLevel |
4206 		    kOSKextLogIPCFlag,
4207 		    "Failed to create serializer on log info for request from user space.");
4208 		/* Incidental error; we're going to (try to) allow the request
4209 		 * itself to succeed. */
4210 	} else {
4211 		if (!logInfoArray->serialize(serializer.get())) {
4212 			OSKextLog(/* kext */ NULL,
4213 			    kOSKextLogErrorLevel |
4214 			    kOSKextLogIPCFlag,
4215 			    "Failed to serialize log info for request from user space.");
4216 			/* Incidental error; we're going to (try to) allow the request
4217 			 * itself to succeed. */
4218 		} else {
4219 			logInfo = serializer->text();
4220 			logInfoLength = serializer->getLength();
4221 
4222 			kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength),
4223 			    KMA_DATA, VM_KERN_MEMORY_OSKEXT);
4224 			if (kmem_result != KERN_SUCCESS) {
4225 				OSKextLog(/* kext */ NULL,
4226 				    kOSKextLogErrorLevel |
4227 				    kOSKextLogIPCFlag,
4228 				    "Failed to copy log info for request from user space.");
4229 				/* Incidental error; we're going to (try to) allow the request
4230 				 * to succeed. */
4231 			} else {
4232 				/* 11981737 - clear uninitialized data in last page */
4233 				bzero((void *)(buffer + logInfoLength),
4234 				    (round_page(logInfoLength) - logInfoLength));
4235 				memcpy(buffer, logInfo, logInfoLength);
4236 				*logInfoOut = buffer;
4237 				*logInfoLengthOut = logInfoLength;
4238 			}
4239 		}
4240 	}
4241 
4242 	result = kOSReturnSuccess;
4243 finish:
4244 	return result;
4245 }
4246 
4247 #if PRAGMA_MARK
4248 #pragma mark Instance Management Methods
4249 #endif
4250 /*********************************************************************
4251 *********************************************************************/
4252 OSSharedPtr<OSKext>
lookupKextWithIdentifier(const char * kextIdentifier)4253 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
4254 {
4255 	OSSharedPtr<OSKext> foundKext;
4256 
4257 	IORecursiveLockLock(sKextLock);
4258 	foundKext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier)), OSRetain);
4259 	IORecursiveLockUnlock(sKextLock);
4260 
4261 	return foundKext;
4262 }
4263 
4264 /*********************************************************************
4265 *********************************************************************/
4266 OSSharedPtr<OSKext>
lookupKextWithIdentifier(OSString * kextIdentifier)4267 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
4268 {
4269 	return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
4270 }
4271 
4272 /*********************************************************************
4273 *********************************************************************/
4274 OSSharedPtr<OSKext>
lookupDextWithIdentifier(OSString * dextIdentifier,OSData * dextUniqueIdentifier)4275 OSKext::lookupDextWithIdentifier(OSString * dextIdentifier, OSData *dextUniqueIdentifier)
4276 {
4277 	OSSharedPtr<OSKext> foundDext;
4278 	foundDext.reset();
4279 
4280 	IORecursiveLockLock(sKextLock);
4281 	OSKext *dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIdentifier->getCStringNoCopy()));
4282 	if (dext != NULL && dext->isDriverKit()) {
4283 		if (dext->dextUniqueID == NULL || dext->dextUniqueID->isEqualTo(dextUniqueIdentifier)) {
4284 			foundDext.reset(dext, OSRetain);
4285 		}
4286 	}
4287 	IORecursiveLockUnlock(sKextLock);
4288 
4289 	return foundDext;
4290 }
4291 
4292 /*********************************************************************
4293 *********************************************************************/
4294 OSSharedPtr<OSKext>
lookupKextWithLoadTag(uint32_t aTag)4295 OSKext::lookupKextWithLoadTag(uint32_t aTag)
4296 {
4297 	OSSharedPtr<OSKext> foundKext;             // returned
4298 	uint32_t i, j;
4299 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4300 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4301 
4302 	IORecursiveLockLock(sKextLock);
4303 
4304 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4305 		for (i = 0; i < count[j]; i++) {
4306 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4307 			if (thisKext->getLoadTag() == aTag) {
4308 				foundKext.reset(thisKext, OSRetain);
4309 				goto finish;
4310 			}
4311 		}
4312 	}
4313 
4314 finish:
4315 	IORecursiveLockUnlock(sKextLock);
4316 
4317 	return foundKext;
4318 }
4319 
4320 /*********************************************************************
4321 *********************************************************************/
4322 OSSharedPtr<OSKext>
lookupKextWithAddress(vm_address_t address)4323 OSKext::lookupKextWithAddress(vm_address_t address)
4324 {
4325 	OSSharedPtr<OSKext> foundKext;             // returned
4326 	uint32_t count, i;
4327 	kmod_info_t *kmod_info;
4328 	vm_address_t originalAddress;
4329 #if defined(__arm64__)
4330 	uint64_t   textExecBase;
4331 	size_t     textExecSize;
4332 #endif /* defined(__arm64__) */
4333 
4334 	originalAddress = address;
4335 #if  __has_feature(ptrauth_calls)
4336 	address = (vm_address_t)VM_KERNEL_STRIP_PTR(address);
4337 #endif /*  __has_feature(ptrauth_calls) */
4338 
4339 	IORecursiveLockLock(sKextLock);
4340 
4341 	count = sLoadedKexts->getCount();
4342 	for (i = 0; i < count; i++) {
4343 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
4344 		if (thisKext == sKernelKext) {
4345 			continue;
4346 		}
4347 		if (thisKext->kmod_info && thisKext->kmod_info->address) {
4348 			kmod_info = thisKext->kmod_info;
4349 			vm_address_t kext_start = kmod_info->address;
4350 			vm_address_t kext_end = kext_start + kmod_info->size;
4351 			if ((kext_start <= address) && (address < kext_end)) {
4352 				foundKext.reset(thisKext, OSRetain);
4353 				goto finish;
4354 			}
4355 #if defined(__arm64__)
4356 			textExecBase = (uintptr_t) getsegdatafromheader((kernel_mach_header_t *)kmod_info->address, "__TEXT_EXEC", &textExecSize);
4357 
4358 			/**
4359 			 * If the addresses within the Mach-O are unslid, then manually
4360 			 * slide any addresses coming from the Mach-O before usage.
4361 			 */
4362 			if (thisKext->flags.unslidMachO) {
4363 				textExecBase = (uintptr_t) ml_static_slide((vm_offset_t) textExecBase);
4364 			}
4365 
4366 			if ((textExecBase <= address) && (address < textExecBase + textExecSize)) {
4367 				foundKext.reset(thisKext, OSRetain);
4368 				goto finish;
4369 			}
4370 #endif /* defined (__arm64__) */
4371 		}
4372 	}
4373 	if ((address >= vm_kernel_stext) && (address < vm_kernel_etext)) {
4374 		foundKext.reset(sKernelKext, OSRetain);
4375 		goto finish;
4376 	}
4377 	/*
4378 	 * DriverKit userspace executables do not have a kernel linkedExecutable,
4379 	 * so we "fake" their address range with the LoadTag. We cannot use the ptrauth-stripped address
4380 	 * here, so use the original address passed to this method.
4381 	 *
4382 	 * This is supposed to be used for logging reasons only. When logd
4383 	 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
4384 	 * remove it here before checking it against the LoadTag.
4385 	 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
4386 	 */
4387 
4388 	address = originalAddress & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
4389 	count = sLoadedDriverKitKexts->getCount();
4390 	for (i = 0; i < count; i++) {
4391 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
4392 		if (thisKext->getLoadTag() == address) {
4393 			foundKext.reset(thisKext, OSRetain);
4394 		}
4395 	}
4396 
4397 finish:
4398 	IORecursiveLockUnlock(sKextLock);
4399 
4400 	return foundKext;
4401 }
4402 
4403 OSSharedPtr<OSData>
copyKextUUIDForAddress(OSNumber * address)4404 OSKext::copyKextUUIDForAddress(OSNumber *address)
4405 {
4406 	OSSharedPtr<OSData>   uuid;
4407 	OSSharedPtr<OSKext>   kext;
4408 
4409 	if (!address) {
4410 		return NULL;
4411 	}
4412 
4413 #if CONFIG_MACF
4414 	/* Is the calling process allowed to query kext info? */
4415 	if (current_task() != kernel_task) {
4416 		int macCheckResult = 0;
4417 		kauth_cred_t cred = NULL;
4418 
4419 		cred = kauth_cred_get_with_ref();
4420 		macCheckResult = mac_kext_check_query(cred);
4421 		kauth_cred_unref(&cred);
4422 
4423 		if (macCheckResult != 0) {
4424 			OSKextLog(/* kext */ NULL,
4425 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
4426 			    "Failed to query kext UUID (MAC policy error 0x%x).",
4427 			    macCheckResult);
4428 			return NULL;
4429 		}
4430 	}
4431 #endif
4432 
4433 	uintptr_t slidAddress = ml_static_slide((uintptr_t)address->unsigned64BitValue());
4434 	if (slidAddress != 0) {
4435 		kext = lookupKextWithAddress(slidAddress);
4436 		if (kext) {
4437 			uuid = kext->copyTextUUID();
4438 		}
4439 	}
4440 
4441 	if (!uuid) {
4442 		/*
4443 		 * If we still don't have a UUID, then we failed to match the slid + stripped address with
4444 		 * a kext. This might have happened because the log message came from a dext.
4445 		 *
4446 		 * Try again with the original address.
4447 		 */
4448 		kext = lookupKextWithAddress((vm_address_t)address->unsigned64BitValue());
4449 		if (kext && kext->isDriverKit()) {
4450 			uuid = kext->copyTextUUID();
4451 		}
4452 	}
4453 
4454 	return uuid;
4455 }
4456 
4457 /*********************************************************************
4458 *********************************************************************/
4459 OSSharedPtr<OSKext>
lookupKextWithUUID(uuid_t wanted)4460 OSKext::lookupKextWithUUID(uuid_t wanted)
4461 {
4462 	OSSharedPtr<OSKext> foundKext;             // returned
4463 	uint32_t j, i;
4464 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4465 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4466 
4467 
4468 	IORecursiveLockLock(sKextLock);
4469 
4470 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4471 		for (i = 0; i < count[j]; i++) {
4472 			OSKext   * thisKext     = NULL;
4473 
4474 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4475 			if (!thisKext) {
4476 				continue;
4477 			}
4478 
4479 			OSSharedPtr<OSData> uuid_data = thisKext->copyUUID();
4480 			if (!uuid_data) {
4481 				continue;
4482 			}
4483 
4484 			uuid_t uuid;
4485 			memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
4486 
4487 			if (0 == uuid_compare(wanted, uuid)) {
4488 				foundKext.reset(thisKext, OSRetain);
4489 				goto finish;
4490 			}
4491 		}
4492 	}
4493 finish:
4494 	IORecursiveLockUnlock(sKextLock);
4495 
4496 	return foundKext;
4497 }
4498 
4499 
4500 
4501 
4502 /*********************************************************************
4503 *********************************************************************/
4504 /* static */
4505 bool
isKextWithIdentifierLoaded(const char * kextIdentifier)4506 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
4507 {
4508 	bool result = false;
4509 	OSKext * foundKext = NULL;             // returned
4510 
4511 	IORecursiveLockLock(sKextLock);
4512 
4513 	foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4514 	if (foundKext && foundKext->isLoaded()) {
4515 		result = true;
4516 	}
4517 
4518 	IORecursiveLockUnlock(sKextLock);
4519 
4520 	return result;
4521 }
4522 
4523 /*********************************************************************
4524 * xxx - should spawn a separate thread so a kext can safely have
4525 * xxx - itself unloaded.
4526 *********************************************************************/
4527 /* static */
4528 OSReturn
removeKext(OSKext * aKext,__unused bool terminateServicesAndRemovePersonalitiesFlag)4529 OSKext::removeKext(
4530 	OSKext * aKext,
4531 #if CONFIG_EMBEDDED
4532 	__unused
4533 #endif
4534 	bool     terminateServicesAndRemovePersonalitiesFlag)
4535 {
4536 #if CONFIG_EMBEDDED
4537 	if (!aKext->isDriverKit()) {
4538 		OSKextLog(aKext,
4539 		    kOSKextLogErrorLevel |
4540 		    kOSKextLogKextBookkeepingFlag,
4541 		    "removeKext() called for %s, only supported on embedded for DriverKit dexts",
4542 		    aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
4543 
4544 		return kOSReturnSuccess;
4545 	}
4546 #endif /* CONFIG_EMBEDDED */
4547 	OSReturn result    = kOSKextReturnInUse;
4548 	OSKext * checkKext = NULL;         // do not release
4549 #if CONFIG_MACF
4550 	int macCheckResult = 0;
4551 	kauth_cred_t cred  = NULL;
4552 #endif
4553 
4554 	IORecursiveLockLock(sKextLock);
4555 
4556 	/* If the kext has no identifier, it failed to init
4557 	 * so isn't in sKextsByID and it isn't loaded.
4558 	 */
4559 	if (!aKext->getIdentifier()) {
4560 		result = kOSReturnSuccess;
4561 		goto finish;
4562 	}
4563 
4564 	checkKext = OSDynamicCast(OSKext,
4565 	    sKextsByID->getObject(aKext->getIdentifier()));
4566 	if (checkKext != aKext) {
4567 		result = kOSKextReturnNotFound;
4568 		goto finish;
4569 	}
4570 
4571 	if (aKext->isLoaded() || aKext->isDriverKit()) {
4572 #if CONFIG_MACF
4573 		if (current_task() != kernel_task) {
4574 			cred = kauth_cred_get_with_ref();
4575 			macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
4576 			kauth_cred_unref(&cred);
4577 		}
4578 
4579 		if (macCheckResult != 0) {
4580 			result = kOSReturnError;
4581 			OSKextLog(aKext,
4582 			    kOSKextLogErrorLevel |
4583 			    kOSKextLogKextBookkeepingFlag,
4584 			    "Failed to remove kext %s (MAC policy error 0x%x).",
4585 			    aKext->getIdentifierCString(), macCheckResult);
4586 			goto finish;
4587 		}
4588 #endif
4589 
4590 		/* make sure there are no resource requests in flight - 17187548 */
4591 		if (aKext->declaresExecutable() && aKext->countRequestCallbacks()) {
4592 			goto finish;
4593 		}
4594 		if (aKext->flags.unloadUnsupported) {
4595 			result = kOSKextReturnInUse;
4596 			OSKextLog(aKext,
4597 			    kOSKextLogErrorLevel |
4598 			    kOSKextLogKextBookkeepingFlag,
4599 			    "Can't remove kext %s; unsupported by cache.",
4600 			    aKext->getIdentifierCString());
4601 			goto finish;
4602 		}
4603 
4604 		/* If we are terminating, send the request to the IOCatalogue
4605 		 * (which will actually call us right back but that's ok we have
4606 		 * a recursive lock don't you know) but do not ask the IOCatalogue
4607 		 * to call back with an unload, we'll do that right here.
4608 		 */
4609 		if (terminateServicesAndRemovePersonalitiesFlag) {
4610 			result = gIOCatalogue->terminateDriversForModule(
4611 				aKext->getIdentifierCString(), /* unload */ false);
4612 			if (result != kOSReturnSuccess) {
4613 				OSKextLog(aKext,
4614 				    kOSKextLogErrorLevel |
4615 				    kOSKextLogKextBookkeepingFlag,
4616 				    "Can't remove kext %s; services failed to terminate - 0x%x.",
4617 				    aKext->getIdentifierCString(), result);
4618 				goto finish;
4619 			}
4620 		}
4621 
4622 		result = aKext->unload();
4623 		if (result != kOSReturnSuccess) {
4624 			OSKextLog(aKext,
4625 			    kOSKextLogErrorLevel |
4626 			    kOSKextLogKextBookkeepingFlag,
4627 			    "Can't remove kext %s; kext failed to unload - 0x%x.",
4628 			    aKext->getIdentifierCString(), result);
4629 			goto finish;
4630 		}
4631 	}
4632 
4633 	/* Remove personalities as requested. This is a bit redundant for a loaded
4634 	 * kext as IOCatalogue::terminateDriversForModule() removes driver
4635 	 * personalities, but it doesn't restart matching, which we always want
4636 	 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
4637 	 * that happens.
4638 	 */
4639 	if (terminateServicesAndRemovePersonalitiesFlag) {
4640 		aKext->removePersonalitiesFromCatalog();
4641 	}
4642 
4643 	if (aKext->isInFileset()) {
4644 		OSKextLog(aKext,
4645 		    kOSKextLogProgressLevel |
4646 		    kOSKextLogKextBookkeepingFlag,
4647 		    "Fileset kext %s unloaded.",
4648 		    aKext->getIdentifierCString());
4649 	} else {
4650 		OSKextLog(aKext,
4651 		    kOSKextLogProgressLevel |
4652 		    kOSKextLogKextBookkeepingFlag,
4653 		    "Removing kext %s.",
4654 		    aKext->getIdentifierCString());
4655 
4656 		sKextsByID->removeObject(aKext->getIdentifier());
4657 	}
4658 	result = kOSReturnSuccess;
4659 
4660 finish:
4661 	IORecursiveLockUnlock(sKextLock);
4662 	return result;
4663 }
4664 
4665 /*********************************************************************
4666 *********************************************************************/
4667 /* static */
4668 OSReturn
removeKextWithIdentifier(const char * kextIdentifier,bool terminateServicesAndRemovePersonalitiesFlag)4669 OSKext::removeKextWithIdentifier(
4670 	const char * kextIdentifier,
4671 	bool         terminateServicesAndRemovePersonalitiesFlag)
4672 {
4673 	OSReturn result = kOSReturnError;
4674 
4675 	IORecursiveLockLock(sKextLock);
4676 
4677 	OSKext * aKext = OSDynamicCast(OSKext,
4678 	    sKextsByID->getObject(kextIdentifier));
4679 	if (!aKext) {
4680 		result = kOSKextReturnNotFound;
4681 		OSKextLog(/* kext */ NULL,
4682 		    kOSKextLogErrorLevel |
4683 		    kOSKextLogKextBookkeepingFlag,
4684 		    "Can't remove kext %s - not found.",
4685 		    kextIdentifier);
4686 		goto finish;
4687 	}
4688 
4689 	result = OSKext::removeKext(aKext,
4690 	    terminateServicesAndRemovePersonalitiesFlag);
4691 
4692 finish:
4693 	IORecursiveLockUnlock(sKextLock);
4694 
4695 	return result;
4696 }
4697 
4698 /*********************************************************************
4699 *********************************************************************/
4700 /* static */
4701 OSReturn
removeKextWithLoadTag(OSKextLoadTag loadTag,bool terminateServicesAndRemovePersonalitiesFlag)4702 OSKext::removeKextWithLoadTag(
4703 	OSKextLoadTag loadTag,
4704 	bool          terminateServicesAndRemovePersonalitiesFlag)
4705 {
4706 	OSReturn result    = kOSReturnError;
4707 	OSKext * foundKext = NULL;
4708 	uint32_t i, j;
4709 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
4710 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
4711 
4712 
4713 	IORecursiveLockLock(sKextLock);
4714 
4715 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
4716 		for (i = 0; i < count[j]; i++) {
4717 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
4718 			if (thisKext->loadTag == loadTag) {
4719 				foundKext = thisKext;
4720 				break;
4721 			}
4722 		}
4723 	}
4724 
4725 	if (!foundKext) {
4726 		result = kOSKextReturnNotFound;
4727 		OSKextLog(/* kext */ NULL,
4728 		    kOSKextLogErrorLevel |
4729 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4730 		    "Can't remove kext with load tag %d - not found.",
4731 		    loadTag);
4732 		goto finish;
4733 	}
4734 
4735 	result = OSKext::removeKext(foundKext,
4736 	    terminateServicesAndRemovePersonalitiesFlag);
4737 
4738 finish:
4739 	IORecursiveLockUnlock(sKextLock);
4740 
4741 	return result;
4742 }
4743 
4744 /*********************************************************************
4745 *********************************************************************/
4746 OSSharedPtr<OSDictionary>
copyKexts(void)4747 OSKext::copyKexts(void)
4748 {
4749 	OSSharedPtr<OSDictionary> result;
4750 
4751 	IORecursiveLockLock(sKextLock);
4752 	result = OSDynamicPtrCast<OSDictionary>(sKextsByID->copyCollection());
4753 	IORecursiveLockUnlock(sKextLock);
4754 
4755 	return result;
4756 }
4757 
4758 /*********************************************************************
4759 *********************************************************************/
4760 #define BOOTER_KEXT_PREFIX   "Driver-"
4761 
4762 typedef struct _DeviceTreeBuffer {
4763 	uint32_t paddr;
4764 	uint32_t length;
4765 } _DeviceTreeBuffer;
4766 
4767 /*********************************************************************
4768 * Create a dictionary of excluded kexts from the given booter data.
4769 *********************************************************************/
4770 /* static */
4771 void
createExcludeListFromBooterData(OSDictionary * theDictionary,OSCollectionIterator * theIterator)4772 OSKext::createExcludeListFromBooterData(
4773 	OSDictionary *          theDictionary,
4774 	OSCollectionIterator *  theIterator )
4775 {
4776 	OSString                  * deviceTreeName      = NULL;        // do not release
4777 	const _DeviceTreeBuffer   * deviceTreeBuffer    = NULL;        // do not release
4778 	char                      * booterDataPtr       = NULL;        // do not release
4779 	_BooterKextFileInfo       * kextFileInfo        = NULL;        // do not release
4780 	char                      * infoDictAddr        = NULL;        // do not release
4781 	OSSharedPtr<OSObject>       parsedXML;
4782 	OSDictionary              * theInfoDict         = NULL;        // do not release
4783 
4784 	theIterator->reset();
4785 
4786 	/* look for AppleKextExcludeList.kext */
4787 	while ((deviceTreeName =
4788 	    OSDynamicCast(OSString, theIterator->getNextObject()))) {
4789 		const char *    devTreeNameCString;
4790 		OSData *        deviceTreeEntry;        // do not release
4791 		OSString *      myBundleID;        // do not release
4792 
4793 		deviceTreeEntry =
4794 		    OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
4795 		if (!deviceTreeEntry) {
4796 			continue;
4797 		}
4798 
4799 		/* Make sure it is a kext */
4800 		devTreeNameCString = deviceTreeName->getCStringNoCopy();
4801 		if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
4802 		    (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
4803 			OSKextLog(NULL,
4804 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4805 			    "\"%s\" not a kext",
4806 			    devTreeNameCString);
4807 			continue;
4808 		}
4809 
4810 		deviceTreeBuffer = (const _DeviceTreeBuffer *)
4811 		    deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
4812 		if (!deviceTreeBuffer) {
4813 			continue;
4814 		}
4815 
4816 		booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
4817 		if (!booterDataPtr) {
4818 			continue;
4819 		}
4820 
4821 		kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
4822 		if (!kextFileInfo->infoDictPhysAddr ||
4823 		    !kextFileInfo->infoDictLength) {
4824 			continue;
4825 		}
4826 
4827 		infoDictAddr = (char *)
4828 		    ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
4829 		if (!infoDictAddr) {
4830 			continue;
4831 		}
4832 
4833 		parsedXML = OSUnserializeXML(infoDictAddr);
4834 		if (!parsedXML) {
4835 			continue;
4836 		}
4837 
4838 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML.get());
4839 		if (!theInfoDict) {
4840 			continue;
4841 		}
4842 
4843 		myBundleID =
4844 		    OSDynamicCast(OSString,
4845 		    theInfoDict->getObject(kCFBundleIdentifierKey));
4846 		if (myBundleID &&
4847 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4848 			boolean_t updated = updateExcludeList(theInfoDict);
4849 			if (!updated) {
4850 				/* 25322874 */
4851 				panic("Missing OSKextExcludeList dictionary");
4852 			}
4853 			break;
4854 		}
4855 	}         // while ( (deviceTreeName = ...) )
4856 
4857 	return;
4858 }
4859 
4860 /*********************************************************************
4861 * Create a dictionary of excluded kexts from the given prelink
4862 * info (kernelcache).
4863 *********************************************************************/
4864 /* static */
4865 void
createExcludeListFromPrelinkInfo(OSArray * theInfoArray)4866 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
4867 {
4868 	OSDictionary *  myInfoDict = NULL;        // do not release
4869 	OSString *      myBundleID;        // do not release
4870 	u_int           i;
4871 
4872 	/* Find the Apple Kext Exclude List. */
4873 	for (i = 0; i < theInfoArray->getCount(); i++) {
4874 		myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
4875 		if (!myInfoDict) {
4876 			continue;
4877 		}
4878 		myBundleID =
4879 		    OSDynamicCast(OSString,
4880 		    myInfoDict->getObject(kCFBundleIdentifierKey));
4881 		if (myBundleID &&
4882 		    strcmp( myBundleID->getCStringNoCopy(), kIOExcludeListBundleID ) == 0) {
4883 			boolean_t updated = updateExcludeList(myInfoDict);
4884 			if (!updated) {
4885 				/* 25322874 */
4886 				panic("Missing OSKextExcludeList dictionary");
4887 			}
4888 			break;
4889 		}
4890 	}         // for (i = 0; i < theInfoArray->getCount()...
4891 
4892 	return;
4893 }
4894 
4895 /* static */
4896 boolean_t
updateExcludeList(OSDictionary * infoDict)4897 OSKext::updateExcludeList(OSDictionary *infoDict)
4898 {
4899 	OSDictionary *myTempDict = NULL;         // do not free
4900 	OSString     *myTempString = NULL;        // do not free
4901 	OSKextVersion newVersion = 0;
4902 	boolean_t updated = false;
4903 
4904 	if (!infoDict) {
4905 		return false;
4906 	}
4907 
4908 	myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
4909 	if (!myTempDict) {
4910 		return false;
4911 	}
4912 
4913 	myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
4914 	if (!myTempString) {
4915 		return false;
4916 	}
4917 
4918 	newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
4919 	if (newVersion == 0) {
4920 		return false;
4921 	}
4922 
4923 	IORecursiveLockLock(sKextLock);
4924 
4925 	if (newVersion > sExcludeListVersion) {
4926 		sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
4927 		sExcludeListVersion = newVersion;
4928 		updated = true;
4929 	}
4930 
4931 	IORecursiveLockUnlock(sKextLock);
4932 	return updated;
4933 }
4934 
4935 #if PRAGMA_MARK
4936 #pragma mark Accessors
4937 #endif
4938 
4939 /*********************************************************************
4940 *********************************************************************/
4941 const OSObject *
getBundleExecutable(void)4942 OSKext::getBundleExecutable(void)
4943 {
4944 	return infoDict->getObject(kCFBundleExecutableKey);
4945 }
4946 
4947 /*********************************************************************
4948 *********************************************************************/
4949 const OSSymbol *
getIdentifier(void)4950 OSKext::getIdentifier(void)
4951 {
4952 	return bundleID.get();
4953 }
4954 
4955 /*********************************************************************
4956 * A kext must have a bundle identifier to even survive initialization;
4957 * this is guaranteed to exist past then.
4958 *********************************************************************/
4959 const char *
getIdentifierCString(void)4960 OSKext::getIdentifierCString(void)
4961 {
4962 	return bundleID->getCStringNoCopy();
4963 }
4964 
4965 /*********************************************************************
4966 *********************************************************************/
4967 OSKextVersion
getVersion(void)4968 OSKext::getVersion(void)
4969 {
4970 	return version;
4971 }
4972 
4973 /*********************************************************************
4974 *********************************************************************/
4975 OSKextVersion
getCompatibleVersion(void)4976 OSKext::getCompatibleVersion(void)
4977 {
4978 	return compatibleVersion;
4979 }
4980 
4981 /*********************************************************************
4982 *********************************************************************/
4983 bool
isLibrary(void)4984 OSKext::isLibrary(void)
4985 {
4986 	return getCompatibleVersion() > 0;
4987 }
4988 
4989 /*********************************************************************
4990 *********************************************************************/
4991 bool
isCompatibleWithVersion(OSKextVersion aVersion)4992 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
4993 {
4994 	if ((compatibleVersion > -1 && version > -1) &&
4995 	    (compatibleVersion <= version && aVersion <= version)) {
4996 		return true;
4997 	}
4998 	return false;
4999 }
5000 
5001 /*********************************************************************
5002 *********************************************************************/
5003 bool
declaresExecutable(void)5004 OSKext::declaresExecutable(void)
5005 {
5006 	if (isDriverKit()) {
5007 		return false;
5008 	}
5009 	return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
5010 }
5011 
5012 /*********************************************************************
5013 *********************************************************************/
5014 OSData *
getExecutable(void)5015 OSKext::getExecutable(void)
5016 {
5017 	OSData * result              = NULL;
5018 	OSSharedPtr<OSData> extractedExecutable;
5019 
5020 	if (flags.builtin) {
5021 		return sKernelKext->linkedExecutable.get();
5022 	}
5023 
5024 	result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
5025 	if (result) {
5026 		return result;
5027 	}
5028 
5029 #if CONFIG_KXLD
5030 	OSData * mkextExecutableRef  = NULL;        // do not release
5031 	mkextExecutableRef = OSDynamicCast(OSData,
5032 	    getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
5033 
5034 	if (mkextExecutableRef) {
5035 		MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
5036 		    mkextExecutableRef->getBytesNoCopy();
5037 		uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
5038 		if (mkextVersion == MKEXT_VERS_2) {
5039 			mkext2_file_entry * fileinfo =
5040 			    (mkext2_file_entry *)mkextEntryRef->fileinfo;
5041 			uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
5042 			uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
5043 			extractedExecutable = extractMkext2FileData(
5044 				MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
5045 				compressedSize, fullSize);
5046 		} else {
5047 			OSKextLog(this, kOSKextLogErrorLevel |
5048 			    kOSKextLogArchiveFlag,
5049 			    "Kext %s - unknown mkext version 0x%x for executable.",
5050 			    getIdentifierCString(), mkextVersion);
5051 		}
5052 
5053 		/* Regardless of success, remove the mkext executable,
5054 		 * and drop one reference on the mkext.  (setExecutable() does not
5055 		 * replace, it removes, or panics if asked to replace.)
5056 		 */
5057 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
5058 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
5059 
5060 		if (extractedExecutable && extractedExecutable->getLength()) {
5061 			if (!setExecutable(extractedExecutable.get())) {
5062 				goto finish;
5063 			}
5064 			result = extractedExecutable.get();
5065 		} else {
5066 			goto finish;
5067 		}
5068 	}
5069 
5070 finish:
5071 #endif // CONFIG_KXLD
5072 	return result;
5073 }
5074 
5075 /*********************************************************************
5076 *********************************************************************/
5077 bool
isInterface(void)5078 OSKext::isInterface(void)
5079 {
5080 	return flags.interface;
5081 }
5082 
5083 /*********************************************************************
5084 *********************************************************************/
5085 bool
isKernel(void)5086 OSKext::isKernel(void)
5087 {
5088 	return this == sKernelKext;
5089 }
5090 
5091 /*********************************************************************
5092 *********************************************************************/
5093 bool
isKernelComponent(void)5094 OSKext::isKernelComponent(void)
5095 {
5096 	return flags.kernelComponent ? true : false;
5097 }
5098 
5099 /*********************************************************************
5100 *********************************************************************/
5101 bool
isExecutable(void)5102 OSKext::isExecutable(void)
5103 {
5104 	return !isKernel() && !isInterface() && declaresExecutable();
5105 }
5106 
5107 /*********************************************************************
5108 *********************************************************************/
5109 bool
isSpecialKernelBinary(void)5110 OSKext::isSpecialKernelBinary(void)
5111 {
5112 #if CONFIG_SPTM
5113 	return (this->kmod_info) &&
5114 	       ((this->kmod_info->id == kOSKextSPTMLoadTag) ||
5115 	       (this->kmod_info->id == kOSKextTXMLoadTag));
5116 #else
5117 	return false;
5118 #endif
5119 }
5120 
5121 /*********************************************************************
5122 * We might want to check this recursively for all dependencies,
5123 * since a subtree of dependencies could get loaded before we hit
5124 * a dependency that isn't safe-boot-loadable.
5125 *
5126 * xxx - Might want to return false if OSBundleEnableKextLogging or
5127 * OSBundleDebugLevel
5128 * or IOKitDebug is nonzero too (we used to do that, but I don't see
5129 * the point except it's usually development drivers, which might
5130 * cause panics on startup, that have those properties). Heh; could
5131 * use a "kx" boot-arg!
5132 *********************************************************************/
5133 bool
isLoadableInSafeBoot(void)5134 OSKext::isLoadableInSafeBoot(void)
5135 {
5136 	bool       result   = false;
5137 	OSString * required = NULL;         // do not release
5138 
5139 	if (isKernel()) {
5140 		result = true;
5141 		goto finish;
5142 	}
5143 
5144 	if (isDriverKit()) {
5145 		result = true;
5146 		goto finish;
5147 	}
5148 
5149 	required = OSDynamicCast(OSString,
5150 	    getPropertyForHostArch(kOSBundleRequiredKey));
5151 	if (!required) {
5152 		goto finish;
5153 	}
5154 	if (required->isEqualTo(kOSBundleRequiredRoot) ||
5155 	    required->isEqualTo(kOSBundleRequiredLocalRoot) ||
5156 	    required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
5157 	    required->isEqualTo(kOSBundleRequiredSafeBoot) ||
5158 	    required->isEqualTo(kOSBundleRequiredConsole)) {
5159 		result = true;
5160 	}
5161 
5162 finish:
5163 	return result;
5164 }
5165 
5166 /*********************************************************************
5167 *********************************************************************/
5168 bool
isPrelinked(void)5169 OSKext::isPrelinked(void)
5170 {
5171 	return flags.prelinked ? true : false;
5172 }
5173 
5174 /*********************************************************************
5175 *********************************************************************/
5176 bool
isLoaded(void)5177 OSKext::isLoaded(void)
5178 {
5179 	return flags.loaded ? true : false;
5180 }
5181 
5182 /*********************************************************************
5183 *********************************************************************/
5184 bool
isStarted(void)5185 OSKext::isStarted(void)
5186 {
5187 	return flags.started ? true : false;
5188 }
5189 
5190 /*********************************************************************
5191 *********************************************************************/
5192 bool
isCPPInitialized(void)5193 OSKext::isCPPInitialized(void)
5194 {
5195 	return flags.CPPInitialized;
5196 }
5197 
5198 /*********************************************************************
5199 *********************************************************************/
5200 void
setCPPInitialized(bool initialized)5201 OSKext::setCPPInitialized(bool initialized)
5202 {
5203 	flags.CPPInitialized = initialized;
5204 }
5205 
5206 /*********************************************************************
5207 *********************************************************************/
5208 uint32_t
getLoadTag(void)5209 OSKext::getLoadTag(void)
5210 {
5211 	return loadTag;
5212 }
5213 
5214 /*********************************************************************
5215 *********************************************************************/
5216 void
getSizeInfo(uint32_t * loadSize,uint32_t * wiredSize)5217 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
5218 {
5219 	if (linkedExecutable) {
5220 		*loadSize = linkedExecutable->getLength();
5221 
5222 		/* If we have a kmod_info struct, calculated the wired size
5223 		 * from that. Otherwise it's the full load size.
5224 		 */
5225 		if (kmod_info) {
5226 			*wiredSize = *loadSize - (uint32_t)kmod_info->hdr_size;
5227 		} else {
5228 			*wiredSize = *loadSize;
5229 		}
5230 	} else {
5231 		*wiredSize = 0;
5232 		*loadSize = 0;
5233 	}
5234 }
5235 
5236 /*********************************************************************
5237 *********************************************************************/
5238 OSSharedPtr<OSData>
copyUUID(void)5239 OSKext::copyUUID(void)
5240 {
5241 	OSSharedPtr<OSData>          result;
5242 	OSData                     * theExecutable = NULL;        // do not release
5243 	const kernel_mach_header_t * header;
5244 
5245 	/* An interface kext doesn't have a linked executable with an LC_UUID,
5246 	 * we create one when it's linked.
5247 	 */
5248 	if (interfaceUUID) {
5249 		result = interfaceUUID;
5250 		goto finish;
5251 	}
5252 
5253 	if (flags.builtin || isInterface()) {
5254 		return sKernelKext->copyUUID();
5255 	}
5256 
5257 	if (isDriverKit() && infoDict) {
5258 		return driverKitUUID;
5259 	}
5260 
5261 	/* For real kexts, try to get the UUID from the linked executable,
5262 	 * or if is hasn't been linked yet, the unrelocated executable.
5263 	 */
5264 	theExecutable = linkedExecutable.get();
5265 	if (!theExecutable) {
5266 		theExecutable = getExecutable();
5267 	}
5268 
5269 	if (!theExecutable) {
5270 		goto finish;
5271 	}
5272 
5273 	header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
5274 	result = copyMachoUUID(header);
5275 
5276 finish:
5277 	return result;
5278 }
5279 
5280 /*********************************************************************
5281 *********************************************************************/
5282 OSSharedPtr<OSData>
copyTextUUID(void)5283 OSKext::copyTextUUID(void)
5284 {
5285 	if (flags.builtin) {
5286 		return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
5287 	}
5288 	return copyUUID();
5289 }
5290 
5291 /*********************************************************************
5292 *********************************************************************/
5293 OSSharedPtr<OSData>
copyMachoUUID(const kernel_mach_header_t * header)5294 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
5295 {
5296 	OSSharedPtr<OSData>                     result;
5297 	const struct load_command  * load_cmd      = NULL;
5298 	const struct uuid_command  * uuid_cmd      = NULL;
5299 	uint32_t                     i;
5300 
5301 	load_cmd = (const struct load_command *)&header[1];
5302 
5303 	if (header->magic != MH_MAGIC_KERNEL) {
5304 		OSKextLog(NULL,
5305 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
5306 		    "%s: bad header %p",
5307 		    __func__,
5308 		    header);
5309 		goto finish;
5310 	}
5311 
5312 	for (i = 0; i < header->ncmds; i++) {
5313 		if (load_cmd->cmd == LC_UUID) {
5314 			uuid_cmd = (struct uuid_command *)load_cmd;
5315 			result = OSData::withValue(uuid_cmd->uuid);
5316 			goto finish;
5317 		}
5318 		load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
5319 	}
5320 
5321 finish:
5322 	return result;
5323 }
5324 
5325 void
setDriverKitUUID(OSData * uuid)5326 OSKext::setDriverKitUUID(OSData *uuid)
5327 {
5328 	if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
5329 		OSSafeReleaseNULL(uuid);
5330 	}
5331 }
5332 
5333 OSData *
getDextUniqueID(void)5334 OSKext::getDextUniqueID(void)
5335 {
5336 	if (isDriverKit() && dextUniqueID != NULL) {
5337 		return dextUniqueID.get();
5338 	}
5339 
5340 	return NULL;
5341 }
5342 
5343 /*
5344  * In case a DextUniqueID exists this function returns
5345  * an allocated char* with the hexadecimal represantition of
5346  * DextUniqueID.
5347  * The returned pinter needs to be freed with kfree_data, the
5348  * size of the allocated buffer is returned in size.
5349  */
5350 static const char *
getDextUniqueIDCString(OSData * dextUniqueID,unsigned int * size)5351 getDextUniqueIDCString(OSData *dextUniqueID, unsigned int *size)
5352 {
5353 	if (dextUniqueID != NULL) {
5354 		char *s_buffer = NULL;
5355 		unsigned int d_length = dextUniqueID->getLength();
5356 		/*
5357 		 * We are converting in hex, so for every byte we will have
5358 		 * 2 hex chars and one last \0.
5359 		 */
5360 		unsigned int s_length = d_length * 2 + 1;
5361 		s_buffer = (char *) kalloc_data(s_length, Z_WAITOK_ZERO);
5362 
5363 		char *uid = (char*) dextUniqueID->getBytesNoCopy();
5364 		int cpos = 0;
5365 		for (unsigned int i = 0; i < d_length && cpos < (s_length - 1); i++) {
5366 			int ret = snprintf(s_buffer + cpos, s_length - cpos - 1, "%02X", uid[i]);
5367 			if (ret <= 0) {
5368 				break;
5369 			}
5370 			cpos += ret;
5371 		}
5372 		*size = s_length;
5373 
5374 		return s_buffer;
5375 	}
5376 
5377 	return NULL;
5378 }
5379 
5380 /*
5381  * Atomically swaps the olddext with newdext.
5382  * olddext will be unloaded, so it might be freed
5383  * after this call unless it was previously retained.
5384  *
5385  * If newdext is NULL, this unloads olddext and does not perform an upgrade
5386  */
5387 void
replaceDextInternal(OSKext * olddext,OSKext * newdext)5388 OSKext::replaceDextInternal(OSKext *olddext, OSKext *newdext)
5389 {
5390 	OSReturn result;
5391 	const OSSymbol * dextID = olddext->getIdentifier();
5392 	OSData * oldDextUniqueIdentifier = olddext->getDextUniqueID();
5393 	OSSharedPtr<OSArray> new_personalities;
5394 	OSSharedPtr<OSString> kextIdentifier;
5395 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5396 	assert(lock_held);
5397 
5398 	// The old dext will be unloaded and release dextID, so we need to retain dextID here
5399 	dextID->retain();
5400 
5401 	if (newdext != NULL) {
5402 		__assert_only bool eq = dextID->isEqualTo(newdext->getIdentifier());
5403 		assert(eq);
5404 	}
5405 
5406 	if (newdext != NULL) {
5407 		/*
5408 		 * Swap the catalog personalities.
5409 		 */
5410 		new_personalities = newdext->copyPersonalitiesArray();
5411 		olddext->updatePersonalitiesInCatalog(new_personalities.get());
5412 	}
5413 
5414 	if (NULL != oldDextUniqueIdentifier) {
5415 		oldDextUniqueIdentifier->retain();
5416 	}
5417 
5418 	/*
5419 	 * Unload the dext.
5420 	 */
5421 	result = olddext->unload();
5422 	if (result != kOSReturnSuccess) {
5423 		OSKextLog(NULL,
5424 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5425 		    "Cannot unload dext for upgrade %s: %d\n",
5426 		    dextID->getCStringNoCopy(), result);
5427 	}
5428 
5429 	if (newdext != NULL) {
5430 		/*
5431 		 * Swap the dexts on the OSKext dictionary.
5432 		 * This might free the dext.
5433 		 */
5434 		sKextsByID->setObject(dextID, newdext);
5435 	} else {
5436 		/*
5437 		 * Remove the old dext
5438 		 */
5439 		removeKext(olddext, true);
5440 	}
5441 
5442 	/*
5443 	 * Inform userspace.
5444 	 */
5445 	if (newdext != NULL) {
5446 		result = notifyDextUpgrade(OSDynamicCast(OSString, dextID), newdext->getDextUniqueID());
5447 		if (result != kOSReturnSuccess) {
5448 			OSKextLog(NULL,
5449 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5450 			    "Cannot send upgrade notification for %s\n",
5451 			    dextID->getCStringNoCopy());
5452 		}
5453 	} else {
5454 		// notify dext removal
5455 		queueKextNotification(kKextRequestPredicateUnloadNotification,
5456 		    OSDynamicCast(OSString, dextID), oldDextUniqueIdentifier);
5457 	}
5458 
5459 	OSSafeReleaseNULL(dextID);
5460 	OSSafeReleaseNULL(oldDextUniqueIdentifier);
5461 }
5462 
5463 /*
5464  * To be called with sKextLock held.
5465  * NOTE: this could unload the olddext.
5466  */
5467 bool
upgradeDext(OSKext * olddext,OSKext * newdext)5468 OSKext::upgradeDext(OSKext *olddext, OSKext *newdext)
5469 {
5470 	const char * dextIDCS = newdext->getIdentifierCString();
5471 	__assert_only bool old_isDext = olddext->isDriverKit();
5472 	__assert_only bool new_isDext = newdext->isDriverKit();
5473 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5474 
5475 	assert(old_isDext && new_isDext);
5476 	assert(lock_held);
5477 
5478 	/*
5479 	 * New dext and old dext have the same ID.
5480 	 * We use this ID as key on the OSKext
5481 	 * dictionarys/arrays.
5482 	 */
5483 	const OSSymbol * dextID = newdext->getIdentifier();
5484 	__assert_only bool eq = dextID->isEqualTo(olddext->getIdentifier());
5485 	assert(eq);
5486 
5487 	/*
5488 	 * Set this OSKect as to update.
5489 	 * Note that this flags will never be removed once set.
5490 	 * When a OSKext is marked, it will be substitued by a new
5491 	 * OSKext, and every subsystem having a reference on this
5492 	 * OSKext need to know they have check if they can use
5493 	 * this OSKext or look for a new one.
5494 	 */
5495 	olddext->flags.dextToReplace = 1;
5496 
5497 	/*
5498 	 * Check if the current OSKext has any
5499 	 * userspace processes launched.
5500 	 * In this case we cannot upgrade and we have to
5501 	 * delay the upgrade until all processes
5502 	 * are done.
5503 	 */
5504 	if (olddext->dextLaunchedCount == 0) {
5505 		/*
5506 		 * Be sure that if there are no launched dexts, no
5507 		 * pending upgrades exist.
5508 		 * This is an error if it happens, as the decrement
5509 		 * should have removed the dext from sDriverKitToUpgradeByID
5510 		 * in case it reached 0.
5511 		 */
5512 		OSObject *pending_upgdare = sDriverKitToUpgradeByID->getObject(dextID);
5513 		if (pending_upgdare != NULL) {
5514 			OSKextLog(NULL,
5515 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5516 			    "Pending upgrade found for %s but dextLaunchedCount is 0!\n",
5517 			    dextIDCS);
5518 			goto out;
5519 		}
5520 
5521 		replaceDextInternal(olddext, newdext);
5522 		return true;
5523 	}
5524 
5525 out:
5526 
5527 	/*
5528 	 * Delay the upgrade.
5529 	 * Make the new dext available in sDriverKitToUpgradeByID.
5530 	 * In case there was already a pending upgrade, this will
5531 	 * overwrite it.
5532 	 */
5533 	sDriverKitToUpgradeByID->setObject(dextID, newdext);
5534 	return false;
5535 }
5536 
5537 /*
5538  * To be called with sKextLock held.
5539  * NOTE: this could unload the dext.
5540  */
5541 bool
removeDext(OSKext * dext)5542 OSKext::removeDext(OSKext *dext)
5543 {
5544 	__assert_only bool dext_isDext = dext->isDriverKit();
5545 	__assert_only bool lock_held = IORecursiveLockHaveLock(sKextLock);
5546 	IOReturn result;
5547 
5548 	assert(dext_isDext);
5549 	assert(lock_held);
5550 
5551 	/*
5552 	 * Set this OSKext to be unloaded when all running instances exit.
5553 	 */
5554 	dext->flags.dextToReplace = 1;
5555 
5556 	result = gIOCatalogue->terminateDriversForModule(
5557 		dext->getIdentifierCString(), /* unload */ false, /* asynchronous */ true);
5558 	if (result != kOSReturnSuccess) {
5559 		OSKextLog(dext,
5560 		    kOSKextLogErrorLevel |
5561 		    kOSKextLogKextBookkeepingFlag,
5562 		    "%s services failed to terminate - 0x%x.",
5563 		    dext->getIdentifierCString(), result);
5564 	}
5565 
5566 	dext->removePersonalitiesFromCatalog();
5567 	sDriverKitToUpgradeByID->removeObject(dext->getIdentifier());
5568 
5569 	/*
5570 	 * Check if the current OSKext has any
5571 	 * userspace processes launched.
5572 	 * In this case we cannot unload and we have to
5573 	 * delay the unload until all processes
5574 	 * are done.
5575 	 */
5576 	if (dext->dextLaunchedCount == 0) {
5577 		replaceDextInternal(dext, NULL);
5578 		return true;
5579 	}
5580 
5581 	return false;
5582 }
5583 
5584 bool
incrementDextLaunchCount(OSKext * dext,OSData * dextUniqueIDToMatch)5585 OSKext::incrementDextLaunchCount(OSKext *dext, OSData *dextUniqueIDToMatch)
5586 {
5587 	bool ret = false;
5588 	__assert_only bool isDext = dext->isDriverKit();
5589 	assert(isDext);
5590 
5591 	const char * dextIDCS = dext->getIdentifierCString();
5592 	OSData *myDextUniqueID = dext->getDextUniqueID();
5593 
5594 	if (!myDextUniqueID || !dextUniqueIDToMatch) {
5595 		OSKextLog(dext,
5596 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5597 		    "Cannot find dext UniqueID for %s, cannot increment dext launches\n",
5598 		    dextIDCS);
5599 		return ret;
5600 	}
5601 
5602 	unsigned int dextUniqueIDCStringSize = 0, dextUniqueIDToMatchCStringSize = 0;
5603 	const char *dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
5604 	const char *dextUniqueIDToMatchCString = getDextUniqueIDCString(dextUniqueIDToMatch, &dextUniqueIDToMatchCStringSize);
5605 	assert(dextUniqueIDCString != NULL);
5606 	assert(dextUniqueIDToMatchCString != NULL);
5607 
5608 	IORecursiveLockLock(sKextLock);
5609 
5610 	/*
5611 	 * Check that the dext we are referencing is the same
5612 	 * looked for the match.
5613 	 */
5614 	if (myDextUniqueID->isEqualTo(dextUniqueIDToMatch)) {
5615 		if (dext->flags.dextToReplace == 0 || dext->dextLaunchedCount > 0) {
5616 			if (dext->dextLaunchedCount == kOSKextMaxDextLaunchedCount) {
5617 				OSKextLog(dext,
5618 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5619 				    "Too many dexts launched for %s UniqueID %s\n",
5620 				    dextIDCS, dextUniqueIDCString);
5621 			} else {
5622 				dext->dextLaunchedCount++;
5623 				ret = true;
5624 
5625 				OSKextLog(dext,
5626 				    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5627 				    "New dext launched for  %s UniqueID %s",
5628 				    dextIDCS, dextUniqueIDCString);
5629 			}
5630 		} else {
5631 			OSKextLog(dext,
5632 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5633 			    "Dext %s UniqueID %s requires update, cannot launch a new dext\n",
5634 			    dextIDCS, dextUniqueIDCString);
5635 		}
5636 	} else {
5637 		OSKextLog(dext,
5638 		    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5639 		    "Dext %s: UniqueID %s does not match UniqueID looked for %s, cannot launch a new dext\n",
5640 		    dextIDCS, dextUniqueIDCString, dextUniqueIDToMatchCString);
5641 	}
5642 
5643 	IORecursiveLockUnlock(sKextLock);
5644 
5645 	if (dextUniqueIDCString != NULL) {
5646 		kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
5647 	}
5648 	if (dextUniqueIDToMatchCString != NULL) {
5649 		kfree_data(dextUniqueIDToMatchCString, dextUniqueIDToMatchCStringSize);
5650 	}
5651 	return ret;
5652 }
5653 
5654 bool
decrementDextLaunchCount(OSString * bundleID)5655 OSKext::decrementDextLaunchCount(OSString *bundleID)
5656 {
5657 	bool ret = false;
5658 	const char * dextIDCS;
5659 	OSData *myDextUniqueID;
5660 	unsigned int dextUniqueIDCStringSize = 0;
5661 	const char * dextUniqueIDCString = NULL;
5662 	OSKext* dext = NULL;
5663 
5664 	if (!bundleID) {
5665 		return ret;
5666 	}
5667 	dextIDCS = bundleID->getCStringNoCopy();
5668 
5669 	IORecursiveLockLock(sKextLock);
5670 
5671 	/*
5672 	 * Look for the dext with the bundle it. This
5673 	 * call is triggered only if a previous increment was
5674 	 * performed. It means that the dext could have not
5675 	 * been upgraded as its dextLaunchedCount was at least 1.
5676 	 * Because of this it still needs to be available
5677 	 * in sKextsByID.
5678 	 */
5679 	dext = OSDynamicCast(OSKext, sKextsByID->getObject(dextIDCS));
5680 	if (!dext || !dext->isDriverKit()) {
5681 		OSKextLog(NULL,
5682 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5683 		    "Cannot find dext for %s, cannot decrement dext launches\n",
5684 		    dextIDCS);
5685 
5686 		goto out_locked;
5687 	}
5688 
5689 	myDextUniqueID = dext->getDextUniqueID();
5690 	if (!myDextUniqueID) {
5691 		OSKextLog(dext,
5692 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5693 		    "Cannot find dext UniqueID for %s, cannot decrement dext launches\n",
5694 		    dextIDCS);
5695 
5696 		goto out_locked;
5697 	}
5698 	dextUniqueIDCString = getDextUniqueIDCString(myDextUniqueID, &dextUniqueIDCStringSize);
5699 	assert(dextUniqueIDCString != NULL);
5700 
5701 	if (dext->dextLaunchedCount == 0) {
5702 		OSKextLog(dext,
5703 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5704 		    "Over decrementing dext launch for %s UniqueID %s\n",
5705 		    dextIDCS, dextUniqueIDCString);
5706 
5707 		goto out_locked;
5708 	}
5709 
5710 	dext->dextLaunchedCount--;
5711 
5712 	OSKextLog(dext,
5713 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5714 	    "Dext terminated for %s UniqueID %s",
5715 	    dextIDCS, dextUniqueIDCString);
5716 
5717 	if (dext->dextLaunchedCount == 0 && dext->flags.dextToReplace == 1) {
5718 		/*
5719 		 * Find the upgraded dext.
5720 		 */
5721 		OSKext *newdext = OSDynamicCast(OSKext, sDriverKitToUpgradeByID->getObject(dextIDCS));
5722 		if (newdext) {
5723 			OSKextLog(dext,
5724 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5725 			    "Dext upgrade for %s UniqueID %s",
5726 			    dextIDCS, dextUniqueIDCString);
5727 			replaceDextInternal(dext, newdext);
5728 			/* NOTE dext could have been freed past this point */
5729 
5730 			sDriverKitToUpgradeByID->removeObject(dextIDCS);
5731 		} else {
5732 			OSKextLog(dext,
5733 			    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
5734 			    "Dext unload for %s UniqueID %s",
5735 			    dextIDCS, dextUniqueIDCString);
5736 			replaceDextInternal(dext, NULL);
5737 		}
5738 
5739 		ret = true;
5740 	}
5741 out_locked:
5742 	IORecursiveLockUnlock(sKextLock);
5743 
5744 	if (dextUniqueIDCString != NULL) {
5745 		kfree_data(dextUniqueIDCString, dextUniqueIDCStringSize);
5746 	}
5747 
5748 	return ret;
5749 }
5750 
5751 /*********************************************************************
5752 *********************************************************************/
5753 #if defined (__arm__)
5754 #include <arm/arch.h>
5755 #endif
5756 
5757 #if   defined (__x86_64__)
5758 #define ARCHNAME "x86_64"
5759 #elif defined (__arm64__)
5760 #define ARCHNAME "arm64"
5761 #elif defined (__arm__)
5762 
5763 #if defined (__ARM_ARCH_7S__)
5764 #define ARCHNAME "armv7s"
5765 #elif defined (__ARM_ARCH_7F__)
5766 #define ARCHNAME "armv7f"
5767 #elif defined (__ARM_ARCH_7K__)
5768 #define ARCHNAME "armv7k"
5769 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
5770 #define ARCHNAME "armv7"
5771 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
5772 #define ARCHNAME "armv6"
5773 #endif
5774 
5775 #elif defined (__arm64__)
5776 #define ARCHNAME "arm64"
5777 #else
5778 #error architecture not supported
5779 #endif
5780 
5781 #define ARCH_SEPARATOR_CHAR  '_'
5782 
5783 static char *
makeHostArchKey(const char * key,size_t * keySizeOut)5784 makeHostArchKey(const char * key, size_t * keySizeOut)
5785 {
5786 	char     * result = NULL;
5787 	size_t     keyLength = strlen(key);
5788 	size_t     keySize;
5789 
5790 	/* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
5791 	 */
5792 	keySize = 1 + 1 + keyLength + strlen(ARCHNAME);
5793 	result = (char *)kalloc_data_tag(keySize, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
5794 
5795 	if (!result) {
5796 		goto finish;
5797 	}
5798 	strlcpy(result, key, keySize);
5799 	result[keyLength++] = ARCH_SEPARATOR_CHAR;
5800 	result[keyLength] = '\0';
5801 	strlcat(result, ARCHNAME, keySize);
5802 	*keySizeOut = keySize;
5803 
5804 finish:
5805 	return result;
5806 }
5807 
5808 /*********************************************************************
5809 *********************************************************************/
5810 OSObject *
getPropertyForHostArch(const char * key)5811 OSKext::getPropertyForHostArch(const char * key)
5812 {
5813 	OSObject * result           = NULL;// do not release
5814 	size_t     hostArchKeySize  = 0;
5815 	char     * hostArchKey      = NULL;// must kfree
5816 
5817 	if (!key || !infoDict) {
5818 		goto finish;
5819 	}
5820 
5821 	/* Some properties are not allowed to be arch-variant:
5822 	 * - Any CFBundle... property.
5823 	 * - OSBundleIsInterface.
5824 	 * - OSKernelResource.
5825 	 */
5826 	if (STRING_HAS_PREFIX(key, "OS") ||
5827 	    STRING_HAS_PREFIX(key, "IO")) {
5828 		hostArchKey = makeHostArchKey(key, &hostArchKeySize);
5829 		if (!hostArchKey) {
5830 			OSKextLog(/* kext (this isn't about a kext) */ NULL,
5831 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
5832 			    "Allocation failure.");
5833 			goto finish;
5834 		}
5835 		result = infoDict->getObject(hostArchKey);
5836 	}
5837 
5838 	if (!result) {
5839 		result = infoDict->getObject(key);
5840 	}
5841 
5842 finish:
5843 	if (hostArchKey) {
5844 		kfree_data(hostArchKey, hostArchKeySize);
5845 	}
5846 	return result;
5847 }
5848 
5849 #if PRAGMA_MARK
5850 #pragma mark Load/Start/Stop/Unload
5851 #endif
5852 
5853 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
5854 
5855 /*********************************************************************
5856 * sExcludeListByID is a dictionary with keys / values of:
5857 *  key = bundleID string of kext we will not allow to load
5858 *  value = version string(s) of the kext that is to be denied loading.
5859 *      The version strings can be comma delimited.  For example if kext
5860 *      com.foocompany.fookext has two versions that we want to deny
5861 *      loading then the version strings might look like:
5862 *      1.0.0, 1.0.1
5863 *      If the current fookext has a version of 1.0.0 OR 1.0.1 we will
5864 *      not load the kext.
5865 *
5866 *      Value may also be in the form of "LE 2.0.0" (version numbers
5867 *      less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
5868 *      number less than 2.0.0 will not load)
5869 *
5870 *      NOTE - we cannot use the characters "<=" or "<" because we have code
5871 *      that serializes plists and treats '<' as a special character.
5872 *********************************************************************/
5873 bool
isInExcludeList(void)5874 OSKext::isInExcludeList(void)
5875 {
5876 	OSString *      versionString           = NULL;        // do not release
5877 	char *          versionCString          = NULL;        // do not free
5878 	size_t          i;
5879 	boolean_t       wantLessThan = false;
5880 	boolean_t       wantLessThanEqualTo = false;
5881 	boolean_t       isInExcludeList = true;
5882 	char            myBuffer[32];
5883 
5884 	IORecursiveLockLock(sKextLock);
5885 
5886 	if (!sExcludeListByID) {
5887 		isInExcludeList = false;
5888 	} else {
5889 		/* look up by bundleID in our exclude list and if found get version
5890 		 * string (or strings) that we will not allow to load
5891 		 */
5892 		versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID.get()));
5893 		if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
5894 			isInExcludeList = false;
5895 		}
5896 	}
5897 
5898 	IORecursiveLockUnlock(sKextLock);
5899 
5900 	if (!isInExcludeList) {
5901 		return false;
5902 	}
5903 
5904 	/* parse version strings */
5905 	versionCString = (char *) versionString->getCStringNoCopy();
5906 
5907 	/* look for "LT" or "LE" form of version string, must be in first two
5908 	 * positions.
5909 	 */
5910 	if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
5911 		wantLessThan = true;
5912 		versionCString += 2;
5913 	} else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
5914 		wantLessThanEqualTo = true;
5915 		versionCString += 2;
5916 	}
5917 
5918 	for (i = 0; *versionCString != 0x00; versionCString++) {
5919 		/* skip whitespace */
5920 		if (isWhiteSpace(*versionCString)) {
5921 			continue;
5922 		}
5923 
5924 		/* peek ahead for version string separator or null terminator */
5925 		if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
5926 			/* OK, we have a version string */
5927 			myBuffer[i++] = *versionCString;
5928 			myBuffer[i] = 0x00;
5929 
5930 			OSKextVersion excludeVers;
5931 			excludeVers = OSKextParseVersionString(myBuffer);
5932 
5933 			if (wantLessThanEqualTo) {
5934 				if (version <= excludeVers) {
5935 					return true;
5936 				}
5937 			} else if (wantLessThan) {
5938 				if (version < excludeVers) {
5939 					return true;
5940 				}
5941 			} else if (version == excludeVers) {
5942 				return true;
5943 			}
5944 
5945 			/* reset for the next (if any) version string */
5946 			i = 0;
5947 			wantLessThan = false;
5948 			wantLessThanEqualTo = false;
5949 		} else {
5950 			/* save valid version character */
5951 			myBuffer[i++] = *versionCString;
5952 
5953 			/* make sure bogus version string doesn't overrun local buffer */
5954 			if (i >= sizeof(myBuffer)) {
5955 				break;
5956 			}
5957 		}
5958 	}
5959 
5960 	return false;
5961 }
5962 
5963 /*********************************************************************
5964 * sNonLoadableKextsByID is a dictionary with keys / values of:
5965 *  key = bundleID string of kext we will not allow to load
5966 *  value = boolean (true == loadable, false == not loadable)
5967 *
5968 *  Only kexts which are in the AuxKC will be marked as "not loadble,"
5969 *  i.e., the value for the kext's bundleID will be false. All kexts in
5970 *  the primary and system KCs will always be marked as "loadable."
5971 *
5972 *  This list ultimately comes from kexts which have been uninstalled
5973 *  in user space by deleting the kext from disk, but which have not
5974 *  yet been removed from the AuxKC. Because the user could choose to
5975 *  re-install the exact same version of the kext, we need to keep
5976 *  a dictionary of boolean values so that user space only needs to
5977 *  keep a simple list of "uninstalled" or "missing" bundles. When
5978 *  a bundle is re-installed, the iokit daemon can use the
5979 *  AucKCBundleAvailable  predicate to set the individual kext's
5980 *  availability to true.
5981 *********************************************************************/
5982 bool
isLoadable(void)5983 OSKext::isLoadable(void)
5984 {
5985 	bool isLoadable = true;
5986 
5987 	if (kc_type != KCKindAuxiliary) {
5988 		/* this filtering only applies to kexts in the auxkc */
5989 		return true;
5990 	}
5991 
5992 	IORecursiveLockLock(sKextLock);
5993 
5994 	if (sNonLoadableKextsByID) {
5995 		/* look up by bundleID in our exclude list and if found get version
5996 		 * string (or strings) that we will not allow to load
5997 		 */
5998 		OSBoolean *loadableVal;
5999 		loadableVal = OSDynamicCast(OSBoolean, sNonLoadableKextsByID->getObject(bundleID.get()));
6000 		if (loadableVal && !loadableVal->getValue()) {
6001 			isLoadable = false;
6002 		}
6003 	}
6004 	IORecursiveLockUnlock(sKextLock);
6005 
6006 	return isLoadable;
6007 }
6008 
6009 /*********************************************************************
6010 *********************************************************************/
6011 /* static */
6012 OSReturn
loadKextWithIdentifier(const char * kextIdentifierCString,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)6013 OSKext::loadKextWithIdentifier(
6014 	const char       * kextIdentifierCString,
6015 	Boolean            allowDeferFlag,
6016 	Boolean            delayAutounloadFlag,
6017 	OSKextExcludeLevel startOpt,
6018 	OSKextExcludeLevel startMatchingOpt,
6019 	OSArray          * personalityNames)
6020 {
6021 	OSReturn   result         = kOSReturnError;
6022 	OSSharedPtr<OSString> kextIdentifier;
6023 
6024 	kextIdentifier = OSString::withCString(kextIdentifierCString);
6025 	if (!kextIdentifier) {
6026 		result = kOSKextReturnNoMemory;
6027 		goto finish;
6028 	}
6029 	result = OSKext::loadKextWithIdentifier(kextIdentifier.get(),
6030 	    NULL /* kextRef */,
6031 	    allowDeferFlag, delayAutounloadFlag,
6032 	    startOpt, startMatchingOpt, personalityNames);
6033 
6034 finish:
6035 	return result;
6036 }
6037 
6038 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSSharedPtr<OSObject> & kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)6039 OSKext::loadKextWithIdentifier(
6040 	OSString          * kextIdentifier,
6041 	OSSharedPtr<OSObject>         &kextRef,
6042 	Boolean             allowDeferFlag,
6043 	Boolean             delayAutounloadFlag,
6044 	OSKextExcludeLevel  startOpt,
6045 	OSKextExcludeLevel  startMatchingOpt,
6046 	OSArray           * personalityNames)
6047 {
6048 	OSObject * kextRefRaw = NULL;
6049 	OSReturn result;
6050 
6051 	result = loadKextWithIdentifier(kextIdentifier,
6052 	    &kextRefRaw,
6053 	    allowDeferFlag,
6054 	    delayAutounloadFlag,
6055 	    startOpt,
6056 	    startMatchingOpt,
6057 	    personalityNames);
6058 	if ((kOSReturnSuccess == result) && kextRefRaw) {
6059 		kextRef.reset(kextRefRaw, OSNoRetain);
6060 	}
6061 	return result;
6062 }
6063 
6064 /*********************************************************************
6065 *********************************************************************/
6066 OSReturn
loadKextWithIdentifier(OSString * kextIdentifier,OSObject ** kextRef,Boolean allowDeferFlag,Boolean delayAutounloadFlag,OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)6067 OSKext::loadKextWithIdentifier(
6068 	OSString          * kextIdentifier,
6069 	OSObject         ** kextRef,
6070 	Boolean             allowDeferFlag,
6071 	Boolean             delayAutounloadFlag,
6072 	OSKextExcludeLevel  startOpt,
6073 	OSKextExcludeLevel  startMatchingOpt,
6074 	OSArray           * personalityNames)
6075 {
6076 	OSReturn          result               = kOSReturnError;
6077 	OSReturn          pingResult           = kOSReturnError;
6078 	OSKext          * theKext              = NULL;        // do not release
6079 	OSSharedPtr<OSDictionary>   loadRequest;
6080 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
6081 
6082 	if (kextRef) {
6083 		*kextRef = NULL;
6084 	}
6085 
6086 	IORecursiveLockLock(sKextLock);
6087 
6088 	if (!kextIdentifier) {
6089 		result = kOSKextReturnInvalidArgument;
6090 		goto finish;
6091 	}
6092 
6093 	OSKext::recordIdentifierRequest(kextIdentifier);
6094 
6095 	theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
6096 	if (!theKext) {
6097 		if (!allowDeferFlag) {
6098 			OSKextLog(/* kext */ NULL,
6099 			    kOSKextLogErrorLevel |
6100 			    kOSKextLogLoadFlag,
6101 			    "Can't load kext %s - not found.",
6102 			    kextIdentifier->getCStringNoCopy());
6103 			goto finish;
6104 		}
6105 
6106 		if (!sKernelRequestsEnabled) {
6107 			OSKextLog(theKext,
6108 			    kOSKextLogErrorLevel |
6109 			    kOSKextLogLoadFlag,
6110 			    "Can't load kext %s - requests to user space are disabled.",
6111 			    kextIdentifier->getCStringNoCopy());
6112 			result = kOSKextReturnDisabled;
6113 			goto finish;
6114 		}
6115 
6116 		/* Create a new request unless one is already sitting
6117 		 * in sKernelRequests for this bundle identifier
6118 		 */
6119 		kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
6120 		if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
6121 			result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
6122 			    loadRequest);
6123 			if (result != kOSReturnSuccess) {
6124 				goto finish;
6125 			}
6126 			if (!_OSKextSetRequestArgument(loadRequest.get(),
6127 			    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
6128 				result = kOSKextReturnNoMemory;
6129 				goto finish;
6130 			}
6131 			if (!sKernelRequests->setObject(loadRequest.get())) {
6132 				result = kOSKextReturnNoMemory;
6133 				goto finish;
6134 			}
6135 
6136 			if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
6137 				result = kOSKextReturnNoMemory;
6138 				goto finish;
6139 			}
6140 
6141 			OSKextLog(theKext,
6142 			    kOSKextLogDebugLevel |
6143 			    kOSKextLogLoadFlag,
6144 			    "Kext %s not found; queued load request to user space.",
6145 			    kextIdentifier->getCStringNoCopy());
6146 		}
6147 
6148 		pingResult = OSKext::pingIOKitDaemon();
6149 		if (pingResult == kOSKextReturnDisabled) {
6150 			OSKextLog(/* kext */ NULL,
6151 			    ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
6152 			    kOSKextLogLoadFlag,
6153 			    "Kext %s might not load - " kIOKitDaemonName " is currently unavailable.",
6154 			    kextIdentifier->getCStringNoCopy());
6155 		}
6156 
6157 		result = kOSKextReturnDeferred;
6158 		goto finish;
6159 	}
6160 
6161 	result = theKext->load(startOpt, startMatchingOpt, personalityNames);
6162 
6163 	if (result != kOSReturnSuccess) {
6164 		OSKextLog(theKext,
6165 		    kOSKextLogErrorLevel |
6166 		    kOSKextLogLoadFlag,
6167 		    "Failed to load kext %s (error 0x%x).",
6168 		    kextIdentifier->getCStringNoCopy(), (int)result);
6169 
6170 		if (theKext->kc_type == KCKindUnknown) {
6171 			OSKext::removeKext(theKext,
6172 			    /* terminateService/removePersonalities */ true);
6173 		}
6174 		goto finish;
6175 	}
6176 
6177 	if (delayAutounloadFlag) {
6178 		OSKextLog(theKext,
6179 		    kOSKextLogProgressLevel |
6180 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6181 		    "Setting delayed autounload for %s.",
6182 		    kextIdentifier->getCStringNoCopy());
6183 		theKext->flags.delayAutounload = 1;
6184 	}
6185 
6186 finish:
6187 	if ((kOSReturnSuccess == result) && kextRef) {
6188 		*kextRef = theKext;
6189 		theKext->matchingRefCount++;
6190 		theKext->retain();
6191 	}
6192 
6193 	IORecursiveLockUnlock(sKextLock);
6194 
6195 	return result;
6196 }
6197 
6198 /*********************************************************************
6199 *********************************************************************/
6200 /* static */
6201 OSReturn
loadKextFromKC(OSKext * theKext,OSDictionary * requestDict)6202 OSKext::loadKextFromKC(OSKext *theKext, OSDictionary *requestDict)
6203 {
6204 	OSReturn  result = kOSReturnError;
6205 
6206 	OSBoolean *delayAutounloadBool     = NULL; // do not release
6207 	OSNumber  *startKextExcludeNum     = NULL; // do not release
6208 	OSNumber  *startMatchingExcludeNum = NULL; // do not release
6209 	OSArray   *personalityNames        = NULL; // do not release
6210 
6211 	/*
6212 	 * Default values for these options:
6213 	 *      regular autounload behavior
6214 	 *      start the kext
6215 	 *      send all personalities to the catalog
6216 	 */
6217 	Boolean            delayAutounload           = false;
6218 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
6219 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeNone;
6220 
6221 	IORecursiveLockLock(sKextLock);
6222 
6223 	OSKextLog(/* kext */ NULL,
6224 	    kOSKextLogDebugLevel |
6225 	    kOSKextLogIPCFlag,
6226 	    "Received kext KC load request from user space.");
6227 
6228 	/* Regardless of processing, the fact that we have gotten here means some
6229 	 * user-space program is up and talking to us, so we'll switch our kext
6230 	 * registration to reflect that.
6231 	 */
6232 	if (!sUserLoadsActive) {
6233 		OSKextLog(/* kext */ NULL,
6234 		    kOSKextLogProgressLevel |
6235 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6236 		    "Switching to late startup (user-space) kext loading policy.");
6237 		sUserLoadsActive = true;
6238 	}
6239 
6240 	delayAutounloadBool = OSDynamicCast(OSBoolean,
6241 	    _OSKextGetRequestArgument(requestDict,
6242 	    kKextRequestArgumentDelayAutounloadKey));
6243 	startKextExcludeNum = OSDynamicCast(OSNumber,
6244 	    _OSKextGetRequestArgument(requestDict,
6245 	    kKextRequestArgumentStartExcludeKey));
6246 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
6247 	    _OSKextGetRequestArgument(requestDict,
6248 	    kKextRequestArgumentStartMatchingExcludeKey));
6249 	personalityNames = OSDynamicCast(OSArray,
6250 	    _OSKextGetRequestArgument(requestDict,
6251 	    kKextRequestArgumentPersonalityNamesKey));
6252 
6253 	if (delayAutounloadBool) {
6254 		delayAutounload = delayAutounloadBool->getValue();
6255 	}
6256 	if (startKextExcludeNum) {
6257 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
6258 	}
6259 	if (startMatchingExcludeNum) {
6260 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
6261 	}
6262 
6263 	OSKextLog(/* kext */ NULL,
6264 	    kOSKextLogProgressLevel |
6265 	    kOSKextLogIPCFlag,
6266 	    "Received request from user space to load KC kext %s.",
6267 	    theKext->getIdentifierCString());
6268 
6269 	/* this could be in the Auxiliary KC, so record the load request */
6270 	OSKext::recordIdentifierRequest(OSDynamicCast(OSString, theKext->getIdentifier()));
6271 
6272 	/*
6273 	 * Load the kext
6274 	 */
6275 	result = theKext->load(startKextExcludeLevel,
6276 	    startMatchingExcludeLevel, personalityNames);
6277 
6278 	if (result != kOSReturnSuccess) {
6279 		OSKextLog(theKext,
6280 		    kOSKextLogErrorLevel |
6281 		    kOSKextLogLoadFlag,
6282 		    "Failed to load kext %s (error 0x%x).",
6283 		    theKext->getIdentifierCString(), (int)result);
6284 
6285 		OSKext::removeKext(theKext,
6286 		    /* terminateService/removePersonalities */ true);
6287 		goto finish;
6288 	} else {
6289 		OSKextLog(theKext,
6290 		    kOSKextLogProgressLevel |
6291 		    kOSKextLogLoadFlag,
6292 		    "Kext %s Loaded successfully from %s KC",
6293 		    theKext->getIdentifierCString(), theKext->getKCTypeString());
6294 	}
6295 
6296 	if (delayAutounload) {
6297 		OSKextLog(theKext,
6298 		    kOSKextLogProgressLevel |
6299 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6300 		    "Setting delayed autounload for %s.",
6301 		    theKext->getIdentifierCString());
6302 		theKext->flags.delayAutounload = 1;
6303 	}
6304 
6305 finish:
6306 	IORecursiveLockUnlock(sKextLock);
6307 
6308 	return result;
6309 }
6310 
6311 /*********************************************************************
6312 *********************************************************************/
6313 /* static */
6314 OSReturn
loadCodelessKext(OSString * kextIdentifier,OSDictionary * requestDict)6315 OSKext::loadCodelessKext(OSString *kextIdentifier, OSDictionary *requestDict)
6316 {
6317 	OSReturn  result = kOSReturnError;
6318 	OSDictionary *anInfoDict = NULL; // do not release
6319 
6320 	anInfoDict = OSDynamicCast(OSDictionary,
6321 	    _OSKextGetRequestArgument(requestDict,
6322 	    kKextRequestArgumentCodelessInfoKey));
6323 	if (anInfoDict == NULL) {
6324 		OSKextLog(/* kext */ NULL,
6325 		    kOSKextLogErrorLevel |
6326 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6327 		    "Missing 'Codeless Kext Info' dictionary in codeless kext load request of %s.",
6328 		    kextIdentifier->getCStringNoCopy());
6329 		return kOSKextReturnInvalidArgument;
6330 	}
6331 
6332 	IORecursiveLockLock(sKextLock);
6333 
6334 	OSKextLog(/* kext */ NULL,
6335 	    kOSKextLogProgressLevel |
6336 	    kOSKextLogIPCFlag,
6337 	    "Received request from user space to load codeless kext %s.",
6338 	    kextIdentifier->getCStringNoCopy());
6339 
6340 	{
6341 		// instantiate a new kext, and don't hold a reference
6342 		// (the kext subsystem will hold one implicitly)
6343 		OSKextInitResult ret;
6344 		OSSharedPtr<OSKext> newKext = OSKext::withCodelessInfo(anInfoDict, &ret);
6345 		if (!newKext) {
6346 			/*
6347 			 * We might have failed to create a new OSKext
6348 			 * because the old one should still be used.
6349 			 * Check if that is the case.
6350 			 */
6351 			if (ret != kOSKextInitFailure) {
6352 				result = kOSReturnSuccess;
6353 				goto finish;
6354 			}
6355 			OSKextLog(/* kext */ NULL,
6356 			    kOSKextLogErrorLevel |
6357 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6358 			    "Could not instantiate codeless kext.");
6359 			result = kOSKextReturnNotLoadable;
6360 			goto finish;
6361 		}
6362 		if (!kextIdentifier->isEqualTo(newKext->getIdentifierCString())) {
6363 			OSKextLog(/* kext */ NULL,
6364 			    kOSKextLogErrorLevel |
6365 			    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
6366 			    "Codeless kext identifiers don't match '%s' != '%s'",
6367 			    kextIdentifier->getCStringNoCopy(), newKext->getIdentifierCString());
6368 
6369 			OSKext::removeKext(newKext.get(), false);
6370 			result = kOSKextReturnInvalidArgument;
6371 			goto finish;
6372 		}
6373 
6374 		/* Record the request for the codeless kext */
6375 		OSKext::recordIdentifierRequest(OSDynamicCast(OSString, newKext->getIdentifier()));
6376 
6377 		result = kOSReturnSuccess;
6378 		/* Send the kext's personalities to the IOCatalog. This is an explicit load. */
6379 		result = newKext->sendPersonalitiesToCatalog(true, NULL);
6380 	}
6381 
6382 finish:
6383 	IORecursiveLockUnlock(sKextLock);
6384 
6385 	return result;
6386 }
6387 
6388 /*********************************************************************
6389 *********************************************************************/
6390 /* static */
6391 void
dropMatchingReferences(OSSet * kexts)6392 OSKext::dropMatchingReferences(
6393 	OSSet * kexts)
6394 {
6395 	IORecursiveLockLock(sKextLock);
6396 	kexts->iterateObjects(^bool (OSObject * obj) {
6397 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
6398 		if (!thisKext) {
6399 		        return false;
6400 		}
6401 		thisKext->matchingRefCount--;
6402 		return false;
6403 	});
6404 	IORecursiveLockUnlock(sKextLock);
6405 }
6406 
6407 /*********************************************************************
6408 *********************************************************************/
6409 /* static */
6410 void
recordIdentifierRequest(OSString * kextIdentifier)6411 OSKext::recordIdentifierRequest(
6412 	OSString * kextIdentifier)
6413 {
6414 	OSSharedPtr<const OSSymbol> kextIdentifierSymbol;
6415 	bool             fail                 = false;
6416 
6417 	if (!sAllKextLoadIdentifiers || !kextIdentifier) {
6418 		goto finish;
6419 	}
6420 
6421 	kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
6422 	if (!kextIdentifierSymbol) {
6423 		// xxx - this is really a basic alloc failure
6424 		fail = true;
6425 		goto finish;
6426 	}
6427 
6428 	IORecursiveLockLock(sKextLock);
6429 	if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol.get())) {
6430 		if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol.get())) {
6431 			fail = true;
6432 		} else {
6433 			// xxx - need to find a way to associate this whole func w/the kext
6434 			OSKextLog(/* kext */ NULL,
6435 			    // xxx - check level
6436 			    kOSKextLogStepLevel |
6437 			    kOSKextLogArchiveFlag,
6438 			    "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
6439 			    kextIdentifier->getCStringNoCopy());
6440 		}
6441 	}
6442 	IORecursiveLockUnlock(sKextLock);
6443 
6444 finish:
6445 
6446 	if (fail) {
6447 		OSKextLog(/* kext */ NULL,
6448 		    kOSKextLogErrorLevel |
6449 		    kOSKextLogArchiveFlag,
6450 		    "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
6451 		    kextIdentifier->getCStringNoCopy());
6452 	}
6453 	return;
6454 }
6455 
6456 /*********************************************************************
6457 *********************************************************************/
6458 OSReturn
load(OSKextExcludeLevel startOpt,OSKextExcludeLevel startMatchingOpt,OSArray * personalityNames)6459 OSKext::load(
6460 	OSKextExcludeLevel   startOpt,
6461 	OSKextExcludeLevel   startMatchingOpt,
6462 	OSArray            * personalityNames)
6463 {
6464 	OSReturn             result                       = kOSReturnError;
6465 	OSKextExcludeLevel   dependenciesStartOpt         = startOpt;
6466 	OSKextExcludeLevel   dependenciesStartMatchingOpt = startMatchingOpt;
6467 	unsigned int         i, count;
6468 	Boolean              alreadyLoaded                = false;
6469 	OSKext             * lastLoadedKext               = NULL;        // do not release
6470 
6471 	if (isInExcludeList()) {
6472 		OSKextLog(this,
6473 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
6474 		    kOSKextLogLoadFlag,
6475 		    "Kext %s is in exclude list, not loadable",
6476 		    getIdentifierCString());
6477 
6478 		result = kOSKextReturnNotLoadable;
6479 		goto finish;
6480 	}
6481 	if (!isLoadable()) {
6482 		OSKextLog(this,
6483 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
6484 		    kOSKextLogLoadFlag,
6485 		    "Kext %s is not loadable",
6486 		    getIdentifierCString());
6487 
6488 		result = kOSKextReturnNotLoadable;
6489 		goto finish;
6490 	}
6491 
6492 	if (isLoaded()) {
6493 		alreadyLoaded = true;
6494 		result = kOSReturnSuccess;
6495 
6496 		OSKextLog(this,
6497 		    kOSKextLogDebugLevel |
6498 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6499 		    "Kext %s is already loaded.",
6500 		    getIdentifierCString());
6501 		goto loaded;
6502 	}
6503 
6504 #if CONFIG_MACF
6505 	/*
6506 	 * On kxld and on embedded, only call into the MAC hook when on a
6507 	 * user thread, for access control over userspace kextloads.
6508 	 *
6509 	 * On non-kxld systems, additionally check the MAC hook for kexts in
6510 	 * the Pageable and Aux KCs, regardless of whether we are on a user
6511 	 * thread or not. This means on Apple silicon devices that the MAC
6512 	 * hook will only be useful to block 3rd party kexts loaded via
6513 	 * matching, and any kexts loaded from userspace kextloads.
6514 	 *
6515 	 * Note that this should _not_ be called on kexts loaded from the
6516 	 * kernel bootstrap thread as the kernel proc's cred struct is not
6517 	 * yet initialized! This won't happen on macOS because all the kexts
6518 	 * in the BootKC are self-contained and their kc_type = KCKindPrimary.
6519 	 */
6520 	if (current_task() != kernel_task
6521 #if XNU_TARGET_OS_OSX && !CONFIG_KXLD
6522 	    || (kc_type != KCKindPrimary && kc_type != KCKindUnknown)
6523 #endif
6524 	    ) {
6525 		int                 macCheckResult      = 0;
6526 		kauth_cred_t        cred                = NULL;
6527 
6528 		cred = kauth_cred_get_with_ref();
6529 		macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
6530 		kauth_cred_unref(&cred);
6531 
6532 		if (macCheckResult != 0) {
6533 			result = kOSReturnError;
6534 			OSKextLog(this,
6535 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6536 			    "Failed to load kext %s (MAC policy error 0x%x).",
6537 			    getIdentifierCString(), macCheckResult);
6538 			goto finish;
6539 		}
6540 	}
6541 #endif /* CONFIG_MACF */
6542 
6543 	if (!sLoadEnabled) {
6544 		OSKextLog(this,
6545 		    kOSKextLogErrorLevel |
6546 		    kOSKextLogLoadFlag,
6547 		    "Kext loading is disabled (attempt to load kext %s).",
6548 		    getIdentifierCString());
6549 		result = kOSKextReturnDisabled;
6550 		goto finish;
6551 	}
6552 
6553 	/* If we've pushed the next available load tag to the invalid value,
6554 	 * we can't load any more kexts.
6555 	 */
6556 	if (sNextLoadTag == kOSKextInvalidLoadTag) {
6557 		OSKextLog(this,
6558 		    kOSKextLogErrorLevel |
6559 		    kOSKextLogLoadFlag,
6560 		    "Can't load kext %s - no more load tags to assign.",
6561 		    getIdentifierCString());
6562 		result = kOSKextReturnNoResources;
6563 		goto finish;
6564 	}
6565 
6566 	/* This is a bit of a hack, because we shouldn't be handling
6567 	 * personalities within the load function.
6568 	 */
6569 	if (!declaresExecutable()) {
6570 		/* There is a special case where a non-executable kext can be loaded: the
6571 		 * AppleKextExcludeList.  Detect that special kext by bundle identifier and
6572 		 * load its metadata into the global data structures, if appropriate
6573 		 */
6574 		if (strcmp(getIdentifierCString(), kIOExcludeListBundleID) == 0) {
6575 			boolean_t updated = updateExcludeList(infoDict.get());
6576 			if (updated) {
6577 				OSKextLog(this,
6578 				    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
6579 				    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
6580 			}
6581 		}
6582 
6583 		if (isDriverKit()) {
6584 			if (loadTag == 0) {
6585 				sLoadedDriverKitKexts->setObject(this);
6586 				loadTag = sNextLoadTag++;
6587 			}
6588 		}
6589 		result = kOSReturnSuccess;
6590 		goto loaded;
6591 	}
6592 
6593 	/* Are we in safe boot?
6594 	 */
6595 	if (sSafeBoot && !isLoadableInSafeBoot()) {
6596 		OSKextLog(this,
6597 		    kOSKextLogErrorLevel |
6598 		    kOSKextLogLoadFlag,
6599 		    "Can't load kext %s - not loadable during safe boot.",
6600 		    getIdentifierCString());
6601 		result = kOSKextReturnBootLevel;
6602 		goto finish;
6603 	}
6604 
6605 	OSKextLog(this,
6606 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
6607 	    "Loading kext %s.",
6608 	    getIdentifierCString());
6609 
6610 #if !VM_MAPPED_KEXTS
6611 	if (isPrelinked() == false) {
6612 		OSKextLog(this,
6613 		    kOSKextLogErrorLevel |
6614 		    kOSKextLogLoadFlag,
6615 		    "Can't load kext %s - not in a kext collection.",
6616 		    getIdentifierCString());
6617 		result = kOSKextReturnDisabled;
6618 		goto finish;
6619 	}
6620 #endif /* defined(__x86_64__) */
6621 
6622 #if CONFIG_KXLD
6623 	if (!sKxldContext) {
6624 		kern_return_t kxldResult;
6625 		kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
6626 		    &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
6627 		    /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
6628 		if (kxldResult) {
6629 			OSKextLog(this,
6630 			    kOSKextLogErrorLevel |
6631 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
6632 			    "Can't load kext %s - failed to create link context.",
6633 			    getIdentifierCString());
6634 			result = kOSKextReturnNoMemory;
6635 			goto finish;
6636 		}
6637 	}
6638 #endif // CONFIG_KXLD
6639 
6640 	/* We only need to resolve dependencies once for the whole graph, but
6641 	 * resolveDependencies will just return if there's no work to do, so it's
6642 	 * safe to call it more than once.
6643 	 */
6644 	if (!resolveDependencies()) {
6645 		// xxx - check resolveDependencies() for log msg
6646 		OSKextLog(this,
6647 		    kOSKextLogErrorLevel |
6648 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6649 		    "Can't load kext %s - failed to resolve library dependencies.",
6650 		    getIdentifierCString());
6651 		result = kOSKextReturnDependencies;
6652 		goto finish;
6653 	}
6654 
6655 	/* If we are excluding just the kext being loaded now (and not its
6656 	 * dependencies), drop the exclusion level to none so dependencies
6657 	 * start and/or add their personalities.
6658 	 */
6659 	if (dependenciesStartOpt == kOSKextExcludeKext) {
6660 		dependenciesStartOpt = kOSKextExcludeNone;
6661 	}
6662 
6663 	if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
6664 		dependenciesStartMatchingOpt = kOSKextExcludeNone;
6665 	}
6666 
6667 	/* Load the dependencies, recursively.
6668 	 */
6669 	count = getNumDependencies();
6670 	for (i = 0; i < count; i++) {
6671 		OSKext * dependency = OSDynamicCast(OSKext,
6672 		    dependencies->getObject(i));
6673 		if (dependency == NULL) {
6674 			OSKextLog(this,
6675 			    kOSKextLogErrorLevel |
6676 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6677 			    "Internal error loading kext %s; dependency disappeared.",
6678 			    getIdentifierCString());
6679 			result = kOSKextReturnInternalError;
6680 			goto finish;
6681 		}
6682 
6683 		/* Dependencies must be started accorting to the opt,
6684 		 * but not given the personality names of the main kext.
6685 		 */
6686 		result = dependency->load(dependenciesStartOpt,
6687 		    dependenciesStartMatchingOpt,
6688 		    /* personalityNames */ NULL);
6689 		if (result != KERN_SUCCESS) {
6690 			OSKextLog(this,
6691 			    kOSKextLogErrorLevel |
6692 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
6693 			    "Dependency %s of kext %s failed to load.",
6694 			    dependency->getIdentifierCString(),
6695 			    getIdentifierCString());
6696 
6697 			OSKext::removeKext(dependency,
6698 			    /* terminateService/removePersonalities */ true);
6699 			result = kOSKextReturnDependencyLoadError;
6700 
6701 			goto finish;
6702 		}
6703 	}
6704 
6705 	result = loadExecutable();
6706 	if (result != KERN_SUCCESS) {
6707 		goto finish;
6708 	}
6709 
6710 	pendingPgoHead.next = &pendingPgoHead;
6711 	pendingPgoHead.prev = &pendingPgoHead;
6712 
6713 	// The kernel PRNG is not initialized when the first kext is
6714 	// loaded, so use early random
6715 	uuid_generate_early_random(instance_uuid);
6716 	account = IOMallocType(OSKextAccount);
6717 
6718 	account->loadTag = kmod_info->id;
6719 	account->site.refcount = 0;
6720 	account->site.flags = VM_TAG_KMOD;
6721 
6722 #if DEVELOPMENT || DEBUG
6723 	/* Setup the task reference group. */
6724 	(void)snprintf(account->task_refgrp_name, sizeof(account->task_refgrp_name),
6725 	    "task_%s", getIdentifierCString());
6726 	account->task_refgrp.grp_name = account->task_refgrp_name;
6727 	account->task_refgrp.grp_parent = &task_external_refgrp;
6728 	account->task_refgrp.grp_flags = OS_REFGRP_F_ALWAYS_ENABLED;
6729 	os_ref_log_init(&account->task_refgrp);
6730 #endif /* DEVELOPMENT || DEBUG */
6731 
6732 	account->kext = this;
6733 	if (gIOSurfaceIdentifier == bundleID) {
6734 		vm_tag_alloc(&account->site);
6735 		gIOSurfaceTag = account->site.tag;
6736 	}
6737 
6738 	flags.loaded = true;
6739 
6740 	/* Add the kext to the list of loaded kexts and update the kmod_info
6741 	 * struct to point to that of the last loaded kext (which is the way
6742 	 * it's always been done, though I'd rather do them in order now).
6743 	 */
6744 	lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
6745 	sLoadedKexts->setObject(this);
6746 
6747 	/* Keep the kernel itself out of the kmod list.
6748 	 */
6749 	if (lastLoadedKext->isKernel()) {
6750 		lastLoadedKext = NULL;
6751 	}
6752 
6753 	if (lastLoadedKext) {
6754 		kmod_info->next = lastLoadedKext->kmod_info;
6755 	}
6756 
6757 	notifyKextLoadObservers(this, kmod_info);
6758 
6759 	/* Make the global kmod list point at the just-loaded kext. Note that the
6760 	 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
6761 	 * although we do report it in kextstat these days by using the newer
6762 	 * OSArray of loaded kexts, which does contain it.
6763 	 *
6764 	 * (The OSKext object representing the kernel doesn't even have a kmod_info
6765 	 * struct, though I suppose we could stick a pointer to it from the
6766 	 * static struct in OSRuntime.cpp.)
6767 	 */
6768 	kmod = kmod_info;
6769 
6770 	/* Save the list of loaded kexts in case we panic.
6771 	 */
6772 	OSKext::saveLoadedKextPanicList();
6773 
6774 	if (isExecutable()) {
6775 		OSKext::updateLoadedKextSummaries();
6776 		savePanicString(/* isLoading */ true);
6777 
6778 #if CONFIG_DTRACE
6779 		registerWithDTrace();
6780 #else
6781 		jettisonLinkeditSegment();
6782 #endif /* CONFIG_DTRACE */
6783 
6784 #if !VM_MAPPED_KEXTS
6785 		/* If there is a page (or more) worth of padding after the end
6786 		 * of the last data section but before the end of the data segment
6787 		 * then free it in the same manner the LinkeditSegment is freed
6788 		 */
6789 		jettisonDATASegmentPadding();
6790 #endif
6791 	}
6792 
6793 loaded:
6794 	if (isExecutable() && !flags.started) {
6795 		if (startOpt == kOSKextExcludeNone) {
6796 			result = start();
6797 			if (result != kOSReturnSuccess) {
6798 				OSKextLog(this,
6799 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
6800 				    "Kext %s start failed (result 0x%x).",
6801 				    getIdentifierCString(), result);
6802 				result = kOSKextReturnStartStopError;
6803 			}
6804 		}
6805 	}
6806 
6807 	/* If not excluding matching, send the personalities to the kernel.
6808 	 * This never affects the result of the load operation.
6809 	 * This is a bit of a hack, because we shouldn't be handling
6810 	 * personalities within the load function.
6811 	 */
6812 	if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
6813 		result = sendPersonalitiesToCatalog(true, personalityNames);
6814 	}
6815 
6816 finish:
6817 
6818 	if (result != kOSReturnSuccess) {
6819 		OSKextLog(this,
6820 		    kOSKextLogErrorLevel |
6821 		    kOSKextLogLoadFlag,
6822 		    "Kext %s failed to load (0x%x).",
6823 		    getIdentifierCString(), (int)result);
6824 	} else if (!alreadyLoaded) {
6825 		OSKextLog(this,
6826 		    kOSKextLogProgressLevel |
6827 		    kOSKextLogLoadFlag,
6828 		    "Kext %s loaded.",
6829 		    getIdentifierCString());
6830 
6831 		queueKextNotification(kKextRequestPredicateLoadNotification,
6832 		    OSDynamicCast(OSString, bundleID.get()), getDextUniqueID());
6833 	}
6834 	return result;
6835 }
6836 
6837 #if CONFIG_KXLD
6838 /*********************************************************************
6839 *
6840 *********************************************************************/
6841 static char *
strdup(const char * string)6842 strdup(const char * string)
6843 {
6844 	char * result = NULL;
6845 	size_t size;
6846 
6847 	if (!string) {
6848 		goto finish;
6849 	}
6850 
6851 	size = 1 + strlen(string);
6852 	result = (char *)kalloc_data_tag(size, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
6853 	if (!result) {
6854 		goto finish;
6855 	}
6856 
6857 	memcpy(result, string, size);
6858 
6859 finish:
6860 	return result;
6861 }
6862 #endif // CONFIG_KXLD
6863 
6864 /*********************************************************************
6865 *
6866 *********************************************************************/
6867 
6868 kernel_section_t *
lookupSection(const char * segname,const char * secname)6869 OSKext::lookupSection(const char *segname, const char *secname)
6870 {
6871 	kernel_section_t         * found_section = NULL;
6872 	kernel_mach_header_t     * mh            = NULL;
6873 	kernel_segment_command_t * seg           = NULL;
6874 	kernel_section_t         * sec           = NULL;
6875 
6876 	if (!linkedExecutable) {
6877 		return NULL;
6878 	}
6879 
6880 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6881 
6882 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6883 		if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) {
6884 			continue;
6885 		}
6886 
6887 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6888 			if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) {
6889 				found_section = sec;
6890 				goto out;
6891 			}
6892 		}
6893 	}
6894 
6895 out:
6896 	return found_section;
6897 }
6898 
6899 /*********************************************************************
6900 *
6901 *********************************************************************/
6902 
6903 OSReturn
slidePrelinkedExecutable(bool doCoalescedSlides)6904 OSKext::slidePrelinkedExecutable(bool doCoalescedSlides)
6905 {
6906 	OSReturn                       result           = kOSKextReturnBadData;
6907 	kernel_mach_header_t         * mh               = NULL;
6908 	kernel_segment_command_t     * seg              = NULL;
6909 	kernel_segment_command_t     * linkeditSeg      = NULL;
6910 	kernel_section_t             * sec              = NULL;
6911 	char                         * linkeditBase     = NULL;
6912 	bool                           haveLinkeditBase = false;
6913 	char                         * relocBase        = NULL;
6914 	bool                           haveRelocBase    = false;
6915 	struct dysymtab_command      * dysymtab         = NULL;
6916 	struct linkedit_data_command * segmentSplitInfo = NULL;
6917 	struct symtab_command        * symtab           = NULL;
6918 	kernel_nlist_t               * sym              = NULL;
6919 	struct relocation_info       * reloc            = NULL;
6920 	uint32_t                       i                = 0;
6921 	int                            reloc_size;
6922 	vm_offset_t                    new_kextsize;
6923 	kc_format                    format             = KCFormatUnknown;
6924 
6925 	if (linkedExecutable == NULL || flags.builtin) {
6926 		result = kOSReturnSuccess;
6927 		goto finish;
6928 	}
6929 
6930 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
6931 	if (kernel_mach_header_is_in_fileset(mh)) {
6932 		// kexts in filesets are slid as part of collection sliding
6933 		result = kOSReturnSuccess;
6934 		goto finish;
6935 	}
6936 
6937 	segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
6938 
6939 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
6940 		if (!seg->vmaddr) {
6941 			continue;
6942 		}
6943 
6944 		seg->vmaddr = ml_static_slide(seg->vmaddr);
6945 
6946 #if KASLR_KEXT_DEBUG
6947 		IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
6948 		    seg->segname,
6949 		    (unsigned long)ml_static_unslide(seg->vmaddr),
6950 		    (unsigned long)seg->vmaddr);
6951 #endif
6952 
6953 		if (!haveRelocBase) {
6954 			relocBase = (char *) seg->vmaddr;
6955 			haveRelocBase = true;
6956 		}
6957 		if (!strcmp(seg->segname, "__LINKEDIT")) {
6958 			linkeditBase = (char *) seg->vmaddr - seg->fileoff;
6959 			haveLinkeditBase = true;
6960 			linkeditSeg = seg;
6961 		}
6962 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
6963 			sec->addr = ml_static_slide(sec->addr);
6964 
6965 #if KASLR_KEXT_DEBUG
6966 			IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
6967 			    sec->sectname,
6968 			    (unsigned long)ml_static_unslide(sec->addr),
6969 			    (unsigned long)sec->addr);
6970 #endif
6971 		}
6972 	}
6973 
6974 	dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
6975 
6976 	symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
6977 
6978 	if (symtab != NULL && doCoalescedSlides == false) {
6979 		/* Some pseudo-kexts have symbol tables without segments.
6980 		 * Ignore them. */
6981 		if (symtab->nsyms > 0 && haveLinkeditBase) {
6982 			sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
6983 			for (i = 0; i < symtab->nsyms; i++) {
6984 				if (sym[i].n_type & N_STAB) {
6985 					continue;
6986 				}
6987 				sym[i].n_value = ml_static_slide(sym[i].n_value);
6988 
6989 #if KASLR_KEXT_DEBUG
6990 #define MAX_SYMS_TO_LOG 5
6991 				if (i < MAX_SYMS_TO_LOG) {
6992 					IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
6993 					    (unsigned long)ml_static_unslide(sym[i].n_value),
6994 					    (unsigned long)sym[i].n_value);
6995 				}
6996 #endif
6997 			}
6998 		}
6999 	}
7000 
7001 	if (dysymtab != NULL && doCoalescedSlides == false) {
7002 		if (dysymtab->nextrel > 0) {
7003 			OSKextLog(this,
7004 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
7005 			    kOSKextLogLinkFlag,
7006 			    "Sliding kext %s: External relocations found.",
7007 			    getIdentifierCString());
7008 			goto finish;
7009 		}
7010 
7011 		if (dysymtab->nlocrel > 0) {
7012 			if (!haveLinkeditBase) {
7013 				OSKextLog(this,
7014 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
7015 				    kOSKextLogLinkFlag,
7016 				    "Sliding kext %s: No linkedit segment.",
7017 				    getIdentifierCString());
7018 				goto finish;
7019 			}
7020 
7021 			if (!haveRelocBase) {
7022 				OSKextLog(this,
7023 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
7024 				    kOSKextLogLinkFlag,
7025 #if __x86_64__
7026 				    "Sliding kext %s: No writable segments.",
7027 #else
7028 				    "Sliding kext %s: No segments.",
7029 #endif
7030 				    getIdentifierCString());
7031 				goto finish;
7032 			}
7033 
7034 			reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
7035 			reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
7036 
7037 			for (i = 0; i < dysymtab->nlocrel; i++) {
7038 				if (reloc[i].r_extern != 0
7039 				    || reloc[i].r_type != 0
7040 				    || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
7041 				    ) {
7042 					OSKextLog(this,
7043 					    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
7044 					    kOSKextLogLinkFlag,
7045 					    "Sliding kext %s: Unexpected relocation found.",
7046 					    getIdentifierCString());
7047 					goto finish;
7048 				}
7049 				if (reloc[i].r_pcrel != 0) {
7050 					continue;
7051 				}
7052 				uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
7053 				*relocAddr = ml_static_slide(*relocAddr);
7054 
7055 #if KASLR_KEXT_DEBUG
7056 #define MAX_DYSYMS_TO_LOG 5
7057 				if (i < MAX_DYSYMS_TO_LOG) {
7058 					IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
7059 					    (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
7060 					    (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
7061 				}
7062 #endif
7063 			}
7064 
7065 			/* We should free these relocations, not just delete the reference to them.
7066 			 * <rdar://problem/10535549> Free relocations from PIE kexts.
7067 			 *
7068 			 * For now, we do not free LINKEDIT for kexts with split segments.
7069 			 */
7070 			new_kextsize = round_page(kmod_info->size - reloc_size);
7071 			if (new_kextsize > UINT_MAX) {
7072 				OSKextLog(this,
7073 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
7074 				    kOSKextLogLinkFlag,
7075 				    "Kext %s: new kext size is too large.",
7076 				    getIdentifierCString());
7077 				goto finish;
7078 			}
7079 			if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
7080 				vm_offset_t     endofkext = kmod_info->address + kmod_info->size;
7081 				vm_offset_t     new_endofkext = kmod_info->address + new_kextsize;
7082 				vm_offset_t     endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
7083 				size_t          bytes_remaining = endofkext - endofrelocInfo;
7084 				OSSharedPtr<OSData>        new_osdata;
7085 
7086 				/* fix up symbol offsets if they are after the dsymtab local relocs */
7087 				if (symtab) {
7088 					if (dysymtab->locreloff < symtab->symoff) {
7089 						symtab->symoff -= reloc_size;
7090 					}
7091 					if (dysymtab->locreloff < symtab->stroff) {
7092 						symtab->stroff -= reloc_size;
7093 					}
7094 				}
7095 				if (dysymtab->locreloff < dysymtab->extreloff) {
7096 					dysymtab->extreloff -= reloc_size;
7097 				}
7098 
7099 				/* move data behind reloc info down to new offset */
7100 				if (endofrelocInfo < endofkext) {
7101 					memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
7102 				}
7103 
7104 				/* Create a new OSData for the smaller kext object and reflect
7105 				 * new linkedit segment size.
7106 				 */
7107 				linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
7108 				linkeditSeg->filesize = linkeditSeg->vmsize;
7109 
7110 				new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)new_kextsize);
7111 				if (new_osdata) {
7112 					/* Fix up kmod info and linkedExecutable.
7113 					 */
7114 					kmod_info->size = new_kextsize;
7115 					/*
7116 					 * Fileset KCs are mapped as a whole by iBoot.
7117 					 * Individual kext executables should not be unmapped
7118 					 * by xnu.
7119 					 * Doing so may result in panics like rdar://85419651
7120 					 */
7121 					if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
7122 						new_osdata->setDeallocFunction(NULL);
7123 					} else { // Not from a Fileset KC
7124 #if VM_MAPPED_KEXTS
7125 						new_osdata->setDeallocFunction(osdata_kext_free);
7126 #else
7127 						new_osdata->setDeallocFunction(osdata_phys_free);
7128 #endif
7129 					}
7130 					linkedExecutable->setDeallocFunction(NULL);
7131 					linkedExecutable = os::move(new_osdata);
7132 
7133 #if VM_MAPPED_KEXTS
7134 					kext_free(new_endofkext, (endofkext - new_endofkext));
7135 #else
7136 					ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
7137 #endif
7138 				}
7139 			}
7140 			dysymtab->nlocrel = 0;
7141 			dysymtab->locreloff = 0;
7142 		}
7143 	}
7144 
7145 	result = kOSReturnSuccess;
7146 finish:
7147 	return result;
7148 }
7149 
7150 /*********************************************************************
7151 * called only by load()
7152 *********************************************************************/
7153 OSReturn
loadExecutable()7154 OSKext::loadExecutable()
7155 {
7156 	OSReturn              result             = kOSReturnError;
7157 	OSSharedPtr<OSArray>  linkDependencies;
7158 	uint32_t              num_kmod_refs      = 0;
7159 	OSData              * theExecutable      = NULL;        // do not release
7160 	OSString            * versString         = NULL;        // do not release
7161 	const char          * versCString        = NULL;        // do not free
7162 	const char          * string             = NULL;        // do not free
7163 
7164 #if CONFIG_KXLD
7165 	unsigned int          i;
7166 	uint32_t              numDirectDependencies   = 0;
7167 	kern_return_t         kxldResult;
7168 	KXLDDependency     *  kxlddeps           = NULL;        // must kfree
7169 	uint32_t              num_kxlddeps       = 0;
7170 	struct mach_header ** kxldHeaderPtr      = NULL;        // do not free
7171 	struct mach_header  * kxld_header        = NULL;        // xxx - need to free here?
7172 #endif // CONFIG_KXLD
7173 
7174 	/* We need the version string for a variety of bits below.
7175 	 */
7176 	versString = OSDynamicCast(OSString,
7177 	    getPropertyForHostArch(kCFBundleVersionKey));
7178 	if (!versString) {
7179 		goto finish;
7180 	}
7181 	versCString = versString->getCStringNoCopy();
7182 
7183 	if (isKernelComponent()) {
7184 		if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
7185 			if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
7186 				OSKextLog(this,
7187 				    kOSKextLogErrorLevel |
7188 				    kOSKextLogLoadFlag,
7189 				    "Kernel component %s has incorrect version %s; "
7190 				    "expected %s.",
7191 				    getIdentifierCString(),
7192 				    versCString, KERNEL6_VERSION);
7193 				result = kOSKextReturnInternalError;
7194 				goto finish;
7195 			} else if (strcmp(versCString, osrelease)) {
7196 				OSKextLog(this,
7197 				    kOSKextLogErrorLevel |
7198 				    kOSKextLogLoadFlag,
7199 				    "Kernel component %s has incorrect version %s; "
7200 				    "expected %s.",
7201 				    getIdentifierCString(),
7202 				    versCString, osrelease);
7203 				result = kOSKextReturnInternalError;
7204 				goto finish;
7205 			}
7206 		}
7207 	}
7208 
7209 #if defined(__x86_64__) || defined(__i386__)
7210 	if (flags.resetSegmentsFromVnode) {
7211 		/* Fixup the chains and slide the mach headers */
7212 		kernel_mach_header_t *mh = (kernel_mach_header_t *)kmod_info->address;
7213 
7214 		if (i386_slide_individual_kext(mh, PE_get_kc_slide(kc_type)) != KERN_SUCCESS) {
7215 			result = kOSKextReturnValidation;
7216 			goto finish;
7217 		}
7218 	}
7219 #endif //(__x86_64__) || defined(__i386__)
7220 
7221 	if (isPrelinked()) {
7222 		goto register_kmod;
7223 	}
7224 
7225 	/* <rdar://problem/21444003> all callers must be entitled */
7226 	if (FALSE == IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement)) {
7227 		OSKextLog(this,
7228 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7229 		    "Not entitled to link kext '%s'",
7230 		    getIdentifierCString());
7231 		result = kOSKextReturnNotPrivileged;
7232 		goto finish;
7233 	}
7234 
7235 	theExecutable = getExecutable();
7236 	if (!theExecutable) {
7237 		if (declaresExecutable()) {
7238 			OSKextLog(this,
7239 			    kOSKextLogErrorLevel |
7240 			    kOSKextLogLoadFlag,
7241 			    "Can't load kext %s - executable is missing.",
7242 			    getIdentifierCString());
7243 			result = kOSKextReturnValidation;
7244 			goto finish;
7245 		}
7246 		goto register_kmod;
7247 	}
7248 
7249 	if (isInterface()) {
7250 		OSSharedPtr<OSData> executableCopy = OSData::withData(theExecutable);
7251 		if (executableCopy) {
7252 			setLinkedExecutable(executableCopy.get());
7253 		}
7254 		goto register_kmod;
7255 	}
7256 
7257 #if CONFIG_KXLD
7258 	numDirectDependencies = getNumDependencies();
7259 
7260 	if (flags.hasBleedthrough) {
7261 		linkDependencies = dependencies;
7262 	} else {
7263 		linkDependencies = OSArray::withArray(dependencies.get());
7264 		if (!linkDependencies) {
7265 			OSKextLog(this,
7266 			    kOSKextLogErrorLevel |
7267 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7268 			    "Can't allocate link dependencies to load kext %s.",
7269 			    getIdentifierCString());
7270 			goto finish;
7271 		}
7272 
7273 		for (i = 0; i < numDirectDependencies; ++i) {
7274 			OSKext * dependencyKext = OSDynamicCast(OSKext,
7275 			    dependencies->getObject(i));
7276 			dependencyKext->addBleedthroughDependencies(linkDependencies.get());
7277 		}
7278 	}
7279 
7280 	num_kxlddeps = linkDependencies->getCount();
7281 	if (!num_kxlddeps) {
7282 		OSKextLog(this,
7283 		    kOSKextLogErrorLevel |
7284 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
7285 		    "Can't load kext %s - it has no library dependencies.",
7286 		    getIdentifierCString());
7287 		goto finish;
7288 	}
7289 
7290 	kxlddeps = kalloc_type_tag(KXLDDependency, num_kxlddeps, Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
7291 	if (!kxlddeps) {
7292 		OSKextLog(this,
7293 		    kOSKextLogErrorLevel |
7294 		    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7295 		    "Can't allocate link context to load kext %s.",
7296 		    getIdentifierCString());
7297 		goto finish;
7298 	}
7299 	bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
7300 
7301 	for (i = 0; i < num_kxlddeps; ++i) {
7302 		OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
7303 
7304 		if (dependency->isInterface()) {
7305 			OSKext *interfaceTargetKext = NULL;        //do not release
7306 			OSData * interfaceTarget = NULL;        //do not release
7307 
7308 			if (dependency->isKernelComponent()) {
7309 				interfaceTargetKext = sKernelKext;
7310 				interfaceTarget = sKernelKext->linkedExecutable.get();
7311 			} else {
7312 				interfaceTargetKext = OSDynamicCast(OSKext,
7313 				    dependency->dependencies->getObject(0));
7314 
7315 				interfaceTarget = interfaceTargetKext->linkedExecutable.get();
7316 			}
7317 
7318 			if (!interfaceTarget) {
7319 				// panic?
7320 				goto finish;
7321 			}
7322 
7323 			/* The names set here aren't actually logged yet <rdar://problem/7941514>,
7324 			 * it will be useful to have them in the debugger.
7325 			 * strdup() failing isn't critical right here so we don't check that.
7326 			 */
7327 			kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
7328 			kxlddeps[i].kext_size = interfaceTarget->getLength();
7329 			kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
7330 
7331 			if (dependency->linkedExecutable != NULL) {
7332 				kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
7333 				kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
7334 			} else {
7335 				kxlddeps[i].interface = (u_char *) NULL;
7336 				kxlddeps[i].interface_size = 0;
7337 			}
7338 			kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
7339 		} else {
7340 			kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
7341 			kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
7342 			kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
7343 		}
7344 
7345 		kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
7346 	}
7347 
7348 	kxldHeaderPtr = &kxld_header;
7349 
7350 #if DEBUG
7351 	OSKextLog(this,
7352 	    kOSKextLogExplicitLevel |
7353 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
7354 	    "Kext %s - calling kxld_link_file:\n"
7355 	    "    kxld_context: %p\n"
7356 	    "    executable: %p    executable_length: %d\n"
7357 	    "    user_data: %p\n"
7358 	    "    kxld_dependencies: %p    num_dependencies: %d\n"
7359 	    "    kxld_header_ptr: %p    kmod_info_ptr: %p\n",
7360 	    getIdentifierCString(), sKxldContext,
7361 	    theExecutable->getBytesNoCopy(), theExecutable->getLength(),
7362 	    this, kxlddeps, num_kxlddeps,
7363 	    kxldHeaderPtr, &kmod_info);
7364 #endif
7365 
7366 	/* After this call, the linkedExecutable instance variable
7367 	 * should exist.
7368 	 */
7369 	kxldResult = kxld_link_file(sKxldContext,
7370 	    (u_char *)theExecutable->getBytesNoCopy(),
7371 	    theExecutable->getLength(),
7372 	    getIdentifierCString(), this, kxlddeps, num_kxlddeps,
7373 	    (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
7374 
7375 	if (kxldResult != KERN_SUCCESS) {
7376 		// xxx - add kxldResult here?
7377 		OSKextLog(this,
7378 		    kOSKextLogErrorLevel |
7379 		    kOSKextLogLoadFlag,
7380 		    "Can't load kext %s - link failed.",
7381 		    getIdentifierCString());
7382 		result = kOSKextReturnLinkError;
7383 		goto finish;
7384 	}
7385 
7386 	/* We've written data & instructions into kernel memory, so flush the data
7387 	 * cache and invalidate the instruction cache.
7388 	 * I/D caches are coherent on x86
7389 	 */
7390 #if !defined(__i386__) && !defined(__x86_64__)
7391 	flush_dcache(kmod_info->address, kmod_info->size, false);
7392 	invalidate_icache(kmod_info->address, kmod_info->size, false);
7393 #endif
7394 
7395 #else // !CONFIG_KXLD
7396 	OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7397 	    "Refusing to link non-prelinked kext: %s (no kxld support)", getIdentifierCString());
7398 	result = kOSKextReturnLinkError;
7399 	goto finish;
7400 #endif // CONFIG_KXLD
7401 
7402 register_kmod:
7403 
7404 	if (isInterface()) {
7405 		/* Whip up a fake kmod_info entry for the interface kext.
7406 		 */
7407 		kmod_info = kalloc_type(kmod_info_t, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
7408 		if (!kmod_info) {
7409 			result = KERN_MEMORY_ERROR;
7410 			goto finish;
7411 		}
7412 
7413 		/* A pseudokext has almost nothing in its kmod_info struct.
7414 		 */
7415 		kmod_info->info_version = KMOD_INFO_VERSION;
7416 
7417 		/* An interface kext doesn't have a linkedExecutable, so save a
7418 		 * copy of the UUID out of the original executable via copyUUID()
7419 		 * while we still have the original executable.
7420 		 */
7421 		interfaceUUID = copyUUID();
7422 	}
7423 
7424 	kmod_info->id = loadTag = sNextLoadTag++;
7425 	kmod_info->reference_count = 0;         // KMOD_DECL... sets it to -1 (invalid).
7426 
7427 	/* Stamp the bundle ID and version from the OSKext over anything
7428 	 * resident inside the kmod_info.
7429 	 */
7430 	string = getIdentifierCString();
7431 	strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
7432 
7433 	string = versCString;
7434 	strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
7435 
7436 	/* Add the dependencies' kmod_info structs as kmod_references.
7437 	 */
7438 	num_kmod_refs = getNumDependencies();
7439 	if (num_kmod_refs) {
7440 		kmod_info->reference_list = kalloc_type_tag(kmod_reference_t,
7441 		    num_kmod_refs, Z_WAITOK_ZERO, VM_KERN_MEMORY_OSKEXT);
7442 		if (!kmod_info->reference_list) {
7443 			result = KERN_MEMORY_ERROR;
7444 			goto finish;
7445 		}
7446 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
7447 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
7448 			OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
7449 			ref->info = refKext->kmod_info;
7450 			ref->info->reference_count++;
7451 
7452 			if (refIndex + 1 < num_kmod_refs) {
7453 				ref->next = kmod_info->reference_list + refIndex + 1;
7454 			}
7455 		}
7456 	}
7457 
7458 	if (kmod_info->hdr_size > UINT32_MAX) {
7459 		OSKextLog(this,
7460 		    kOSKextLogErrorLevel |
7461 		    kOSKextLogLoadFlag,
7462 #if __LP64__
7463 		    "Kext %s header size is too large (%lu > UINT32_MAX).",
7464 #else
7465 		    "Kext %s header size is too large (%u > UINT32_MAX).",
7466 #endif
7467 		    kmod_info->name,
7468 		    kmod_info->hdr_size);
7469 		result = KERN_FAILURE;
7470 		goto finish;
7471 	}
7472 
7473 	if (kmod_info->size > UINT32_MAX) {
7474 		OSKextLog(this,
7475 		    kOSKextLogErrorLevel |
7476 		    kOSKextLogLoadFlag,
7477 #if __LP64__
7478 		    "Kext %s size is too large (%lu > UINT32_MAX).",
7479 #else
7480 		    "Kext %s size is too large (%u > UINT32_MAX).",
7481 #endif
7482 		    kmod_info->name,
7483 		    kmod_info->size);
7484 		result = KERN_FAILURE;
7485 		goto finish;
7486 	}
7487 
7488 	if (!isInterface() && linkedExecutable) {
7489 		OSKextLog(this,
7490 		    kOSKextLogProgressLevel |
7491 		    kOSKextLogLoadFlag,
7492 		    "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
7493 		    kmod_info->name,
7494 		    (unsigned)kmod_info->size / PAGE_SIZE,
7495 		    (unsigned long)ml_static_unslide(kmod_info->address),
7496 		    (unsigned)kmod_info->id);
7497 	}
7498 
7499 	/* VM protections and wiring for the Aux KC are done at collection loading time */
7500 	if (kc_type != KCKindAuxiliary || flags.resetSegmentsFromVnode) {
7501 		/* if prelinked and primary KC, VM protections are already set */
7502 		result = setVMAttributes(!isPrelinked() || flags.resetSegmentsFromVnode, true);
7503 		if (result != KERN_SUCCESS) {
7504 			goto finish;
7505 		}
7506 	}
7507 
7508 #if KASAN
7509 	if (linkedExecutable) {
7510 		kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
7511 		    linkedExecutable->getLength(), getIdentifierCString());
7512 	}
7513 #else
7514 	if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
7515 		OSKextLog(this,
7516 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
7517 		    "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
7518 		    getIdentifierCString()
7519 		    );
7520 		result = KERN_FAILURE;
7521 		goto finish;
7522 	}
7523 #endif
7524 
7525 	result = kOSReturnSuccess;
7526 
7527 finish:
7528 
7529 #if CONFIG_KXLD
7530 	/* Clear up locally allocated dependency info.
7531 	 */
7532 	for (i = 0; i < num_kxlddeps; ++i) {
7533 		size_t size;
7534 
7535 		if (kxlddeps[i].kext_name) {
7536 			size = 1 + strlen(kxlddeps[i].kext_name);
7537 			kfree_data(kxlddeps[i].kext_name, size);
7538 		}
7539 		if (kxlddeps[i].interface_name) {
7540 			size = 1 + strlen(kxlddeps[i].interface_name);
7541 			kfree_data(kxlddeps[i].interface_name, size);
7542 		}
7543 	}
7544 	if (kxlddeps) {
7545 		kfree_type(KXLDDependency, num_kxlddeps, kxlddeps);
7546 	}
7547 #endif // CONFIG_KXLD
7548 
7549 	/* We no longer need the unrelocated executable (which the linker
7550 	 * has altered anyhow).
7551 	 */
7552 	setExecutable(NULL);
7553 
7554 	if (result != kOSReturnSuccess) {
7555 		OSKextLog(this,
7556 		    kOSKextLogErrorLevel |
7557 		    kOSKextLogLoadFlag,
7558 		    "Failed to load executable for kext %s.",
7559 		    getIdentifierCString());
7560 
7561 		if (kmod_info && kmod_info->reference_list) {
7562 			kfree_type(kmod_reference_t, num_kmod_refs,
7563 			    kmod_info->reference_list);
7564 		}
7565 		if (isInterface()) {
7566 			kfree_type(kmod_info_t, kmod_info);
7567 			kmod_info = NULL;
7568 		}
7569 		if (kc_type == KCKindUnknown) {
7570 			kmod_info = NULL;
7571 			if (linkedExecutable) {
7572 				linkedExecutable.reset();
7573 			}
7574 		}
7575 	}
7576 
7577 	return result;
7578 }
7579 
7580 /* static */
7581 void
jettisonFileSetLinkeditSegment(kernel_mach_header_t * mh)7582 OSKext::jettisonFileSetLinkeditSegment(kernel_mach_header_t *mh)
7583 {
7584 	kernel_segment_command_t *linkeditseg = NULL;
7585 
7586 	linkeditseg = getsegbynamefromheader(mh, SEG_LINKEDIT);
7587 	if (linkeditseg == NULL) {
7588 		panic("FileSet booted with no Linkedit segment");
7589 	}
7590 
7591 #if VM_MAPPED_KEXTS
7592 	/* BootKC on x86_64 is not vm mapped */
7593 	ml_static_mfree(linkeditseg->vmaddr, linkeditseg->vmsize);
7594 
7595 	OSKextLog(/* kext */ NULL,
7596 	    kOSKextLogProgressLevel |
7597 	    kOSKextLogGeneralFlag,
7598 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
7599 	    linkeditseg->vmaddr, linkeditseg->vmsize);
7600 #else
7601 	/* BootKC on arm64 is not vm mapped, but is slid */
7602 #if !CONFIG_SPTM
7603 	vm_offset_t linkedit_vmaddr = ml_static_ptovirt((vm_offset_t)(linkeditseg->vmaddr - gVirtBase + gPhysBase));
7604 #else
7605 	vm_offset_t linkedit_vmaddr = linkeditseg->vmaddr;
7606 #endif
7607 
7608 	ml_static_mfree(linkedit_vmaddr, (vm_size_t)linkeditseg->vmsize);
7609 
7610 	OSKextLog(/* kext */ NULL,
7611 	    kOSKextLogProgressLevel |
7612 	    kOSKextLogGeneralFlag,
7613 	    "Jettisoning fileset Linkedit segments from vmaddr %llx with size %llu",
7614 	    (unsigned long long)linkedit_vmaddr, (unsigned long long)linkeditseg->vmsize);
7615 #endif /* VM_MAPPED_KEXTS */
7616 }
7617 
7618 /*********************************************************************
7619 * The linkedit segment is used by the kext linker for dependency
7620 * resolution, and by dtrace for probe initialization. We can free it
7621 * for non-library kexts, since no kexts depend on non-library kexts
7622 * by definition, once dtrace has been initialized.
7623 *********************************************************************/
7624 void
jettisonLinkeditSegment(void)7625 OSKext::jettisonLinkeditSegment(void)
7626 {
7627 	kernel_mach_header_t     * machhdr = (kernel_mach_header_t *)kmod_info->address;
7628 	kernel_segment_command_t * linkedit = NULL;
7629 	vm_offset_t                start;
7630 	vm_size_t                  linkeditsize, kextsize;
7631 	OSSharedPtr<OSData>        data;
7632 	kc_format                format    = KCFormatUnknown;
7633 
7634 	if (isInFileset()) {
7635 		return;
7636 	}
7637 
7638 #if NO_KEXTD
7639 	/* We can free symbol tables for all embedded kexts because we don't
7640 	 * support runtime kext linking.
7641 	 */
7642 	if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
7643 #else
7644 	if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
7645 #endif
7646 		goto finish;
7647 	}
7648 
7649 	/* Find the linkedit segment.  If it's not the last segment, then freeing
7650 	 * it will fragment the kext into multiple VM regions, which OSKext is not
7651 	 * designed to handle, so we'll have to skip it.
7652 	 */
7653 	linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
7654 	if (!linkedit) {
7655 		goto finish;
7656 	}
7657 
7658 	if (round_page(kmod_info->address + kmod_info->size) !=
7659 	    round_page(linkedit->vmaddr + linkedit->vmsize)) {
7660 		goto finish;
7661 	}
7662 
7663 	/* Create a new OSData for the smaller kext object.
7664 	 */
7665 	linkeditsize = round_page(linkedit->vmsize);
7666 	kextsize = kmod_info->size - linkeditsize;
7667 	start = linkedit->vmaddr;
7668 
7669 	if (kextsize > UINT_MAX) {
7670 		goto finish;
7671 	}
7672 	data = OSData::withBytesNoCopy((void *)kmod_info->address, (unsigned int)kextsize);
7673 	if (!data) {
7674 		goto finish;
7675 	}
7676 
7677 	/* Fix the kmod info and linkedExecutable.
7678 	 */
7679 	kmod_info->size = kextsize;
7680 
7681 	/*
7682 	 * Fileset KCs are mapped as a whole by iBoot.
7683 	 * Individual kext executables should not be unmapped by xnu
7684 	 * Doing so may result in panics like rdar://85419651
7685 	 */
7686 	if (PE_get_kc_format(kc_type, &format) && (format == KCFormatFileset)) {
7687 		data->setDeallocFunction(NULL);
7688 	} else { // Not from a Fileset KC
7689 #if VM_MAPPED_KEXTS
7690 		data->setDeallocFunction(osdata_kext_free);
7691 #else
7692 		data->setDeallocFunction(osdata_phys_free);
7693 #endif
7694 	}
7695 	linkedExecutable->setDeallocFunction(NULL);
7696 	linkedExecutable = os::move(data);
7697 	flags.jettisonLinkeditSeg = 1;
7698 
7699 	/* Free the linkedit segment.
7700 	 */
7701 #if VM_MAPPED_KEXTS
7702 	kext_free(start, linkeditsize);
7703 #else
7704 	ml_static_mfree(start, linkeditsize);
7705 #endif
7706 
7707 finish:
7708 	return;
7709 }
7710 
7711 /*********************************************************************
7712 * If there are whole pages that are unused betweem the last section
7713 * of the DATA segment and the end of the DATA segment then we can free
7714 * them
7715 *********************************************************************/
7716 void
7717 OSKext::jettisonDATASegmentPadding(void)
7718 {
7719 	kernel_mach_header_t * mh;
7720 	kernel_segment_command_t * dataSeg;
7721 	kernel_section_t * sec, * lastSec;
7722 	vm_offset_t dataSegEnd, lastSecEnd;
7723 	vm_size_t padSize;
7724 
7725 	if (flags.builtin) {
7726 		return;
7727 	}
7728 	mh = (kernel_mach_header_t *)kmod_info->address;
7729 
7730 	if (isInFileset()) {
7731 		return;
7732 	}
7733 
7734 	dataSeg = getsegbynamefromheader(mh, SEG_DATA);
7735 	if (dataSeg == NULL) {
7736 		return;
7737 	}
7738 
7739 	lastSec = NULL;
7740 	sec = firstsect(dataSeg);
7741 	while (sec != NULL) {
7742 		lastSec = sec;
7743 		sec = nextsect(dataSeg, sec);
7744 	}
7745 
7746 	if (lastSec == NULL) {
7747 		return;
7748 	}
7749 
7750 	if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
7751 	    (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
7752 		return;
7753 	}
7754 
7755 	dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
7756 	lastSecEnd = round_page(lastSec->addr + lastSec->size);
7757 
7758 	if (dataSegEnd <= lastSecEnd) {
7759 		return;
7760 	}
7761 
7762 	padSize = dataSegEnd - lastSecEnd;
7763 
7764 	if (padSize >= PAGE_SIZE) {
7765 #if VM_MAPPED_KEXTS
7766 		kext_free(lastSecEnd, padSize);
7767 #else
7768 		ml_static_mfree(lastSecEnd, padSize);
7769 #endif
7770 	}
7771 }
7772 
7773 /*********************************************************************
7774 *********************************************************************/
7775 void
7776 OSKext::setLinkedExecutable(OSData * anExecutable)
7777 {
7778 	if (linkedExecutable) {
7779 		panic("Attempt to set linked executable on kext "
7780 		    "that already has one (%s).\n",
7781 		    getIdentifierCString());
7782 	}
7783 	linkedExecutable.reset(anExecutable, OSRetain);
7784 	return;
7785 }
7786 
7787 #if CONFIG_DTRACE
7788 /*********************************************************************
7789 * Go through all loaded kexts and tell them to register with dtrace.
7790 * The instance method only registers if necessary.
7791 *********************************************************************/
7792 /* static */
7793 void
7794 OSKext::registerKextsWithDTrace(void)
7795 {
7796 	uint32_t count = sLoadedKexts->getCount();
7797 	uint32_t i;
7798 
7799 	IORecursiveLockLock(sKextLock);
7800 
7801 	for (i = 0; i < count; i++) {
7802 		OSKext   * thisKext     = NULL;        // do not release
7803 
7804 		thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
7805 		if (!thisKext || !thisKext->isExecutable()) {
7806 			continue;
7807 		}
7808 
7809 		thisKext->registerWithDTrace();
7810 	}
7811 
7812 	IORecursiveLockUnlock(sKextLock);
7813 
7814 	return;
7815 }
7816 
7817 extern "C" {
7818 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
7819 extern int (*dtrace_modunload)(struct kmod_info *);
7820 };
7821 
7822 /*********************************************************************
7823 *********************************************************************/
7824 void
7825 OSKext::registerWithDTrace(void)
7826 {
7827 	/* Register kext with dtrace. A dtrace_modload failure should not
7828 	 * prevent a kext from loading, so we ignore the return code.
7829 	 */
7830 	if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
7831 		uint32_t modflag = 0;
7832 		OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
7833 
7834 		if (!sKeepSymbols && kc_type == KCKindPrimary) {
7835 			if (forceInit == kOSBooleanTrue) {
7836 				OSKextLog(this,
7837 				    kOSKextLogBasicLevel |
7838 				    kOSKextLogGeneralFlag,
7839 				    "Ignoring OSBundleForceDTraceInit for Boot KC Kext %s",
7840 				    getIdentifierCString());
7841 				forceInit = kOSBooleanFalse;
7842 			}
7843 			/* Linkedit segment of the Boot KC is gone, make sure fbt_provide_module don't use kernel symbols */
7844 			modflag |= KMOD_DTRACE_NO_KERNEL_SYMS;
7845 		}
7846 
7847 		if (forceInit == kOSBooleanTrue) {
7848 			modflag |= KMOD_DTRACE_FORCE_INIT;
7849 		}
7850 		if (flags.builtin) {
7851 			modflag |= KMOD_DTRACE_STATIC_KEXT;
7852 		}
7853 
7854 		(void)(*dtrace_modload)(kmod_info, modflag);
7855 		flags.dtraceInitialized = true;
7856 		jettisonLinkeditSegment();
7857 	}
7858 	return;
7859 }
7860 /*********************************************************************
7861 *********************************************************************/
7862 void
7863 OSKext::unregisterWithDTrace(void)
7864 {
7865 	/* Unregister kext with dtrace. A dtrace_modunload failure should not
7866 	 * prevent a kext from loading, so we ignore the return code.
7867 	 */
7868 	if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
7869 		(void)(*dtrace_modunload)(kmod_info);
7870 		flags.dtraceInitialized = false;
7871 	}
7872 	return;
7873 }
7874 #endif /* CONFIG_DTRACE */
7875 
7876 
7877 /*********************************************************************
7878 * called only by loadExecutable()
7879 *********************************************************************/
7880 #if !VM_MAPPED_KEXTS
7881 #if defined(__arm__) || defined(__arm64__)
7882 static inline kern_return_t
7883 OSKext_protect(
7884 	kernel_mach_header_t *kext_mh,
7885 	vm_map_t   map,
7886 	vm_map_offset_t    start,
7887 	vm_map_size_t      size,
7888 	vm_prot_t  new_prot,
7889 	boolean_t  set_max,
7890 	kc_kind_t  kc_type)
7891 {
7892 	vm_map_offset_t    end = start + size;
7893 
7894 #pragma unused(kext_mh,map,kc_type)
7895 	assert(map == kernel_map);         // we can handle KEXTs arising from the PRELINK segment and no others
7896 	assert(start <= end);
7897 	if (start >= end) {
7898 		return KERN_SUCCESS;         // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
7899 	} else if (set_max) {
7900 		return KERN_SUCCESS;         // Punt set_max, as there's no mechanism to record that state
7901 	} else {
7902 		return ml_static_protect(start, size, new_prot);
7903 	}
7904 }
7905 
7906 static inline kern_return_t
7907 OSKext_wire(
7908 	kernel_mach_header_t *kext_mh,
7909 	vm_map_t   map,
7910 	vm_map_offset_t    start,
7911 	vm_map_offset_t    end,
7912 	vm_prot_t  access_type,
7913 	boolean_t       user_wire,
7914 	kc_kind_t       kc_type)
7915 {
7916 #pragma unused(kext_mh,map,start,end,access_type,user_wire,kc_type)
7917 	return KERN_SUCCESS;         // No-op as PRELINK kexts are cemented into physical memory at boot
7918 }
7919 #else
7920 #error Unrecognized architecture
7921 #endif
7922 #else
7923 static inline kern_return_t
7924 OSKext_protect(
7925 	kernel_mach_header_t *kext_mh,
7926 	vm_map_t   map,
7927 	vm_map_offset_t    start,
7928 	vm_map_size_t      size,
7929 	vm_prot_t  new_prot,
7930 	boolean_t  set_max,
7931 	kc_kind_t  kc_type)
7932 {
7933 	vm_map_offset_t    end = start + size;
7934 
7935 	if (start == end) {         // 10538581
7936 		return KERN_SUCCESS;
7937 	}
7938 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7939 		/*
7940 		 * XXX: This will probably need to be different for AuxKC and
7941 		 * pageableKC!
7942 		 */
7943 		return ml_static_protect(start, size, new_prot);
7944 	}
7945 	return mach_vm_protect(map, start, size, set_max, new_prot);
7946 }
7947 
7948 static inline kern_return_t
7949 OSKext_wire(
7950 	kernel_mach_header_t *kext_mh,
7951 	vm_map_t   map,
7952 	vm_map_offset_t    start,
7953 	vm_map_offset_t    end,
7954 	vm_prot_t  access_type,
7955 	boolean_t       user_wire,
7956 	kc_kind_t       kc_type)
7957 {
7958 	if (kernel_mach_header_is_in_fileset(kext_mh) && kc_type == KCKindPrimary) {
7959 		/* TODO: we may need to hook this for the pageableKC */
7960 		return KERN_SUCCESS;
7961 	}
7962 	return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
7963 }
7964 #endif
7965 
7966 OSReturn
7967 OSKext::setVMAttributes(bool protect, bool wire)
7968 {
7969 	vm_map_t                    kext_map        = NULL;
7970 	kernel_segment_command_t  * seg             = NULL;
7971 	vm_map_offset_t             start_protect   = 0;
7972 	vm_map_offset_t             start_wire      = 0;
7973 	vm_map_offset_t             end_protect     = 0;
7974 	vm_map_size_t               size_protect    = 0;
7975 	vm_map_offset_t             end_wire        = 0;
7976 	OSReturn                    result          = kOSReturnError;
7977 
7978 	if (isInterface() || !declaresExecutable() || flags.builtin) {
7979 		result = kOSReturnSuccess;
7980 		goto finish;
7981 	}
7982 
7983 	/* Get the kext's vm map */
7984 	kext_map = kext_get_vm_map(kmod_info);
7985 	if (!kext_map) {
7986 		result = KERN_MEMORY_ERROR;
7987 		goto finish;
7988 	}
7989 
7990 #if !VM_MAPPED_KEXTS
7991 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
7992 		/* This is a split kext in a prelinked kernelcache; we'll let the
7993 		 * platform code take care of protecting it.  It is already wired.
7994 		 */
7995 		/* TODO: Should this still allow protections for the first segment
7996 		 * to go through, in the event that we have a mix of split and
7997 		 * unsplit kexts?
7998 		 */
7999 		result = KERN_SUCCESS;
8000 		goto finish;
8001 	}
8002 
8003 	if (isInFileset() && kc_type != KCKindPageable) {
8004 		// kexts in filesets have protections setup as part of collection loading
8005 		result = KERN_SUCCESS;
8006 		goto finish;
8007 	}
8008 #endif
8009 
8010 	/* Protect the headers as read-only; they do not need to be wired */
8011 	result = (protect) ? OSKext_protect((kernel_mach_header_t *)kmod_info->address,
8012 	    kext_map, kmod_info->address,
8013 	    kmod_info->hdr_size, VM_PROT_READ, TRUE, kc_type)
8014 	    : KERN_SUCCESS;
8015 	if (result != KERN_SUCCESS) {
8016 		goto finish;
8017 	}
8018 
8019 	/* Set the VM protections and wire down each of the segments */
8020 	seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8021 	while (seg) {
8022 #if __arm__
8023 		/* We build all ARM kexts, so we can ensure they are aligned */
8024 		assert((seg->vmaddr & PAGE_MASK) == 0);
8025 		assert((seg->vmsize & PAGE_MASK) == 0);
8026 #endif
8027 
8028 		/*
8029 		 * For the non page aligned segments, the range calculation for protection
8030 		 * and wiring differ as follows:
8031 		 *
8032 		 * Protection: The non page aligned data at the start or at the end of the
8033 		 * segment is excluded from the protection. This exclusion is needed to make
8034 		 * sure OSKext_protect is not called twice on same page, if the page is shared
8035 		 * between two segments.
8036 		 *
8037 		 * Wiring: The non page aligned data at the start or at the end of the
8038 		 * segment is included in the wiring range, this inclusion is needed to make sure
8039 		 * all the data of the segment is wired.
8040 		 */
8041 		start_protect = round_page(seg->vmaddr);
8042 		end_protect = trunc_page(seg->vmaddr + seg->vmsize);
8043 		size_protect = end_protect - start_protect;
8044 
8045 		start_wire = trunc_page(seg->vmaddr);
8046 		end_wire = round_page(seg->vmaddr + seg->vmsize);
8047 
8048 		/*
8049 		 * Linkedit and Linkinfo for the Pageable KC and the Aux KC are shared
8050 		 * across kexts and data from kexts is not page aligned
8051 		 */
8052 		if (protect && (end_protect > start_protect) &&
8053 		    ((strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0 &&
8054 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) != 0) ||
8055 		    (kc_type != KCKindPageable && kc_type != KCKindAuxiliary))) {
8056 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
8057 			    kext_map, start_protect, size_protect, seg->maxprot, TRUE, kc_type);
8058 			if (result != KERN_SUCCESS) {
8059 				OSKextLog(this,
8060 				    kOSKextLogErrorLevel |
8061 				    kOSKextLogLoadFlag,
8062 				    "Kext %s failed to set maximum VM protections "
8063 				    "for segment %s - 0x%x.",
8064 				    getIdentifierCString(), seg->segname, (int)result);
8065 				goto finish;
8066 			}
8067 
8068 			result = OSKext_protect((kernel_mach_header_t *)kmod_info->address,
8069 			    kext_map, start_protect, size_protect, seg->initprot, FALSE, kc_type);
8070 			if (result != KERN_SUCCESS) {
8071 				OSKextLog(this,
8072 				    kOSKextLogErrorLevel |
8073 				    kOSKextLogLoadFlag,
8074 				    "Kext %s failed to set initial VM protections "
8075 				    "for segment %s - 0x%x.",
8076 				    getIdentifierCString(), seg->segname, (int)result);
8077 				goto finish;
8078 			}
8079 		}
8080 
8081 		if (segmentShouldBeWired(seg) && wire) {
8082 			result = OSKext_wire((kernel_mach_header_t *)kmod_info->address,
8083 			    kext_map, start_wire, end_wire, seg->initprot, FALSE, kc_type);
8084 			if (result != KERN_SUCCESS) {
8085 				goto finish;
8086 			}
8087 		}
8088 
8089 		seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8090 	}
8091 
8092 finish:
8093 	return result;
8094 }
8095 
8096 /*********************************************************************
8097 *********************************************************************/
8098 boolean_t
8099 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
8100 {
8101 	return sKeepSymbols || (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) &&
8102 	       strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)));
8103 }
8104 
8105 /*********************************************************************
8106 *********************************************************************/
8107 OSReturn
8108 OSKext::validateKextMapping(bool startFlag)
8109 {
8110 	OSReturn                              result      = kOSReturnError;
8111 	const char                          * whichOp = startFlag ? "start" : "stop";
8112 	kern_return_t                         kern_result = 0;
8113 	vm_map_t                              kext_map    = NULL;
8114 	kernel_segment_command_t            * seg         = NULL;
8115 	mach_vm_address_t                     address     = 0;
8116 	mach_vm_size_t                        size        = 0;
8117 	uint32_t                              depth       = 0;
8118 	uint64_t                              kext_segbase = 0;
8119 	uint64_t                              kext_segsize = 0;
8120 	mach_msg_type_number_t                count;
8121 	vm_region_submap_short_info_data_64_t info;
8122 	uintptr_t                             kext_slide = PE_get_kc_slide(kc_type);
8123 
8124 	if (flags.builtin) {
8125 		return kOSReturnSuccess;
8126 	}
8127 
8128 	count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
8129 	bzero(&info, sizeof(info));
8130 
8131 	// xxx - do we need a distinct OSReturn value for these or is "bad data"
8132 	// xxx - sufficient?
8133 
8134 	/* Verify that the kmod_info and start/stop pointers are non-NULL.
8135 	 */
8136 	if (!kmod_info) {
8137 		OSKextLog(this,
8138 		    kOSKextLogErrorLevel |
8139 		    kOSKextLogLoadFlag,
8140 		    "Kext %s - NULL kmod_info pointer.",
8141 		    getIdentifierCString());
8142 		result = kOSKextReturnBadData;
8143 		goto finish;
8144 	}
8145 
8146 	if (startFlag) {
8147 		address = (mach_vm_address_t)kmod_info->start;
8148 	} else {
8149 		address = (mach_vm_address_t)kmod_info->stop;
8150 	}
8151 
8152 	if (!address) {
8153 		OSKextLog(this,
8154 		    kOSKextLogErrorLevel |
8155 		    kOSKextLogLoadFlag,
8156 		    "Kext %s - NULL module %s pointer.",
8157 		    getIdentifierCString(), whichOp);
8158 		result = kOSKextReturnBadData;
8159 		goto finish;
8160 	}
8161 
8162 	kext_map = kext_get_vm_map(kmod_info);
8163 	depth = (kernel_map == kext_map) ? 1 : 2;
8164 	if (isInFileset()) {
8165 #if defined(HAS_APPLE_PAC)
8166 		address = (mach_vm_address_t)ptrauth_auth_data((void*)address, ptrauth_key_function_pointer, 0);
8167 #endif /* defined(HAS_APPLE_PAC) */
8168 	}
8169 
8170 	/* Verify that the start/stop function lies within the kext's address range.
8171 	 */
8172 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO) ||
8173 	    isInFileset()) {
8174 		/* This will likely be how we deal with split kexts; walk the segments to
8175 		 * check that the function lies inside one of the segments of this kext.
8176 		 */
8177 		for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8178 		    seg != NULL;
8179 		    seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
8180 			if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
8181 				kext_segbase = seg->vmaddr;
8182 				kext_segsize = seg->vmsize;
8183 				break;
8184 			}
8185 		}
8186 
8187 		if (!seg) {
8188 			OSKextLog(this,
8189 			    kOSKextLogErrorLevel |
8190 			    kOSKextLogLoadFlag,
8191 			    "Kext %s module %s pointer is outside of kext range "
8192 			    "(%s %p - kext starts at %p).",
8193 			    getIdentifierCString(),
8194 			    whichOp,
8195 			    whichOp,
8196 			    (void *)(((uintptr_t)address) - kext_slide),
8197 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide));
8198 			result = kOSKextReturnBadData;
8199 			goto finish;
8200 		}
8201 
8202 		seg = NULL;
8203 	} else {
8204 		if (address < kmod_info->address + kmod_info->hdr_size ||
8205 		    kmod_info->address + kmod_info->size <= address) {
8206 			OSKextLog(this,
8207 			    kOSKextLogErrorLevel |
8208 			    kOSKextLogLoadFlag,
8209 			    "Kext %s module %s pointer is outside of kext range "
8210 			    "(%s %p - kext at %p-%p).",
8211 			    getIdentifierCString(),
8212 			    whichOp,
8213 			    whichOp,
8214 			    (void *)(((uintptr_t)address) - kext_slide),
8215 			    (void *)(((uintptr_t)kmod_info->address) - kext_slide),
8216 			    (void *)((((uintptr_t)kmod_info->address) - kext_slide) + kmod_info->size));
8217 			result = kOSKextReturnBadData;
8218 			goto finish;
8219 		}
8220 	}
8221 
8222 	/* Only do these checks before calling the start function;
8223 	 * If anything goes wrong with the mapping while the kext is running,
8224 	 * we'll likely have panicked well before any attempt to stop the kext.
8225 	 */
8226 	if (startFlag) {
8227 		if (!isInFileset() || kc_type != KCKindPrimary) {
8228 			/*
8229 			 * Verify that the start/stop function is executable.
8230 			 */
8231 			kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
8232 			    (vm_region_recurse_info_t)&info, &count);
8233 			if (kern_result != KERN_SUCCESS) {
8234 				OSKextLog(this,
8235 				    kOSKextLogErrorLevel |
8236 				    kOSKextLogLoadFlag,
8237 				    "Kext %s - bad %s pointer %p.",
8238 				    getIdentifierCString(),
8239 				    whichOp, (void *)ml_static_unslide(address));
8240 				result = kOSKextReturnBadData;
8241 				goto finish;
8242 			}
8243 		} else {
8244 			/*
8245 			 * Since kexts loaded from the primary KC are held in memory
8246 			 * allocated by efiboot, we cannot use mach_vm_region_recurse() to
8247 			 * discover that memory's protection flags.  Instead, we need to
8248 			 * get that information from the kernel pmap itself.  Above, we
8249 			 * (potentially) saved the size of the segment in which the address
8250 			 * in question was located.  If we have a non-zero size, verify
8251 			 * that all pages in the (address, address + kext_segsize) range
8252 			 * are marked executable.  If we somehow did not record the size
8253 			 * (or the base) just verify the single page that includes the address.
8254 			 */
8255 			if (kext_segbase == 0 || kext_segsize == 0) {
8256 				kext_segbase = address & ~(uint64_t)PAGE_MASK;
8257 				kext_segsize = PAGE_SIZE;
8258 			}
8259 		}
8260 
8261 #if VM_MAPPED_KEXTS
8262 		if (((!isInFileset() || kc_type != KCKindPrimary) && !(info.protection & VM_PROT_EXECUTE)) ||
8263 		    ((isInFileset() && kc_type == KCKindPrimary) &&
8264 		    ml_static_verify_page_protections(kext_segbase, kext_segsize, VM_PROT_EXECUTE) != KERN_SUCCESS)) {
8265 			OSKextLog(this,
8266 			    kOSKextLogErrorLevel |
8267 			    kOSKextLogLoadFlag,
8268 			    "Kext %s - memory region containing module %s function "
8269 			    "is not executable.",
8270 			    getIdentifierCString(), whichOp);
8271 			result = kOSKextReturnBadData;
8272 			goto finish;
8273 		}
8274 #endif
8275 
8276 		/* Verify that the kext's segments are backed by physical memory.
8277 		 */
8278 		seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8279 		while (seg) {
8280 			if (!verifySegmentMapping(seg)) {
8281 				result = kOSKextReturnBadData;
8282 				goto finish;
8283 			}
8284 
8285 			seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8286 		}
8287 	}
8288 
8289 	result = kOSReturnSuccess;
8290 finish:
8291 	return result;
8292 }
8293 
8294 /*********************************************************************
8295 *********************************************************************/
8296 boolean_t
8297 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
8298 {
8299 	mach_vm_address_t address = 0;
8300 
8301 	if (seg->vmsize > UINT32_MAX) {
8302 		return false;
8303 	}
8304 
8305 	if (!segmentShouldBeWired(seg)) {
8306 		return true;
8307 	}
8308 
8309 	for (address = seg->vmaddr;
8310 	    address < round_page(seg->vmaddr + seg->vmsize);
8311 	    address += PAGE_SIZE) {
8312 		if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
8313 			OSKextLog(this,
8314 			    kOSKextLogErrorLevel |
8315 			    kOSKextLogLoadFlag,
8316 			    "Kext %s - page %p is not backed by physical memory.",
8317 			    getIdentifierCString(),
8318 			    (void *)address);
8319 			return false;
8320 		}
8321 	}
8322 
8323 	return true;
8324 }
8325 
8326 /*********************************************************************
8327 *********************************************************************/
8328 static void
8329 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
8330 {
8331 	uint64_t                            stamp = 0;
8332 	firehose_tracepoint_id_u            trace_id;
8333 	struct firehose_trace_uuid_info_s   uuid_info_s;
8334 	firehose_trace_uuid_info_t          uuid_info = &uuid_info_s;
8335 	size_t                              uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
8336 	OSSharedPtr<OSData>                 uuid_data;
8337 
8338 	stamp = firehose_tracepoint_time(firehose_activity_flags_default);
8339 	trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
8340 
8341 	uuid_data = aKext->copyTextUUID();
8342 	if (uuid_data) {
8343 		memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
8344 	}
8345 
8346 	uuid_info->ftui_size    = size;
8347 	if (aKext->isDriverKit()) {
8348 		uuid_info->ftui_address = address;
8349 	} else {
8350 		uuid_info->ftui_address = ml_static_unslide(address);
8351 	}
8352 	os_log_encoded_metadata(trace_id, stamp, uuid_info, uuid_info_len);
8353 	return;
8354 }
8355 
8356 void
8357 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext)
8358 {
8359 	OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load);
8360 }
8361 
8362 /*********************************************************************
8363 *********************************************************************/
8364 OSReturn
8365 OSKext::start(bool startDependenciesFlag)
8366 {
8367 	OSReturn                            result = kOSReturnError;
8368 	kern_return_t                       (* startfunc)(kmod_info_t *, void *);
8369 	unsigned int                        i, count;
8370 	void                              * kmodStartData = NULL;
8371 
8372 	if (isStarted() || isInterface() || isKernelComponent()) {
8373 		result = kOSReturnSuccess;
8374 		goto finish;
8375 	}
8376 
8377 	if (!isLoaded()) {
8378 		OSKextLog(this,
8379 		    kOSKextLogErrorLevel |
8380 		    kOSKextLogLoadFlag,
8381 		    "Attempt to start nonloaded kext %s.",
8382 		    getIdentifierCString());
8383 		result = kOSKextReturnInvalidArgument;
8384 		goto finish;
8385 	}
8386 
8387 	if (!sLoadEnabled) {
8388 		OSKextLog(this,
8389 		    kOSKextLogErrorLevel |
8390 		    kOSKextLogLoadFlag,
8391 		    "Kext loading is disabled (attempt to start kext %s).",
8392 		    getIdentifierCString());
8393 		result = kOSKextReturnDisabled;
8394 		goto finish;
8395 	}
8396 
8397 	result = validateKextMapping(/* start? */ true);
8398 	if (result != kOSReturnSuccess) {
8399 		goto finish;
8400 	}
8401 
8402 	startfunc = kmod_info->start;
8403 
8404 	count = getNumDependencies();
8405 	for (i = 0; i < count; i++) {
8406 		OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
8407 		if (dependency == NULL) {
8408 			OSKextLog(this,
8409 			    kOSKextLogErrorLevel |
8410 			    kOSKextLogLoadFlag,
8411 			    "Kext %s start - internal error, dependency disappeared.",
8412 			    getIdentifierCString());
8413 			goto finish;
8414 		}
8415 		if (!dependency->isStarted()) {
8416 			if (startDependenciesFlag) {
8417 				OSReturn dependencyResult =
8418 				    dependency->start(startDependenciesFlag);
8419 				if (dependencyResult != KERN_SUCCESS) {
8420 					OSKextLog(this,
8421 					    kOSKextLogErrorLevel |
8422 					    kOSKextLogLoadFlag,
8423 					    "Kext %s start - dependency %s failed to start (error 0x%x).",
8424 					    getIdentifierCString(),
8425 					    dependency->getIdentifierCString(),
8426 					    dependencyResult);
8427 					goto finish;
8428 				}
8429 			} else {
8430 				OSKextLog(this,
8431 				    kOSKextLogErrorLevel |
8432 				    kOSKextLogLoadFlag,
8433 				    "Not starting %s - dependency %s not started yet.",
8434 				    getIdentifierCString(),
8435 				    dependency->getIdentifierCString());
8436 				result = kOSKextReturnStartStopError;         // xxx - make new return?
8437 				goto finish;
8438 			}
8439 		}
8440 	}
8441 
8442 	OSKextLog(this,
8443 	    kOSKextLogDetailLevel |
8444 	    kOSKextLogLoadFlag,
8445 	    "Kext %s calling module start function.",
8446 	    getIdentifierCString());
8447 
8448 	flags.starting = 1;
8449 
8450 	// Drop a log message so logd can grab the needed information to decode this kext
8451 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
8452 	result = OSRuntimeInitializeCPP(this);
8453 	if (result == KERN_SUCCESS) {
8454 		result = startfunc(kmod_info, kmodStartData);
8455 	}
8456 
8457 	flags.starting = 0;
8458 
8459 	/* On success overlap the setting of started/starting. On failure just
8460 	 * clear starting.
8461 	 */
8462 	if (result == KERN_SUCCESS) {
8463 		flags.started = 1;
8464 
8465 		// xxx - log start error from kernel?
8466 		OSKextLog(this,
8467 		    kOSKextLogProgressLevel |
8468 		    kOSKextLogLoadFlag,
8469 		    "Kext %s is now started.",
8470 		    getIdentifierCString());
8471 	} else {
8472 		invokeOrCancelRequestCallbacks(
8473 			/* result not actually used */ kOSKextReturnStartStopError,
8474 			/* invokeFlag */ false);
8475 		OSKextLog(this,
8476 		    kOSKextLogWarningLevel |
8477 		    kOSKextLogLoadFlag,
8478 		    "Kext %s did not start (return code 0x%x).",
8479 		    getIdentifierCString(), result);
8480 	}
8481 
8482 finish:
8483 	return result;
8484 }
8485 
8486 /*********************************************************************
8487 *********************************************************************/
8488 /* static */
8489 bool
8490 OSKext::canUnloadKextWithIdentifier(
8491 	OSString * kextIdentifier,
8492 	bool       checkClassesFlag)
8493 {
8494 	bool     result = false;
8495 	OSKext * aKext  = NULL;        // do not release
8496 
8497 	IORecursiveLockLock(sKextLock);
8498 
8499 	aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
8500 
8501 	if (!aKext) {
8502 		goto finish;         // can't unload what's not loaded
8503 	}
8504 
8505 	if (aKext->isLoaded()) {
8506 		if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
8507 			goto finish;
8508 		}
8509 		if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
8510 			goto finish;
8511 		}
8512 	}
8513 
8514 	result = true;
8515 
8516 finish:
8517 	IORecursiveLockUnlock(sKextLock);
8518 	return result;
8519 }
8520 
8521 /*********************************************************************
8522 *********************************************************************/
8523 OSReturn
8524 OSKext::stop(void)
8525 {
8526 	OSReturn result = kOSReturnError;
8527 	kern_return_t (*stopfunc)(kmod_info_t *, void *);
8528 
8529 	if (!isStarted() || isInterface()) {
8530 		result = kOSReturnSuccess;
8531 		goto finish;
8532 	}
8533 
8534 	if (!isLoaded()) {
8535 		OSKextLog(this,
8536 		    kOSKextLogErrorLevel |
8537 		    kOSKextLogLoadFlag,
8538 		    "Attempt to stop nonloaded kext %s.",
8539 		    getIdentifierCString());
8540 		result = kOSKextReturnInvalidArgument;
8541 		goto finish;
8542 	}
8543 
8544 	/* Refuse to stop if we have clients or instances. It is up to
8545 	 * the caller to make sure those aren't true.
8546 	 */
8547 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8548 		OSKextLog(this,
8549 		    kOSKextLogErrorLevel |
8550 		    kOSKextLogLoadFlag,
8551 		    "Kext %s - C++ instances; can't stop.",
8552 		    getIdentifierCString());
8553 		result = kOSKextReturnInUse;
8554 		goto finish;
8555 	}
8556 
8557 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8558 		OSKextLog(this,
8559 		    kOSKextLogErrorLevel |
8560 		    kOSKextLogLoadFlag,
8561 		    "Kext %s - has references (linkage or tracking object); "
8562 		    "can't stop.",
8563 		    getIdentifierCString());
8564 		result = kOSKextReturnInUse;
8565 		goto finish;
8566 	}
8567 
8568 	/* Note: If validateKextMapping fails on the stop & unload path,
8569 	 * we are in serious trouble and a kernel panic is likely whether
8570 	 * we stop & unload the kext or not.
8571 	 */
8572 	result = validateKextMapping(/* start? */ false);
8573 	if (result != kOSReturnSuccess) {
8574 		goto finish;
8575 	}
8576 
8577 	stopfunc = kmod_info->stop;
8578 	if (stopfunc) {
8579 		OSKextLog(this,
8580 		    kOSKextLogDetailLevel |
8581 		    kOSKextLogLoadFlag,
8582 		    "Kext %s calling module stop function.",
8583 		    getIdentifierCString());
8584 
8585 		flags.stopping = 1;
8586 
8587 		result = stopfunc(kmod_info, /* userData */ NULL);
8588 		if (result == KERN_SUCCESS) {
8589 			result = OSRuntimeFinalizeCPP(this);
8590 		}
8591 
8592 		flags.stopping = 0;
8593 
8594 		if (result == KERN_SUCCESS) {
8595 			flags.started = 0;
8596 
8597 			OSKextLog(this,
8598 			    kOSKextLogDetailLevel |
8599 			    kOSKextLogLoadFlag,
8600 			    "Kext %s is now stopped and ready to unload.",
8601 			    getIdentifierCString());
8602 		} else {
8603 			OSKextLog(this,
8604 			    kOSKextLogErrorLevel |
8605 			    kOSKextLogLoadFlag,
8606 			    "Kext %s did not stop (return code 0x%x).",
8607 			    getIdentifierCString(), result);
8608 			result = kOSKextReturnStartStopError;
8609 		}
8610 	}
8611 
8612 finish:
8613 	// Drop a log message so logd can update this kext's metadata
8614 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
8615 	return result;
8616 }
8617 
8618 /*********************************************************************
8619 *********************************************************************/
8620 OSReturn
8621 OSKext::unload(void)
8622 {
8623 	OSReturn        result = kOSReturnError;
8624 	unsigned int    index;
8625 	uint32_t        num_kmod_refs = 0;
8626 	OSKextAccount * freeAccount;
8627 	bool            in_fileset = false;
8628 
8629 	if (!sUnloadEnabled) {
8630 		OSKextLog(this,
8631 		    kOSKextLogErrorLevel |
8632 		    kOSKextLogLoadFlag,
8633 		    "Kext unloading is disabled (%s).",
8634 		    this->getIdentifierCString());
8635 
8636 		result = kOSKextReturnDisabled;
8637 		goto finish;
8638 	}
8639 
8640 	// cache this result so we don't need to access the kmod_info after
8641 	// it's been potentially free'd
8642 	in_fileset = isInFileset();
8643 
8644 	/* Refuse to unload if we have clients or instances. It is up to
8645 	 * the caller to make sure those aren't true.
8646 	 */
8647 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
8648 		// xxx - Don't log under errors? this is more of an info thing
8649 		OSKextLog(this,
8650 		    kOSKextLogErrorLevel |
8651 		    kOSKextLogKextBookkeepingFlag,
8652 		    "Can't unload kext %s; outstanding references %d (linkage or tracking object).",
8653 		    getIdentifierCString(), getRetainCount());
8654 		result = kOSKextReturnInUse;
8655 		goto finish;
8656 	}
8657 
8658 	if (isDriverKit()) {
8659 		index = sLoadedDriverKitKexts->getNextIndexOfObject(this, 0);
8660 		if (index != (unsigned int)-1) {
8661 			sLoadedDriverKitKexts->removeObject(index);
8662 			OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
8663 			loadTag = 0;
8664 		}
8665 	}
8666 
8667 	if (!isLoaded()) {
8668 		result = kOSReturnSuccess;
8669 		goto finish;
8670 	}
8671 
8672 	if (isKernelComponent()) {
8673 		result = kOSKextReturnInvalidArgument;
8674 		goto finish;
8675 	}
8676 
8677 	if (metaClasses && !OSMetaClass::removeClasses(metaClasses.get())) {
8678 		OSKextLog(this,
8679 		    kOSKextLogErrorLevel |
8680 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
8681 		    "Can't unload kext %s; classes have instances:",
8682 		    getIdentifierCString());
8683 		reportOSMetaClassInstances(kOSKextLogErrorLevel |
8684 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
8685 		result = kOSKextReturnInUse;
8686 		goto finish;
8687 	}
8688 
8689 	/* Note that the kext is unloading before running any code that
8690 	 * might be in the kext (request callbacks, module stop function).
8691 	 * We will deny certain requests made against a kext in the process
8692 	 * of unloading.
8693 	 */
8694 	flags.unloading = 1;
8695 
8696 	/* Update the string describing the last kext to unload in case we panic.
8697 	 */
8698 	savePanicString(/* isLoading */ false);
8699 
8700 	if (isStarted()) {
8701 		result = stop();
8702 		if (result != KERN_SUCCESS) {
8703 			OSKextLog(this,
8704 			    kOSKextLogErrorLevel |
8705 			    kOSKextLogLoadFlag,
8706 			    "Kext %s can't unload - module stop returned 0x%x.",
8707 			    getIdentifierCString(), (unsigned)result);
8708 			result = kOSKextReturnStartStopError;
8709 			goto finish;
8710 		}
8711 	}
8712 
8713 	OSKextLog(this,
8714 	    kOSKextLogProgressLevel |
8715 	    kOSKextLogLoadFlag,
8716 	    "Kext %s unloading.",
8717 	    getIdentifierCString());
8718 
8719 	{
8720 		struct list_head *p;
8721 		struct list_head *prev;
8722 		struct list_head *next;
8723 		for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
8724 			OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
8725 			s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
8726 			prev = p->prev;
8727 			next = p->next;
8728 			prev->next = next;
8729 			next->prev = prev;
8730 			p->prev = p;
8731 			p->next = p;
8732 			IORecursiveLockWakeup(sKextLock, s, false);
8733 		}
8734 	}
8735 
8736 
8737 	/* Even if we don't call the stop function, we want to be sure we
8738 	 * have no OSMetaClass references before unloading the kext executable
8739 	 * from memory. OSMetaClasses may have pointers into the kext executable
8740 	 * and that would cause a panic on OSKext::free() when metaClasses is freed.
8741 	 */
8742 	if (metaClasses) {
8743 		metaClasses->flushCollection();
8744 	}
8745 	(void) OSRuntimeFinalizeCPP(this);
8746 
8747 	/* Remove the kext from the list of loaded kexts, patch the gap
8748 	 * in the kmod_info_t linked list, and reset "kmod" to point to the
8749 	 * last loaded kext that isn't the fake kernel kext (sKernelKext).
8750 	 */
8751 	index = sLoadedKexts->getNextIndexOfObject(this, 0);
8752 	if (index != (unsigned int)-1) {
8753 		sLoadedKexts->removeObject(index);
8754 
8755 		OSKext * nextKext = OSDynamicCast(OSKext,
8756 		    sLoadedKexts->getObject(index));
8757 
8758 		if (nextKext) {
8759 			if (index > 0) {
8760 				OSKext * gapKext = OSDynamicCast(OSKext,
8761 				    sLoadedKexts->getObject(index - 1));
8762 
8763 				nextKext->kmod_info->next = gapKext->kmod_info;
8764 			} else {         /* index == 0 */
8765 				nextKext->kmod_info->next = NULL;
8766 			}
8767 		}
8768 
8769 		OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
8770 		if (lastKext && !lastKext->isKernel()) {
8771 			kmod = lastKext->kmod_info;
8772 		} else {
8773 			kmod = NULL;         // clear the global kmod variable
8774 		}
8775 	}
8776 
8777 	/* Clear out the kmod references that we're keeping for compatibility
8778 	 * with current panic backtrace code & kgmacros.
8779 	 * xxx - will want to update those bits sometime and remove this.
8780 	 */
8781 	num_kmod_refs = getNumDependencies();
8782 	if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
8783 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
8784 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
8785 			ref->info->reference_count--;
8786 		}
8787 		kfree_type(kmod_reference_t, num_kmod_refs,
8788 		    kmod_info->reference_list);
8789 	}
8790 
8791 #if CONFIG_DTRACE
8792 	unregisterWithDTrace();
8793 #endif /* CONFIG_DTRACE */
8794 
8795 	notifyKextUnloadObservers(this);
8796 
8797 	freeAccount = NULL;
8798 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
8799 	account->kext = NULL;
8800 	if (account->site.tag) {
8801 		account->site.flags |= VM_TAG_UNLOAD;
8802 	} else {
8803 		freeAccount = account;
8804 	}
8805 
8806 #if DEVELOPMENT || DEBUG
8807 	assertf(account->task_refgrp.grp_count == 0,
8808 	    "unloading a kext with active task references");
8809 #endif /* DEVELOPMENT || DEBUG */
8810 
8811 	lck_ticket_unlock(sKextAccountsLock);
8812 	if (freeAccount) {
8813 		IOFreeType(freeAccount, OSKextAccount);
8814 	}
8815 
8816 	/* Unwire and free the linked executable.
8817 	 */
8818 	if (linkedExecutable) {
8819 #if KASAN
8820 		kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
8821 #endif
8822 
8823 #if VM_MAPPED_KEXTS
8824 		if (!isInterface() && (!in_fileset || flags.resetSegmentsFromVnode)) {
8825 			kernel_segment_command_t *seg = NULL;
8826 			vm_map_t kext_map = kext_get_vm_map(kmod_info);
8827 
8828 			if (!kext_map) {
8829 				OSKextLog(this,
8830 				    kOSKextLogErrorLevel |
8831 				    kOSKextLogLoadFlag,
8832 				    "Failed to free kext %s; couldn't find the kext map.",
8833 				    getIdentifierCString());
8834 				result = kOSKextReturnInternalError;
8835 				goto finish;
8836 			}
8837 
8838 			OSKextLog(this,
8839 			    kOSKextLogProgressLevel |
8840 			    kOSKextLogLoadFlag,
8841 			    "Kext %s unwiring and unmapping linked executable.",
8842 			    getIdentifierCString());
8843 
8844 			seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
8845 			while (seg) {
8846 				if (segmentShouldBeWired(seg)) {
8847 					vm_map_offset_t start_wire = trunc_page(seg->vmaddr);
8848 					vm_map_offset_t end_wire = round_page(seg->vmaddr + seg->vmsize);
8849 
8850 					result = vm_map_unwire(kext_map, start_wire,
8851 					    end_wire, FALSE);
8852 					if (result != KERN_SUCCESS) {
8853 						OSKextLog(this,
8854 						    kOSKextLogErrorLevel |
8855 						    kOSKextLogLoadFlag,
8856 						    "Failed to unwire kext %s.",
8857 						    getIdentifierCString());
8858 						result = kOSKextReturnInternalError;
8859 						goto finish;
8860 					}
8861 				}
8862 
8863 				seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
8864 			}
8865 #if defined(__x86_64__) || defined(__i386__)
8866 			if (in_fileset && flags.resetSegmentsFromVnode) {
8867 				IORecursiveLockLock(sKextLock);
8868 				resetKCFileSetSegments();
8869 				IORecursiveLockUnlock(sKextLock);
8870 			}
8871 #endif // (__x86_64__) || defined(__i386__)
8872 		}
8873 #endif /* VM_MAPPED_KEXTS */
8874 		if (flags.resetSegmentsFromImmutableCopy) {
8875 			result = resetMutableSegments();
8876 			if (result != kOSReturnSuccess) {
8877 				OSKextLog(this,
8878 				    kOSKextLogErrorLevel |
8879 				    kOSKextLogLoadFlag,
8880 				    "Failed to reset kext %s.",
8881 				    getIdentifierCString());
8882 				result = kOSKextReturnInternalError;
8883 				goto finish;
8884 			}
8885 		}
8886 		if (kc_type == KCKindUnknown) {
8887 			linkedExecutable.reset();
8888 		}
8889 	}
8890 
8891 	/* An interface kext has a fake kmod_info that was allocated,
8892 	 * so we have to free it.
8893 	 */
8894 	if (isInterface()) {
8895 		kfree_type(kmod_info_t, kmod_info);
8896 		kmod_info = NULL;
8897 	}
8898 
8899 	if (!in_fileset) {
8900 		kmod_info = NULL;
8901 	}
8902 
8903 	flags.loaded = false;
8904 	flushDependencies();
8905 
8906 	/* save a copy of the bundle ID for us to check when deciding to
8907 	 * rebuild the kernel cache file.  If a kext was already in the kernel
8908 	 * cache and unloaded then later loaded we do not need to rebuild the
8909 	 * kernel cache.  9055303
8910 	 */
8911 	if (isPrelinked()) {
8912 		if (!_OSKextInUnloadedPrelinkedKexts(bundleID.get())) {
8913 			IORecursiveLockLock(sKextLock);
8914 			if (sUnloadedPrelinkedKexts) {
8915 				sUnloadedPrelinkedKexts->setObject(bundleID.get());
8916 			}
8917 			IORecursiveLockUnlock(sKextLock);
8918 		}
8919 	}
8920 
8921 	OSKextLog(this,
8922 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
8923 	    "Kext %s unloaded.", getIdentifierCString());
8924 
8925 	queueKextNotification(kKextRequestPredicateUnloadNotification,
8926 	    OSDynamicCast(OSString, bundleID.get()), getDextUniqueID());
8927 
8928 finish:
8929 	OSKext::saveLoadedKextPanicList();
8930 	OSKext::updateLoadedKextSummaries();
8931 
8932 	flags.unloading = 0;
8933 	return result;
8934 }
8935 
8936 /*********************************************************************
8937 * Assumes sKextLock is held.
8938 *********************************************************************/
8939 /* static */
8940 OSReturn
8941 OSKext::queueKextNotification(
8942 	const char * notificationName,
8943 	OSString   * kextIdentifier,
8944 	OSData     * dextUniqueIdentifier)
8945 {
8946 	OSReturn          result               = kOSReturnError;
8947 	OSSharedPtr<OSDictionary>    loadRequest;
8948 
8949 	if (!kextIdentifier) {
8950 		result = kOSKextReturnInvalidArgument;
8951 		goto finish;
8952 	}
8953 
8954 	/* Create a new request unless one is already sitting
8955 	 * in sKernelRequests for this bundle identifier
8956 	 */
8957 	result = _OSKextCreateRequest(notificationName, loadRequest);
8958 	if (result != kOSReturnSuccess) {
8959 		goto finish;
8960 	}
8961 	if (!_OSKextSetRequestArgument(loadRequest.get(),
8962 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
8963 		result = kOSKextReturnNoMemory;
8964 		goto finish;
8965 	}
8966 	if (NULL != dextUniqueIdentifier) {
8967 		if (!_OSKextSetRequestArgument(loadRequest.get(),
8968 		    kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) {
8969 			result = kOSKextReturnNoMemory;
8970 			goto finish;
8971 		}
8972 	}
8973 	if (!sKernelRequests->setObject(loadRequest.get())) {
8974 		result = kOSKextReturnNoMemory;
8975 		goto finish;
8976 	}
8977 
8978 	/* We might want to only queue the notification if the IOKit daemon is active,
8979 	 * but that wouldn't work for embedded. Note that we don't care if
8980 	 * the ping immediately succeeds here so don't do anything with the
8981 	 * result of this call.
8982 	 */
8983 	OSKext::pingIOKitDaemon();
8984 
8985 	result = kOSReturnSuccess;
8986 
8987 finish:
8988 	return result;
8989 }
8990 
8991 
8992 #if CONFIG_KXLD
8993 /*********************************************************************
8994 *********************************************************************/
8995 static void
8996 _OSKextConsiderDestroyingLinkContext(
8997 	__unused thread_call_param_t p0,
8998 	__unused thread_call_param_t p1)
8999 {
9000 	/* Take multiple locks in the correct order.
9001 	 */
9002 	IORecursiveLockLock(sKextLock);
9003 	IORecursiveLockLock(sKextInnerLock);
9004 
9005 	/* The first time we destroy the kxldContext is in the first
9006 	 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
9007 	 * before calling this function. Thereafter any call to this function
9008 	 * will actually destroy the context.
9009 	 */
9010 	if (sConsiderUnloadsCalled && sKxldContext) {
9011 		kxld_destroy_context(sKxldContext);
9012 		sKxldContext = NULL;
9013 	}
9014 
9015 	/* Free the thread_call that was allocated to execute this function.
9016 	 */
9017 	if (sDestroyLinkContextThread) {
9018 		if (!thread_call_free(sDestroyLinkContextThread)) {
9019 			OSKextLog(/* kext */ NULL,
9020 			    kOSKextLogErrorLevel |
9021 			    kOSKextLogGeneralFlag,
9022 			    "thread_call_free() failed for kext link context.");
9023 		}
9024 		sDestroyLinkContextThread = NULL;
9025 	}
9026 
9027 	IORecursiveLockUnlock(sKextInnerLock);
9028 	IORecursiveLockUnlock(sKextLock);
9029 
9030 	return;
9031 }
9032 
9033 /*********************************************************************
9034 * Destroying the kxldContext requires checking variables under both
9035 * sKextInnerLock and sKextLock, so we do it on a separate thread
9036 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
9037 * call relationship.
9038 *
9039 * This function must be invoked with sKextInnerLock held.
9040 * Do not call any function that takes sKextLock here!
9041 *********************************************************************/
9042 /* static */
9043 void
9044 OSKext::considerDestroyingLinkContext(void)
9045 {
9046 	IORecursiveLockLock(sKextInnerLock);
9047 
9048 	/* If we have already queued a thread to destroy the link context,
9049 	 * don't bother resetting; that thread will take care of it.
9050 	 */
9051 	if (sDestroyLinkContextThread) {
9052 		goto finish;
9053 	}
9054 
9055 	/* The function to be invoked in the thread will deallocate
9056 	 * this thread_call, so don't share it around.
9057 	 */
9058 	sDestroyLinkContextThread = thread_call_allocate(
9059 		&_OSKextConsiderDestroyingLinkContext, NULL);
9060 	if (!sDestroyLinkContextThread) {
9061 		OSKextLog(/* kext */ NULL,
9062 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
9063 		    "Can't create thread to destroy kext link context.");
9064 		goto finish;
9065 	}
9066 
9067 	thread_call_enter(sDestroyLinkContextThread);
9068 
9069 finish:
9070 	IORecursiveLockUnlock(sKextInnerLock);
9071 	return;
9072 }
9073 
9074 #else // !CONFIG_KXLD
9075 
9076 /* static */
9077 void
9078 OSKext::considerDestroyingLinkContext(void)
9079 {
9080 	return;
9081 }
9082 
9083 #endif // CONFIG_KXLD
9084 
9085 #if PRAGMA_MARK
9086 #pragma mark Autounload
9087 #endif
9088 /*********************************************************************
9089 * This is a static method because the kext will be deallocated if it
9090 * does unload!
9091 *********************************************************************/
9092 /* static */
9093 OSReturn
9094 OSKext::autounloadKext(OSKext * aKext)
9095 {
9096 	OSReturn result = kOSKextReturnInUse;
9097 
9098 #if NO_KEXTD
9099 	/*
9100 	 * Do not unload prelinked kexts on platforms that do not have an
9101 	 * IOKit daemon as there is no way to reload the kext or restart
9102 	 * matching.
9103 	 */
9104 	if (aKext->isPrelinked()) {
9105 		goto finish;
9106 	}
9107 #endif /* defined(__x86_64__) */
9108 
9109 	/* Check for external references to this kext (usu. dependents),
9110 	 * instances of defined classes (or classes derived from them),
9111 	 * outstanding requests.
9112 	 */
9113 	if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
9114 	    !aKext->flags.autounloadEnabled ||
9115 	    aKext->isKernelComponent()) {
9116 		goto finish;
9117 	}
9118 
9119 	/* Skip a delay-autounload kext, once.
9120 	 */
9121 	if (aKext->flags.delayAutounload) {
9122 		OSKextLog(aKext,
9123 		    kOSKextLogProgressLevel |
9124 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
9125 		    "Kext %s has delayed autounload set; skipping and clearing flag.",
9126 		    aKext->getIdentifierCString());
9127 		aKext->flags.delayAutounload = 0;
9128 		goto finish;
9129 	}
9130 
9131 	if (aKext->hasOSMetaClassInstances() ||
9132 	    aKext->countRequestCallbacks()) {
9133 		goto finish;
9134 	}
9135 
9136 	result = OSKext::removeKext(aKext);
9137 
9138 finish:
9139 	return result;
9140 }
9141 
9142 /*********************************************************************
9143 *********************************************************************/
9144 void
9145 _OSKextConsiderUnloads(
9146 	__unused thread_call_param_t p0,
9147 	__unused thread_call_param_t p1)
9148 {
9149 	bool         didUnload = false;
9150 	unsigned int count, i;
9151 
9152 	/* Take multiple locks in the correct order
9153 	 * (note also sKextSummaries lock further down).
9154 	 */
9155 	IORecursiveLockLock(sKextLock);
9156 	IORecursiveLockLock(sKextInnerLock);
9157 
9158 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
9159 
9160 	/* If the system is powering down, don't try to unload anything.
9161 	 */
9162 	if (sSystemSleep) {
9163 		goto finish;
9164 	}
9165 
9166 	OSKextLog(/* kext */ NULL,
9167 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
9168 	    "Checking for unused kexts to autounload.");
9169 
9170 	/*****
9171 	 * Remove any request callbacks marked as stale,
9172 	 * and mark as stale any currently in flight.
9173 	 */
9174 	count = sRequestCallbackRecords->getCount();
9175 	if (count) {
9176 		i = count - 1;
9177 		do {
9178 			OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
9179 			    sRequestCallbackRecords->getObject(i));
9180 			if (callbackRecord) {
9181 				OSBoolean * stale = OSDynamicCast(OSBoolean,
9182 				    callbackRecord->getObject(kKextRequestStaleKey));
9183 
9184 				if (stale == kOSBooleanTrue) {
9185 					OSKext::invokeRequestCallback(callbackRecord,
9186 					    kOSKextReturnTimeout);
9187 				} else {
9188 					callbackRecord->setObject(kKextRequestStaleKey,
9189 					    kOSBooleanTrue);
9190 				}
9191 			}
9192 		} while (i--);
9193 	}
9194 
9195 	/*****
9196 	 * Make multiple passes through the array of loaded kexts until
9197 	 * we don't unload any. This handles unwinding of dependency
9198 	 * chains. We have to go *backwards* through the array because
9199 	 * kexts are removed from it when unloaded, and we cannot make
9200 	 * a copy or we'll mess up the retain counts we rely on to
9201 	 * check whether a kext will unload. If only we could have
9202 	 * nonretaining collections like CF has....
9203 	 */
9204 	do {
9205 		didUnload = false;
9206 
9207 		count = sLoadedKexts->getCount();
9208 		if (count) {
9209 			i = count - 1;
9210 			do {
9211 				OSKext * thisKext = OSDynamicCast(OSKext,
9212 				    sLoadedKexts->getObject(i));
9213 				didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
9214 			} while (i--);
9215 		}
9216 	} while (didUnload);
9217 
9218 finish:
9219 	sConsiderUnloadsPending = false;
9220 	sConsiderUnloadsExecuted = true;
9221 
9222 	(void) OSKext::considerRebuildOfPrelinkedKernel();
9223 
9224 	IORecursiveLockUnlock(sKextInnerLock);
9225 	IORecursiveLockUnlock(sKextLock);
9226 
9227 	return;
9228 }
9229 
9230 /*********************************************************************
9231 * Do not call any function that takes sKextLock here!
9232 *********************************************************************/
9233 void
9234 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
9235 {
9236 	AbsoluteTime when;
9237 
9238 	IORecursiveLockLock(sKextInnerLock);
9239 
9240 	if (!sUnloadCallout) {
9241 		sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL);
9242 	}
9243 
9244 	/* we only reset delay value for unloading if we already have something
9245 	 * pending.  rescheduleOnlyFlag should not start the count down.
9246 	 */
9247 	if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
9248 		goto finish;
9249 	}
9250 
9251 	thread_call_cancel(sUnloadCallout);
9252 	if (OSKext::getAutounloadEnabled() && !sSystemSleep
9253 #if !NO_KEXTD
9254 	    && sIOKitDaemonActive
9255 #endif
9256 	    ) {
9257 		clock_interval_to_deadline(sConsiderUnloadDelay,
9258 		    1000 * 1000 * 1000, &when);
9259 
9260 		OSKextLog(/* kext */ NULL,
9261 		    kOSKextLogProgressLevel |
9262 		    kOSKextLogLoadFlag,
9263 		    "%scheduling %sscan for unused kexts in %lu seconds.",
9264 		    sConsiderUnloadsPending ? "Res" : "S",
9265 		    sConsiderUnloadsCalled ? "" : "initial ",
9266 		    (unsigned long)sConsiderUnloadDelay);
9267 
9268 		sConsiderUnloadsPending = true;
9269 		thread_call_enter_delayed(sUnloadCallout, when);
9270 	}
9271 
9272 finish:
9273 	/* The kxld context should be reused throughout boot.  We mark the end of
9274 	 * period as the first time considerUnloads() is called, and we destroy
9275 	 * the first kxld context in that function.  Afterwards, it will be
9276 	 * destroyed in flushNonloadedKexts.
9277 	 */
9278 	if (!sConsiderUnloadsCalled) {
9279 		sConsiderUnloadsCalled = true;
9280 		OSKext::considerDestroyingLinkContext();
9281 	}
9282 
9283 	IORecursiveLockUnlock(sKextInnerLock);
9284 	return;
9285 }
9286 
9287 /*********************************************************************
9288 * Do not call any function that takes sKextLock here!
9289 *********************************************************************/
9290 extern "C" {
9291 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
9292 IOReturn
9293 OSKextSystemSleepOrWake(UInt32 messageType)
9294 {
9295 	IORecursiveLockLock(sKextInnerLock);
9296 
9297 	/* If the system is going to sleep, cancel the reaper thread timer,
9298 	 * and note that we're in a sleep state in case it just fired but hasn't
9299 	 * taken the lock yet. If we are coming back from sleep, just
9300 	 * clear the sleep flag; IOService's normal operation will cause
9301 	 * unloads to be considered soon enough.
9302 	 */
9303 	if (messageType == kIOMessageSystemWillSleep) {
9304 		if (sUnloadCallout) {
9305 			thread_call_cancel(sUnloadCallout);
9306 		}
9307 		sSystemSleep = true;
9308 		AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
9309 	} else if (messageType == kIOMessageSystemHasPoweredOn) {
9310 		sSystemSleep = false;
9311 		clock_get_uptime(&sLastWakeTime);
9312 	}
9313 	IORecursiveLockUnlock(sKextInnerLock);
9314 
9315 	return kIOReturnSuccess;
9316 }
9317 };
9318 
9319 
9320 #if PRAGMA_MARK
9321 #pragma mark Prelinked Kernel
9322 #endif
9323 
9324 #ifdef CONFIG_KXLD
9325 /*********************************************************************
9326 * Do not access sConsiderUnloads... variables other than
9327 * sConsiderUnloadsExecuted in this function. They are guarded by a
9328 * different lock.
9329 *********************************************************************/
9330 /* static */
9331 void
9332 OSKext::considerRebuildOfPrelinkedKernel(void)
9333 {
9334 	static bool     requestedPrelink        = false;
9335 	OSReturn        checkResult             = kOSReturnError;
9336 	OSSharedPtr<OSDictionary>         prelinkRequest;
9337 	OSSharedPtr<OSCollectionIterator> kextIterator;
9338 	const OSSymbol * thisID                 = NULL;        // do not release
9339 	bool            doRebuild               = false;
9340 	AbsoluteTime    my_abstime;
9341 	UInt64          my_ns;
9342 	SInt32          delta_secs;
9343 
9344 	/* Only one auto rebuild per boot and only on boot from prelinked kernel */
9345 	if (requestedPrelink || !sPrelinkBoot) {
9346 		return;
9347 	}
9348 
9349 	/* no direct return from this point */
9350 	IORecursiveLockLock(sKextLock);
9351 
9352 	/* We need to wait for the IOKit daemon to get up and running with unloads already done
9353 	 * and any new startup kexts loaded.
9354 	 */
9355 	if (!sConsiderUnloadsExecuted ||
9356 	    !sDeferredLoadSucceeded) {
9357 		goto finish;
9358 	}
9359 
9360 	/* we really only care about boot / system start up related kexts so bail
9361 	 * if we're here after REBUILD_MAX_TIME.
9362 	 */
9363 	if (!_OSKextInPrelinkRebuildWindow()) {
9364 		OSKextLog(/* kext */ NULL,
9365 		    kOSKextLogArchiveFlag,
9366 		    "%s prebuild rebuild has expired",
9367 		    __FUNCTION__);
9368 		requestedPrelink = true;
9369 		goto finish;
9370 	}
9371 
9372 	/* we do not want to trigger a rebuild if we get here too close to waking
9373 	 * up.  (see radar 10233768)
9374 	 */
9375 	IORecursiveLockLock(sKextInnerLock);
9376 
9377 	clock_get_uptime(&my_abstime);
9378 	delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
9379 	if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
9380 		SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
9381 		absolutetime_to_nanoseconds(my_abstime, &my_ns);
9382 		delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
9383 	}
9384 	IORecursiveLockUnlock(sKextInnerLock);
9385 
9386 	if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
9387 		/* too close to time of last wake from sleep */
9388 		goto finish;
9389 	}
9390 	requestedPrelink = true;
9391 
9392 	/* Now it's time to see if we have a reason to rebuild.  We may have done
9393 	 * some loads and unloads but the kernel cache didn't actually change.
9394 	 * We will rebuild if any kext is not marked prelinked AND is not in our
9395 	 * list of prelinked kexts that got unloaded.  (see radar 9055303)
9396 	 */
9397 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
9398 	if (!kextIterator) {
9399 		goto finish;
9400 	}
9401 
9402 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
9403 		OSKext *    thisKext;        // do not release
9404 
9405 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
9406 		if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
9407 			continue;
9408 		}
9409 
9410 		if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID.get())) {
9411 			continue;
9412 		}
9413 		/* kext is loaded and was not in current kernel cache so let's rebuild
9414 		 */
9415 		doRebuild = true;
9416 		OSKextLog(/* kext */ NULL,
9417 		    kOSKextLogArchiveFlag,
9418 		    "considerRebuildOfPrelinkedKernel %s triggered rebuild",
9419 		    thisKext->bundleID->getCStringNoCopy());
9420 		break;
9421 	}
9422 	sUnloadedPrelinkedKexts->flushCollection();
9423 
9424 	if (!doRebuild) {
9425 		goto finish;
9426 	}
9427 
9428 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
9429 	    prelinkRequest);
9430 	if (checkResult != kOSReturnSuccess) {
9431 		goto finish;
9432 	}
9433 
9434 	if (!sKernelRequests->setObject(prelinkRequest.get())) {
9435 		goto finish;
9436 	}
9437 
9438 	OSKext::pingIOKitDaemon();
9439 
9440 finish:
9441 	IORecursiveLockUnlock(sKextLock);
9442 
9443 	return;
9444 }
9445 
9446 #else /* !CONFIG_KXLD */
9447 
9448 void
9449 OSKext::considerRebuildOfPrelinkedKernel(void)
9450 {
9451 	/* in a non-dynamic kext loading world, there is never a reason to rebuild */
9452 	return;
9453 }
9454 
9455 #endif /* CONFIG_KXLD */
9456 
9457 #if PRAGMA_MARK
9458 #pragma mark Dependencies
9459 #endif
9460 /*********************************************************************
9461 *********************************************************************/
9462 bool
9463 OSKext::resolveDependencies(
9464 	OSArray * loopStack)
9465 {
9466 	bool                   result                   = false;
9467 	OSSharedPtr<OSArray>   localLoopStack;
9468 	bool                   addedToLoopStack         = false;
9469 	OSDictionary         * libraries                = NULL;        // do not release
9470 	OSSharedPtr<OSCollectionIterator> libraryIterator;
9471 	OSString             * libraryID                = NULL;        // do not release
9472 	OSKext               * libraryKext              = NULL;        // do not release
9473 	bool                   hasRawKernelDependency   = false;
9474 	bool                   hasKernelDependency      = false;
9475 	bool                   hasKPIDependency         = false;
9476 	bool                   hasPrivateKPIDependency  = false;
9477 	unsigned int           count;
9478 
9479 #if CONFIG_KXLD
9480 	OSString             * infoString               = NULL;        // do not release
9481 	OSString             * readableString           = NULL;        // do not release
9482 #endif // CONFIG_KXLD
9483 
9484 	/* A kernel component will automatically have this flag set,
9485 	 * and a loaded kext should also have it set (as should all its
9486 	 * loaded dependencies).
9487 	 */
9488 	if (flags.hasAllDependencies) {
9489 		result = true;
9490 		goto finish;
9491 	}
9492 
9493 	/* Check for loops in the dependency graph.
9494 	 */
9495 	if (loopStack) {
9496 		if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
9497 			OSKextLog(this,
9498 			    kOSKextLogErrorLevel |
9499 			    kOSKextLogDependenciesFlag,
9500 			    "Kext %s has a dependency loop; can't resolve dependencies.",
9501 			    getIdentifierCString());
9502 			goto finish;
9503 		}
9504 	} else {
9505 		OSKextLog(this,
9506 		    kOSKextLogStepLevel |
9507 		    kOSKextLogDependenciesFlag,
9508 		    "Kext %s resolving dependencies.",
9509 		    getIdentifierCString());
9510 
9511 		localLoopStack = OSArray::withCapacity(6);         // any small capacity will do
9512 		if (!localLoopStack) {
9513 			OSKextLog(this,
9514 			    kOSKextLogErrorLevel |
9515 			    kOSKextLogDependenciesFlag,
9516 			    "Kext %s can't create bookkeeping stack to resolve dependencies.",
9517 			    getIdentifierCString());
9518 			goto finish;
9519 		}
9520 		loopStack = localLoopStack.get();
9521 	}
9522 	if (!loopStack->setObject(this)) {
9523 		OSKextLog(this,
9524 		    kOSKextLogErrorLevel |
9525 		    kOSKextLogDependenciesFlag,
9526 		    "Kext %s - internal error resolving dependencies.",
9527 		    getIdentifierCString());
9528 		goto finish;
9529 	}
9530 	addedToLoopStack = true;
9531 
9532 	/* Purge any existing kexts in the dependency list and start over.
9533 	 */
9534 	flushDependencies();
9535 	if (dependencies) {
9536 		OSKextLog(this,
9537 		    kOSKextLogErrorLevel |
9538 		    kOSKextLogDependenciesFlag,
9539 		    "Kext %s - internal error resolving dependencies.",
9540 		    getIdentifierCString());
9541 	}
9542 
9543 	libraries = OSDynamicCast(OSDictionary,
9544 	    getPropertyForHostArch(kOSBundleLibrariesKey));
9545 	if (libraries == NULL || libraries->getCount() == 0) {
9546 		OSKextLog(this,
9547 		    kOSKextLogErrorLevel |
9548 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9549 		    "Kext %s - can't resolve dependencies; %s missing/invalid type.",
9550 		    getIdentifierCString(), kOSBundleLibrariesKey);
9551 		goto finish;
9552 	}
9553 
9554 	/* Make a new array to hold the dependencies (flush freed the old one).
9555 	 */
9556 	dependencies = OSArray::withCapacity(libraries->getCount());
9557 	if (!dependencies) {
9558 		OSKextLog(this,
9559 		    kOSKextLogErrorLevel |
9560 		    kOSKextLogDependenciesFlag,
9561 		    "Kext %s - can't allocate dependencies array.",
9562 		    getIdentifierCString());
9563 		goto finish;
9564 	}
9565 
9566 	// xxx - compat: We used to add an implicit dependency on kernel 6.0
9567 	// xxx - compat: if none were declared.
9568 
9569 	libraryIterator = OSCollectionIterator::withCollection(libraries);
9570 	if (!libraryIterator) {
9571 		OSKextLog(this,
9572 		    kOSKextLogErrorLevel |
9573 		    kOSKextLogDependenciesFlag,
9574 		    "Kext %s - can't allocate dependencies iterator.",
9575 		    getIdentifierCString());
9576 		goto finish;
9577 	}
9578 
9579 	while ((libraryID = OSDynamicCast(OSString,
9580 	    libraryIterator->getNextObject()))) {
9581 		const char * library_id = libraryID->getCStringNoCopy();
9582 
9583 		OSString * libraryVersion = OSDynamicCast(OSString,
9584 		    libraries->getObject(libraryID));
9585 		if (libraryVersion == NULL) {
9586 			OSKextLog(this,
9587 			    kOSKextLogErrorLevel |
9588 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9589 			    "Kext %s - illegal type in OSBundleLibraries.",
9590 			    getIdentifierCString());
9591 			goto finish;
9592 		}
9593 
9594 		OSKextVersion libraryVers =
9595 		    OSKextParseVersionString(libraryVersion->getCStringNoCopy());
9596 		if (libraryVers == -1) {
9597 			OSKextLog(this,
9598 			    kOSKextLogErrorLevel |
9599 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9600 			    "Kext %s - invalid library version %s.",
9601 			    getIdentifierCString(),
9602 			    libraryVersion->getCStringNoCopy());
9603 			goto finish;
9604 		}
9605 
9606 		libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
9607 		if (libraryKext == NULL) {
9608 			OSKextLog(this,
9609 			    kOSKextLogErrorLevel |
9610 			    kOSKextLogDependenciesFlag,
9611 			    "Kext %s - library kext %s not found.",
9612 			    getIdentifierCString(), library_id);
9613 			goto finish;
9614 		}
9615 
9616 		if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
9617 			OSKextLog(this,
9618 			    kOSKextLogErrorLevel |
9619 			    kOSKextLogDependenciesFlag,
9620 			    "Kext %s - library kext %s not compatible "
9621 			    "with requested version %s.",
9622 			    getIdentifierCString(), library_id,
9623 			    libraryVersion->getCStringNoCopy());
9624 			goto finish;
9625 		}
9626 
9627 		/* If a nonprelinked library somehow got into the mix for a
9628 		 * prelinked kext, at any point in the chain, we must fail
9629 		 * because the prelinked relocs for the library will be all wrong.
9630 		 */
9631 		if (this->isPrelinked() &&
9632 		    libraryKext->declaresExecutable() &&
9633 		    !libraryKext->isPrelinked()) {
9634 			OSKextLog(this,
9635 			    kOSKextLogErrorLevel |
9636 			    kOSKextLogDependenciesFlag,
9637 			    "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
9638 			    getIdentifierCString(), library_id,
9639 			    libraryVersion->getCStringNoCopy());
9640 			goto finish;
9641 		}
9642 
9643 		if (!libraryKext->resolveDependencies(loopStack)) {
9644 			goto finish;
9645 		}
9646 
9647 		/* Add the library directly only if it has an executable to link.
9648 		 * Otherwise it's just used to collect other dependencies, so put
9649 		 * *its* dependencies on the list for this kext.
9650 		 */
9651 		// xxx - We are losing info here; would like to make fake entries or
9652 		// xxx - keep these in the dependency graph for loaded kexts.
9653 		// xxx - I really want to make kernel components not a special case!
9654 		if (libraryKext->declaresExecutable() ||
9655 		    libraryKext->isInterface()) {
9656 			if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
9657 				dependencies->setObject(libraryKext);
9658 
9659 				OSKextLog(this,
9660 				    kOSKextLogDetailLevel |
9661 				    kOSKextLogDependenciesFlag,
9662 				    "Kext %s added dependency %s.",
9663 				    getIdentifierCString(),
9664 				    libraryKext->getIdentifierCString());
9665 			}
9666 		} else {
9667 			int       numLibDependencies  = libraryKext->getNumDependencies();
9668 			OSArray * libraryDependencies = libraryKext->getDependencies();
9669 			int       index;
9670 
9671 			if (numLibDependencies) {
9672 				// xxx - this msg level should be 1 lower than the per-kext one
9673 				OSKextLog(this,
9674 				    kOSKextLogDetailLevel |
9675 				    kOSKextLogDependenciesFlag,
9676 				    "Kext %s pulling %d dependencies from codeless library %s.",
9677 				    getIdentifierCString(),
9678 				    numLibDependencies,
9679 				    libraryKext->getIdentifierCString());
9680 			}
9681 			for (index = 0; index < numLibDependencies; index++) {
9682 				OSKext * thisLibDependency = OSDynamicCast(OSKext,
9683 				    libraryDependencies->getObject(index));
9684 				if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
9685 					dependencies->setObject(thisLibDependency);
9686 					OSKextLog(this,
9687 					    kOSKextLogDetailLevel |
9688 					    kOSKextLogDependenciesFlag,
9689 					    "Kext %s added dependency %s from codeless library %s.",
9690 					    getIdentifierCString(),
9691 					    thisLibDependency->getIdentifierCString(),
9692 					    libraryKext->getIdentifierCString());
9693 				}
9694 			}
9695 		}
9696 
9697 		if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
9698 		    0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
9699 			hasRawKernelDependency = true;
9700 		} else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
9701 			hasKernelDependency = true;
9702 		} else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
9703 			hasKPIDependency = true;
9704 			if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
9705 				hasPrivateKPIDependency = true;
9706 			}
9707 		}
9708 	}
9709 
9710 	if (hasRawKernelDependency) {
9711 		OSKextLog(this,
9712 		    kOSKextLogErrorLevel |
9713 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9714 		    "Error - kext %s declares a dependency on %s, which is not permitted.",
9715 		    getIdentifierCString(), KERNEL_LIB);
9716 		goto finish;
9717 	}
9718 #if __LP64__
9719 	if (hasKernelDependency) {
9720 		OSKextLog(this,
9721 		    kOSKextLogErrorLevel |
9722 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
9723 		    "Error - kext %s declares %s dependencies. "
9724 		    "Only %s* dependencies are supported for 64-bit kexts.",
9725 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
9726 		goto finish;
9727 	}
9728 	if (!hasKPIDependency) {
9729 		OSKextLog(this,
9730 		    kOSKextLogWarningLevel |
9731 		    kOSKextLogDependenciesFlag,
9732 		    "Warning - kext %s declares no %s* dependencies. "
9733 		    "If it uses any KPIs, the link may fail with undefined symbols.",
9734 		    getIdentifierCString(), KPI_LIB_PREFIX);
9735 	}
9736 #else /* __LP64__ */
9737 	// xxx - will change to flatly disallow "kernel" dependencies at some point
9738 	// xxx - is it invalid to do both "com.apple.kernel" and any
9739 	// xxx - "com.apple.kernel.*"?
9740 
9741 	if (hasKernelDependency && hasKPIDependency) {
9742 		OSKextLog(this,
9743 		    kOSKextLogWarningLevel |
9744 		    kOSKextLogDependenciesFlag,
9745 		    "Warning - kext %s has immediate dependencies on both "
9746 		    "%s* and %s* components; use only one style.",
9747 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
9748 	}
9749 
9750 	if (!hasKernelDependency && !hasKPIDependency) {
9751 		// xxx - do we want to use validation flag for these too?
9752 		OSKextLog(this,
9753 		    kOSKextLogWarningLevel |
9754 		    kOSKextLogDependenciesFlag,
9755 		    "Warning - %s declares no kernel dependencies; using %s.",
9756 		    getIdentifierCString(), KERNEL6_LIB);
9757 		OSKext * kernelKext = OSDynamicCast(OSKext,
9758 		    sKextsByID->getObject(KERNEL6_LIB));
9759 		if (kernelKext) {
9760 			dependencies->setObject(kernelKext);
9761 		} else {
9762 			OSKextLog(this,
9763 			    kOSKextLogErrorLevel |
9764 			    kOSKextLogDependenciesFlag,
9765 			    "Error - Library %s not found for %s.",
9766 			    KERNEL6_LIB, getIdentifierCString());
9767 		}
9768 	}
9769 
9770 	/* If the kext doesn't have a raw kernel or KPI dependency, then add all of
9771 	 * its indirect dependencies to simulate old-style linking.  XXX - Should
9772 	 * check for duplicates.
9773 	 */
9774 	if (!hasKPIDependency) {
9775 		unsigned int i;
9776 
9777 		flags.hasBleedthrough = true;
9778 
9779 		count = getNumDependencies();
9780 
9781 		/* We add to the dependencies array in this loop, but do not iterate
9782 		 * past its original count.
9783 		 */
9784 		for (i = 0; i < count; i++) {
9785 			OSKext * dependencyKext = OSDynamicCast(OSKext,
9786 			    dependencies->getObject(i));
9787 			dependencyKext->addBleedthroughDependencies(dependencies.get());
9788 		}
9789 	}
9790 #endif /* __LP64__ */
9791 
9792 #if CONFIG_KXLD
9793 	/*
9794 	 * If we're not dynamically linking kexts, then we don't need to check
9795 	 * copyright strings. The linker in user space has already done this.
9796 	 */
9797 	if (hasPrivateKPIDependency) {
9798 		bool hasApplePrefix = false;
9799 		bool infoCopyrightIsValid = false;
9800 		bool readableCopyrightIsValid = false;
9801 
9802 		hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
9803 		    APPLE_KEXT_PREFIX);
9804 
9805 		infoString = OSDynamicCast(OSString,
9806 		    getPropertyForHostArch("CFBundleGetInfoString"));
9807 		if (infoString) {
9808 			infoCopyrightIsValid =
9809 			    kxld_validate_copyright_string(infoString->getCStringNoCopy());
9810 		}
9811 
9812 		readableString = OSDynamicCast(OSString,
9813 		    getPropertyForHostArch("NSHumanReadableCopyright"));
9814 		if (readableString) {
9815 			readableCopyrightIsValid =
9816 			    kxld_validate_copyright_string(readableString->getCStringNoCopy());
9817 		}
9818 
9819 		if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
9820 			OSKextLog(this,
9821 			    kOSKextLogErrorLevel |
9822 			    kOSKextLogDependenciesFlag,
9823 			    "Error - kext %s declares a dependency on %s. "
9824 			    "Only Apple kexts may declare a dependency on %s.",
9825 			    getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
9826 			goto finish;
9827 		}
9828 	}
9829 #endif // CONFIG_KXLD
9830 
9831 	result = true;
9832 	flags.hasAllDependencies = 1;
9833 
9834 finish:
9835 
9836 	if (addedToLoopStack) {
9837 		count = loopStack->getCount();
9838 		if (count > 0 && (this == loopStack->getObject(count - 1))) {
9839 			loopStack->removeObject(count - 1);
9840 		} else {
9841 			OSKextLog(this,
9842 			    kOSKextLogErrorLevel |
9843 			    kOSKextLogDependenciesFlag,
9844 			    "Kext %s - internal error resolving dependencies.",
9845 			    getIdentifierCString());
9846 		}
9847 	}
9848 
9849 	if (result && localLoopStack) {
9850 		OSKextLog(this,
9851 		    kOSKextLogStepLevel |
9852 		    kOSKextLogDependenciesFlag,
9853 		    "Kext %s successfully resolved dependencies.",
9854 		    getIdentifierCString());
9855 	}
9856 
9857 	return result;
9858 }
9859 
9860 /*********************************************************************
9861 *********************************************************************/
9862 bool
9863 OSKext::addBleedthroughDependencies(OSArray * anArray)
9864 {
9865 	bool result = false;
9866 	unsigned int dependencyIndex, dependencyCount;
9867 
9868 	dependencyCount = getNumDependencies();
9869 
9870 	for (dependencyIndex = 0;
9871 	    dependencyIndex < dependencyCount;
9872 	    dependencyIndex++) {
9873 		OSKext * dependency = OSDynamicCast(OSKext,
9874 		    dependencies->getObject(dependencyIndex));
9875 		if (!dependency) {
9876 			OSKextLog(this,
9877 			    kOSKextLogErrorLevel |
9878 			    kOSKextLogDependenciesFlag,
9879 			    "Kext %s - internal error propagating compatibility dependencies.",
9880 			    getIdentifierCString());
9881 			goto finish;
9882 		}
9883 		if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
9884 			anArray->setObject(dependency);
9885 		}
9886 		dependency->addBleedthroughDependencies(anArray);
9887 	}
9888 
9889 	result = true;
9890 
9891 finish:
9892 	return result;
9893 }
9894 
9895 /*********************************************************************
9896 *********************************************************************/
9897 bool
9898 OSKext::flushDependencies(bool forceFlag)
9899 {
9900 	bool result = false;
9901 
9902 	/* Only clear the dependencies if the kext isn't loaded;
9903 	 * we need the info for loaded kexts to track references.
9904 	 */
9905 	if (!isLoaded() || forceFlag) {
9906 		if (dependencies) {
9907 			// xxx - check level
9908 			OSKextLog(this,
9909 			    kOSKextLogProgressLevel |
9910 			    kOSKextLogDependenciesFlag,
9911 			    "Kext %s flushing dependencies.",
9912 			    getIdentifierCString());
9913 			dependencies.reset();
9914 		}
9915 		if (!isKernelComponent()) {
9916 			flags.hasAllDependencies = 0;
9917 		}
9918 		result = true;
9919 	}
9920 
9921 	return result;
9922 }
9923 
9924 /*********************************************************************
9925 *********************************************************************/
9926 uint32_t
9927 OSKext::getNumDependencies(void)
9928 {
9929 	if (!dependencies) {
9930 		return 0;
9931 	}
9932 	return dependencies->getCount();
9933 }
9934 
9935 /*********************************************************************
9936 *********************************************************************/
9937 OSArray *
9938 OSKext::getDependencies(void)
9939 {
9940 	return dependencies.get();
9941 }
9942 
9943 bool
9944 OSKext::hasDependency(const OSSymbol * depID)
9945 {
9946 	bool result __block;
9947 
9948 	if (depID == getIdentifier()) {
9949 		return true;
9950 	}
9951 	if (!dependencies) {
9952 		return false;
9953 	}
9954 	result = false;
9955 	dependencies->iterateObjects(^bool (OSObject * obj) {
9956 		OSKext * kext;
9957 		kext = OSDynamicCast(OSKext, obj);
9958 		if (!kext) {
9959 		        return false;
9960 		}
9961 		result = (depID == kext->getIdentifier());
9962 		return result;
9963 	});
9964 	return result;
9965 }
9966 
9967 #if PRAGMA_MARK
9968 #pragma mark OSMetaClass Support
9969 #endif
9970 /*********************************************************************
9971 *********************************************************************/
9972 OSReturn
9973 OSKext::addClass(
9974 	OSMetaClass * aClass,
9975 	uint32_t      numClasses)
9976 {
9977 	OSReturn result = kOSMetaClassNoInsKModSet;
9978 
9979 	if (!metaClasses) {
9980 		metaClasses = OSSet::withCapacity(numClasses);
9981 		if (!metaClasses) {
9982 			goto finish;
9983 		}
9984 	}
9985 
9986 	if (metaClasses->containsObject(aClass)) {
9987 		OSKextLog(this,
9988 		    kOSKextLogWarningLevel |
9989 		    kOSKextLogLoadFlag,
9990 		    "Notice - kext %s has already registered class %s.",
9991 		    getIdentifierCString(),
9992 		    aClass->getClassName());
9993 		result = kOSReturnSuccess;
9994 		goto finish;
9995 	}
9996 
9997 	if (!metaClasses->setObject(aClass)) {
9998 		goto finish;
9999 	} else {
10000 		OSKextLog(this,
10001 		    kOSKextLogDetailLevel |
10002 		    kOSKextLogLoadFlag,
10003 		    "Kext %s registered class %s.",
10004 		    getIdentifierCString(),
10005 		    aClass->getClassName());
10006 	}
10007 
10008 	if (!flags.autounloadEnabled) {
10009 		const OSMetaClass * metaScan  = NULL;        // do not release
10010 
10011 		for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
10012 			if (metaScan == OSTypeID(IOService)) {
10013 				OSKextLog(this,
10014 				    kOSKextLogProgressLevel |
10015 				    kOSKextLogLoadFlag,
10016 				    "Kext %s has IOService subclass %s; enabling autounload.",
10017 				    getIdentifierCString(),
10018 				    aClass->getClassName());
10019 
10020 				flags.autounloadEnabled = (0 == flags.unloadUnsupported);
10021 				break;
10022 			}
10023 		}
10024 	}
10025 
10026 	notifyAddClassObservers(this, aClass, flags);
10027 
10028 	result = kOSReturnSuccess;
10029 
10030 finish:
10031 	if (result != kOSReturnSuccess) {
10032 		OSKextLog(this,
10033 		    kOSKextLogErrorLevel |
10034 		    kOSKextLogLoadFlag,
10035 		    "Kext %s failed to register class %s.",
10036 		    getIdentifierCString(),
10037 		    aClass->getClassName());
10038 	}
10039 
10040 	return result;
10041 }
10042 
10043 /*********************************************************************
10044 *********************************************************************/
10045 OSReturn
10046 OSKext::removeClass(
10047 	OSMetaClass * aClass)
10048 {
10049 	OSReturn result = kOSMetaClassNoKModSet;
10050 
10051 	if (!metaClasses) {
10052 		goto finish;
10053 	}
10054 
10055 	if (!metaClasses->containsObject(aClass)) {
10056 		OSKextLog(this,
10057 		    kOSKextLogWarningLevel |
10058 		    kOSKextLogLoadFlag,
10059 		    "Notice - kext %s asked to unregister unknown class %s.",
10060 		    getIdentifierCString(),
10061 		    aClass->getClassName());
10062 		result = kOSReturnSuccess;
10063 		goto finish;
10064 	}
10065 
10066 	OSKextLog(this,
10067 	    kOSKextLogDetailLevel |
10068 	    kOSKextLogLoadFlag,
10069 	    "Kext %s unregistering class %s.",
10070 	    getIdentifierCString(),
10071 	    aClass->getClassName());
10072 
10073 	metaClasses->removeObject(aClass);
10074 
10075 	notifyRemoveClassObservers(this, aClass, flags);
10076 
10077 	result = kOSReturnSuccess;
10078 
10079 finish:
10080 	if (result != kOSReturnSuccess) {
10081 		OSKextLog(this,
10082 		    kOSKextLogErrorLevel |
10083 		    kOSKextLogLoadFlag,
10084 		    "Failed to unregister kext %s class %s.",
10085 		    getIdentifierCString(),
10086 		    aClass->getClassName());
10087 	}
10088 	return result;
10089 }
10090 
10091 /*********************************************************************
10092 *********************************************************************/
10093 OSSet *
10094 OSKext::getMetaClasses(void)
10095 {
10096 	return metaClasses.get();
10097 }
10098 
10099 /*********************************************************************
10100 *********************************************************************/
10101 bool
10102 OSKext::hasOSMetaClassInstances(void)
10103 {
10104 	bool                   result        = false;
10105 	OSSharedPtr<OSCollectionIterator> classIterator;
10106 	OSMetaClass          * checkClass    = NULL;        // do not release
10107 
10108 	if (!metaClasses) {
10109 		goto finish;
10110 	}
10111 
10112 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
10113 	if (!classIterator) {
10114 		// xxx - log alloc failure?
10115 		goto finish;
10116 	}
10117 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
10118 		if (checkClass->getInstanceCount()) {
10119 			result = true;
10120 			goto finish;
10121 		}
10122 	}
10123 
10124 finish:
10125 	return result;
10126 }
10127 
10128 /*********************************************************************
10129 *********************************************************************/
10130 /* static */
10131 void
10132 OSKext::reportOSMetaClassInstances(
10133 	const char     * kextIdentifier,
10134 	OSKextLogSpec    msgLogSpec)
10135 {
10136 	OSSharedPtr<OSKext> theKext;
10137 
10138 	theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
10139 	if (!theKext) {
10140 		goto finish;
10141 	}
10142 
10143 	theKext->reportOSMetaClassInstances(msgLogSpec);
10144 finish:
10145 	return;
10146 }
10147 
10148 /*********************************************************************
10149 *********************************************************************/
10150 void
10151 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
10152 {
10153 	OSSharedPtr<OSCollectionIterator> classIterator;
10154 	OSMetaClass          * checkClass    = NULL;        // do not release
10155 
10156 	if (!metaClasses) {
10157 		goto finish;
10158 	}
10159 
10160 	classIterator = OSCollectionIterator::withCollection(metaClasses.get());
10161 	if (!classIterator) {
10162 		goto finish;
10163 	}
10164 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
10165 		if (checkClass->getInstanceCount()) {
10166 			OSKextLog(this,
10167 			    msgLogSpec,
10168 			    "    Kext %s class %s has %d instance%s.",
10169 			    getIdentifierCString(),
10170 			    checkClass->getClassName(),
10171 			    checkClass->getInstanceCount(),
10172 			    checkClass->getInstanceCount() == 1 ? "" : "s");
10173 		}
10174 	}
10175 
10176 finish:
10177 	return;
10178 }
10179 
10180 #if PRAGMA_MARK
10181 #pragma mark User-Space Requests
10182 #endif
10183 
10184 static kern_return_t
10185 patchDextLaunchRequests(task_t calling_task, OSArray *requests)
10186 {
10187 	OSReturn result = kOSReturnSuccess;
10188 	for (uint32_t requestIndex = 0; requestIndex < requests->getCount(); requestIndex++) {
10189 		OSDictionary * request = NULL;         //do not release
10190 		IOUserServerCheckInToken * token = NULL;         //do not release
10191 		OSString * requestPredicate = NULL;         //do not release
10192 		OSSharedPtr<OSNumber> portNameNumber;
10193 		mach_port_name_t portName = 0;
10194 		request = OSDynamicCast(OSDictionary, requests->getObject(requestIndex));
10195 		if (!request) {
10196 			OSKextLog(/* kext */ NULL,
10197 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10198 			    "Elements of request should be of type OSDictionary");
10199 			result = kOSKextReturnInternalError;
10200 			goto finish;
10201 		}
10202 		requestPredicate = _OSKextGetRequestPredicate(request);
10203 		if (!requestPredicate) {
10204 			OSKextLog(/* kext */ NULL,
10205 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10206 			    "Failed to get request predicate");
10207 			result = kOSKextReturnInternalError;
10208 			goto finish;
10209 		}
10210 		// is this a dext launch?
10211 		if (requestPredicate->isEqualTo(kKextRequestPredicateRequestDaemonLaunch)) {
10212 			token = OSDynamicCast(IOUserServerCheckInToken, _OSKextGetRequestArgument(request, kKextRequestArgumentCheckInToken));
10213 			if (!token) {
10214 				OSKextLog(/* kext */ NULL,
10215 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10216 				    "Could not find a IOUserServerCheckInToken in daemon launch request.");
10217 				result = kOSKextReturnInternalError;
10218 				goto finish;
10219 			}
10220 			portName = iokit_make_send_right(calling_task, token, IKOT_IOKIT_IDENT);
10221 			if (portName == 0 || portName == MACH_PORT_DEAD) {
10222 				OSKextLog(/* kext */ NULL,
10223 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10224 				    "Could not create send right for object.");
10225 				result = kOSKextReturnInternalError;
10226 				goto finish;
10227 			}
10228 			// Store the mach port name as a OSNumber
10229 			portNameNumber = OSNumber::withNumber(portName, CHAR_BIT * sizeof(portName));
10230 			if (!portNameNumber) {
10231 				OSKextLog(/* kext */ NULL,
10232 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10233 				    "Could not create OSNumber object.");
10234 				result = kOSKextReturnNoMemory;
10235 				goto finish;
10236 			}
10237 			if (!_OSKextSetRequestArgument(request, kKextRequestArgumentCheckInToken, portNameNumber.get())) {
10238 				OSKextLog(/* kext */ NULL,
10239 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10240 				    "Could not set OSNumber object as request " kKextRequestArgumentCheckInToken);
10241 				result = kOSKextReturnNoMemory;
10242 				goto finish;
10243 			}
10244 		}
10245 finish:
10246 		if (result != kOSReturnSuccess) {
10247 			break;
10248 		}
10249 	}
10250 	return result;
10251 }
10252 
10253 bool
10254 OSKext::iokitDaemonActive()
10255 {
10256 	bool result;
10257 	IORecursiveLockLock(sKextLock);
10258 	result = sIOKitDaemonActive && !sOSKextWasResetAfterUserspaceReboot;
10259 	IORecursiveLockUnlock(sKextLock);
10260 	return result;
10261 }
10262 
10263 /*********************************************************************
10264 * XXX - this function is a big ugly mess
10265 *********************************************************************/
10266 /* static */
10267 OSReturn
10268 OSKext::handleRequest(
10269 	host_priv_t     hostPriv,
10270 	OSKextLogSpec   clientLogFilter,
10271 	char          * requestBuffer,
10272 	uint32_t        requestLength,
10273 	char         ** responseOut,
10274 	uint32_t      * responseLengthOut,
10275 	char         ** logInfoOut,
10276 	uint32_t      * logInfoLengthOut)
10277 {
10278 	OSReturn       result             = kOSReturnError;
10279 	kern_return_t  kmem_result        = KERN_FAILURE;
10280 
10281 	char         * response           = NULL;        // returned by reference
10282 	uint32_t       responseLength     = 0;
10283 
10284 	bool           taskCanManageAllKCs   = false;
10285 	bool           taskOnlyManagesBootKC = false;
10286 
10287 	OSSharedPtr<OSObject>     parsedXML;
10288 	OSDictionary            * requestDict    = NULL;        // do not release
10289 	OSSharedPtr<OSString>     errorString;
10290 
10291 	OSSharedPtr<OSObject>     responseObject;
10292 
10293 	OSSharedPtr<OSSerialize>  serializer;
10294 
10295 	OSSharedPtr<OSArray>      logInfoArray;
10296 
10297 	OSString     * predicate          = NULL;        // do not release
10298 	OSString     * kextIdentifier     = NULL;        // do not release
10299 	OSArray      * kextIdentifiers    = NULL;        // do not release
10300 	OSKext       * theKext            = NULL;        // do not release
10301 	OSBoolean    * boolArg            = NULL;        // do not release
10302 
10303 
10304 	IORecursiveLockLock(sKextLock);
10305 
10306 	if (responseOut) {
10307 		*responseOut = NULL;
10308 		*responseLengthOut = 0;
10309 	}
10310 	if (logInfoOut) {
10311 		*logInfoOut = NULL;
10312 		*logInfoLengthOut = 0;
10313 	}
10314 
10315 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
10316 
10317 	/* XML must be nul-terminated.
10318 	 */
10319 	if (requestBuffer[requestLength - 1] != '\0') {
10320 		OSKextLog(/* kext */ NULL,
10321 		    kOSKextLogErrorLevel |
10322 		    kOSKextLogIPCFlag,
10323 		    "Invalid request from user space (not nul-terminated).");
10324 		result = kOSKextReturnBadData;
10325 		goto finish;
10326 	}
10327 	parsedXML = OSUnserializeXML((const char *)requestBuffer, errorString);
10328 	if (parsedXML) {
10329 		requestDict = OSDynamicCast(OSDictionary, parsedXML.get());
10330 	}
10331 	if (!requestDict) {
10332 		const char * errorCString = "(unknown error)";
10333 
10334 		if (errorString && errorString->getCStringNoCopy()) {
10335 			errorCString = errorString->getCStringNoCopy();
10336 		} else if (parsedXML) {
10337 			errorCString = "not a dictionary";
10338 		}
10339 		OSKextLog(/* kext */ NULL,
10340 		    kOSKextLogErrorLevel |
10341 		    kOSKextLogIPCFlag,
10342 		    "Error unserializing request from user space: %s.",
10343 		    errorCString);
10344 		result = kOSKextReturnSerialization;
10345 		goto finish;
10346 	}
10347 
10348 	predicate = _OSKextGetRequestPredicate(requestDict);
10349 	if (!predicate) {
10350 		OSKextLog(/* kext */ NULL,
10351 		    kOSKextLogErrorLevel |
10352 		    kOSKextLogIPCFlag,
10353 		    "Recieved kext request from user space with no predicate.");
10354 		result = kOSKextReturnInvalidArgument;
10355 		goto finish;
10356 	}
10357 	OSKextLog(/* kext */ NULL,
10358 	    kOSKextLogDebugLevel |
10359 	    kOSKextLogIPCFlag,
10360 	    "Received '%s' request from user space.",
10361 	    predicate->getCStringNoCopy());
10362 
10363 	/*
10364 	 * All management of file sets requires an entitlement
10365 	 */
10366 	result = kOSKextReturnNotPrivileged;
10367 	if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
10368 	    predicate->isEqualTo(kKextRequestPredicateStart) ||
10369 	    predicate->isEqualTo(kKextRequestPredicateStop) ||
10370 	    predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
10371 	    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
10372 	    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
10373 	    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
10374 	    predicate->isEqualTo(kKextRequestPredicateLoadFromKC) ||
10375 	    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
10376 	    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
10377 	    predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
10378 		if (!iokitDaemonAvailable()) {
10379 			panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable");
10380 		}
10381 		if (hostPriv == HOST_PRIV_NULL) {
10382 			OSKextLog(/* kext */ NULL,
10383 			    kOSKextLogErrorLevel |
10384 			    kOSKextLogIPCFlag,
10385 			    "Access Failure - must be root user.");
10386 			goto finish;
10387 		}
10388 		taskCanManageAllKCs = IOCurrentTaskHasEntitlement(kOSKextCollectionManagementEntitlement) == TRUE;
10389 		taskOnlyManagesBootKC = IOCurrentTaskHasEntitlement(kOSKextOnlyBootKCManagementEntitlement) == TRUE;
10390 
10391 		if (!taskCanManageAllKCs && !taskOnlyManagesBootKC) {
10392 			OSKextLog(/* kext */ NULL,
10393 			    kOSKextLogErrorLevel |
10394 			    kOSKextLogIPCFlag,
10395 			    "Access Failure - client not entitled to manage file sets.");
10396 			goto finish;
10397 		}
10398 
10399 		/*
10400 		 * The OnlyBootKC entitlement restricts the
10401 		 * collection-management entitlement to only managing kexts in
10402 		 * the BootKC. All other predicates that alter global state or
10403 		 * add new KCs are disallowed.
10404 		 */
10405 		if (taskOnlyManagesBootKC &&
10406 		    (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
10407 		    predicate->isEqualTo(kKextRequestPredicateSendResource) ||
10408 		    predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC) ||
10409 		    predicate->isEqualTo(kKextRequestPredicateLoadCodeless) ||
10410 		    predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles) ||
10411 		    predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable) ||
10412 		    predicate->isEqualTo(kKextRequestPredicateDaemonReady))) {
10413 			OSKextLog(/* kext */ NULL,
10414 			    kOSKextLogErrorLevel |
10415 			    kOSKextLogIPCFlag,
10416 			    "Access Failure - client not entitled to manage non-primary KCs");
10417 			goto finish;
10418 		}
10419 
10420 		/*
10421 		 * If we get here, then the process either has the full KC
10422 		 * management entitlement, or it has the BootKC-only
10423 		 * entitlement and the request is about the BootKC.
10424 		 */
10425 	}
10426 
10427 	/* Get common args in anticipation of use.
10428 	 */
10429 	kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
10430 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
10431 	kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
10432 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
10433 	if (kextIdentifier) {
10434 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
10435 	}
10436 	boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
10437 		    requestDict, kKextRequestArgumentValueKey));
10438 
10439 	if (taskOnlyManagesBootKC &&
10440 	    theKext &&
10441 	    theKext->isInFileset() &&
10442 	    theKext->kc_type != KCKindPrimary) {
10443 		OSKextLog(/* kext */ NULL,
10444 		    kOSKextLogErrorLevel |
10445 		    kOSKextLogIPCFlag,
10446 		    "Access Failure - client not entitled to manage kext in non-primary KC");
10447 		result = kOSKextReturnNotPrivileged;
10448 		goto finish;
10449 	}
10450 	result = kOSKextReturnInvalidArgument;
10451 
10452 	if (predicate->isEqualTo(kKextRequestPredicateStart)) {
10453 		if (!kextIdentifier) {
10454 			OSKextLog(/* kext */ NULL,
10455 			    kOSKextLogErrorLevel |
10456 			    kOSKextLogIPCFlag,
10457 			    "Invalid arguments to kext start request.");
10458 		} else if (!theKext) {
10459 			OSKextLog(/* kext */ NULL,
10460 			    kOSKextLogErrorLevel |
10461 			    kOSKextLogIPCFlag,
10462 			    "Kext %s not found for start request.",
10463 			    kextIdentifier->getCStringNoCopy());
10464 			result = kOSKextReturnNotFound;
10465 		} else {
10466 			result = theKext->start();
10467 		}
10468 	} else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
10469 		if (!kextIdentifier) {
10470 			OSKextLog(/* kext */ NULL,
10471 			    kOSKextLogErrorLevel |
10472 			    kOSKextLogIPCFlag,
10473 			    "Invalid arguments to kext stop request.");
10474 		} else if (!theKext) {
10475 			OSKextLog(/* kext */ NULL,
10476 			    kOSKextLogErrorLevel |
10477 			    kOSKextLogIPCFlag,
10478 			    "Kext %s not found for stop request.",
10479 			    kextIdentifier->getCStringNoCopy());
10480 			result = kOSKextReturnNotFound;
10481 		} else {
10482 			result = theKext->stop();
10483 		}
10484 	} else if (predicate->isEqualTo(kKextRequestPredicateMissingAuxKCBundles)) {
10485 		result = OSKext::setMissingAuxKCBundles(requestDict);
10486 	} else if (predicate->isEqualTo(kKextRequestPredicateAuxKCBundleAvailable)) {
10487 		if (!kextIdentifier) {
10488 			OSKextLog(/* kext */ NULL,
10489 			    kOSKextLogErrorLevel |
10490 			    kOSKextLogIPCFlag,
10491 			    "Invalid arguments to AuxKC Bundle Available request.");
10492 		} else {
10493 			result = OSKext::setAuxKCBundleAvailable(kextIdentifier, requestDict);
10494 		}
10495 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFromKC)) {
10496 		if (!kextIdentifier) {
10497 			OSKextLog(/* kext */ NULL,
10498 			    kOSKextLogErrorLevel |
10499 			    kOSKextLogIPCFlag,
10500 			    "Invalid arguments to kext load from KC request.");
10501 		} else if (!theKext) {
10502 			OSKextLog(/* kext */ NULL,
10503 			    kOSKextLogErrorLevel |
10504 			    kOSKextLogIPCFlag,
10505 			    "Kext %s not found for load from KC request.",
10506 			    kextIdentifier->getCStringNoCopy());
10507 			result = kOSKextReturnNotFound;
10508 		} else if (!theKext->isInFileset()) {
10509 			OSKextLog(/* kext */ NULL,
10510 			    kOSKextLogErrorLevel |
10511 			    kOSKextLogIPCFlag,
10512 			    "Kext %s does not exist in a KC: refusing to load.",
10513 			    kextIdentifier->getCStringNoCopy());
10514 			result = kOSKextReturnNotLoadable;
10515 		} else {
10516 			result = OSKext::loadKextFromKC(theKext, requestDict);
10517 		}
10518 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadCodeless)) {
10519 		if (!kextIdentifier) {
10520 			OSKextLog(/* kext */ NULL,
10521 			    kOSKextLogErrorLevel |
10522 			    kOSKextLogIPCFlag,
10523 			    "Invalid arguments to codeless kext load interface (missing identifier).");
10524 		} else {
10525 			result = OSKext::loadCodelessKext(kextIdentifier, requestDict);
10526 		}
10527 	} else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
10528 		if (!kextIdentifier) {
10529 			OSKextLog(/* kext */ NULL,
10530 			    kOSKextLogErrorLevel |
10531 			    kOSKextLogIPCFlag,
10532 			    "Invalid arguments to kext unload request.");
10533 		} else if (!theKext) {
10534 			OSKextLog(/* kext */ NULL,
10535 			    kOSKextLogErrorLevel |
10536 			    kOSKextLogIPCFlag,
10537 			    "Kext %s not found for unload request.",
10538 			    kextIdentifier->getCStringNoCopy());
10539 			result = kOSKextReturnNotFound;
10540 		} else {
10541 			if (theKext->isDriverKit()) {
10542 				result = OSKext::removeDext(theKext);
10543 			} else {
10544 				OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
10545 				    _OSKextGetRequestArgument(requestDict,
10546 				    kKextRequestArgumentTerminateIOServicesKey));
10547 				result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
10548 			}
10549 		}
10550 	} else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
10551 		result = OSKext::dispatchResource(requestDict);
10552 	} else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
10553 		OSNumber     *lookupNum   = NULL;
10554 		lookupNum = OSDynamicCast(OSNumber,
10555 		    _OSKextGetRequestArgument(requestDict,
10556 		    kKextRequestArgumentLookupAddressKey));
10557 
10558 		responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
10559 		if (responseObject) {
10560 			result = kOSReturnSuccess;
10561 		} else {
10562 			goto finish;
10563 		}
10564 	} else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
10565 	    predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID) ||
10566 	    predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection) ||
10567 	    predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
10568 		OSBoolean    * delayAutounloadBool = NULL;
10569 		OSObject     * infoKeysRaw         = NULL;
10570 		OSArray      * infoKeys            = NULL;
10571 		uint32_t       infoKeysCount       = 0;
10572 
10573 		delayAutounloadBool = OSDynamicCast(OSBoolean,
10574 		    _OSKextGetRequestArgument(requestDict,
10575 		    kKextRequestArgumentDelayAutounloadKey));
10576 
10577 		/* If asked to delay autounload, reset the timer if it's currently set.
10578 		 * (That is, don't schedule an unload if one isn't already pending.
10579 		 */
10580 		if (delayAutounloadBool == kOSBooleanTrue) {
10581 			OSKext::considerUnloads(/* rescheduleOnly? */ true);
10582 		}
10583 
10584 		infoKeysRaw = _OSKextGetRequestArgument(requestDict,
10585 		    kKextRequestArgumentInfoKeysKey);
10586 		infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
10587 		if (infoKeysRaw && !infoKeys) {
10588 			OSKextLog(/* kext */ NULL,
10589 			    kOSKextLogErrorLevel |
10590 			    kOSKextLogIPCFlag,
10591 			    "Invalid arguments to kext info request.");
10592 			goto finish;
10593 		}
10594 
10595 		if (infoKeys) {
10596 			infoKeysCount = infoKeys->getCount();
10597 			for (uint32_t i = 0; i < infoKeysCount; i++) {
10598 				if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
10599 					OSKextLog(/* kext */ NULL,
10600 					    kOSKextLogErrorLevel |
10601 					    kOSKextLogIPCFlag,
10602 					    "Invalid arguments to kext info request.");
10603 					goto finish;
10604 				}
10605 			}
10606 		}
10607 
10608 		if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
10609 			responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
10610 		} else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
10611 			responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
10612 		} else if (predicate->isEqualTo(kKextRequestPredicateGetKextsInCollection)) {
10613 			responseObject = OSKext::copyKextCollectionInfo(requestDict, infoKeys);
10614 		} else if (predicate->isEqualTo(kKextRequestPredicateGetDexts)) {
10615 			responseObject = OSKext::copyDextsInfo(kextIdentifiers, infoKeys);
10616 		}
10617 
10618 		if (!responseObject) {
10619 			result = kOSKextReturnInternalError;
10620 		} else {
10621 			OSKextLog(/* kext */ NULL,
10622 			    kOSKextLogDebugLevel |
10623 			    kOSKextLogIPCFlag,
10624 			    "Returning loaded kext info.");
10625 			result = kOSReturnSuccess;
10626 		}
10627 	} else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
10628 		/* Hand the current sKernelRequests array to the caller
10629 		 * (who must release it), and make a new one.
10630 		 */
10631 		responseObject = os::move(sKernelRequests);
10632 		sKernelRequests = OSArray::withCapacity(0);
10633 		sPostedKextLoadIdentifiers->flushCollection();
10634 		OSKextLog(/* kext */ NULL,
10635 		    kOSKextLogDebugLevel |
10636 		    kOSKextLogIPCFlag,
10637 		    "Returning kernel requests.");
10638 		result = kOSReturnSuccess;
10639 	} else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
10640 		/* Return the set of all requested bundle identifiers */
10641 		responseObject = sAllKextLoadIdentifiers;
10642 		OSKextLog(/* kext */ NULL,
10643 		    kOSKextLogDebugLevel |
10644 		    kOSKextLogIPCFlag,
10645 		    "Returning load requests.");
10646 		result = kOSReturnSuccess;
10647 	} else if (predicate->isEqualTo(kKextRequestPredicateLoadFileSetKC)) {
10648 		printf("KextLog: Loading FileSet KC(s)\n");
10649 		result = OSKext::loadFileSetKexts(requestDict);
10650 	} else if (predicate->isEqualTo(kKextRequestPredicateDaemonReady)) {
10651 		bool active = iokitDaemonActive();
10652 		printf("KextLog: " kIOKitDaemonName " is %s\n", active ? "active" : "not active");
10653 		if (sOSKextWasResetAfterUserspaceReboot) {
10654 			printf("KextLog: was reset after userspace reboot\n");
10655 		}
10656 		result = active ? kOSReturnSuccess : kIOReturnNotReady;
10657 	} else {
10658 		OSKextLog(/* kext */ NULL,
10659 		    kOSKextLogDebugLevel |
10660 		    kOSKextLogIPCFlag,
10661 		    "Received '%s' invalid request from user space.",
10662 		    predicate->getCStringNoCopy());
10663 		goto finish;
10664 	}
10665 
10666 	/**********
10667 	 * Now we have handle the request, or not. Gather up the response & logging
10668 	 * info to ship to user space.
10669 	 *********/
10670 
10671 	/* Note: Nothing in OSKext is supposed to retain requestDict,
10672 	 * but you never know....
10673 	 */
10674 	if (requestDict->getRetainCount() > 1) {
10675 		OSKextLog(/* kext */ NULL,
10676 		    kOSKextLogWarningLevel |
10677 		    kOSKextLogIPCFlag,
10678 		    "Request from user space still retained by a kext; "
10679 		    "probable memory leak.");
10680 	}
10681 
10682 	if (responseOut && responseObject) {
10683 		serializer = OSSerialize::withCapacity(0);
10684 		if (!serializer) {
10685 			result = kOSKextReturnNoMemory;
10686 			goto finish;
10687 		}
10688 		/*
10689 		 * Before serializing the kernel requests, patch the dext launch requests so
10690 		 * that the value for kKextRequestArgumentCheckInToken is a mach port name for the
10691 		 * IOUserServerCheckInToken kernel object.
10692 		 */
10693 		if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
10694 			OSArray * requests = OSDynamicCast(OSArray, responseObject.get());
10695 			task_t calling_task = current_task();
10696 			if (!requests) {
10697 				OSKextLog(/* kext */ NULL,
10698 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10699 				    "responseObject should be an OSArray if predicate is " kKextRequestPredicateGetKernelRequests);
10700 				result = kOSKextReturnInternalError;
10701 				goto finish;
10702 			}
10703 			result = patchDextLaunchRequests(calling_task, requests);
10704 			if (result != kOSReturnSuccess) {
10705 				OSKextLog(/* kext */ NULL,
10706 				    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10707 				    "Failed to patch dext launch requests.");
10708 				goto finish;
10709 			}
10710 		}
10711 
10712 		if (!responseObject->serialize(serializer.get())) {
10713 			OSKextLog(/* kext */ NULL,
10714 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
10715 			    "Failed to serialize response to request from user space.");
10716 			result = kOSKextReturnSerialization;
10717 			goto finish;
10718 		}
10719 
10720 		response = (char *)serializer->text();
10721 		responseLength = serializer->getLength();
10722 	}
10723 
10724 	if (responseOut && response) {
10725 		char * buffer;
10726 
10727 		/* This kmem_alloc sets the return value of the function.
10728 		 */
10729 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
10730 		    round_page(responseLength), KMA_DATA, VM_KERN_MEMORY_OSKEXT);
10731 		if (kmem_result != KERN_SUCCESS) {
10732 			OSKextLog(/* kext */ NULL,
10733 			    kOSKextLogErrorLevel |
10734 			    kOSKextLogIPCFlag,
10735 			    "Failed to copy response to request from user space.");
10736 			result = kmem_result;
10737 			goto finish;
10738 		} else {
10739 			/* 11981737 - clear uninitialized data in last page */
10740 			bzero((void *)(buffer + responseLength),
10741 			    (round_page(responseLength) - responseLength));
10742 			memcpy(buffer, response, responseLength);
10743 			*responseOut = buffer;
10744 			*responseLengthOut = responseLength;
10745 		}
10746 	}
10747 
10748 finish:
10749 
10750 	/* Gather up the collected log messages for user space. Any messages
10751 	 * messages past this call will not make it up as log messages but
10752 	 * will be in the system log. Note that we ignore the return of the
10753 	 * serialize; it has no bearing on the operation at hand even if we
10754 	 * fail to get the log messages.
10755 	 */
10756 	logInfoArray = OSKext::clearUserSpaceLogFilter();
10757 
10758 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
10759 		(void)OSKext::serializeLogInfo(logInfoArray.get(),
10760 		    logInfoOut, logInfoLengthOut);
10761 	}
10762 
10763 	IORecursiveLockUnlock(sKextLock);
10764 
10765 	return result;
10766 }
10767 
10768 #if PRAGMA_MARK
10769 #pragma mark Linked Kext Collection Support
10770 #endif
10771 
10772 static int
10773 __whereIsAddr(vm_offset_t theAddr, unsigned long *segSizes, vm_offset_t *segAddrs, int segCount)
10774 {
10775 	for (int i = 0; i < segCount; i++) {
10776 		vm_offset_t segStart = segAddrs[i];
10777 		vm_offset_t segEnd = segStart + (vm_offset_t)segSizes[i];
10778 
10779 		if (theAddr >= segStart && theAddr < segEnd) {
10780 			return i;
10781 		}
10782 	}
10783 	return -1;
10784 }
10785 
10786 static void
10787 __slideOldKaslrOffsets(kernel_mach_header_t *mh,
10788     kernel_segment_command_t *kextTextSeg,
10789     OSData *kaslrOffsets)
10790 {
10791 	static const char *plk_segNames[] = {
10792 		"__TEXT",
10793 		"__TEXT_EXEC",
10794 		"__DATA",
10795 		"__DATA_CONST",
10796 		"__LINKEDIT",
10797 		"__PRELINK_TEXT",
10798 		"__PLK_TEXT_EXEC",
10799 		"__PRELINK_DATA",
10800 		"__PLK_DATA_CONST",
10801 		"__PLK_LLVM_COV",
10802 		"__PLK_LINKEDIT",
10803 		"__PRELINK_INFO"
10804 	};
10805 	static const size_t num_plk_seg = (size_t)(sizeof(plk_segNames) / sizeof(plk_segNames[0]));
10806 
10807 	unsigned long plk_segSizes[num_plk_seg];
10808 	vm_offset_t   plk_segAddrs[num_plk_seg];
10809 
10810 	for (size_t i = 0; i < num_plk_seg; i++) {
10811 		plk_segSizes[i] = 0;
10812 		plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(mh, plk_segNames[i], &plk_segSizes[i]);
10813 	}
10814 
10815 	uint64_t kextTextStart = (uint64_t)kextTextSeg->vmaddr;
10816 
10817 	int slidKextAddrCount = 0;
10818 	int badSlideAddr = 0;
10819 	int badSlideTarget = 0;
10820 
10821 	struct kaslrPackedOffsets {
10822 		uint32_t    count;          /* number of offsets */
10823 		uint32_t    offsetsArray[];        /* offsets to slide */
10824 	};
10825 	const struct kaslrPackedOffsets *myOffsets = NULL;
10826 	myOffsets = (const struct kaslrPackedOffsets *)kaslrOffsets->getBytesNoCopy();
10827 
10828 	for (uint32_t j = 0; j < myOffsets->count; j++) {
10829 		uint64_t   slideOffset = (uint64_t)myOffsets->offsetsArray[j];
10830 		vm_offset_t *slideAddr = (vm_offset_t *)((uint64_t)kextTextStart + slideOffset);
10831 		int        slideAddrSegIndex = -1;
10832 		int        addrToSlideSegIndex = -1;
10833 
10834 		slideAddrSegIndex = __whereIsAddr((vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
10835 		if (slideAddrSegIndex >= 0) {
10836 			addrToSlideSegIndex = __whereIsAddr(ml_static_slide(*slideAddr), &plk_segSizes[0], &plk_segAddrs[0], num_plk_seg);
10837 			if (addrToSlideSegIndex < 0) {
10838 				badSlideTarget++;
10839 				continue;
10840 			}
10841 		} else {
10842 			badSlideAddr++;
10843 			continue;
10844 		}
10845 
10846 		slidKextAddrCount++;
10847 		*slideAddr = ml_static_slide(*slideAddr);
10848 	}         // for ...
10849 }
10850 
10851 
10852 
10853 /********************************************************************
10854 * addKextsFromKextCollection
10855 *
10856 * Input: MachO header of kext collection. The MachO is assumed to
10857 *        have a section named 'info_seg_name,info_sect_name' that
10858 *        contains a serialized XML info dictionary. This dictionary
10859 *        contains a UUID, possibly a set of relocations (for older
10860 *        kxld-built binaries), and an array of kext personalities.
10861 *
10862 ********************************************************************/
10863 bool
10864 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10865     OSDictionary *infoDict, const char *text_seg_name,
10866     OSData **kcUUID, kc_kind_t type)
10867 {
10868 	bool result = false;
10869 
10870 	OSArray *kextArray     = NULL;        // do not release
10871 	OSData *infoDictKCUUID = NULL;         // do not release
10872 	OSData *kaslrOffsets   = NULL;        // do not release
10873 
10874 	IORegistryEntry *registryRoot = NULL;         // do not release
10875 	OSSharedPtr<OSNumber> kcKextCount;
10876 
10877 	/* extract the KC UUID from the dictionary */
10878 	infoDictKCUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
10879 	if (infoDictKCUUID) {
10880 		if (infoDictKCUUID->getLength() != sizeof(uuid_t)) {
10881 			panic("kcUUID length is %d, expected %lu",
10882 			    infoDictKCUUID->getLength(), sizeof(uuid_t));
10883 		}
10884 	}
10885 
10886 	/* locate the array of kext dictionaries */
10887 	kextArray = OSDynamicCast(OSArray, infoDict->getObject(kPrelinkInfoDictionaryKey));
10888 	if (!kextArray) {
10889 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10890 		    "The given KC has no kext info dictionaries");
10891 		goto finish;
10892 	}
10893 
10894 	/*
10895 	 * old-style KASLR offsets may be present in the info dictionary. If
10896 	 * we find them, use them and eventually slide them.
10897 	 */
10898 	kaslrOffsets = OSDynamicCast(OSData, infoDict->getObject(kPrelinkLinkKASLROffsetsKey));
10899 
10900 	/*
10901 	 * Before processing any kexts, locate the special kext bundle which
10902 	 * contains a list of kexts that we are to prevent from loading.
10903 	 */
10904 	createExcludeListFromPrelinkInfo(kextArray);
10905 
10906 	/*
10907 	 * Create OSKext objects for each kext we find in the array of kext
10908 	 * info plist dictionaries.
10909 	 */
10910 	for (int i = 0; i < (int)kextArray->getCount(); ++i) {
10911 		OSDictionary *kextDict = NULL;
10912 		kextDict = OSDynamicCast(OSDictionary, kextArray->getObject(i));
10913 		if (!kextDict) {
10914 			OSKextLog(/* kext */ NULL,
10915 			    kOSKextLogErrorLevel |
10916 			    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10917 			    "Kext info dictionary for kext #%d isn't a dictionary?", i);
10918 			continue;
10919 		}
10920 
10921 		/*
10922 		 * Create the kext for the entry, then release it, because the
10923 		 * kext system keeps a reference around until the kext is
10924 		 * explicitly removed.  Any creation/registration failures are
10925 		 * already logged for us.
10926 		 */
10927 		withPrelinkedInfoDict(kextDict, (kaslrOffsets ? TRUE : FALSE), type);
10928 	}
10929 
10930 	/*
10931 	 * slide old-style kxld relocations
10932 	 * NOTE: this is still used on embedded KCs built with kcgen
10933 	 * TODO: Remove this once we use the new kext linker everywhere!
10934 	 */
10935 	if (kaslrOffsets && vm_kernel_slide > 0) {
10936 		kernel_segment_command_t *text_segment = NULL;
10937 		text_segment = getsegbynamefromheader(mh, text_seg_name);
10938 		if (!text_segment) {
10939 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
10940 			    "Can't find a TEXT segment named '%s' in macho header", text_seg_name);
10941 			goto finish;
10942 		}
10943 
10944 		__slideOldKaslrOffsets(mh, text_segment, kaslrOffsets);
10945 		/* All kexts covered by the old-style kaslr relocation list are now slid, set VM protections for them */
10946 		setAllVMAttributes();
10947 	}
10948 
10949 	/* Store the number of prelinked kexts in the registry so we can tell
10950 	 * when the system has been started from a prelinked kernel.
10951 	 */
10952 	registryRoot = IORegistryEntry::getRegistryRoot();
10953 	assert(registryRoot);
10954 
10955 	kcKextCount = OSNumber::withNumber((unsigned long long)infoDict->getCount(), 8 * sizeof(uint32_t));
10956 	assert(kcKextCount);
10957 	if (kcKextCount) {
10958 		OSSharedPtr<OSObject> prop = registryRoot->copyProperty(kOSPrelinkKextCountKey);
10959 		OSNumber *num;
10960 		num = OSDynamicCast(OSNumber, prop.get());
10961 		if (num) {
10962 			kcKextCount->addValue(num->unsigned64BitValue());
10963 		}
10964 		registryRoot->setProperty(kOSPrelinkKextCountKey, kcKextCount.get());
10965 	}
10966 
10967 	OSKextLog(/* kext */ NULL,
10968 	    kOSKextLogProgressLevel |
10969 	    kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
10970 	    kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
10971 	    "%u prelinked kexts", infoDict->getCount());
10972 
10973 
10974 	if (kcUUID && infoDictKCUUID) {
10975 		*kcUUID = OSData::withData(infoDictKCUUID).detach();
10976 	}
10977 
10978 	result = true;
10979 
10980 finish:
10981 	return result;
10982 }
10983 
10984 bool
10985 OSKext::addKextsFromKextCollection(kernel_mach_header_t *mh,
10986     OSDictionary *infoDict, const char *text_seg_name,
10987     OSSharedPtr<OSData> &kcUUID, kc_kind_t type)
10988 {
10989 	OSData  *result = NULL;
10990 	bool success = addKextsFromKextCollection(mh,
10991 	    infoDict,
10992 	    text_seg_name,
10993 	    &result,
10994 	    type);
10995 	if (success) {
10996 		kcUUID.reset(result, OSNoRetain);
10997 	}
10998 	return success;
10999 }
11000 
11001 static OSSharedPtr<OSObject> deferredAuxKCXML;
11002 bool
11003 OSKext::registerDeferredKextCollection(kernel_mach_header_t *mh,
11004     OSSharedPtr<OSObject> &parsedXML, kc_kind_t type)
11005 {
11006 	if (type != KCKindAuxiliary) {
11007 		return false;
11008 	}
11009 
11010 	kernel_mach_header_t *_mh;
11011 	_mh = (kernel_mach_header_t*)PE_get_kc_header(type);
11012 	if (!_mh || _mh != mh) {
11013 		return false;
11014 	}
11015 
11016 	if (deferredAuxKCXML) {
11017 		/* only allow this to be called once */
11018 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
11019 		    "An Aux KC has already been registered for deferred processing.");
11020 		return false;
11021 	}
11022 
11023 	OSDictionary *infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
11024 	if (!infoDict) {
11025 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
11026 		    "The Aux KC has info dictionary");
11027 		return false;
11028 	}
11029 
11030 	OSData *kcUUID = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
11031 	if (!kcUUID || kcUUID->getLength() != sizeof(uuid_t)) {
11032 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
11033 		    "The Aux KC has no UUID in %s", kPrelinkInfoKCIDKey);
11034 		return false;
11035 	}
11036 
11037 	/*
11038 	 * Copy the AuxKC UUID to make sure that the kern.auxiliaryfilesetuuid
11039 	 * sysctl can return the UUID to user space which will check this
11040 	 * value for errors.
11041 	 */
11042 	memcpy((void *)&auxkc_uuid, (const void *)kcUUID->getBytesNoCopy(),
11043 	    kcUUID->getLength());
11044 	uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
11045 	auxkc_uuid_valid = TRUE;
11046 
11047 	deferredAuxKCXML = parsedXML;
11048 
11049 	return true;
11050 }
11051 
11052 OSSharedPtr<OSObject>
11053 OSKext::consumeDeferredKextCollection(kc_kind_t type)
11054 {
11055 	if (type != KCKindAuxiliary || !deferredAuxKCXML) {
11056 		return NULL;
11057 	}
11058 
11059 	return os::move(deferredAuxKCXML);
11060 }
11061 
11062 #if PRAGMA_MARK
11063 #pragma mark Profile-Guided-Optimization Support
11064 #endif
11065 
11066 // #include <InstrProfiling.h>
11067 extern "C" {
11068 uint64_t __llvm_profile_get_size_for_buffer_internal(
11069 	const char *DataBegin,
11070 	const char *DataEnd,
11071 	const char *CountersBegin,
11072 	const char *CountersEnd,
11073 	const char *BitmapBegin,
11074 	const char *BitmapEnd,
11075 	const char *NamesBegin,
11076 	const char *NamesEnd,
11077 	const char *VTableBegin,
11078 	const char *VTableEnd,
11079 	const char *VNamesBegin,
11080 	const char *VNamesEnd);
11081 int __llvm_profile_write_buffer_internal(
11082 	char *Buffer,
11083 	const char *DataBegin,
11084 	const char *DataEnd,
11085 	const char *CountersBegin,
11086 	const char *CountersEnd,
11087 	const char *BitmapBegin,
11088 	const char *BitmapEnd,
11089 	const char *NamesBegin,
11090 	const char *NamesEnd);
11091 }
11092 
11093 static
11094 void
11095 OSKextPgoMetadataPut(char *pBuffer,
11096     size_t *position,
11097     size_t bufferSize,
11098     uint32_t *num_pairs,
11099     const char *key,
11100     const char *value)
11101 {
11102 	size_t strlen_key = strlen(key);
11103 	size_t strlen_value = strlen(value);
11104 	size_t len = strlen(key) + 1 + strlen(value) + 1;
11105 	char *pos = pBuffer + *position;
11106 	*position += len;
11107 	if (pBuffer && bufferSize && *position <= bufferSize) {
11108 		memcpy(pos, key, strlen_key); pos += strlen_key;
11109 		*(pos++) = '=';
11110 		memcpy(pos, value, strlen_value); pos += strlen_value;
11111 		*(pos++) = 0;
11112 		if (num_pairs) {
11113 			(*num_pairs)++;
11114 		}
11115 	}
11116 }
11117 
11118 
11119 static
11120 void
11121 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
11122 {
11123 	*position += strlen(key) + 1 + value_max + 1;
11124 }
11125 
11126 
11127 static
11128 void
11129 OSKextPgoMetadataPutAll(OSKext *kext,
11130     uuid_t instance_uuid,
11131     char *pBuffer,
11132     size_t *position,
11133     size_t bufferSize,
11134     uint32_t *num_pairs)
11135 {
11136 	_static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
11137 	//log_10 2^16 ≈ 4.82
11138 	const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
11139 	const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
11140 
11141 	if (!pBuffer) {
11142 		OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
11143 		OSKextPgoMetadataPutMax(position, "UUID", 36);
11144 		OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
11145 	} else {
11146 		uuid_string_t instance_uuid_string;
11147 		uuid_unparse(instance_uuid, instance_uuid_string);
11148 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11149 		    "INSTANCE", instance_uuid_string);
11150 
11151 		OSSharedPtr<OSData> uuid_data;
11152 		uuid_t uuid;
11153 		uuid_string_t uuid_string;
11154 		uuid_data = kext->copyUUID();
11155 		if (uuid_data) {
11156 			memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
11157 			uuid_unparse(uuid, uuid_string);
11158 			OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11159 			    "UUID", uuid_string);
11160 		}
11161 
11162 		clock_sec_t secs;
11163 		clock_usec_t usecs;
11164 		clock_get_calendar_microtime(&secs, &usecs);
11165 		assert(usecs < 1000000);
11166 		char timestamp[max_timestamp_string_size + 1];
11167 		_static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
11168 		snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
11169 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11170 		    "TIMESTAMP", timestamp);
11171 	}
11172 
11173 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11174 	    "NAME", kext->getIdentifierCString());
11175 
11176 	char versionCString[kOSKextVersionMaxLength];
11177 	OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
11178 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
11179 	    "VERSION", versionCString);
11180 }
11181 
11182 static
11183 size_t
11184 OSKextPgoMetadataSize(OSKext *kext)
11185 {
11186 	size_t position = 0;
11187 	uuid_t fakeuuid = {};
11188 	OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
11189 	return position;
11190 }
11191 
11192 int
11193 OSKextGrabPgoDataLocked(OSKext *kext,
11194     bool metadata,
11195     uuid_t instance_uuid,
11196     uint64_t *pSize,
11197     char *pBuffer,
11198     uint64_t bufferSize)
11199 {
11200 	int err = 0;
11201 
11202 	kernel_section_t *sect_prf_data = NULL;
11203 	kernel_section_t *sect_prf_name = NULL;
11204 	kernel_section_t *sect_prf_cnts = NULL;
11205 	uint64_t size;
11206 	size_t metadata_size = 0;
11207 	size_t offset_to_pairs = 0;
11208 
11209 	sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
11210 	sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
11211 	if (!sect_prf_name) {
11212 		// kextcache sometimes truncates the section name to 15 chars
11213 		// <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache
11214 		sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
11215 	}
11216 	sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
11217 
11218 	// Ignore some sections used by optional PGO variants.
11219 	const char *unused_section = NULL;
11220 
11221 	if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
11222 		err = ENOTSUP;
11223 		goto out;
11224 	}
11225 
11226 	size = __llvm_profile_get_size_for_buffer_internal(
11227 		(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
11228 		(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
11229 		unused_section /* bits */, unused_section /* bits end */,
11230 		(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size,
11231 		unused_section /* vtab */, unused_section /* vtab end */,
11232 		unused_section /* vnam */, unused_section /* vnam end */);
11233 
11234 	if (metadata) {
11235 		metadata_size = OSKextPgoMetadataSize(kext);
11236 		size += metadata_size;
11237 		size += sizeof(pgo_metadata_footer);
11238 	}
11239 
11240 
11241 	if (pSize) {
11242 		*pSize = size;
11243 	}
11244 
11245 	if (pBuffer && bufferSize) {
11246 		if (bufferSize < size) {
11247 			err = ERANGE;
11248 			goto out;
11249 		}
11250 
11251 		err = __llvm_profile_write_buffer_internal(
11252 			pBuffer,
11253 			(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
11254 			(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
11255 			unused_section /* bits */, unused_section /* bits end */,
11256 			(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
11257 
11258 		if (err) {
11259 			err = EIO;
11260 			goto out;
11261 		}
11262 
11263 		if (metadata) {
11264 			offset_to_pairs = sizeof(struct pgo_metadata_footer) + metadata_size;
11265 			if (offset_to_pairs > UINT32_MAX) {
11266 				err = E2BIG;
11267 				goto out;
11268 			}
11269 
11270 			char *end_of_buffer = pBuffer + size;
11271 			struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
11272 			char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
11273 
11274 			size_t metadata_position = 0;
11275 			uint32_t num_pairs = 0;
11276 			OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
11277 			while (metadata_position < metadata_size) {
11278 				metadata_buffer[metadata_position++] = 0;
11279 			}
11280 
11281 			struct pgo_metadata_footer footer;
11282 			footer.magic = htonl(0x6d657461);
11283 			footer.number_of_pairs = htonl( num_pairs );
11284 			footer.offset_to_pairs = htonl((uint32_t)offset_to_pairs );
11285 			memcpy(footerp, &footer, sizeof(footer));
11286 		}
11287 	}
11288 
11289 out:
11290 	return err;
11291 }
11292 
11293 
11294 int
11295 OSKextGrabPgoData(uuid_t uuid,
11296     uint64_t *pSize,
11297     char *pBuffer,
11298     uint64_t bufferSize,
11299     int wait_for_unload,
11300     int metadata)
11301 {
11302 	int err = 0;
11303 	OSSharedPtr<OSKext> kext;
11304 
11305 
11306 	IORecursiveLockLock(sKextLock);
11307 
11308 	kext = OSKext::lookupKextWithUUID(uuid);
11309 	if (!kext) {
11310 		err = ENOENT;
11311 		goto out;
11312 	}
11313 
11314 	if (wait_for_unload) {
11315 		OSKextGrabPgoStruct s;
11316 
11317 		s.metadata = metadata;
11318 		s.pSize = pSize;
11319 		s.pBuffer = pBuffer;
11320 		s.bufferSize = bufferSize;
11321 		s.err = EINTR;
11322 
11323 		struct list_head *prev = &kext->pendingPgoHead;
11324 		struct list_head *next = kext->pendingPgoHead.next;
11325 
11326 		s.list_head.prev = prev;
11327 		s.list_head.next = next;
11328 
11329 		prev->next = &s.list_head;
11330 		next->prev = &s.list_head;
11331 
11332 		kext.reset();
11333 
11334 		IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
11335 
11336 		prev = s.list_head.prev;
11337 		next = s.list_head.next;
11338 
11339 		prev->next = next;
11340 		next->prev = prev;
11341 
11342 		err = s.err;
11343 	} else {
11344 		err = OSKextGrabPgoDataLocked(kext.get(), metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
11345 	}
11346 
11347 out:
11348 
11349 	IORecursiveLockUnlock(sKextLock);
11350 
11351 	return err;
11352 }
11353 
11354 void
11355 OSKextResetPgoCountersLock()
11356 {
11357 	IORecursiveLockLock(sKextLock);
11358 }
11359 
11360 void
11361 OSKextResetPgoCountersUnlock()
11362 {
11363 	IORecursiveLockUnlock(sKextLock);
11364 }
11365 
11366 
11367 extern unsigned int not_in_kdp;
11368 
11369 void
11370 OSKextResetPgoCounters()
11371 {
11372 	assert(!not_in_kdp);
11373 	uint32_t count = sLoadedKexts->getCount();
11374 	for (uint32_t i = 0; i < count; i++) {
11375 		OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
11376 		kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
11377 		if (!sect_prf_cnts) {
11378 			continue;
11379 		}
11380 		memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
11381 	}
11382 }
11383 
11384 OSSharedPtr<OSDictionary>
11385 OSKext::copyLoadedKextInfoByUUID(
11386 	OSArray * kextIdentifiers,
11387 	OSArray * infoKeys)
11388 {
11389 	OSSharedPtr<OSDictionary> result;
11390 	OSSharedPtr<OSDictionary> kextInfo;
11391 	uint32_t       max_count, i, j;
11392 	uint32_t       idCount = 0;
11393 	uint32_t       idIndex = 0;
11394 	IORecursiveLockLock(sKextLock);
11395 	OSArray *list[2] = {sLoadedKexts.get(), sLoadedDriverKitKexts.get()};
11396 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
11397 
11398 #if CONFIG_MACF
11399 	/* Is the calling process allowed to query kext info? */
11400 	if (current_task() != kernel_task) {
11401 		int                 macCheckResult      = 0;
11402 		kauth_cred_t        cred                = NULL;
11403 
11404 		cred = kauth_cred_get_with_ref();
11405 		macCheckResult = mac_kext_check_query(cred);
11406 		kauth_cred_unref(&cred);
11407 
11408 		if (macCheckResult != 0) {
11409 			OSKextLog(/* kext */ NULL,
11410 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11411 			    "Failed to query kext info (MAC policy error 0x%x).",
11412 			    macCheckResult);
11413 			goto finish;
11414 		}
11415 	}
11416 #endif
11417 
11418 	/* Empty list of UUIDs is equivalent to no list (get all).
11419 	 */
11420 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11421 		kextIdentifiers = NULL;
11422 	} else if (kextIdentifiers) {
11423 		idCount = kextIdentifiers->getCount();
11424 	}
11425 
11426 	/* Same for keys.
11427 	 */
11428 	if (infoKeys && !infoKeys->getCount()) {
11429 		infoKeys = NULL;
11430 	}
11431 
11432 	max_count = count[0] + count[1];
11433 	result = OSDictionary::withCapacity(max_count);
11434 	if (!result) {
11435 		goto finish;
11436 	}
11437 
11438 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
11439 		for (i = 0; i < count[j]; i++) {
11440 			OSKext       *thisKext     = NULL;        // do not release
11441 			Boolean       includeThis  = true;
11442 			uuid_t        thisKextUUID;
11443 			uuid_t        thisKextTextUUID;
11444 			OSSharedPtr<OSData> uuid_data;
11445 			uuid_string_t uuid_key;
11446 
11447 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
11448 			if (!thisKext) {
11449 				continue;
11450 			}
11451 
11452 			uuid_data = thisKext->copyUUID();
11453 			if (!uuid_data) {
11454 				continue;
11455 			}
11456 
11457 			memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
11458 
11459 			uuid_unparse(thisKextUUID, uuid_key);
11460 
11461 			uuid_data = thisKext->copyTextUUID();
11462 			if (!uuid_data) {
11463 				continue;
11464 			}
11465 			memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
11466 
11467 			/* Skip current kext if we have a list of UUIDs and
11468 			 * it isn't in the list.
11469 			 */
11470 			if (kextIdentifiers) {
11471 				includeThis = false;
11472 
11473 				for (idIndex = 0; idIndex < idCount; idIndex++) {
11474 					const OSString* wantedUUID = OSDynamicCast(OSString,
11475 					    kextIdentifiers->getObject(idIndex));
11476 
11477 					uuid_t uuid;
11478 					uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
11479 
11480 					if ((0 == uuid_compare(uuid, thisKextUUID))
11481 					    || (0 == uuid_compare(uuid, thisKextTextUUID))) {
11482 						includeThis = true;
11483 						/* Only need to find the first kext if multiple match,
11484 						 * ie. asking for the kernel uuid does not need to find
11485 						 * interface kexts or builtin static kexts.
11486 						 */
11487 						kextIdentifiers->removeObject(idIndex);
11488 						uuid_unparse(uuid, uuid_key);
11489 						break;
11490 					}
11491 				}
11492 			}
11493 
11494 			if (!includeThis) {
11495 				continue;
11496 			}
11497 
11498 			kextInfo = thisKext->copyInfo(infoKeys);
11499 			if (kextInfo) {
11500 				result->setObject(uuid_key, kextInfo.get());
11501 			}
11502 
11503 			if (kextIdentifiers && !kextIdentifiers->getCount()) {
11504 				goto finish;
11505 			}
11506 		}
11507 	}
11508 
11509 finish:
11510 	IORecursiveLockUnlock(sKextLock);
11511 
11512 	return result;
11513 }
11514 
11515 /*********************************************************************
11516 *********************************************************************/
11517 /* static */
11518 OSSharedPtr<OSDictionary>
11519 OSKext::copyKextCollectionInfo(
11520 	OSDictionary *requestDict,
11521 	OSArray  *infoKeys)
11522 {
11523 	OSSharedPtr<OSDictionary> result;
11524 	OSString *collectionType = NULL;
11525 	OSObject *rawLoadedState = NULL;
11526 	OSString *loadedState    = NULL;
11527 
11528 	kc_kind_t kc_request_kind = KCKindUnknown;
11529 	bool onlyLoaded = false;
11530 	bool onlyUnloaded = false;
11531 
11532 #if CONFIG_MACF
11533 	/* Is the calling process allowed to query kext info? */
11534 	if (current_task() != kernel_task) {
11535 		int                 macCheckResult      = 0;
11536 		kauth_cred_t        cred                = NULL;
11537 
11538 		cred = kauth_cred_get_with_ref();
11539 		macCheckResult = mac_kext_check_query(cred);
11540 		kauth_cred_unref(&cred);
11541 
11542 		if (macCheckResult != 0) {
11543 			OSKextLog(/* kext */ NULL,
11544 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11545 			    "Failed to query kext info (MAC policy error 0x%x).",
11546 			    macCheckResult);
11547 			goto finish;
11548 		}
11549 	}
11550 #endif
11551 
11552 	if (infoKeys && !infoKeys->getCount()) {
11553 		infoKeys = NULL;
11554 	}
11555 
11556 	collectionType = OSDynamicCast(OSString,
11557 	    _OSKextGetRequestArgument(requestDict,
11558 	    kKextRequestArgumentCollectionTypeKey));
11559 	if (!collectionType) {
11560 		OSKextLog(/* kext */ NULL,
11561 		    kOSKextLogErrorLevel |
11562 		    kOSKextLogIPCFlag,
11563 		    "Invalid '%s' argument to kext collection info request.",
11564 		    kKextRequestArgumentCollectionTypeKey);
11565 		goto finish;
11566 	}
11567 	if (collectionType->isEqualTo(kKCTypePrimary)) {
11568 		kc_request_kind = KCKindPrimary;
11569 	} else if (collectionType->isEqualTo(kKCTypeSystem)) {
11570 		kc_request_kind = KCKindPageable;
11571 	} else if (collectionType->isEqualTo(kKCTypeAuxiliary)) {
11572 		kc_request_kind = KCKindAuxiliary;
11573 	} else if (collectionType->isEqualTo(kKCTypeCodeless)) {
11574 		kc_request_kind = KCKindNone;
11575 	} else if (!collectionType->isEqualTo(kKCTypeAny)) {
11576 		OSKextLog(/* kext */ NULL,
11577 		    kOSKextLogErrorLevel |
11578 		    kOSKextLogIPCFlag,
11579 		    "Invalid '%s' argument value '%s' to kext collection info request.",
11580 		    kKextRequestArgumentCollectionTypeKey,
11581 		    collectionType->getCStringNoCopy());
11582 		goto finish;
11583 	}
11584 
11585 	rawLoadedState = _OSKextGetRequestArgument(requestDict,
11586 	    kKextRequestArgumentLoadedStateKey);
11587 	if (rawLoadedState) {
11588 		loadedState = OSDynamicCast(OSString, rawLoadedState);
11589 		if (!loadedState) {
11590 			OSKextLog(/* kext */ NULL,
11591 			    kOSKextLogErrorLevel |
11592 			    kOSKextLogIPCFlag,
11593 			    "Invalid '%s' argument to kext collection info request.",
11594 			    kKextRequestArgumentLoadedStateKey);
11595 			goto finish;
11596 		}
11597 	}
11598 	if (loadedState) {
11599 		if (loadedState->isEqualTo("Loaded")) {
11600 			onlyLoaded = true;
11601 		} else if (loadedState->isEqualTo("Unloaded")) {
11602 			onlyUnloaded = true;
11603 		} else if (!loadedState->isEqualTo("Any")) {
11604 			OSKextLog(/* kext */ NULL,
11605 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11606 			    "Invalid '%s' argument value '%s' for '%s' collection info",
11607 			    kKextRequestArgumentLoadedStateKey,
11608 			    loadedState->getCStringNoCopy(),
11609 			    collectionType->getCStringNoCopy());
11610 			goto finish;
11611 		}
11612 	}
11613 
11614 	result = OSDictionary::withCapacity(sKextsByID->getCount());
11615 	if (!result) {
11616 		goto finish;
11617 	}
11618 
11619 	IORecursiveLockLock(sKextLock);
11620 	{         // start block scope
11621 		sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11622 		{
11623 			OSKext       *thisKext    = NULL;  // do not release
11624 			OSSharedPtr<OSDictionary> kextInfo;
11625 
11626 			(void)thisKextID;
11627 
11628 			thisKext = OSDynamicCast(OSKext, obj);
11629 			if (!thisKext) {
11630 			        return false;
11631 			}
11632 
11633 			/*
11634 			 * skip the kext if it came from the wrong collection type
11635 			 * (and the caller requested a specific type)
11636 			 */
11637 			if ((kc_request_kind != KCKindUnknown) && (thisKext->kc_type != kc_request_kind)) {
11638 			        return false;
11639 			}
11640 
11641 			/*
11642 			 * respect the caller's desire to find only loaded or
11643 			 * unloaded kexts
11644 			 */
11645 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11646 			        return false;
11647 			}
11648 			if (onlyUnloaded && (-1U != sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11649 			        return false;
11650 			}
11651 
11652 			kextInfo = thisKext->copyInfo(infoKeys);
11653 			if (kextInfo) {
11654 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
11655 			}
11656 			return false;
11657 		});
11658 	} // end block scope
11659 	IORecursiveLockUnlock(sKextLock);
11660 
11661 finish:
11662 	return result;
11663 }
11664 
11665 /* static */
11666 OSSharedPtr<OSArray>
11667 OSKext::copyDextsInfo(
11668 	OSArray *kextIdentifiers,
11669 	OSArray *infoKeys)
11670 {
11671 	OSSharedPtr<OSArray> result = NULL;
11672 	uint32_t idCount = 0;
11673 	bool getActive = false;
11674 	bool getLoaded = false;
11675 	bool getUnloaded = false;
11676 	bool getPendingUpgrade = false;
11677 	unsigned int avgDextCount = 0;
11678 
11679 #if CONFIG_MACF
11680 	/* Is the calling process allowed to query dext info? */
11681 	if (current_task() != kernel_task) {
11682 		int                 macCheckResult      = 0;
11683 		kauth_cred_t        cred                = NULL;
11684 
11685 		cred = kauth_cred_get_with_ref();
11686 		macCheckResult = mac_kext_check_query(cred);
11687 		kauth_cred_unref(&cred);
11688 
11689 		if (macCheckResult != 0) {
11690 			OSKextLog(/* kext */ NULL,
11691 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11692 			    "Failed to query kext info (MAC policy error 0x%x).",
11693 			    macCheckResult);
11694 			goto finish;
11695 		}
11696 	}
11697 #endif
11698 	/*
11699 	 * No infoKeys means return everything we
11700 	 * know about the dexts.
11701 	 */
11702 	if (infoKeys && !infoKeys->getCount()) {
11703 		infoKeys = NULL;
11704 	}
11705 
11706 	/*
11707 	 * Empty list of bundle ids is equivalent to
11708 	 * no list (get all).
11709 	 */
11710 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11711 		kextIdentifiers = NULL;
11712 	} else if (kextIdentifiers) {
11713 		idCount = kextIdentifiers->getCount();
11714 	}
11715 
11716 	/*
11717 	 * Caller can specify which state of dexts to query.
11718 	 */
11719 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveKey)) {
11720 		getActive = true;
11721 	}
11722 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveLoadedKey)) {
11723 		getLoaded = true;
11724 	}
11725 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStateActiveUnloadedKey)) {
11726 		getUnloaded = true;
11727 	}
11728 	if (infoKeys && _OSArrayContainsCString(infoKeys, kOSBundleDextStatePendingUpgradeKey)) {
11729 		getPendingUpgrade = true;
11730 	}
11731 
11732 	/*
11733 	 * By default we are going to return all active and pendingUpgrade dexts
11734 	 * only.
11735 	 */
11736 	if (!(getActive || getLoaded || getUnloaded || getPendingUpgrade)) {
11737 		getActive = true;
11738 		getPendingUpgrade = true;
11739 	}
11740 
11741 	/*
11742 	 * We return a dictionary of dexts
11743 	 * for every group requested.
11744 	 */
11745 	avgDextCount = sLoadedDriverKitKexts->getCount() + sDriverKitToUpgradeByID->getCount();
11746 	result = OSArray::withCapacity(avgDextCount);
11747 	if (!result) {
11748 		goto finish;
11749 	}
11750 
11751 	IORecursiveLockLock(sKextLock);
11752 	{ // start block scope
11753 		if (getActive || getLoaded || getUnloaded) {
11754 			sKextsByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11755 			{
11756 				OSKext *thisKext = NULL;  // do not release
11757 				OSSharedPtr<OSDictionary> kextInfo;
11758 				Boolean includeThis = true;
11759 				(void)thisKextID;
11760 
11761 				thisKext = OSDynamicCast(OSKext, obj);
11762 				if (!thisKext || !thisKext->isDriverKit()) {
11763 				        return false;
11764 				}
11765 
11766 				/*
11767 				 * Skip current dext if we have a list of bundle IDs and
11768 				 * it isn't in the list.
11769 				 */
11770 				if (kextIdentifiers) {
11771 				        includeThis = false;
11772 
11773 				        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11774 				                const OSString * thisRequestID = OSDynamicCast(OSString,
11775 				                kextIdentifiers->getObject(idIndex));
11776 				                if (thisKextID->isEqualTo(thisRequestID)) {
11777 				                        includeThis = true;
11778 				                        break;
11779 						}
11780 					}
11781 				}
11782 
11783 				if (!includeThis) {
11784 				        return false;
11785 				}
11786 
11787 				OSSharedPtr<OSString> state;
11788 				if (sLoadedDriverKitKexts->getNextIndexOfObject(thisKext, 0) == -1U) {
11789 				        if (!(getActive || getUnloaded)) {
11790 				                return false;
11791 					}
11792 				        state = OSString::withCString(kOSBundleDextStateActiveUnloadedKey);
11793 				} else {
11794 				        if (!(getActive || getLoaded)) {
11795 				                return false;
11796 					}
11797 				        state = OSString::withCString(kOSBundleDextStateActiveLoadedKey);
11798 				}
11799 
11800 				kextInfo = thisKext->copyInfo(infoKeys);
11801 				if (kextInfo) {
11802 				        kextInfo->setObject(kOSBundleDextStateKey, state.get());
11803 				        result->setObject(kextInfo.get());
11804 				}
11805 
11806 				return false;
11807 			});
11808 		}
11809 
11810 		if (getPendingUpgrade) {
11811 			sDriverKitToUpgradeByID->iterateObjects(^bool (const OSSymbol *thisKextID, OSObject *obj)
11812 			{
11813 				OSKext *thisKext = NULL;  // do not release
11814 				OSSharedPtr<OSDictionary> kextInfo;
11815 				Boolean includeThis = true;
11816 				(void)thisKextID;
11817 
11818 				thisKext = OSDynamicCast(OSKext, obj);
11819 				if (!thisKext) {
11820 				        return false;
11821 				}
11822 				__assert_only bool isDext = thisKext->isDriverKit();
11823 				assert(isDext == true);
11824 
11825 				/*
11826 				 * Skip current dext if we have a list of bundle IDs and
11827 				 * it isn't in the list.
11828 				 */
11829 				if (kextIdentifiers) {
11830 				        includeThis = false;
11831 
11832 				        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11833 				                const OSString * thisRequestID = OSDynamicCast(OSString,
11834 				                kextIdentifiers->getObject(idIndex));
11835 				                if (thisKextID->isEqualTo(thisRequestID)) {
11836 				                        includeThis = true;
11837 				                        break;
11838 						}
11839 					}
11840 				}
11841 
11842 				if (!includeThis) {
11843 				        return false;
11844 				}
11845 
11846 				kextInfo = thisKext->copyInfo(infoKeys);
11847 				if (kextInfo) {
11848 				        OSSharedPtr<OSString> state = OSString::withCString(kOSBundleDextStatePendingUpgradeKey);
11849 				        kextInfo->setObject(kOSBundleDextStateKey, state.get());
11850 				        result->setObject(kextInfo.get());
11851 				}
11852 				return false;
11853 			});
11854 		}
11855 	} // end block scope
11856 	IORecursiveLockUnlock(sKextLock);
11857 finish:
11858 	return result;
11859 }
11860 
11861 /*********************************************************************
11862 *********************************************************************/
11863 /* static */
11864 OSSharedPtr<OSDictionary>
11865 OSKext::copyLoadedKextInfo(
11866 	OSArray * kextIdentifiers,
11867 	OSArray * infoKeys)
11868 {
11869 	OSSharedPtr<OSDictionary> result;
11870 	uint32_t       idCount = 0;
11871 	bool           onlyLoaded;
11872 
11873 	IORecursiveLockLock(sKextLock);
11874 
11875 #if CONFIG_MACF
11876 	/* Is the calling process allowed to query kext info? */
11877 	if (current_task() != kernel_task) {
11878 		int                 macCheckResult      = 0;
11879 		kauth_cred_t        cred                = NULL;
11880 
11881 		cred = kauth_cred_get_with_ref();
11882 		macCheckResult = mac_kext_check_query(cred);
11883 		kauth_cred_unref(&cred);
11884 
11885 		if (macCheckResult != 0) {
11886 			OSKextLog(/* kext */ NULL,
11887 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
11888 			    "Failed to query kext info (MAC policy error 0x%x).",
11889 			    macCheckResult);
11890 			goto finish;
11891 		}
11892 	}
11893 #endif
11894 
11895 	/* Empty list of bundle ids is equivalent to no list (get all).
11896 	 */
11897 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
11898 		kextIdentifiers = NULL;
11899 	} else if (kextIdentifiers) {
11900 		idCount = kextIdentifiers->getCount();
11901 	}
11902 
11903 	/* Same for keys.
11904 	 */
11905 	if (infoKeys && !infoKeys->getCount()) {
11906 		infoKeys = NULL;
11907 	}
11908 
11909 	onlyLoaded =  (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
11910 
11911 	result = OSDictionary::withCapacity(128);
11912 	if (!result) {
11913 		goto finish;
11914 	}
11915 
11916 #if 0
11917 	OSKextLog(/* kext */ NULL,
11918 	    kOSKextLogErrorLevel |
11919 	    kOSKextLogGeneralFlag,
11920 	    "kaslr: vm_kernel_slide 0x%lx \n",
11921 	    vm_kernel_slide);
11922 	OSKextLog(/* kext */ NULL,
11923 	    kOSKextLogErrorLevel |
11924 	    kOSKextLogGeneralFlag,
11925 	    "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
11926 	    vm_kernel_stext, vm_kernel_etext);
11927 	OSKextLog(/* kext */ NULL,
11928 	    kOSKextLogErrorLevel |
11929 	    kOSKextLogGeneralFlag,
11930 	    "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
11931 	    vm_kernel_base, vm_kernel_top);
11932 	OSKextLog(/* kext */ NULL,
11933 	    kOSKextLogErrorLevel |
11934 	    kOSKextLogGeneralFlag,
11935 	    "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
11936 	    vm_kext_base, vm_kext_top);
11937 	OSKextLog(/* kext */ NULL,
11938 	    kOSKextLogErrorLevel |
11939 	    kOSKextLogGeneralFlag,
11940 	    "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
11941 	    vm_prelink_stext, vm_prelink_etext);
11942 	OSKextLog(/* kext */ NULL,
11943 	    kOSKextLogErrorLevel |
11944 	    kOSKextLogGeneralFlag,
11945 	    "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
11946 	    vm_prelink_sinfo, vm_prelink_einfo);
11947 	OSKextLog(/* kext */ NULL,
11948 	    kOSKextLogErrorLevel |
11949 	    kOSKextLogGeneralFlag,
11950 	    "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
11951 	    vm_slinkedit, vm_elinkedit);
11952 #endif
11953 	{         // start block scope
11954 		sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
11955 		{
11956 			OSKext       * thisKext     = NULL;        // do not release
11957 			Boolean        includeThis  = true;
11958 			OSSharedPtr<OSDictionary> kextInfo;
11959 
11960 			thisKext = OSDynamicCast(OSKext, obj);
11961 			if (!thisKext) {
11962 			        return false;
11963 			}
11964 
11965 			/* Skip current kext if not yet started and caller didn't request all.
11966 			 */
11967 			if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
11968 			        return false;
11969 			}
11970 
11971 			/* Skip current kext if we have a list of bundle IDs and
11972 			 * it isn't in the list.
11973 			 */
11974 			if (kextIdentifiers) {
11975 			        includeThis = false;
11976 
11977 			        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
11978 			                const OSString * thisRequestID = OSDynamicCast(OSString,
11979 			                kextIdentifiers->getObject(idIndex));
11980 			                if (thisKextID->isEqualTo(thisRequestID)) {
11981 			                        includeThis = true;
11982 			                        break;
11983 					}
11984 				}
11985 			}
11986 
11987 			if (!includeThis) {
11988 			        return false;
11989 			}
11990 
11991 			kextInfo = thisKext->copyInfo(infoKeys);
11992 			if (kextInfo) {
11993 			        result->setObject(thisKext->getIdentifier(), kextInfo.get());
11994 			}
11995 			return false;
11996 		});
11997 	}         // end block scope
11998 
11999 finish:
12000 	IORecursiveLockUnlock(sKextLock);
12001 
12002 	return result;
12003 }
12004 
12005 /*********************************************************************
12006 * Any info that needs to do allocations must goto finish on alloc
12007 * failure. Info that is just a lookup should just not set the object
12008 * if the info does not exist.
12009 *********************************************************************/
12010 #define _OSKextLoadInfoDictCapacity   (12)
12011 
12012 OSSharedPtr<OSDictionary>
12013 OSKext::copyInfo(OSArray * infoKeys)
12014 {
12015 	OSSharedPtr<OSDictionary>  result;
12016 	bool                       success                     = false;
12017 	OSSharedPtr<OSData>        headerData;
12018 	OSSharedPtr<OSData>        logData;
12019 	OSSharedPtr<OSNumber>      cpuTypeNumber;
12020 	OSSharedPtr<OSNumber>      cpuSubtypeNumber;
12021 	OSString                 * versionString               = NULL;        // do not release
12022 	OSString                 * bundleType                  = NULL;        // do not release
12023 	uint32_t                   executablePathCStringSize   = 0;
12024 	char                     * executablePathCString       = NULL;        // must kfree
12025 	OSSharedPtr<OSString>      executablePathString;
12026 	OSSharedPtr<OSData>        uuid;
12027 	OSSharedPtr<OSArray>       dependencyLoadTags;
12028 	OSSharedPtr<OSCollectionIterator>      metaClassIterator;
12029 	OSSharedPtr<OSArray>       metaClassInfo;
12030 	OSSharedPtr<OSDictionary>  metaClassDict;
12031 	OSMetaClass              * thisMetaClass               = NULL;        // do not release
12032 	OSSharedPtr<OSString>      metaClassName;
12033 	OSSharedPtr<OSString>      superclassName;
12034 	kc_format_t                kcformat;
12035 	uint32_t                   count, i;
12036 
12037 	result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
12038 	if (!result) {
12039 		goto finish;
12040 	}
12041 
12042 
12043 	/* Empty keys means no keys, but NULL is quicker to check.
12044 	 */
12045 	if (infoKeys && !infoKeys->getCount()) {
12046 		infoKeys = NULL;
12047 	}
12048 
12049 	if (!PE_get_primary_kc_format(&kcformat)) {
12050 		goto finish;
12051 	}
12052 
12053 	/* Headers, CPU type, and CPU subtype.
12054 	 */
12055 	if (!infoKeys ||
12056 	    _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
12057 	    _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
12058 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
12059 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
12060 		if (linkedExecutable && !isInterface()) {
12061 			kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
12062 			    linkedExecutable->getBytesNoCopy();
12063 
12064 #if !SECURE_KERNEL || XNU_TARGET_OS_OSX
12065 			// do not return macho header info on shipping embedded - 19095897
12066 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
12067 				kernel_mach_header_t *  temp_kext_mach_hdr;
12068 				struct load_command *   lcp;
12069 
12070 				headerData = OSData::withBytes(kext_mach_hdr,
12071 				    (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
12072 				if (!headerData) {
12073 					goto finish;
12074 				}
12075 
12076 				// unslide any vmaddrs we return to userspace - 10726716
12077 				temp_kext_mach_hdr = (kernel_mach_header_t *)
12078 				    headerData->getBytesNoCopy();
12079 				if (temp_kext_mach_hdr == NULL) {
12080 					goto finish;
12081 				}
12082 
12083 				lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
12084 				for (i = 0; (i < temp_kext_mach_hdr->ncmds) && !flags.unslidMachO; i++) {
12085 					if (lcp->cmd == LC_SEGMENT_KERNEL) {
12086 						kernel_segment_command_t *  segp;
12087 						kernel_section_t *          secp;
12088 
12089 						segp = (kernel_segment_command_t *) lcp;
12090 						// 10543468 - if we jettisoned __LINKEDIT clear size info
12091 						if (flags.jettisonLinkeditSeg) {
12092 							if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
12093 								segp->vmsize = 0;
12094 								segp->fileoff = 0;
12095 								segp->filesize = 0;
12096 							}
12097 						}
12098 
12099 #if __arm__ || __arm64__
12100 						// iBoot disregards zero-size segments, just set their addresses to gVirtBase
12101 						// and unslide them to avoid vm assertion failures / kernel logging breakage.
12102 						if (segp->vmsize == 0 && segp->vmaddr < gVirtBase) {
12103 							segp->vmaddr = gVirtBase;
12104 							for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
12105 								secp->size = 0; // paranoia :)
12106 								secp->addr = gVirtBase;
12107 							}
12108 						}
12109 #endif
12110 
12111 #if 0
12112 						OSKextLog(/* kext */ NULL,
12113 						    kOSKextLogErrorLevel |
12114 						    kOSKextLogGeneralFlag,
12115 						    "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
12116 						    __FUNCTION__, segp->segname, segp->vmaddr,
12117 						    VM_KERNEL_UNSLIDE(segp->vmaddr),
12118 						    segp->vmsize, segp->nsects);
12119 						if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
12120 						    (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
12121 						    (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
12122 						    (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
12123 						    (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
12124 							OSKextLog(/* kext */ NULL,
12125 							    kOSKextLogErrorLevel |
12126 							    kOSKextLogGeneralFlag,
12127 							    "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
12128 							    __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
12129 						}
12130 #endif
12131 						segp->vmaddr = ml_static_unslide(segp->vmaddr);
12132 
12133 						for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
12134 							secp->addr = ml_static_unslide(secp->addr);
12135 						}
12136 					}
12137 					lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
12138 				}
12139 				result->setObject(kOSBundleMachOHeadersKey, headerData.get());
12140 			}
12141 #endif // !SECURE_KERNEL || XNU_TARGET_OS_OSX
12142 
12143 			if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
12144 				osLogDataHeaderRef *header;
12145 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
12146 
12147 				void *os_log_data               = NULL;
12148 				void *cstring_data              = NULL;
12149 				void *asan_cstring_data         = NULL;
12150 				unsigned long os_log_size       = 0;
12151 				unsigned long cstring_size      = 0;
12152 				unsigned long asan_cstring_size = 0;
12153 				uint32_t os_log_offset          = 0;
12154 				uint32_t cstring_offset         = 0;
12155 				uint32_t asan_cstring_offset    = 0;
12156 				bool res;
12157 
12158 				os_log_data         = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
12159 				cstring_data        = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
12160 				asan_cstring_data   = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__asan_cstring", &asan_cstring_size);
12161 
12162 				/*
12163 				 * If the addresses in the Mach-O header are unslid, manually
12164 				 * slide them to allow for dereferencing.
12165 				 */
12166 				if (flags.unslidMachO) {
12167 					os_log_data = (os_log_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)os_log_data) : nullptr;
12168 					cstring_data = (cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)cstring_data) : nullptr;
12169 					asan_cstring_data = (asan_cstring_data != nullptr) ? (void*)ml_static_slide((vm_offset_t)asan_cstring_data) : nullptr;
12170 				}
12171 
12172 				os_log_offset       = (uintptr_t)os_log_data - (uintptr_t)kext_mach_hdr;
12173 				cstring_offset      = (uintptr_t)cstring_data - (uintptr_t)kext_mach_hdr;
12174 				asan_cstring_offset = (uintptr_t)asan_cstring_data - (uintptr_t)kext_mach_hdr;
12175 
12176 				header             = (osLogDataHeaderRef *) headerBytes;
12177 				header->version    = OS_LOG_HDR_VERSION;
12178 				header->sect_count = NUM_OS_LOG_SECTIONS;
12179 				header->sections[OS_LOG_SECT_IDX].sect_offset       = os_log_offset;
12180 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) os_log_size;
12181 				header->sections[CSTRING_SECT_IDX].sect_offset      = cstring_offset;
12182 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) cstring_size;
12183 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = asan_cstring_offset;
12184 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) asan_cstring_size;
12185 
12186 
12187 				logData = OSData::withValue(*header);
12188 				if (!logData) {
12189 					goto finish;
12190 				}
12191 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
12192 				if (!res) {
12193 					goto finish;
12194 				}
12195 				if (os_log_data) {
12196 					res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
12197 					if (!res) {
12198 						goto finish;
12199 					}
12200 				}
12201 				if (cstring_data) {
12202 					res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
12203 					if (!res) {
12204 						goto finish;
12205 					}
12206 				}
12207 				if (asan_cstring_data) {
12208 					res = logData->appendBytes(asan_cstring_data, (u_int)header->sections[ASAN_CSTRING_SECT_IDX].sect_size);
12209 					if (!res) {
12210 						goto finish;
12211 					}
12212 				}
12213 				result->setObject(kOSBundleLogStringsKey, logData.get());
12214 			}
12215 
12216 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
12217 				cpuTypeNumber = OSNumber::withNumber(
12218 					(uint64_t) kext_mach_hdr->cputype,
12219 					8 * sizeof(kext_mach_hdr->cputype));
12220 				if (!cpuTypeNumber) {
12221 					goto finish;
12222 				}
12223 				result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber.get());
12224 			}
12225 
12226 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
12227 				cpuSubtypeNumber = OSNumber::withNumber(
12228 					(uint64_t) kext_mach_hdr->cpusubtype,
12229 					8 * sizeof(kext_mach_hdr->cpusubtype));
12230 				if (!cpuSubtypeNumber) {
12231 					goto finish;
12232 				}
12233 				result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber.get());
12234 			}
12235 		} else {
12236 			if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
12237 				osLogDataHeaderRef *header;
12238 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
12239 				bool res;
12240 
12241 				header             = (osLogDataHeaderRef *) headerBytes;
12242 				header->version    = OS_LOG_HDR_VERSION;
12243 				header->sect_count = NUM_OS_LOG_SECTIONS;
12244 				header->sections[OS_LOG_SECT_IDX].sect_offset       = 0;
12245 				header->sections[OS_LOG_SECT_IDX].sect_size         = (uint32_t) 0;
12246 				header->sections[CSTRING_SECT_IDX].sect_offset      = 0;
12247 				header->sections[CSTRING_SECT_IDX].sect_size        = (uint32_t) 0;
12248 				header->sections[ASAN_CSTRING_SECT_IDX].sect_offset = 0;
12249 				header->sections[ASAN_CSTRING_SECT_IDX].sect_size   = (uint32_t) 0;
12250 
12251 				logData = OSData::withValue(*header);
12252 				if (!logData) {
12253 					goto finish;
12254 				}
12255 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
12256 				if (!res) {
12257 					goto finish;
12258 				}
12259 				result->setObject(kOSBundleLogStringsKey, logData.get());
12260 			}
12261 		}
12262 	}
12263 
12264 	/* CFBundleIdentifier. We set this regardless because it's just stupid not to.
12265 	 */
12266 	result->setObject(kCFBundleIdentifierKey, bundleID.get());
12267 
12268 	/* kOSBundleDextUniqueIdentifierKey if present.
12269 	 */
12270 	if (isDriverKit() && dextUniqueID != NULL) {
12271 		result->setObject(kOSBundleDextUniqueIdentifierKey, dextUniqueID.get());
12272 	}
12273 
12274 	/* CFBundlePackageType
12275 	 */
12276 	bundleType = infoDict ? OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey)): NULL;
12277 	if (bundleType) {
12278 		result->setObject(kCFBundlePackageTypeKey, bundleType);
12279 	}
12280 
12281 	/* CFBundleVersion.
12282 	 */
12283 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
12284 		versionString = OSDynamicCast(OSString,
12285 		    getPropertyForHostArch(kCFBundleVersionKey));
12286 		if (versionString) {
12287 			result->setObject(kCFBundleVersionKey, versionString);
12288 		}
12289 	}
12290 
12291 	/* OSBundleCompatibleVersion.
12292 	 */
12293 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
12294 		versionString = OSDynamicCast(OSString,
12295 		    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
12296 		if (versionString) {
12297 			result->setObject(kOSBundleCompatibleVersionKey, versionString);
12298 		}
12299 	}
12300 
12301 	/* Path.
12302 	 */
12303 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
12304 		if (path) {
12305 			result->setObject(kOSBundlePathKey, path.get());
12306 		}
12307 	}
12308 
12309 
12310 	/* OSBundleExecutablePath.
12311 	 */
12312 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
12313 		if (path && executableRelPath) {
12314 			uint32_t pathLength = path->getLength();         // gets incremented below
12315 
12316 			// +1 for slash, +1 for \0
12317 			executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
12318 
12319 			executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
12320 			    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);         // +1 for \0
12321 			if (!executablePathCString) {
12322 				goto finish;
12323 			}
12324 			strlcpy(executablePathCString, path->getCStringNoCopy(),
12325 			    executablePathCStringSize);
12326 			executablePathCString[pathLength++] = '/';
12327 			executablePathCString[pathLength++] = '\0';
12328 			strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
12329 			    executablePathCStringSize);
12330 
12331 			executablePathString = OSString::withCString(executablePathCString);
12332 
12333 			if (!executablePathString) {
12334 				goto finish;
12335 			}
12336 
12337 			result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
12338 		} else if (flags.builtin) {
12339 			result->setObject(kOSBundleExecutablePathKey, bundleID.get());
12340 		} else if (isDriverKit()) {
12341 			if (path) {
12342 				// +1 for slash, +1 for \0
12343 				uint32_t pathLength = path->getLength();
12344 				executablePathCStringSize = pathLength + 2;
12345 
12346 				executablePathCString = (char *)kalloc_data_tag(executablePathCStringSize,
12347 				    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
12348 				if (!executablePathCString) {
12349 					goto finish;
12350 				}
12351 				strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize);
12352 				executablePathCString[pathLength++] = '/';
12353 				executablePathCString[pathLength++] = '\0';
12354 
12355 				executablePathString = OSString::withCString(executablePathCString);
12356 
12357 				if (!executablePathString) {
12358 					goto finish;
12359 				}
12360 
12361 				result->setObject(kOSBundleExecutablePathKey, executablePathString.get());
12362 			}
12363 		}
12364 	}
12365 
12366 	/* UUID, if the kext has one.
12367 	 */
12368 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
12369 		uuid = copyUUID();
12370 		if (uuid) {
12371 			result->setObject(kOSBundleUUIDKey, uuid.get());
12372 		}
12373 	}
12374 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
12375 		uuid = copyTextUUID();
12376 		if (uuid) {
12377 			result->setObject(kOSBundleTextUUIDKey, uuid.get());
12378 		}
12379 	}
12380 
12381 	/*
12382 	 * Info.plist digest
12383 	 */
12384 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextInfoPlistDigestKey)) {
12385 		OSData *digest;
12386 		digest = infoDict ? OSDynamicCast(OSData, infoDict->getObject(kOSKextInfoPlistDigestKey)) : NULL;
12387 		if (digest) {
12388 			result->setObject(kOSKextInfoPlistDigestKey, digest);
12389 		}
12390 	}
12391 
12392 	/*
12393 	 * Collection type
12394 	 */
12395 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextBundleCollectionTypeKey)) {
12396 		result->setObject(kOSKextBundleCollectionTypeKey, OSString::withCString(getKCTypeString()));
12397 	}
12398 
12399 	/*
12400 	 * Collection availability
12401 	 */
12402 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKextAuxKCAvailabilityKey)) {
12403 		result->setObject(kOSKextAuxKCAvailabilityKey,
12404 		    isLoadable() ? kOSBooleanTrue : kOSBooleanFalse);
12405 	}
12406 
12407 	/*
12408 	 * Allows user load
12409 	 */
12410 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleAllowUserLoadKey)) {
12411 		OSBoolean *allowUserLoad = OSDynamicCast(OSBoolean, getPropertyForHostArch(kOSBundleAllowUserLoadKey));
12412 		if (allowUserLoad) {
12413 			result->setObject(kOSBundleAllowUserLoadKey, allowUserLoad);
12414 		}
12415 	}
12416 
12417 	/*
12418 	 * Bundle Dependencies (OSBundleLibraries)
12419 	 */
12420 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLibrariesKey)) {
12421 		OSDictionary *libraries = OSDynamicCast(OSDictionary, getPropertyForHostArch(kOSBundleLibrariesKey));
12422 		if (libraries) {
12423 			result->setObject(kOSBundleLibrariesKey, libraries);
12424 		}
12425 	}
12426 
12427 	/*****
12428 	 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
12429 	 */
12430 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
12431 		result->setObject(kOSKernelResourceKey,
12432 		    isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
12433 	}
12434 
12435 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
12436 		result->setObject(kOSBundleIsInterfaceKey,
12437 		    isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
12438 	}
12439 
12440 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
12441 		result->setObject(kOSBundlePrelinkedKey,
12442 		    isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
12443 	}
12444 
12445 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
12446 		result->setObject(kOSBundleStartedKey,
12447 		    isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
12448 	}
12449 
12450 	/* LoadTag (Index).
12451 	 */
12452 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
12453 		OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
12454 		    /* numBits */ 8 * sizeof(loadTag));
12455 		if (!scratchNumber) {
12456 			goto finish;
12457 		}
12458 		result->setObject(kOSBundleLoadTagKey, scratchNumber.get());
12459 	}
12460 
12461 	/* LoadAddress, LoadSize.
12462 	 */
12463 	if (!infoKeys ||
12464 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
12465 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
12466 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
12467 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
12468 	    _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
12469 		bool is_dext = isDriverKit();
12470 		if (isInterface() || flags.builtin || linkedExecutable || is_dext) {
12471 			/* These go to userspace via serialization, so we don't want any doubts
12472 			 * about their size.
12473 			 */
12474 			uint64_t    loadAddress     = 0;
12475 			uint32_t    loadSize        = 0;
12476 			uint32_t    wiredSize       = 0;
12477 			uint64_t    execLoadAddress = 0;
12478 			uint32_t    execLoadSize    = 0;
12479 
12480 			/* Interfaces always report 0 load address & size.
12481 			 * Just the way they roll.
12482 			 *
12483 			 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
12484 			 * xxx - shouldn't have one!
12485 			 */
12486 
12487 			if (flags.builtin || linkedExecutable) {
12488 				kernel_mach_header_t     *mh  = NULL;
12489 				kernel_segment_command_t *seg = NULL;
12490 
12491 				if (flags.builtin) {
12492 					loadAddress = kmod_info->address;
12493 					loadSize    = (uint32_t)kmod_info->size;
12494 				} else {
12495 					loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
12496 					loadSize = linkedExecutable->getLength();
12497 				}
12498 				mh = (kernel_mach_header_t *)loadAddress;
12499 				loadAddress = ml_static_unslide(loadAddress);
12500 
12501 				/* Walk through the kext, looking for the first executable
12502 				 * segment in case we were asked for its size/address.
12503 				 */
12504 				for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
12505 					if (seg->initprot & VM_PROT_EXECUTE) {
12506 						execLoadAddress = (flags.unslidMachO) ? seg->vmaddr : ml_static_unslide(seg->vmaddr);
12507 						execLoadSize = (uint32_t)seg->vmsize;
12508 						break;
12509 					}
12510 				}
12511 
12512 				/* If we have a kmod_info struct, calculated the wired size
12513 				 * from that. Otherwise it's the full load size.
12514 				 */
12515 				if (kmod_info) {
12516 					wiredSize = loadSize - (uint32_t)kmod_info->hdr_size;
12517 				} else {
12518 					wiredSize = loadSize;
12519 				}
12520 			} else if (is_dext) {
12521 				/*
12522 				 * DriverKit userspace executables do not have a kernel linkedExecutable,
12523 				 * so we "fake" their address range with the LoadTag.
12524 				 */
12525 				if (loadTag) {
12526 					loadAddress = execLoadAddress = loadTag;
12527 					loadSize = execLoadSize = 1;
12528 				}
12529 			}
12530 
12531 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
12532 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12533 					(unsigned long long)(loadAddress),
12534 					/* numBits */ 8 * sizeof(loadAddress));
12535 				if (!scratchNumber) {
12536 					goto finish;
12537 				}
12538 				result->setObject(kOSBundleLoadAddressKey, scratchNumber.get());
12539 			}
12540 			if (kcformat == KCFormatStatic || kcformat == KCFormatKCGEN) {
12541 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
12542 				    && loadAddress && loadSize) {
12543 					void *baseAddress = PE_get_kc_baseaddress(KCKindPrimary);
12544 					if (!baseAddress) {
12545 						goto finish;
12546 					}
12547 
12548 					OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12549 						(unsigned long long)ml_static_unslide((vm_offset_t)baseAddress),
12550 						/* numBits */ 8 * sizeof(loadAddress));
12551 					if (!scratchNumber) {
12552 						goto finish;
12553 					}
12554 					result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber.get());
12555 				}
12556 				if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
12557 				    && (this == sKernelKext) && gBuiltinKmodsCount) {
12558 					result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
12559 				}
12560 			}
12561 
12562 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
12563 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12564 					(unsigned long long)(execLoadAddress),
12565 					/* numBits */ 8 * sizeof(execLoadAddress));
12566 				if (!scratchNumber) {
12567 					goto finish;
12568 				}
12569 				result->setObject(kOSBundleExecLoadAddressKey, scratchNumber.get());
12570 			}
12571 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
12572 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12573 					(unsigned long long)(loadSize),
12574 					/* numBits */ 8 * sizeof(loadSize));
12575 				if (!scratchNumber) {
12576 					goto finish;
12577 				}
12578 				result->setObject(kOSBundleLoadSizeKey, scratchNumber.get());
12579 			}
12580 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
12581 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12582 					(unsigned long long)(execLoadSize),
12583 					/* numBits */ 8 * sizeof(execLoadSize));
12584 				if (!scratchNumber) {
12585 					goto finish;
12586 				}
12587 				result->setObject(kOSBundleExecLoadSizeKey, scratchNumber.get());
12588 			}
12589 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
12590 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12591 					(unsigned long long)(wiredSize),
12592 					/* numBits */ 8 * sizeof(wiredSize));
12593 				if (!scratchNumber) {
12594 					goto finish;
12595 				}
12596 				result->setObject(kOSBundleWiredSizeKey, scratchNumber.get());
12597 			}
12598 		}
12599 	}
12600 
12601 	/* OSBundleDependencies. In descending order for
12602 	 * easy compatibility with kextstat(8).
12603 	 */
12604 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
12605 		if ((count = getNumDependencies())) {
12606 			dependencyLoadTags = OSArray::withCapacity(count);
12607 			result->setObject(kOSBundleDependenciesKey, dependencyLoadTags.get());
12608 
12609 			i = count - 1;
12610 			do {
12611 				OSKext * dependency = OSDynamicCast(OSKext,
12612 				    dependencies->getObject(i));
12613 
12614 				if (!dependency) {
12615 					continue;
12616 				}
12617 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12618 					(unsigned long long)dependency->getLoadTag(),
12619 					/* numBits*/ 8 * sizeof(loadTag));
12620 				if (!scratchNumber) {
12621 					goto finish;
12622 				}
12623 				dependencyLoadTags->setObject(scratchNumber.get());
12624 			} while (i--);
12625 		}
12626 	}
12627 
12628 	/* OSBundleMetaClasses.
12629 	 */
12630 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
12631 		if (metaClasses && metaClasses->getCount()) {
12632 			metaClassIterator = OSCollectionIterator::withCollection(metaClasses.get());
12633 			metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
12634 			if (!metaClassIterator || !metaClassInfo) {
12635 				goto finish;
12636 			}
12637 			result->setObject(kOSBundleClassesKey, metaClassInfo.get());
12638 
12639 			while ((thisMetaClass = OSDynamicCast(OSMetaClass,
12640 			    metaClassIterator->getNextObject()))) {
12641 				metaClassDict = OSDictionary::withCapacity(3);
12642 				if (!metaClassDict) {
12643 					goto finish;
12644 				}
12645 
12646 				metaClassName = OSString::withCString(thisMetaClass->getClassName());
12647 				if (thisMetaClass->getSuperClass()) {
12648 					superclassName = OSString::withCString(
12649 						thisMetaClass->getSuperClass()->getClassName());
12650 				}
12651 				OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
12652 				    8 * sizeof(unsigned int));
12653 
12654 				/* Bail if any of the essentials is missing. The root class lacks a superclass,
12655 				 * of course.
12656 				 */
12657 				if (!metaClassDict || !metaClassName || !scratchNumber) {
12658 					goto finish;
12659 				}
12660 
12661 				metaClassInfo->setObject(metaClassDict.get());
12662 				metaClassDict->setObject(kOSMetaClassNameKey, metaClassName.get());
12663 				if (superclassName) {
12664 					metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName.get());
12665 				}
12666 				metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber.get());
12667 			}
12668 		}
12669 	}
12670 
12671 	/* OSBundleRetainCount.
12672 	 */
12673 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
12674 		{
12675 			int kextRetainCount = getRetainCount() - 1;
12676 			if (isLoaded()) {
12677 				kextRetainCount--;
12678 			}
12679 			OSSharedPtr<OSNumber> scratchNumber = OSNumber::withNumber(
12680 				(int)kextRetainCount,
12681 				/* numBits*/ 8 * sizeof(int));
12682 			if (scratchNumber) {
12683 				result->setObject(kOSBundleRetainCountKey, scratchNumber.get());
12684 			}
12685 		}
12686 	}
12687 
12688 	success = true;
12689 
12690 finish:
12691 	if (executablePathCString) {
12692 		kfree_data(executablePathCString, executablePathCStringSize);
12693 	}
12694 	if (!success) {
12695 		result.reset();
12696 	}
12697 	return result;
12698 }
12699 
12700 /*********************************************************************
12701 *********************************************************************/
12702 /* static */
12703 bool
12704 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
12705 {
12706 	bool ok;
12707 	OSSharedPtr<OSKext> kext;
12708 
12709 	IORecursiveLockLock(sKextLock);
12710 	kext.reset(OSDynamicCast(OSKext, sKextsByID->getObject(bundleID)), OSRetain);
12711 	IORecursiveLockUnlock(sKextLock);
12712 
12713 	if (!kext || !kext->path || !kext->userExecutableRelPath) {
12714 		return false;
12715 	}
12716 	snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
12717 	    kext->path->getCStringNoCopy(),
12718 	    kext->userExecutableRelPath->getCStringNoCopy());
12719 	ok = true;
12720 
12721 	return ok;
12722 }
12723 
12724 /*********************************************************************
12725 *********************************************************************/
12726 /* static */
12727 OSReturn
12728 OSKext::requestResource(
12729 	const char                    * kextIdentifierCString,
12730 	const char                    * resourceNameCString,
12731 	OSKextRequestResourceCallback   callback,
12732 	void                          * context,
12733 	OSKextRequestTag              * requestTagOut)
12734 {
12735 	OSReturn                        result = kOSReturnError;
12736 	OSSharedPtr<OSKext>             callbackKext;        // looked up
12737 
12738 	OSKextRequestTag   requestTag      = -1;
12739 	OSSharedPtr<OSNumber>           requestTagNum;
12740 	OSSharedPtr<OSDictionary>       requestDict;
12741 	OSSharedPtr<OSString>           kextIdentifier;
12742 	OSSharedPtr<OSString>           resourceName;
12743 
12744 	OSSharedPtr<OSDictionary>       callbackRecord;
12745 	OSSharedPtr<OSValueObject<OSKextRequestResourceCallback> > callbackWrapper;
12746 
12747 	OSSharedPtr<OSValueObject<void *> > contextWrapper;
12748 
12749 	IORecursiveLockLock(sKextLock);
12750 
12751 	if (requestTagOut) {
12752 		*requestTagOut = kOSKextRequestTagInvalid;
12753 	}
12754 
12755 	/* If requests to user space are disabled, don't go any further */
12756 	if (!sKernelRequestsEnabled) {
12757 		OSKextLog(/* kext */ NULL,
12758 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12759 		    "Can't request resource %s for %s - requests to user space are disabled.",
12760 		    resourceNameCString,
12761 		    kextIdentifierCString);
12762 		result = kOSKextReturnDisabled;
12763 		goto finish;
12764 	}
12765 
12766 	if (!kextIdentifierCString || !resourceNameCString || !callback) {
12767 		result = kOSKextReturnInvalidArgument;
12768 		goto finish;
12769 	}
12770 
12771 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
12772 	if (!callbackKext) {
12773 		OSKextLog(/* kext */ NULL,
12774 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12775 		    "Resource request has bad callback address.");
12776 		result = kOSKextReturnInvalidArgument;
12777 		goto finish;
12778 	}
12779 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
12780 		OSKextLog(/* kext */ NULL,
12781 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12782 		    "Resource request callback is in a kext that is not started.");
12783 		result = kOSKextReturnInvalidArgument;
12784 		goto finish;
12785 	}
12786 
12787 	/* Do not allow any new requests to be made on a kext that is unloading.
12788 	 */
12789 	if (callbackKext->flags.stopping) {
12790 		result = kOSKextReturnStopping;
12791 		goto finish;
12792 	}
12793 
12794 	/* If we're wrapped the next available request tag around to the negative
12795 	 * numbers, we can't service any more requests.
12796 	 */
12797 	if (sNextRequestTag == kOSKextRequestTagInvalid) {
12798 		OSKextLog(/* kext */ NULL,
12799 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
12800 		    "No more request tags available; restart required.");
12801 		result = kOSKextReturnNoResources;
12802 		goto finish;
12803 	}
12804 	requestTag = sNextRequestTag++;
12805 
12806 	result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
12807 	    requestDict);
12808 	if (result != kOSReturnSuccess) {
12809 		goto finish;
12810 	}
12811 
12812 	kextIdentifier = OSString::withCString(kextIdentifierCString);
12813 	resourceName   = OSString::withCString(resourceNameCString);
12814 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
12815 	    8 * sizeof(requestTag));
12816 	if (!kextIdentifier ||
12817 	    !resourceName ||
12818 	    !requestTagNum ||
12819 	    !_OSKextSetRequestArgument(requestDict.get(),
12820 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier.get()) ||
12821 	    !_OSKextSetRequestArgument(requestDict.get(),
12822 	    kKextRequestArgumentNameKey, resourceName.get()) ||
12823 	    !_OSKextSetRequestArgument(requestDict.get(),
12824 	    kKextRequestArgumentRequestTagKey, requestTagNum.get())) {
12825 		result = kOSKextReturnNoMemory;
12826 		goto finish;
12827 	}
12828 
12829 	callbackRecord = OSDynamicPtrCast<OSDictionary>(requestDict->copyCollection());
12830 	if (!callbackRecord) {
12831 		result = kOSKextReturnNoMemory;
12832 		goto finish;
12833 	}
12834 	// we validate callback address at call time
12835 	callbackWrapper = OSValueObjectWithValue(callback);
12836 	if (context) {
12837 		contextWrapper = OSValueObjectWithValue(context);
12838 	}
12839 	if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
12840 	    kKextRequestArgumentCallbackKey, callbackWrapper.get())) {
12841 		result = kOSKextReturnNoMemory;
12842 		goto finish;
12843 	}
12844 
12845 	if (context) {
12846 		if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord.get(),
12847 		    kKextRequestArgumentContextKey, contextWrapper.get())) {
12848 			result = kOSKextReturnNoMemory;
12849 			goto finish;
12850 		}
12851 	}
12852 
12853 	/* Only post the requests after all the other potential failure points
12854 	 * have been passed.
12855 	 */
12856 	if (!sKernelRequests->setObject(requestDict.get()) ||
12857 	    !sRequestCallbackRecords->setObject(callbackRecord.get())) {
12858 		result = kOSKextReturnNoMemory;
12859 		goto finish;
12860 	}
12861 
12862 	OSKext::pingIOKitDaemon();
12863 
12864 	result = kOSReturnSuccess;
12865 	if (requestTagOut) {
12866 		*requestTagOut = requestTag;
12867 	}
12868 
12869 finish:
12870 
12871 	/* If we didn't succeed, yank the request & callback
12872 	 * from their holding arrays.
12873 	 */
12874 	if (result != kOSReturnSuccess) {
12875 		unsigned int index;
12876 
12877 		index = sKernelRequests->getNextIndexOfObject(requestDict.get(), 0);
12878 		if (index != (unsigned int)-1) {
12879 			sKernelRequests->removeObject(index);
12880 		}
12881 		index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord.get(), 0);
12882 		if (index != (unsigned int)-1) {
12883 			sRequestCallbackRecords->removeObject(index);
12884 		}
12885 	}
12886 
12887 	OSKext::considerUnloads(/* rescheduleOnly? */ true);
12888 
12889 	IORecursiveLockUnlock(sKextLock);
12890 
12891 	return result;
12892 }
12893 
12894 OSReturn
12895 OSKext::requestDaemonLaunch(
12896 	OSString *kextIdentifier,
12897 	OSString *serverName,
12898 	OSNumber *serverTag,
12899 	OSBoolean *reslide,
12900 	IOUserServerCheckInToken * checkInToken,
12901 	OSData *serverDUI)
12902 {
12903 	OSReturn       result        = kOSReturnError;
12904 	OSSharedPtr<OSDictionary> requestDict;
12905 	unsigned int size = 0;
12906 	const char *dextUniqueIDCString = NULL;
12907 
12908 	if (!kextIdentifier || !serverName || !serverTag || !checkInToken) {
12909 		return kOSKextReturnInvalidArgument;
12910 	}
12911 	if (!iokitDaemonAvailable()) {
12912 		panic("Received unexpected request in environment where " kIOKitDaemonName " is unavailable");
12913 	}
12914 
12915 	if (serverDUI != NULL) {
12916 		dextUniqueIDCString = getDextUniqueIDCString(serverDUI, &size);
12917 	}
12918 
12919 	IORecursiveLockLock(sKextLock);
12920 
12921 	OSKextLog(/* kext */ NULL,
12922 	    kOSKextLogDebugLevel |
12923 	    kOSKextLogGeneralFlag,
12924 	    "Requesting daemon launch for %s %s with serverName %s and tag %llu%s",
12925 	    kextIdentifier->getCStringNoCopy(),
12926 	    (dextUniqueIDCString != NULL)?dextUniqueIDCString:"",
12927 	    serverName->getCStringNoCopy(),
12928 	    serverTag->unsigned64BitValue(),
12929 	    reslide == kOSBooleanTrue ? " with reslid shared cache" : ""
12930 	    );
12931 
12932 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, requestDict);
12933 	if (result != kOSReturnSuccess) {
12934 		goto finish;
12935 	}
12936 
12937 	if (!_OSKextSetRequestArgument(requestDict.get(),
12938 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
12939 	    !_OSKextSetRequestArgument(requestDict.get(),
12940 	    kKextRequestArgumentDriverExtensionServerName, serverName) ||
12941 	    !_OSKextSetRequestArgument(requestDict.get(),
12942 	    kKextRequestArgumentDriverExtensionServerTag, serverTag) ||
12943 	    !_OSKextSetRequestArgument(requestDict.get(),
12944 	    kKextRequestArgumentDriverExtensionReslideSharedCache, reslide) ||
12945 	    !_OSKextSetRequestArgument(requestDict.get(),
12946 	    kKextRequestArgumentCheckInToken, checkInToken)) {
12947 		result = kOSKextReturnNoMemory;
12948 		goto finish;
12949 	}
12950 
12951 	if (serverDUI) {
12952 		if (!_OSKextSetRequestArgument(requestDict.get(),
12953 		    kOSBundleDextUniqueIdentifierKey, serverDUI)) {
12954 			result = kOSKextReturnNoMemory;
12955 			goto finish;
12956 		}
12957 	}
12958 
12959 	/* Only post the requests after all the other potential failure points
12960 	 * have been passed.
12961 	 */
12962 	if (!sKernelRequests->setObject(requestDict.get())) {
12963 		result = kOSKextReturnNoMemory;
12964 		goto finish;
12965 	}
12966 	result = OSKext::pingIOKitDaemon();
12967 	if (result != kOSReturnSuccess) {
12968 		goto finish;
12969 	}
12970 
12971 	result = kOSReturnSuccess;
12972 finish:
12973 	IORecursiveLockUnlock(sKextLock);
12974 	if (dextUniqueIDCString) {
12975 		kfree_data(dextUniqueIDCString, size);
12976 	}
12977 	return result;
12978 }
12979 
12980 OSReturn
12981 OSKext::notifyDextUpgrade(
12982 	OSString *kextIdentifier,
12983 	OSData *dextUniqueIdentifier)
12984 {
12985 	OSReturn result = kOSReturnError;
12986 	OSSharedPtr<OSDictionary> requestDict;
12987 	unsigned int size = 0;
12988 	const char *dextUniqueIDCString = getDextUniqueIDCString(dextUniqueIdentifier, &size);
12989 	assert(dextUniqueIDCString != NULL);
12990 
12991 	IORecursiveLockLock(sKextLock);
12992 
12993 	OSKextLog(NULL,
12994 	    kOSKextLogDebugLevel |
12995 	    kOSKextLogGeneralFlag,
12996 	    "Notifying of dext upgrade for %s with UniqueID %s",
12997 	    kextIdentifier->getCStringNoCopy(), dextUniqueIDCString);
12998 
12999 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonUpgradeNotification, requestDict);
13000 	if (result != kOSReturnSuccess) {
13001 		goto finish;
13002 	}
13003 
13004 	if (!_OSKextSetRequestArgument(requestDict.get(),
13005 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
13006 	    !_OSKextSetRequestArgument(requestDict.get(),
13007 	    kKextRequestArgumentDriverUniqueIdentifier, dextUniqueIdentifier)) {
13008 		result = kOSKextReturnNoMemory;
13009 		goto finish;
13010 	}
13011 
13012 	/* Only post the requests after all the other potential failure points
13013 	 * have been passed.
13014 	 */
13015 	if (!sKernelRequests->setObject(requestDict.get())) {
13016 		result = kOSKextReturnNoMemory;
13017 		goto finish;
13018 	}
13019 	OSKext::pingIOKitDaemon();
13020 
13021 	result = kOSReturnSuccess;
13022 finish:
13023 	IORecursiveLockUnlock(sKextLock);
13024 
13025 	if (dextUniqueIDCString != NULL) {
13026 		kfree_data(dextUniqueIDCString, size);
13027 	}
13028 	return result;
13029 }
13030 
13031 /*********************************************************************
13032 * Assumes sKextLock is held.
13033 *********************************************************************/
13034 /* static */
13035 OSReturn
13036 OSKext::dequeueCallbackForRequestTag(
13037 	OSKextRequestTag    requestTag,
13038 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
13039 {
13040 	OSDictionary * callbackRecordOutRaw = NULL;
13041 	OSReturn result;
13042 
13043 	result = dequeueCallbackForRequestTag(requestTag,
13044 	    &callbackRecordOutRaw);
13045 
13046 	if (kOSReturnSuccess == result) {
13047 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
13048 	}
13049 
13050 	return result;
13051 }
13052 OSReturn
13053 OSKext::dequeueCallbackForRequestTag(
13054 	OSKextRequestTag    requestTag,
13055 	OSDictionary     ** callbackRecordOut)
13056 {
13057 	OSReturn   result = kOSReturnError;
13058 	OSSharedPtr<OSNumber> requestTagNum;
13059 
13060 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
13061 	    8 * sizeof(requestTag));
13062 	if (!requestTagNum) {
13063 		goto finish;
13064 	}
13065 
13066 	result = OSKext::dequeueCallbackForRequestTag(requestTagNum.get(),
13067 	    callbackRecordOut);
13068 
13069 finish:
13070 	return result;
13071 }
13072 
13073 /*********************************************************************
13074 * Assumes sKextLock is held.
13075 *********************************************************************/
13076 /* static */
13077 OSReturn
13078 OSKext::dequeueCallbackForRequestTag(
13079 	OSNumber     *    requestTagNum,
13080 	OSSharedPtr<OSDictionary>     &callbackRecordOut)
13081 {
13082 	OSDictionary * callbackRecordOutRaw = NULL;
13083 	OSReturn result;
13084 
13085 	result = dequeueCallbackForRequestTag(requestTagNum,
13086 	    &callbackRecordOutRaw);
13087 
13088 	if (kOSReturnSuccess == result) {
13089 		callbackRecordOut.reset(callbackRecordOutRaw, OSNoRetain);
13090 	}
13091 
13092 	return result;
13093 }
13094 OSReturn
13095 OSKext::dequeueCallbackForRequestTag(
13096 	OSNumber     *    requestTagNum,
13097 	OSDictionary ** callbackRecordOut)
13098 {
13099 	OSReturn        result          = kOSKextReturnInvalidArgument;
13100 	OSDictionary  * callbackRecord  = NULL;        // retain if matched!
13101 	OSNumber      * callbackTagNum  = NULL;        // do not release
13102 	unsigned int    count, i;
13103 
13104 	result = kOSReturnError;
13105 	count = sRequestCallbackRecords->getCount();
13106 	for (i = 0; i < count; i++) {
13107 		callbackRecord = OSDynamicCast(OSDictionary,
13108 		    sRequestCallbackRecords->getObject(i));
13109 		if (!callbackRecord) {
13110 			goto finish;
13111 		}
13112 
13113 		/* If we don't find a tag, we basically have a leak here. Maybe
13114 		 * we should just remove it.
13115 		 */
13116 		callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
13117 			    callbackRecord, kKextRequestArgumentRequestTagKey));
13118 		if (!callbackTagNum) {
13119 			goto finish;
13120 		}
13121 
13122 		/* We could be even more paranoid and check that all the incoming
13123 		 * args match what's in the callback record.
13124 		 */
13125 		if (callbackTagNum->isEqualTo(requestTagNum)) {
13126 			if (callbackRecordOut) {
13127 				*callbackRecordOut = callbackRecord;
13128 				callbackRecord->retain();
13129 			}
13130 			sRequestCallbackRecords->removeObject(i);
13131 			result = kOSReturnSuccess;
13132 			goto finish;
13133 		}
13134 	}
13135 	result = kOSKextReturnNotFound;
13136 
13137 finish:
13138 	return result;
13139 }
13140 
13141 
13142 /*********************************************************************
13143 * Busy timeout triage
13144 *********************************************************************/
13145 /* static */
13146 bool
13147 OSKext::pendingIOKitDaemonRequests(void)
13148 {
13149 	return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
13150 }
13151 
13152 /*********************************************************************
13153 * Acquires and releases sKextLock
13154 *
13155 * This function is designed to be called by kernelmanagerd and driverkitd
13156 * and it gathers all codeless kext and dext personalities, and then attempts
13157 * to map a System (pageable) KC and an Auxiliary (aux) KC.
13158 *
13159 * The pageable and aux KC can be loaded only once at boot time.
13160 * Even if the pageable or aux KC fail to load - this function will
13161 * not allow a new pageable or aux KC to be installed by subsequent calls.
13162 * This is done to avoid security issues where userspace has been compromised
13163 * or the pageable kc has been tampered with and the attacker
13164 * attempts to re-load a malicious variant.
13165 * However dexts can be dynamically loaded, so this function can be used
13166 * to request the installation of a new set of dexts even after boot time.
13167 *
13168 *
13169 *
13170 * Return: if a KC fails to load the return value will contain:
13171 *         kOSKextReturnKCLoadFailure. If the pageable KC fails,
13172 *         the return value will contain kOSKextReturnKCLoadFailureSystemKC.
13173 *         Similarly, if the aux kc load fails, the return value will
13174 *         contain kOSKextReturnKCLoadFailureAuxKC. The two values
13175 *         compose with each other and with kOSKextReturnKCLoadFailure.
13176 *********************************************************************/
13177 /* static */
13178 OSReturn
13179 OSKext::loadFileSetKexts(OSDictionary * requestDict __unused)
13180 {
13181 	static bool daemon_ready = false;
13182 
13183 	OSReturn ret = kOSKextReturnInvalidArgument;
13184 	OSReturn kcerr = 0;
13185 	bool start_matching = false;
13186 
13187 	bool allow_fileset_load = !daemon_ready;
13188 #if !(defined(__x86_64__) || defined(__i386__))
13189 	/* never allow KCs full of kexts on non-x86 machines */
13190 	allow_fileset_load = false;
13191 #endif
13192 
13193 	/*
13194 	 * Change with 70582300
13195 	 */
13196 #if 0 || !defined(VM_MAPPED_KEXTS)
13197 	/*
13198 	 * On platforms that don't support the SystemKC or a file-backed
13199 	 * AuxKC, the kext receipt for 3rd party kexts loaded by the booter
13200 	 * needs to be queried before we load any codeless kexts or release
13201 	 * any 3rd party kexts to run. On platforms that support a file-backed
13202 	 * AuxKC, this process is done via the kext audit mechanism.
13203 	 */
13204 
13205 	printf("KextLog: waiting for kext receipt to be queried.\n");
13206 	while (!IOServiceWaitForMatchingResource(kOSKextReceiptQueried, UINT64_MAX)) {
13207 		IOSleep(30);
13208 	}
13209 #endif /* !VM_MAPPED_KEXTS */
13210 
13211 	/*
13212 	 * Get the args from the request. Right now we need the file
13213 	 * name for the pageable and the aux kext collection file sets.
13214 	 */
13215 	OSDictionary * requestArgs                = NULL;        // do not release
13216 	OSString     * pageable_filepath          = NULL;        // do not release
13217 	OSString     * aux_filepath               = NULL;        // do not release
13218 	OSArray      * codeless_kexts             = NULL;        // do not release
13219 
13220 	kernel_mach_header_t *akc_mh              = NULL;
13221 
13222 	requestArgs = OSDynamicCast(OSDictionary,
13223 	    requestDict->getObject(kKextRequestArgumentsKey));
13224 
13225 	if (requestArgs == NULL) {
13226 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13227 		    "KextLog: No arguments in plist for loading fileset kext\n");
13228 		printf("KextLog: No arguments in plist for loading fileset kext\n");
13229 		return ret;
13230 	}
13231 
13232 	ret = kOSKextReturnDisabled;
13233 
13234 	IORecursiveLockLock(sKextLock);
13235 
13236 	if (!sLoadEnabled) {
13237 		OSKextLog(NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13238 		    "KextLog: Kext loading is disabled (attempt to load KCs).");
13239 		IORecursiveLockUnlock(sKextLock);
13240 		return ret;
13241 	}
13242 
13243 	pageable_filepath = OSDynamicCast(OSString,
13244 	    requestArgs->getObject(kKextRequestArgumentPageableKCFilename));
13245 
13246 	if (allow_fileset_load && pageable_filepath != NULL) {
13247 		printf("KextLog: Loading Pageable KC from file %s\n", pageable_filepath->getCStringNoCopy());
13248 
13249 		ret = OSKext::loadKCFileSet(pageable_filepath->getCStringNoCopy(), KCKindPageable);
13250 		if (ret) {
13251 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13252 			    "KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
13253 
13254 			printf("KextLog: loadKCFileSet for Pageable KC returned %d\n", ret);
13255 			ret = kOSKextReturnKCLoadFailure;
13256 			kcerr |= kOSKextReturnKCLoadFailureSystemKC;
13257 			goto try_auxkc;
13258 		}
13259 		/*
13260 		 * Even if the AuxKC fails to load, we still want to send
13261 		 * the System KC personalities to the catalog for matching
13262 		 */
13263 		start_matching = true;
13264 	} else if (pageable_filepath != NULL) {
13265 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13266 		    "KextLog: ignoring Pageable KC load from %s\n", pageable_filepath->getCStringNoCopy());
13267 		ret = kOSKextReturnUnsupported;
13268 	}
13269 
13270 try_auxkc:
13271 	akc_mh = (kernel_mach_header_t*)PE_get_kc_header(KCKindAuxiliary);
13272 	if (akc_mh) {
13273 		/*
13274 		 * If we try to load a deferred AuxKC, then don't ever attempt
13275 		 * a filesystem map of a file
13276 		 */
13277 		allow_fileset_load = false;
13278 
13279 		/*
13280 		 * This function is only called once per boot, so we haven't
13281 		 * yet loaded an AuxKC. If we have registered the AuxKC mach
13282 		 * header, that means that the kext collection has been placed
13283 		 * in memory for us by the booter, and is waiting for us to
13284 		 * process it.  Grab the deferred XML plist of info
13285 		 * dictionaries and add all the kexts.
13286 		 */
13287 		OSSharedPtr<OSObject>  parsedXML;
13288 		OSSharedPtr<OSData>    loaded_kcUUID;
13289 		OSDictionary          *infoDict;
13290 		parsedXML = consumeDeferredKextCollection(KCKindAuxiliary);
13291 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
13292 #if !defined(VM_MAPPED_KEXTS)
13293 		/*
13294 		 * On platforms where we don't dynamically wire-down / page-in
13295 		 * kext memory, we need to maintain the invariant that if the
13296 		 * AuxKC in memory does not contain a kext receipt, then we
13297 		 * should not load any of the kexts.
13298 		 */
13299 		size_t receipt_sz = 0;
13300 		if (getsectdatafromheader(akc_mh, kReceiptInfoSegment, kAuxKCReceiptSection, &receipt_sz) == NULL || receipt_sz == 0) {
13301 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13302 			    "KextLog: WARNING: Failed to load AuxKC from memory: missing receipt");
13303 			ret = kOSKextReturnKCLoadFailure;
13304 			goto try_codeless;
13305 		}
13306 #endif
13307 		if (infoDict) {
13308 			bool added;
13309 			printf("KextLog: Adding kexts from in-memory AuxKC\n");
13310 			added = OSKext::addKextsFromKextCollection(akc_mh, infoDict,
13311 			    kPrelinkTextSegment, loaded_kcUUID, KCKindAuxiliary);
13312 			if (!loaded_kcUUID) {
13313 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13314 				    "KextLog: WARNING: did not find UUID in deferred Aux KC!");
13315 			} else if (!added) {
13316 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13317 				    "KextLog: WARNING: Failed to load AuxKC from memory.");
13318 			}
13319 			/* only return success if the pageable load (above) was successful */
13320 			if (ret != kOSKextReturnKCLoadFailure) {
13321 				ret = kOSReturnSuccess;
13322 			}
13323 			/* the registration of the AuxKC parsed out the KC's UUID already */
13324 		} else {
13325 			if (daemon_ready) {
13326 				/*
13327 				 * Complain, but don't return an error if this isn't the first time the
13328 				 * IOKit daemon is checking in. If the daemon ever restarts, we will
13329 				 * hit this case because we've already consumed the deferred personalities.
13330 				 * We return success here so that a call to this function from a restarted
13331 				 * daemon with no codeless kexts will succeed.
13332 				 */
13333 				OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13334 				    "KextLog: can't re-parse deferred AuxKC personalities on IOKit daemon restart");
13335 				if (ret != kOSKextReturnKCLoadFailure) {
13336 					ret = kOSReturnSuccess;
13337 				}
13338 			} else {
13339 				/* this is a real error case */
13340 				OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogIPCFlag,
13341 				    "KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary");
13342 				printf("KextLog: ERROR loading deferred AuxKC: PRELINK_INFO wasn't an OSDictionary\n");
13343 				ret = kOSKextReturnKCLoadFailure;
13344 				kcerr |= kOSKextReturnKCLoadFailureAuxKC;
13345 			}
13346 		}
13347 	}
13348 
13349 	aux_filepath = OSDynamicCast(OSString,
13350 	    requestArgs->getObject(kKextRequestArgumentAuxKCFilename));
13351 	if (allow_fileset_load && aux_filepath != NULL) {
13352 		printf("KextLog: Loading Aux KC from file %s\n", aux_filepath->getCStringNoCopy());
13353 
13354 		ret = OSKext::loadKCFileSet(aux_filepath->getCStringNoCopy(), KCKindAuxiliary);
13355 		if (ret) {
13356 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13357 			    "KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
13358 
13359 			printf("KextLog: loadKCFileSet for Aux KC returned %d\n", ret);
13360 			ret = kOSKextReturnKCLoadFailure;
13361 			kcerr |= kOSKextReturnKCLoadFailureAuxKC;
13362 			goto try_codeless;
13363 		}
13364 		start_matching = true;
13365 	} else if (aux_filepath != NULL) {
13366 		OSKextLog(/* kext */ NULL, kOSKextLogBasicLevel | kOSKextLogIPCFlag,
13367 		    "KextLog: Ignoring AuxKC load from %s\n", aux_filepath->getCStringNoCopy());
13368 		if (ret != kOSKextReturnKCLoadFailure) {
13369 			ret = kOSKextReturnUnsupported;
13370 		}
13371 	}
13372 
13373 try_codeless:
13374 	/*
13375 	 * Load codeless kexts last so that there is no possibilty of a
13376 	 * codeless kext bundle ID preventing a kext in the system KC from
13377 	 * loading
13378 	 */
13379 	codeless_kexts = OSDynamicCast(OSArray,
13380 	    requestArgs->getObject(kKextRequestArgumentCodelessPersonalities));
13381 	if (codeless_kexts != NULL) {
13382 		uint32_t count = codeless_kexts->getCount();
13383 		OSKextLog(NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13384 		    "KextLog: loading %d codeless kexts/dexts", count);
13385 		for (uint32_t i = 0; i < count; i++) {
13386 			OSDictionary *infoDict;
13387 			infoDict = OSDynamicCast(OSDictionary,
13388 			    codeless_kexts->getObject(i));
13389 			if (!infoDict) {
13390 				continue;
13391 			}
13392 			// instantiate a new kext, and don't hold a reference
13393 			// (the kext subsystem will hold one implicitly)
13394 			OSKext::withCodelessInfo(infoDict, NULL);
13395 		}
13396 		/* ignore errors that are not KC load failures */
13397 		if (ret != kOSKextReturnKCLoadFailure) {
13398 			ret = kOSReturnSuccess;
13399 		}
13400 		start_matching = true;
13401 	}
13402 
13403 	/* send personalities to the IOCatalog once */
13404 	if (ret == kOSReturnSuccess || start_matching || sOSKextWasResetAfterUserspaceReboot) {
13405 		OSKext::sendAllKextPersonalitiesToCatalog(true);
13406 		/*
13407 		 * This request necessarily came from the IOKit daemon (kernelmanagerd), so mark
13408 		 * things as active and start all the delayed matching: the
13409 		 * dext and codeless kext personalities should have all been
13410 		 * delivered via this one call.
13411 		 */
13412 		if (!daemon_ready) {
13413 			OSKext::setIOKitDaemonActive();
13414 			OSKext::setDeferredLoadSucceeded(TRUE);
13415 			IOService::iokitDaemonLaunched();
13416 		}
13417 		if (sOSKextWasResetAfterUserspaceReboot) {
13418 			sOSKextWasResetAfterUserspaceReboot = false;
13419 			OSKext::setIOKitDaemonActive();
13420 			IOService::startDeferredMatches();
13421 		}
13422 	}
13423 
13424 	if (ret == kOSKextReturnKCLoadFailure) {
13425 		ret |= kcerr;
13426 	}
13427 
13428 	/*
13429 	 * Only allow this function to attempt to load the pageable and
13430 	 * aux KCs once per boot.
13431 	 */
13432 	daemon_ready = true;
13433 
13434 	IORecursiveLockUnlock(sKextLock);
13435 
13436 	return ret;
13437 }
13438 
13439 OSReturn
13440 OSKext::resetMutableSegments(void)
13441 {
13442 	kernel_segment_command_t *seg = NULL;
13443 	kernel_mach_header_t *k_mh = (kernel_mach_header_t *)kmod_info->address;
13444 	u_int index = 0;
13445 	OSKextSavedMutableSegment *savedSegment = NULL;
13446 	uintptr_t kext_slide = PE_get_kc_slide(kc_type);
13447 	OSReturn err;
13448 
13449 	if (!savedMutableSegments) {
13450 		OSKextLog(this, kOSKextLogErrorLevel | kOSKextLogLoadFlag,
13451 		    "Kext %s cannot be reset, mutable segments were not saved.", getIdentifierCString());
13452 		err = kOSKextReturnInternalError;
13453 		goto finish;
13454 	}
13455 
13456 	for (seg = firstsegfromheader(k_mh), index = 0; seg; seg = nextsegfromheader(k_mh, seg)) {
13457 		if (!segmentIsMutable(seg)) {
13458 			continue;
13459 		}
13460 		uint64_t unslid_vmaddr = seg->vmaddr - kext_slide;
13461 		uint64_t vmsize = seg->vmsize;
13462 		err = kOSKextReturnInternalError;
13463 		for (index = 0; index < savedMutableSegments->getCount(); index++) {
13464 			savedSegment = OSDynamicCast(OSKextSavedMutableSegment, savedMutableSegments->getObject(index));
13465 			assert(savedSegment);
13466 			if (savedSegment->getVMAddr() == seg->vmaddr && savedSegment->getVMSize() == seg->vmsize) {
13467 				OSKextLog(this, kOSKextLogDebugLevel | kOSKextLogLoadFlag,
13468 				    "Resetting kext %s, mutable segment %.*s %llx->%llx.", getIdentifierCString(), (int)strnlen(seg->segname, sizeof(seg->segname)), seg->segname, unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13469 				err = savedSegment->restoreContents(seg);
13470 				if (err != kOSReturnSuccess) {
13471 					panic("Kext %s cannot be reset, mutable segment %llx->%llx could not be restored.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13472 				}
13473 			}
13474 		}
13475 		if (err != kOSReturnSuccess) {
13476 			panic("Kext %s cannot be reset, could not find saved mutable segment for %llx->%llx.", getIdentifierCString(), unslid_vmaddr, unslid_vmaddr + vmsize - 1);
13477 		}
13478 	}
13479 	err = kOSReturnSuccess;
13480 finish:
13481 	return err;
13482 }
13483 
13484 
13485 /*********************************************************************
13486 * Assumes sKextLock is held.
13487 *********************************************************************/
13488 /* static */
13489 OSReturn
13490 OSKext::loadKCFileSet(
13491 	const char *filepath,
13492 	kc_kind_t   type)
13493 {
13494 #if VM_MAPPED_KEXTS
13495 	/* we only need to load filesets on systems that support VM_MAPPED kexts */
13496 	OSReturn err;
13497 	struct vnode *vp = NULL;
13498 	void *fileset_control;
13499 	off_t fsize;
13500 	bool pageable = (type == KCKindPageable);
13501 
13502 	if ((pageable && pageableKCloaded) ||
13503 	    (!pageable && auxKCloaded)) {
13504 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13505 		    "KC FileSet of type %s is already loaded", (pageable ? "Pageable" : "Aux"));
13506 
13507 		return kOSKextReturnInvalidArgument;
13508 	}
13509 
13510 	/* Do not allow AuxKC to load if Pageable KC is not loaded */
13511 	if (!pageable && !pageableKCloaded) {
13512 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13513 		    "Trying to load the Aux KC without loading the Pageable KC");
13514 		return kOSKextReturnInvalidArgument;
13515 	}
13516 
13517 	fileset_control = ubc_getobject_from_filename(filepath, &vp, &fsize);
13518 
13519 	if (fileset_control == NULL) {
13520 		printf("Could not get memory control object for file %s", filepath);
13521 
13522 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13523 		    "Could not get memory control object for file %s", filepath);
13524 		return kOSKextReturnInvalidArgument;
13525 	}
13526 	if (vp == NULL) {
13527 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13528 		    "Could not find vnode for file %s", filepath);
13529 		return kOSKextReturnInvalidArgument;
13530 	}
13531 
13532 	kernel_mach_header_t *mh = NULL;
13533 	uintptr_t slide = 0;
13534 
13535 #if CONFIG_CSR
13536 	/*
13537 	 * When SIP is enabled, the KC we map must be SIP-protected
13538 	 */
13539 	if (csr_check(CSR_ALLOW_UNRESTRICTED_FS) != 0) {
13540 		struct vnode_attr va;
13541 		int error;
13542 		VATTR_INIT(&va);
13543 		VATTR_WANTED(&va, va_flags);
13544 		error = vnode_getattr(vp, &va, vfs_context_current());
13545 		if (error) {
13546 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13547 			    "vnode_getattr(%s) failed (error=%d)", filepath, error);
13548 			err = kOSKextReturnInternalError;
13549 			goto finish;
13550 		}
13551 		if (!(va.va_flags & SF_RESTRICTED)) {
13552 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13553 			    "Path to KC '%s' is not SIP-protected", filepath);
13554 			err = kOSKextReturnInvalidArgument;
13555 			goto finish;
13556 		}
13557 	}
13558 #endif
13559 
13560 	err = OSKext::mapKCFileSet(fileset_control, (vm_size_t)fsize, &mh, 0, &slide, pageable, NULL);
13561 	if (err) {
13562 		printf("KextLog: mapKCFileSet returned %d\n", err);
13563 
13564 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13565 		    "mapKCFileSet returned %d\n", err);
13566 
13567 		err = kOSKextReturnInvalidArgument;
13568 	}
13569 
13570 #if CONFIG_CSR
13571 finish:
13572 #endif
13573 	/* Drop the vnode ref returned by ubc_getobject_from_filename if mapKCFileSet failed */
13574 	assert(vp != NULL);
13575 	if (err == kOSReturnSuccess) {
13576 		PE_set_kc_vp(type, vp);
13577 		if (pageable) {
13578 			pageableKCloaded = true;
13579 		} else {
13580 			auxKCloaded = true;
13581 		}
13582 	} else {
13583 		vnode_put(vp);
13584 	}
13585 
13586 	return err;
13587 #else
13588 	(void)filepath;
13589 	(void)type;
13590 	return kOSKextReturnUnsupported;
13591 #endif // VM_MAPPED_KEXTS
13592 }
13593 
13594 #if defined(__x86_64__) || defined(__i386__)
13595 /*********************************************************************
13596 * Assumes sKextLock is held.
13597 *********************************************************************/
13598 /* static */
13599 OSReturn
13600 OSKext::mapKCFileSet(
13601 	void                 *control,
13602 	vm_size_t            fsize,
13603 	kernel_mach_header_t **mhp,
13604 	off_t                file_offset,
13605 	uintptr_t            *slidep,
13606 	bool                 pageable,
13607 	void                 *map_entry_list)
13608 {
13609 	bool fileset_load = false;
13610 	kern_return_t ret;
13611 	OSReturn err;
13612 	kernel_section_t *infoPlistSection = NULL;
13613 	OSDictionary *infoDict = NULL;
13614 
13615 	OSSharedPtr<OSObject> parsedXML;
13616 	OSSharedPtr<OSString> errorString;
13617 	OSSharedPtr<OSData> loaded_kcUUID;
13618 
13619 	/* Check if initial load for file set */
13620 	if (*mhp == NULL) {
13621 		fileset_load = true;
13622 
13623 		/* Get a page aligned address from kext map to map the file */
13624 		vm_map_offset_t pagealigned_addr = get_address_from_kext_map(fsize);
13625 		if (pagealigned_addr == 0) {
13626 			return kOSKextReturnNoMemory;
13627 		}
13628 
13629 		*mhp = (kernel_mach_header_t *)pagealigned_addr;
13630 
13631 		/* Allocate memory for bailout mechanism */
13632 		map_entry_list = allocate_kcfileset_map_entry_list();
13633 		if (map_entry_list == NULL) {
13634 			return kOSKextReturnNoMemory;
13635 		}
13636 	}
13637 
13638 	uintptr_t *slideptr = fileset_load ? slidep : NULL;
13639 	err = mapKCTextSegment(control, mhp, file_offset, slideptr, map_entry_list);
13640 	/* mhp and slideptr are updated by mapKCTextSegment */
13641 	if (err) {
13642 		if (fileset_load) {
13643 			deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13644 		}
13645 		return err;
13646 	}
13647 
13648 	/* Initialize the kc header globals */
13649 	if (fileset_load) {
13650 		if (pageable) {
13651 			PE_set_kc_header(KCKindPageable, *mhp, *slidep);
13652 		} else {
13653 			PE_set_kc_header(KCKindAuxiliary, *mhp, *slidep);
13654 		}
13655 	}
13656 
13657 	/* Iterate through all the segments and map necessary segments */
13658 	struct load_command *lcp = (struct load_command *) (*mhp + 1);
13659 	for (unsigned int i = 0; i < (*mhp)->ncmds; i++, lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize)) {
13660 		vm_map_offset_t start;
13661 		kernel_mach_header_t *k_mh = NULL;
13662 		kernel_segment_command_t * seg = NULL;
13663 		struct fileset_entry_command *fse = NULL;
13664 
13665 		if (lcp->cmd == LC_SEGMENT_KERNEL) {
13666 			seg = (kernel_segment_command_t *)lcp;
13667 			start = ((uintptr_t)(seg->vmaddr)) + *slidep;
13668 		} else if (lcp->cmd == LC_FILESET_ENTRY) {
13669 			fse = (struct fileset_entry_command *)lcp;
13670 			k_mh = (kernel_mach_header_t *)(((uintptr_t)(fse->vmaddr)) + *slidep);
13671 
13672 			/* Map the segments of the mach-o binary */
13673 			err = OSKext::mapKCFileSet(control, 0, &k_mh, fse->fileoff, slidep, pageable, map_entry_list);
13674 			if (err) {
13675 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13676 				return kOSKextReturnInvalidArgument;
13677 			}
13678 			continue;
13679 		} else if (lcp->cmd == LC_DYLD_CHAINED_FIXUPS) {
13680 			/* Check if the Aux KC is built pageable style */
13681 			if (!pageable && !fileset_load && !auxKCloaded) {
13682 				resetAuxKCSegmentOnUnload = true;
13683 			}
13684 			continue;
13685 		} else {
13686 			continue;
13687 		}
13688 
13689 		if (fileset_load) {
13690 			if (seg->vmsize == 0) {
13691 				continue;
13692 			}
13693 
13694 			/* Only map __PRELINK_INFO, __BRANCH_STUBS, __BRANCH_GOTS and __LINKEDIT sections */
13695 			if (strncmp(seg->segname, kPrelinkInfoSegment, sizeof(seg->segname)) != 0 &&
13696 			    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) != 0 &&
13697 			    strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) != 0 &&
13698 			    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) != 0) {
13699 				continue;
13700 			}
13701 		} else {
13702 			if (seg->vmsize == 0) {
13703 				continue;
13704 			}
13705 
13706 			/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
13707 			if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
13708 			    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
13709 			    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
13710 				continue;
13711 			}
13712 		}
13713 
13714 		ret = vm_map_kcfileset_segment(
13715 			&start, seg->vmsize,
13716 			(memory_object_control_t)control, seg->fileoff, seg->maxprot);
13717 
13718 		if (ret != KERN_SUCCESS) {
13719 			if (fileset_load) {
13720 				deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13721 			}
13722 			return kOSKextReturnInvalidArgument;
13723 		}
13724 		add_kcfileset_map_entry(map_entry_list, start, seg->vmsize);
13725 	}
13726 
13727 	/* Return if regular mach-o */
13728 	if (!fileset_load) {
13729 		return 0;
13730 	}
13731 
13732 	/*
13733 	 * Fixup for the Pageable KC and the Aux KC is done by
13734 	 * i386_slide_kext_collection_mh_addrs, but it differs in
13735 	 * following ways:
13736 	 *
13737 	 * PageableKC: Fixup only __BRANCH_STUBS segment and top level load commands.
13738 	 * The fixup of kext segments and kext load commands are done at kext
13739 	 * load time by calling i386_slide_individual_kext.
13740 	 *
13741 	 * AuxKC old style: Fixup all the segments and all the load commands.
13742 	 *
13743 	 * AuxKC pageable style: Same as the Pageable KC.
13744 	 */
13745 	bool adjust_mach_header = (pageable ? true : ((resetAuxKCSegmentOnUnload) ? true : false));
13746 	ret = i386_slide_kext_collection_mh_addrs(*mhp, *slidep, adjust_mach_header);
13747 	if (ret != KERN_SUCCESS) {
13748 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13749 		return kOSKextReturnInvalidArgument;
13750 	}
13751 
13752 	/* Get the prelink info dictionary */
13753 	infoPlistSection = getsectbynamefromheader(*mhp, kPrelinkInfoSegment, kPrelinkInfoSection);
13754 	parsedXML = OSUnserializeXML((const char *)infoPlistSection->addr, errorString);
13755 	if (parsedXML) {
13756 		infoDict = OSDynamicCast(OSDictionary, parsedXML.get());
13757 	}
13758 
13759 	if (!infoDict) {
13760 		const char *errorCString = "(unknown error)";
13761 
13762 		if (errorString && errorString->getCStringNoCopy()) {
13763 			errorCString = errorString->getCStringNoCopy();
13764 		} else if (parsedXML) {
13765 			errorCString = "not a dictionary";
13766 		}
13767 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13768 		    "Error unserializing kext info plist section: %s.", errorCString);
13769 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13770 		return kOSKextReturnInvalidArgument;
13771 	}
13772 
13773 	/* Validate that the Kext Collection is prelinked to the loaded KC */
13774 	err = OSKext::validateKCFileSetUUID(infoDict, pageable ? KCKindPageable : KCKindAuxiliary);
13775 	if (err) {
13776 		deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, TRUE, pageable);
13777 		return kOSKextReturnInvalidArgument;
13778 	}
13779 
13780 	/* Set Protection of Segments */
13781 	OSKext::protectKCFileSet(*mhp, pageable ? KCKindPageable : KCKindAuxiliary);
13782 
13783 	OSKext::addKextsFromKextCollection(*mhp,
13784 	    infoDict, kPrelinkTextSegment,
13785 	    loaded_kcUUID, pageable ? KCKindPageable : KCKindAuxiliary);
13786 
13787 	/* Copy in the KC UUID */
13788 	if (!loaded_kcUUID) {
13789 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
13790 		    "WARNING: did not find UUID in prelinked %s KC!", pageable ? "Pageable" : "Aux");
13791 	} else if (pageable) {
13792 		pageablekc_uuid_valid = TRUE;
13793 		memcpy((void *)&pageablekc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
13794 		uuid_unparse_upper(pageablekc_uuid, pageablekc_uuid_string);
13795 	} else {
13796 		auxkc_uuid_valid = TRUE;
13797 		memcpy((void *)&auxkc_uuid, (const void *)loaded_kcUUID->getBytesNoCopy(), loaded_kcUUID->getLength());
13798 		uuid_unparse_upper(auxkc_uuid, auxkc_uuid_string);
13799 	}
13800 
13801 	deallocate_kcfileset_map_entry_list_and_unmap_entries(map_entry_list, FALSE, pageable);
13802 
13803 	return 0;
13804 }
13805 
13806 /*********************************************************************
13807 * Assumes sKextLock is held.
13808 *********************************************************************/
13809 /* static */
13810 OSReturn
13811 OSKext::mapKCTextSegment(
13812 	void                 *control,
13813 	kernel_mach_header_t **mhp,
13814 	off_t                file_offset,
13815 	uintptr_t            *slidep,
13816 	void                 *map_entry_list)
13817 {
13818 	kern_return_t ret;
13819 	vm_map_offset_t mach_header_map_size = vm_map_round_page(sizeof(kernel_mach_header_t),
13820 	    PAGE_MASK);
13821 	vm_map_offset_t load_command_map_size = 0;
13822 	kernel_mach_header_t *base_mh = *mhp;
13823 
13824 	/* Map the mach header at start of fileset for now (vmaddr = 0) */
13825 	ret = vm_map_kcfileset_segment(
13826 		(vm_map_offset_t *)&base_mh, mach_header_map_size,
13827 		(memory_object_control_t)control, file_offset, (VM_PROT_READ | VM_PROT_WRITE));
13828 
13829 	if (ret != KERN_SUCCESS) {
13830 		printf("Kext Log: mapKCTextSegment failed to map mach header of fileset %x", ret);
13831 
13832 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13833 		    "Failed to map mach header of kc fileset with error %d", ret);
13834 		return kOSKextReturnInvalidArgument;
13835 	}
13836 
13837 	if (slidep) {
13838 		/* Verify that it's an MH_FILESET */
13839 		if (base_mh->filetype != MH_FILESET) {
13840 			printf("Kext Log: mapKCTextSegment mach header filetype"
13841 			    " is not an MH_FILESET, it is %x", base_mh->filetype);
13842 
13843 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13844 			    "mapKCTextSegment mach header filetype is not an MH_FILESET, it is %x", base_mh->filetype);
13845 
13846 			/* Unmap the mach header */
13847 			vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13848 			return kOSKextReturnInvalidArgument;
13849 		}
13850 	}
13851 
13852 	/* Map the remaining pages of load commands */
13853 	if (base_mh->sizeofcmds > mach_header_map_size) {
13854 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
13855 		load_command_map_size = base_mh->sizeofcmds - mach_header_map_size;
13856 
13857 		/* Map the load commands */
13858 		ret = vm_map_kcfileset_segment(
13859 			&load_command_addr, load_command_map_size,
13860 			(memory_object_control_t)control, file_offset + mach_header_map_size,
13861 			(VM_PROT_READ | VM_PROT_WRITE));
13862 
13863 		if (ret != KERN_SUCCESS) {
13864 			printf("KextLog: mapKCTextSegment failed to map load commands of fileset %x", ret);
13865 			OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13866 			    "Failed to map load commands of kc fileset with error %d", ret);
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 	kernel_segment_command_t *text_seg;
13875 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)base_mh, SEG_TEXT);
13876 
13877 	/* Calculate the slide and vm addr of mach header */
13878 	if (slidep) {
13879 		*mhp = (kernel_mach_header_t *)((uintptr_t)base_mh + text_seg->vmaddr);
13880 		*slidep = ((uintptr_t)*mhp) - text_seg->vmaddr;
13881 	}
13882 
13883 	/* Cache the text segment size and file offset before unmapping */
13884 	vm_map_offset_t text_segment_size = text_seg->vmsize;
13885 	vm_object_offset_t text_segment_fileoff = text_seg->fileoff;
13886 	vm_prot_t text_maxprot = text_seg->maxprot;
13887 
13888 	/* Unmap the first page and loadcommands and map the text segment */
13889 	ret = vm_unmap_kcfileset_segment((vm_map_offset_t *)&base_mh, mach_header_map_size);
13890 	assert(ret == KERN_SUCCESS);
13891 
13892 	if (load_command_map_size) {
13893 		vm_map_offset_t load_command_addr = ((vm_map_offset_t)base_mh) + mach_header_map_size;
13894 		ret = vm_unmap_kcfileset_segment(&load_command_addr, load_command_map_size);
13895 		assert(ret == KERN_SUCCESS);
13896 	}
13897 
13898 	/* Map the text segment at actual vm addr specified in fileset */
13899 	ret = vm_map_kcfileset_segment((vm_map_offset_t *)mhp, text_segment_size,
13900 	    (memory_object_control_t)control, text_segment_fileoff, text_maxprot);
13901 	if (ret != KERN_SUCCESS) {
13902 		OSKextLog(/* kext */ NULL, kOSKextLogDebugLevel | kOSKextLogIPCFlag,
13903 		    "Failed to map Text segment of kc fileset with error %d", ret);
13904 		return kOSKextReturnInvalidArgument;
13905 	}
13906 
13907 	add_kcfileset_map_entry(map_entry_list, (vm_map_offset_t)*mhp, text_segment_size);
13908 	return 0;
13909 }
13910 
13911 /*********************************************************************
13912 * Assumes sKextLock is held.
13913 *********************************************************************/
13914 /* static */
13915 OSReturn
13916 OSKext::protectKCFileSet(
13917 	kernel_mach_header_t *mh,
13918 	kc_kind_t            type)
13919 {
13920 	vm_map_t                    kext_map        = g_kext_map;
13921 	kernel_segment_command_t  * seg             = NULL;
13922 	vm_map_offset_t             start           = 0;
13923 	vm_map_offset_t             end             = 0;
13924 	vm_map_size_t               size            = 0;
13925 	OSReturn                    ret             = 0;
13926 
13927 	/* Set VM permissions */
13928 	seg = firstsegfromheader((kernel_mach_header_t *)mh);
13929 	while (seg) {
13930 		start = round_page(seg->vmaddr);
13931 		end = trunc_page(seg->vmaddr + seg->vmsize);
13932 		size = end - start;
13933 
13934 		/*
13935 		 * Wire down and protect __TEXT, __BRANCH_STUBS and __BRANCH_GOTS
13936 		 * for the Pageable KC and the Aux KC, wire down and protect __LINKEDIT
13937 		 * for the Aux KC as well.
13938 		 */
13939 		if (strncmp(seg->segname, kKCBranchGots, sizeof(seg->segname)) == 0 ||
13940 		    strncmp(seg->segname, kKCBranchStubs, sizeof(seg->segname)) == 0 ||
13941 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0 ||
13942 		    (type == KCKindAuxiliary && !resetAuxKCSegmentOnUnload &&
13943 		    strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0)) {
13944 			ret = OSKext_protect((kernel_mach_header_t *)mh,
13945 			    kext_map, start, size, seg->maxprot, TRUE, type);
13946 			if (ret != KERN_SUCCESS) {
13947 				printf("OSKext protect failed with error %d", ret);
13948 				return kOSKextReturnInvalidArgument;
13949 			}
13950 
13951 			ret = OSKext_protect((kernel_mach_header_t *)mh,
13952 			    kext_map, start, size, seg->initprot, FALSE, type);
13953 			if (ret != KERN_SUCCESS) {
13954 				printf("OSKext protect failed with error %d", ret);
13955 				return kOSKextReturnInvalidArgument;
13956 			}
13957 
13958 			ret = OSKext_wire((kernel_mach_header_t *)mh,
13959 			    kext_map, start, end, seg->initprot, FALSE, type);
13960 			if (ret != KERN_SUCCESS) {
13961 				printf("OSKext wire failed with error %d", ret);
13962 				return kOSKextReturnInvalidArgument;
13963 			}
13964 		}
13965 
13966 		seg = nextsegfromheader((kernel_mach_header_t *) mh, seg);
13967 	}
13968 
13969 	return 0;
13970 }
13971 
13972 /*********************************************************************
13973 * Assumes sKextLock is held.
13974 *********************************************************************/
13975 /* static */
13976 void
13977 OSKext::freeKCFileSetcontrol(void)
13978 {
13979 	PE_reset_all_kc_vp();
13980 }
13981 
13982 /*********************************************************************
13983 * Assumes sKextLock is held.
13984 *
13985 * resetKCFileSetSegments: Kext start function expects data segment to
13986 * be pristine on every load, unmap the dirty segments on unload and
13987 * remap them from FileSet on disk. Remap all segments of kext since
13988 * fixups are done per kext and not per segment.
13989 *********************************************************************/
13990 OSReturn
13991 OSKext::resetKCFileSetSegments(void)
13992 {
13993 	kernel_segment_command_t *seg = NULL;
13994 	kernel_segment_command_t *text_seg;
13995 	uint32_t text_fileoff;
13996 	kernel_mach_header_t *k_mh = NULL;
13997 	uintptr_t slide;
13998 	struct vnode *vp = NULL;
13999 	void *fileset_control = NULL;
14000 	bool pageable = (kc_type == KCKindPageable);
14001 	OSReturn err;
14002 	kern_return_t kr;
14003 
14004 	/* Check the vnode reference is still available */
14005 	vp = (struct vnode *)PE_get_kc_vp(kc_type);
14006 	if (vp == NULL) {
14007 		OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
14008 		    "Kext %s could not be reset, since reboot released the vnode ref", getIdentifierCString());
14009 		return kOSKextReturnInternalError;
14010 	}
14011 
14012 	fileset_control = ubc_getobject(vp, 0);
14013 	assert(fileset_control != NULL);
14014 
14015 	OSKextLog(this, kOSKextLogProgressLevel | kOSKextLogLoadFlag,
14016 	    "Kext %s resetting all segments", getIdentifierCString());
14017 
14018 	k_mh = (kernel_mach_header_t *)kmod_info->address;
14019 	text_seg = getsegbynamefromheader((kernel_mach_header_t *)kmod_info->address, SEG_TEXT);
14020 	text_fileoff = text_seg->fileoff;
14021 	slide = PE_get_kc_slide(kc_type);
14022 
14023 	seg = firstsegfromheader((kernel_mach_header_t *)k_mh);
14024 	while (seg) {
14025 		if (seg->vmsize == 0) {
14026 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
14027 			continue;
14028 		}
14029 
14030 		/* Skip the __LINKEDIT, __LINKINFO and __TEXT segments */
14031 		if (strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)) == 0 ||
14032 		    strncmp(seg->segname, SEG_LINKINFO, sizeof(seg->segname)) == 0 ||
14033 		    strncmp(seg->segname, SEG_TEXT, sizeof(seg->segname)) == 0) {
14034 			seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
14035 			continue;
14036 		}
14037 
14038 		kr = vm_unmap_kcfileset_segment(&seg->vmaddr, seg->vmsize);
14039 		assert(kr == KERN_SUCCESS);
14040 		seg = nextsegfromheader((kernel_mach_header_t *) k_mh, seg);
14041 	}
14042 
14043 	/* Unmap the text segment */
14044 	kr = vm_unmap_kcfileset_segment(&text_seg->vmaddr, text_seg->vmsize);
14045 	assert(kr == KERN_SUCCESS);
14046 
14047 	/* Map all the segments of the kext */
14048 	err = OSKext::mapKCFileSet(fileset_control, 0, &k_mh, text_fileoff, &slide, pageable, NULL);
14049 	if (err) {
14050 		panic("Could not reset segments of a mapped kext, error %x", err);
14051 	}
14052 
14053 	/* Update address in kmod_info, since it has been reset */
14054 	if (kmod_info->address) {
14055 		kmod_info->address = (((uintptr_t)(kmod_info->address)) + slide);
14056 	}
14057 
14058 	return 0;
14059 }
14060 
14061 /*********************************************************************
14062 * Mechanism to track all segment mapping while mapping KC fileset.
14063 *********************************************************************/
14064 
14065 struct kcfileset_map_entry {
14066 	vm_map_offset_t me_start;
14067 	vm_map_offset_t me_size;
14068 };
14069 
14070 struct kcfileset_map_entry_list {
14071 	int                        kme_list_count;
14072 	int                        kme_list_index;
14073 	struct kcfileset_map_entry kme_list[];
14074 };
14075 
14076 #define KCFILESET_MAP_ENTRY_MAX (16380)
14077 
14078 static void *
14079 allocate_kcfileset_map_entry_list(void)
14080 {
14081 	struct kcfileset_map_entry_list *entry_list;
14082 
14083 	entry_list = kalloc_type(struct kcfileset_map_entry_list,
14084 	    struct kcfileset_map_entry, KCFILESET_MAP_ENTRY_MAX, Z_WAITOK_ZERO);
14085 
14086 	entry_list->kme_list_count = KCFILESET_MAP_ENTRY_MAX;
14087 	entry_list->kme_list_index = 0;
14088 	return entry_list;
14089 }
14090 
14091 static void
14092 add_kcfileset_map_entry(
14093 	void            *map_entry_list,
14094 	vm_map_offset_t start,
14095 	vm_map_offset_t size)
14096 {
14097 	if (map_entry_list == NULL) {
14098 		return;
14099 	}
14100 
14101 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
14102 
14103 	if (entry_list->kme_list_index >= entry_list->kme_list_count) {
14104 		panic("Ran out of map kc fileset list");
14105 	}
14106 
14107 	entry_list->kme_list[entry_list->kme_list_index].me_start = start;
14108 	entry_list->kme_list[entry_list->kme_list_index].me_size = size;
14109 
14110 	entry_list->kme_list_index++;
14111 }
14112 
14113 static void
14114 deallocate_kcfileset_map_entry_list_and_unmap_entries(
14115 	void      *map_entry_list,
14116 	boolean_t unmap_entries,
14117 	bool      pageable)
14118 {
14119 	struct kcfileset_map_entry_list *entry_list = (struct kcfileset_map_entry_list *)map_entry_list;
14120 
14121 	if (unmap_entries) {
14122 		for (int i = 0; i < entry_list->kme_list_index; i++) {
14123 			kern_return_t ret;
14124 			ret = vm_unmap_kcfileset_segment(
14125 				&(entry_list->kme_list[i].me_start),
14126 				entry_list->kme_list[i].me_size);
14127 			assert(ret == KERN_SUCCESS);
14128 		}
14129 
14130 		PE_reset_kc_header(pageable ? KCKindPageable : KCKindAuxiliary);
14131 	}
14132 
14133 	kfree_type(struct kcfileset_map_entry_list, struct kcfileset_map_entry,
14134 	    KCFILESET_MAP_ENTRY_MAX, entry_list);
14135 }
14136 
14137 /*********************************************************************
14138 * Mechanism to map kext segment.
14139 *********************************************************************/
14140 
14141 kern_return_t
14142 vm_map_kcfileset_segment(
14143 	vm_map_offset_t    *start,
14144 	vm_map_offset_t    size,
14145 	void               *control,
14146 	vm_object_offset_t fileoffset,
14147 	vm_prot_t          max_prot)
14148 {
14149 	vm_map_kernel_flags_t vmk_flags = {
14150 		.vmf_fixed = true,
14151 		.vmkf_no_copy_on_read = true,
14152 		.vmkf_cs_enforcement_override = true,
14153 		.vm_tag = VM_KERN_MEMORY_OSKEXT,
14154 	};
14155 	kern_return_t ret;
14156 
14157 	/* Add Write to max prot to allow fixups */
14158 	max_prot = max_prot | VM_PROT_WRITE;
14159 
14160 	/*
14161 	 * Map the segments from file as COPY mappings to
14162 	 * make sure changes on disk to the file does not affect
14163 	 * mapped segments.
14164 	 */
14165 	ret = vm_map_enter_mem_object_control(
14166 		g_kext_map,
14167 		start,
14168 		size,
14169 		(mach_vm_offset_t)0,
14170 		vmk_flags,
14171 		(memory_object_control_t)control,
14172 		fileoffset,
14173 		TRUE,         /* copy */
14174 		(VM_PROT_READ | VM_PROT_WRITE), max_prot,
14175 		VM_INHERIT_NONE);
14176 
14177 	return ret;
14178 }
14179 
14180 kern_return_t
14181 vm_unmap_kcfileset_segment(
14182 	vm_map_offset_t    *start,
14183 	vm_map_offset_t    size)
14184 {
14185 	return mach_vm_deallocate(g_kext_map, *start, size);
14186 }
14187 
14188 #endif //(__x86_64__) || defined(__i386__)
14189 
14190 /*********************************************************************
14191 * Assumes sKextLock is held.
14192 *********************************************************************/
14193 /* static */
14194 OSReturn
14195 OSKext::validateKCFileSetUUID(
14196 	OSDictionary         *infoDict,
14197 	kc_kind_t            type)
14198 {
14199 	OSReturn ret           = kOSReturnSuccess;
14200 
14201 	if (!kernelcache_uuid_valid) {
14202 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14203 		    "validateKCFileSetUUID Boot KC UUID was not set at boot.");
14204 		ret = kOSKextReturnInvalidArgument;
14205 		goto finish;
14206 	}
14207 	ret = OSKext::validateKCUUIDfromPrelinkInfo(&kernelcache_uuid, type, infoDict, kPrelinkInfoBootKCIDKey);
14208 	if (ret != 0) {
14209 		goto finish;
14210 	}
14211 
14212 #if defined(__x86_64__) || defined(__i386__)
14213 	/* Check if the Aux KC is prelinked to correct Pageable KC */
14214 	if (type == KCKindAuxiliary) {
14215 		if (!pageablekc_uuid_valid) {
14216 			OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14217 			    "validateKCFileSetUUID Pageable KC UUID was not set while loading Pageable KC.");
14218 			ret = kOSKextReturnInvalidArgument;
14219 			goto finish;
14220 		}
14221 		ret = OSKext::validateKCUUIDfromPrelinkInfo(&pageablekc_uuid, type, infoDict, kPrelinkInfoPageableKCIDKey);
14222 		if (ret != 0) {
14223 			goto finish;
14224 		}
14225 	}
14226 #endif //(__x86_64__) || defined(__i386__)
14227 
14228 	printf("KextLog: Collection UUID matches with loaded KCs.\n");
14229 finish:
14230 	return ret;
14231 }
14232 
14233 /*********************************************************************
14234 * Assumes sKextLock is held.
14235 *********************************************************************/
14236 /* static */
14237 OSReturn
14238 OSKext::validateKCUUIDfromPrelinkInfo(
14239 	uuid_t               *loaded_kcuuid,
14240 	kc_kind_t             type,
14241 	OSDictionary         *infoDict,
14242 	const char           *uuid_key)
14243 {
14244 	/* extract the UUID from the dictionary */
14245 	OSData *prelinkinfoKCUUID = OSDynamicCast(OSData, infoDict->getObject(uuid_key));
14246 	if (!prelinkinfoKCUUID) {
14247 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14248 		    "validateKCUUID Info plist does not contain %s KC UUID key.", uuid_key);
14249 		return kOSKextReturnInvalidArgument;
14250 	}
14251 
14252 	if (prelinkinfoKCUUID->getLength() != sizeof(uuid_t)) {
14253 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14254 		    "validateKCUUID %s KC UUID has wrong length: %d.", uuid_key, prelinkinfoKCUUID->getLength());
14255 		return kOSKextReturnInvalidArgument;
14256 	}
14257 
14258 	if (memcmp((void *)loaded_kcuuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(),
14259 	    prelinkinfoKCUUID->getLength())) {
14260 		OSData       *info_dict_uuid;
14261 		uuid_string_t info_dict_uuid_str = {};
14262 		uuid_string_t expected_uuid_str = {};
14263 		uuid_string_t given_uuid_str = {};
14264 		uuid_t        given_uuid;
14265 
14266 		/* extract the KC UUID from the dictionary */
14267 		info_dict_uuid = OSDynamicCast(OSData, infoDict->getObject(kPrelinkInfoKCIDKey));
14268 		if (info_dict_uuid && info_dict_uuid->getLength() == sizeof(uuid_t)) {
14269 			uuid_t tmp_uuid;
14270 			memcpy(tmp_uuid, (const void *)info_dict_uuid->getBytesNoCopy(), sizeof(tmp_uuid));
14271 			uuid_unparse(tmp_uuid, info_dict_uuid_str);
14272 		}
14273 
14274 		uuid_unparse(*loaded_kcuuid, expected_uuid_str);
14275 		memcpy(given_uuid, (const void *)prelinkinfoKCUUID->getBytesNoCopy(), sizeof(given_uuid));
14276 		uuid_unparse(given_uuid, given_uuid_str);
14277 
14278 		printf("KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
14279 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
14280 		OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
14281 		    "KextLog: ERROR: UUID from key:%s %s != expected %s (KC UUID: %s)\n", uuid_key,
14282 		    given_uuid_str, expected_uuid_str, info_dict_uuid_str);
14283 		if (type == KCKindPageable && sPanicOnKCMismatch) {
14284 			panic("System KC UUID %s linked against %s, but %s is loaded",
14285 			    info_dict_uuid_str, given_uuid_str, expected_uuid_str);
14286 		}
14287 		return kOSKextReturnInvalidArgument;
14288 	}
14289 
14290 	return 0;
14291 }
14292 
14293 /*********************************************************************
14294 * Assumes sKextLock is held.
14295 *********************************************************************/
14296 /* static */
14297 OSReturn
14298 OSKext::dispatchResource(OSDictionary * requestDict)
14299 {
14300 	OSReturn                        result          = kOSReturnError;
14301 	OSSharedPtr<OSDictionary>       callbackRecord;
14302 	OSNumber                      * requestTag      = NULL;        // do not release
14303 	OSNumber                      * requestResult   = NULL;        // do not release
14304 	OSData                        * dataObj         = NULL;        // do not release
14305 	uint32_t                        dataLength      = 0;
14306 	const void                    * dataPtr         = NULL;        // do not free
14307 	OSValueObject<OSKextRequestResourceCallback> * callbackWrapper = nullptr; // do not release
14308 	OSKextRequestResourceCallback   callback        = NULL;
14309 	OSValueObject<void *>         * contextWrapper  = nullptr;     // do not release
14310 	void                          * context         = NULL;        // do not free
14311 	OSSharedPtr<OSKext>             callbackKext;
14312 
14313 	/* Get the args from the request. Right now we need the tag
14314 	 * to look up the callback record, and the result for invoking the callback.
14315 	 */
14316 	requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
14317 	    kKextRequestArgumentRequestTagKey));
14318 	requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
14319 	    kKextRequestArgumentResultKey));
14320 	if (!requestTag || !requestResult) {
14321 		result = kOSKextReturnInvalidArgument;
14322 		goto finish;
14323 	}
14324 
14325 	/* Look for a callback record matching this request's tag.
14326 	 */
14327 	result = dequeueCallbackForRequestTag(requestTag, callbackRecord);
14328 	if (result != kOSReturnSuccess) {
14329 		goto finish;
14330 	}
14331 
14332 	/*****
14333 	 * Get the context pointer of the callback record (if there is one).
14334 	 */
14335 	contextWrapper = OSDynamicCast(OSValueObject<void *>, _OSKextGetRequestArgument(
14336 		    callbackRecord.get(), kKextRequestArgumentContextKey));
14337 	context = _OSKextExtractPointer(contextWrapper);
14338 	if (contextWrapper && !context) {
14339 		goto finish;
14340 	}
14341 
14342 	callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14343 	    _OSKextGetRequestArgument(callbackRecord.get(),
14344 	    kKextRequestArgumentCallbackKey));
14345 	callback = _OSKextExtractCallbackPointer(callbackWrapper);
14346 	if (!callback) {
14347 		goto finish;
14348 	}
14349 
14350 	/* Check for a data obj. We might not have one and that's ok, that means
14351 	 * we didn't find the requested resource, and we still have to tell the
14352 	 * caller that via the callback.
14353 	 */
14354 	dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
14355 	    kKextRequestArgumentValueKey));
14356 	if (dataObj) {
14357 		dataPtr = dataObj->getBytesNoCopy();
14358 		dataLength = dataObj->getLength();
14359 	}
14360 
14361 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
14362 	if (!callbackKext) {
14363 		OSKextLog(/* kext */ NULL,
14364 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
14365 		    "Can't invoke callback for resource request; ");
14366 		goto finish;
14367 	}
14368 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
14369 		OSKextLog(/* kext */ NULL,
14370 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
14371 		    "Can't invoke kext resource callback; ");
14372 		goto finish;
14373 	}
14374 
14375 	(void)callback(requestTag->unsigned32BitValue(),
14376 	    (OSReturn)requestResult->unsigned32BitValue(),
14377 	    dataPtr, dataLength, context);
14378 
14379 	result = kOSReturnSuccess;
14380 
14381 finish:
14382 	return result;
14383 }
14384 
14385 /*********************************************************************
14386 * Assumes sKextLock is held.
14387 *********************************************************************/
14388 /* static */
14389 OSReturn
14390 OSKext::setMissingAuxKCBundles(OSDictionary * requestDict)
14391 {
14392 	OSSharedPtr<OSDictionary> missingIDs;
14393 	OSArray *bundleIDList     = NULL; // do not release
14394 
14395 	bundleIDList = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
14396 		    requestDict, kKextRequestArgumentMissingBundleIDs));
14397 	if (!bundleIDList) {
14398 		return kOSKextReturnInvalidArgument;
14399 	}
14400 
14401 	missingIDs = OSDictionary::withCapacity(bundleIDList->getCount());
14402 	if (!missingIDs) {
14403 		return kOSKextReturnNoMemory;
14404 	}
14405 
14406 	uint32_t count, i;
14407 	count = bundleIDList->getCount();
14408 	for (i = 0; i < count; i++) {
14409 		OSString *thisID = OSDynamicCast(OSString, bundleIDList->getObject(i));
14410 		if (thisID) {
14411 			missingIDs->setObject(thisID, kOSBooleanFalse);
14412 		}
14413 	}
14414 
14415 	sNonLoadableKextsByID.reset(missingIDs.get(), OSRetain);
14416 
14417 	return kOSReturnSuccess;
14418 }
14419 
14420 /*********************************************************************
14421 * Assumes sKextLock is held.
14422 *********************************************************************/
14423 /* static */
14424 OSReturn
14425 OSKext::setAuxKCBundleAvailable(OSString *kextIdentifier, OSDictionary *requestDict)
14426 {
14427 	bool loadable = true;
14428 	if (!kextIdentifier) {
14429 		return kOSKextReturnInvalidArgument;
14430 	}
14431 
14432 	if (requestDict) {
14433 		OSBoolean *loadableArg;
14434 		loadableArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
14435 			    requestDict, kKextRequestArgumentBundleAvailability));
14436 		/* If we find the "Bundle Available" arg, and it's false, then
14437 		 * mark the bundle ID as _not_ loadable
14438 		 */
14439 		if (loadableArg && !loadableArg->getValue()) {
14440 			loadable = false;
14441 		}
14442 	}
14443 
14444 	if (!sNonLoadableKextsByID) {
14445 		sNonLoadableKextsByID = OSDictionary::withCapacity(1);
14446 	}
14447 
14448 	sNonLoadableKextsByID->setObject(kextIdentifier, OSBoolean::withBoolean(loadable));
14449 
14450 	OSKextLog(/* kext */ NULL,
14451 	    kOSKextLogBasicLevel | kOSKextLogIPCFlag,
14452 	    "KextLog: AuxKC bundle %s marked as %s",
14453 	    kextIdentifier->getCStringNoCopy(),
14454 	    (loadable ? "loadable" : "NOT loadable"));
14455 
14456 	return kOSReturnSuccess;
14457 }
14458 
14459 /*********************************************************************
14460 *********************************************************************/
14461 /* static */
14462 void
14463 OSKext::invokeRequestCallback(
14464 	OSDictionary * callbackRecord,
14465 	OSReturn       callbackResult)
14466 {
14467 	OSString * predicate  = _OSKextGetRequestPredicate(callbackRecord);
14468 	OSSharedPtr<OSNumber> resultNum;
14469 
14470 	if (!predicate) {
14471 		goto finish;
14472 	}
14473 
14474 	resultNum  = OSNumber::withNumber((long long unsigned int)callbackResult,
14475 	    8 * sizeof(callbackResult));
14476 	if (!resultNum) {
14477 		goto finish;
14478 	}
14479 
14480 	/* Insert the result into the callback record and dispatch it as if it
14481 	 * were the reply coming down from user space.
14482 	 */
14483 	_OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
14484 	    resultNum.get());
14485 
14486 	if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
14487 		/* This removes the pending callback record.
14488 		 */
14489 		OSKext::dispatchResource(callbackRecord);
14490 	}
14491 
14492 finish:
14493 	return;
14494 }
14495 
14496 /*********************************************************************
14497 * Assumes sKextLock is held.
14498 *********************************************************************/
14499 /* static */
14500 OSReturn
14501 OSKext::cancelRequest(
14502 	OSKextRequestTag    requestTag,
14503 	void             ** contextOut)
14504 {
14505 	OSReturn       result         = kOSKextReturnNoMemory;
14506 	OSSharedPtr<OSDictionary> callbackRecord;
14507 	OSValueObject<void *> * contextWrapper = nullptr; // do not release
14508 
14509 	IORecursiveLockLock(sKextLock);
14510 	result = OSKext::dequeueCallbackForRequestTag(requestTag,
14511 	    callbackRecord);
14512 	IORecursiveLockUnlock(sKextLock);
14513 
14514 	if (result == kOSReturnSuccess && contextOut) {
14515 		contextWrapper = OSDynamicCast(OSValueObject<void *>,
14516 		    _OSKextGetRequestArgument(callbackRecord.get(),
14517 		    kKextRequestArgumentContextKey));
14518 		*contextOut = _OSKextExtractPointer(contextWrapper);
14519 	}
14520 
14521 	return result;
14522 }
14523 
14524 /*********************************************************************
14525 * Assumes sKextLock is held.
14526 *********************************************************************/
14527 void
14528 OSKext::invokeOrCancelRequestCallbacks(
14529 	OSReturn callbackResult,
14530 	bool     invokeFlag)
14531 {
14532 	unsigned int count, i;
14533 
14534 	count = sRequestCallbackRecords->getCount();
14535 	if (!count) {
14536 		goto finish;
14537 	}
14538 
14539 	i = count - 1;
14540 	do {
14541 		OSDictionary * request = OSDynamicCast(OSDictionary,
14542 		    sRequestCallbackRecords->getObject(i));
14543 
14544 		if (!request) {
14545 			continue;
14546 		}
14547 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14548 		    _OSKextGetRequestArgument(request,
14549 		    kKextRequestArgumentCallbackKey));
14550 
14551 		if (!callbackWrapper) {
14552 			sRequestCallbackRecords->removeObject(i);
14553 			continue;
14554 		}
14555 
14556 		vm_address_t callbackAddress = (vm_address_t)
14557 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
14558 
14559 		if ((kmod_info->address <= callbackAddress) &&
14560 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
14561 			if (invokeFlag) {
14562 				/* This removes the callback record.
14563 				 */
14564 				invokeRequestCallback(request, callbackResult);
14565 			} else {
14566 				sRequestCallbackRecords->removeObject(i);
14567 			}
14568 		}
14569 	} while (i--);
14570 
14571 finish:
14572 	return;
14573 }
14574 
14575 /*********************************************************************
14576 * Assumes sKextLock is held.
14577 *********************************************************************/
14578 uint32_t
14579 OSKext::countRequestCallbacks(void)
14580 {
14581 	uint32_t     result = 0;
14582 	unsigned int count, i;
14583 
14584 	count = sRequestCallbackRecords->getCount();
14585 	if (!count) {
14586 		goto finish;
14587 	}
14588 
14589 	i = count - 1;
14590 	do {
14591 		OSDictionary * request = OSDynamicCast(OSDictionary,
14592 		    sRequestCallbackRecords->getObject(i));
14593 
14594 		if (!request) {
14595 			continue;
14596 		}
14597 		auto * callbackWrapper = OSDynamicCast(OSValueObject<OSKextRequestResourceCallback>,
14598 		    _OSKextGetRequestArgument(request,
14599 		    kKextRequestArgumentCallbackKey));
14600 
14601 		if (!callbackWrapper) {
14602 			continue;
14603 		}
14604 
14605 		vm_address_t callbackAddress = (vm_address_t)
14606 		    ptrauth_strip(_OSKextExtractPointer(callbackWrapper), ptrauth_key_function_pointer);
14607 
14608 		if ((kmod_info->address <= callbackAddress) &&
14609 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
14610 			result++;
14611 		}
14612 	} while (i--);
14613 
14614 finish:
14615 	return result;
14616 }
14617 
14618 /*********************************************************************
14619 *********************************************************************/
14620 static OSReturn
14621 _OSKextCreateRequest(
14622 	const char    * predicate,
14623 	OSSharedPtr<OSDictionary> & requestR)
14624 {
14625 	OSReturn result = kOSKextReturnNoMemory;
14626 	OSSharedPtr<OSDictionary> request;
14627 
14628 	request = OSDictionary::withCapacity(2);
14629 	if (!request) {
14630 		goto finish;
14631 	}
14632 	result = _OSDictionarySetCStringValue(request.get(),
14633 	    kKextRequestPredicateKey, predicate);
14634 	if (result != kOSReturnSuccess) {
14635 		goto finish;
14636 	}
14637 	result = kOSReturnSuccess;
14638 
14639 finish:
14640 	if (result == kOSReturnSuccess) {
14641 		requestR = os::move(request);
14642 	}
14643 
14644 	return result;
14645 }
14646 
14647 /*********************************************************************
14648 *********************************************************************/
14649 static OSString *
14650 _OSKextGetRequestPredicate(OSDictionary * requestDict)
14651 {
14652 	return OSDynamicCast(OSString,
14653 	           requestDict->getObject(kKextRequestPredicateKey));
14654 }
14655 
14656 /*********************************************************************
14657 *********************************************************************/
14658 static OSObject *
14659 _OSKextGetRequestArgument(
14660 	OSDictionary * requestDict,
14661 	const char   * argName)
14662 {
14663 	OSDictionary * args = OSDynamicCast(OSDictionary,
14664 	    requestDict->getObject(kKextRequestArgumentsKey));
14665 	if (args) {
14666 		return args->getObject(argName);
14667 	}
14668 	return NULL;
14669 }
14670 
14671 /*********************************************************************
14672 *********************************************************************/
14673 static bool
14674 _OSKextSetRequestArgument(
14675 	OSDictionary    * requestDict,
14676 	const char      * argName,
14677 	OSMetaClassBase * value)
14678 {
14679 	OSDictionary * args = OSDynamicCast(OSDictionary,
14680 	    requestDict->getObject(kKextRequestArgumentsKey));
14681 	OSSharedPtr<OSDictionary> newArgs;
14682 	if (!args) {
14683 		newArgs = OSDictionary::withCapacity(2);
14684 		args = newArgs.get();
14685 		if (!args) {
14686 			goto finish;
14687 		}
14688 		requestDict->setObject(kKextRequestArgumentsKey, args);
14689 	}
14690 	if (args) {
14691 		return args->setObject(argName, value);
14692 	}
14693 finish:
14694 	return false;
14695 }
14696 
14697 /*********************************************************************
14698 *********************************************************************/
14699 template <typename T>
14700 static T *
14701 _OSKextExtractPointer(OSValueObject<T *> * wrapper)
14702 {
14703 	if (!wrapper) {
14704 		return nullptr;
14705 	}
14706 	return wrapper->getRef();
14707 }
14708 
14709 /*********************************************************************
14710 *********************************************************************/
14711 static OSKextRequestResourceCallback
14712 _OSKextExtractCallbackPointer(OSValueObject<OSKextRequestResourceCallback> * wrapper)
14713 {
14714 	if (!wrapper) {
14715 		return nullptr;
14716 	}
14717 	return wrapper->getRef();
14718 }
14719 
14720 
14721 /*********************************************************************
14722 *********************************************************************/
14723 static OSReturn
14724 _OSDictionarySetCStringValue(
14725 	OSDictionary * dict,
14726 	const char   * cKey,
14727 	const char   * cValue)
14728 {
14729 	OSReturn result = kOSKextReturnNoMemory;
14730 	OSSharedPtr<const OSSymbol> key;
14731 	OSSharedPtr<OSString> value;
14732 
14733 	key = OSSymbol::withCString(cKey);
14734 	value = OSString::withCString(cValue);
14735 	if (!key || !value) {
14736 		goto finish;
14737 	}
14738 	if (dict->setObject(key.get(), value.get())) {
14739 		result = kOSReturnSuccess;
14740 	}
14741 
14742 finish:
14743 	return result;
14744 }
14745 
14746 /*********************************************************************
14747 *********************************************************************/
14748 static bool
14749 _OSArrayContainsCString(
14750 	OSArray    * array,
14751 	const char * cString)
14752 {
14753 	bool             result = false;
14754 	OSSharedPtr<const OSSymbol> symbol;
14755 	uint32_t         count, i;
14756 
14757 	if (!array || !cString) {
14758 		goto finish;
14759 	}
14760 
14761 	symbol = OSSymbol::withCStringNoCopy(cString);
14762 	if (!symbol) {
14763 		goto finish;
14764 	}
14765 
14766 	count = array->getCount();
14767 	for (i = 0; i < count; i++) {
14768 		OSObject * thisObject = array->getObject(i);
14769 		if (symbol->isEqualTo(thisObject)) {
14770 			result = true;
14771 			goto finish;
14772 		}
14773 	}
14774 
14775 finish:
14776 	return result;
14777 }
14778 
14779 #if CONFIG_KXLD
14780 /*********************************************************************
14781 * We really only care about boot / system start up related kexts.
14782 * We return true if we're less than REBUILD_MAX_TIME since start up,
14783 * otherwise return false.
14784 *********************************************************************/
14785 bool
14786 _OSKextInPrelinkRebuildWindow(void)
14787 {
14788 	static bool     outside_the_window = false;
14789 	AbsoluteTime    my_abstime;
14790 	UInt64          my_ns;
14791 	SInt32          my_secs;
14792 
14793 	if (outside_the_window) {
14794 		return false;
14795 	}
14796 	clock_get_uptime(&my_abstime);
14797 	absolutetime_to_nanoseconds(my_abstime, &my_ns);
14798 	my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
14799 	if (my_secs > REBUILD_MAX_TIME) {
14800 		outside_the_window = true;
14801 		return false;
14802 	}
14803 	return true;
14804 }
14805 #endif /* CONFIG_KXLD */
14806 
14807 /*********************************************************************
14808 *********************************************************************/
14809 bool
14810 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
14811 {
14812 	int unLoadedCount, i;
14813 	bool result = false;
14814 
14815 	IORecursiveLockLock(sKextLock);
14816 
14817 	if (sUnloadedPrelinkedKexts == NULL) {
14818 		goto finish;
14819 	}
14820 	unLoadedCount = sUnloadedPrelinkedKexts->getCount();
14821 	if (unLoadedCount == 0) {
14822 		goto finish;
14823 	}
14824 
14825 	for (i = 0; i < unLoadedCount; i++) {
14826 		const OSSymbol *    myBundleID;        // do not release
14827 
14828 		myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
14829 		if (!myBundleID) {
14830 			continue;
14831 		}
14832 		if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
14833 			result = true;
14834 			break;
14835 		}
14836 	}
14837 finish:
14838 	IORecursiveLockUnlock(sKextLock);
14839 	return result;
14840 }
14841 
14842 #if PRAGMA_MARK
14843 #pragma mark Personalities (IOKit Drivers)
14844 #endif
14845 /*********************************************************************
14846 *********************************************************************/
14847 /* static */
14848 OSSharedPtr<OSArray>
14849 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
14850 {
14851 	OSSharedPtr<OSArray>              result;
14852 	OSSharedPtr<OSCollectionIterator> kextIterator;
14853 	OSSharedPtr<OSArray>              personalities;
14854 
14855 	OSString             * kextID                = NULL;        // do not release
14856 	OSKext               * theKext               = NULL;        // do not release
14857 
14858 	IORecursiveLockLock(sKextLock);
14859 
14860 	/* Let's conservatively guess that any given kext has around 3
14861 	 * personalities for now.
14862 	 */
14863 	result = OSArray::withCapacity(sKextsByID->getCount() * 3);
14864 	if (!result) {
14865 		goto finish;
14866 	}
14867 
14868 	kextIterator = OSCollectionIterator::withCollection(sKextsByID.get());
14869 	if (!kextIterator) {
14870 		goto finish;
14871 	}
14872 
14873 	while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
14874 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
14875 		if (theKext->flags.requireExplicitLoad) {
14876 			OSKextLog(theKext,
14877 			    kOSKextLogDebugLevel |
14878 			    kOSKextLogLoadFlag,
14879 			    "Kext %s requires an explicit kextload; "
14880 			    "omitting its personalities.",
14881 			    theKext->getIdentifierCString());
14882 		} else if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
14883 			personalities = theKext->copyPersonalitiesArray();
14884 			if (!personalities) {
14885 				continue;
14886 			}
14887 			result->merge(personalities.get());
14888 		} else {
14889 			// xxx - check for better place to put this log msg
14890 			OSKextLog(theKext,
14891 			    kOSKextLogWarningLevel |
14892 			    kOSKextLogLoadFlag,
14893 			    "Kext %s is not loadable during safe boot; "
14894 			    "omitting its personalities.",
14895 			    theKext->getIdentifierCString());
14896 		}
14897 	}
14898 
14899 finish:
14900 	IORecursiveLockUnlock(sKextLock);
14901 
14902 	return result;
14903 }
14904 
14905 /*********************************************************************
14906 *********************************************************************/
14907 /* static */
14908 void
14909 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
14910 {
14911 	int numPersonalities = 0;
14912 
14913 	OSKextLog(/* kext */ NULL,
14914 	    kOSKextLogStepLevel |
14915 	    kOSKextLogLoadFlag,
14916 	    "Sending all eligible registered kexts' personalities "
14917 	    "to the IOCatalogue %s.",
14918 	    startMatching ? "and starting matching" : "but not starting matching");
14919 
14920 	OSSharedPtr<OSArray> personalities = OSKext::copyAllKextPersonalities(
14921 		/* filterSafeBootFlag */ true);
14922 
14923 	if (personalities) {
14924 		gIOCatalogue->addDrivers(personalities.get(), startMatching);
14925 		numPersonalities = personalities->getCount();
14926 	}
14927 
14928 	OSKextLog(/* kext */ NULL,
14929 	    kOSKextLogStepLevel |
14930 	    kOSKextLogLoadFlag,
14931 	    "%d kext personalit%s sent to the IOCatalogue; %s.",
14932 	    numPersonalities, numPersonalities > 0 ? "ies" : "y",
14933 	    startMatching ? "matching started" : "matching not started");
14934 	return;
14935 }
14936 
14937 /*********************************************************************
14938 * Do not make a deep copy, just convert the IOKitPersonalities dict
14939 * to an array for sending to the IOCatalogue.
14940 *********************************************************************/
14941 OSSharedPtr<OSArray>
14942 OSKext::copyPersonalitiesArray(void)
14943 {
14944 	OSSharedPtr<OSArray>              result;
14945 	OSDictionary         * personalities               = NULL;        // do not release
14946 	OSSharedPtr<OSCollectionIterator> personalitiesIterator;
14947 
14948 	OSString             * personalityName             = NULL;        // do not release
14949 	OSString             * personalityBundleIdentifier = NULL;        // do not release
14950 
14951 	personalities = OSDynamicCast(OSDictionary,
14952 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
14953 	if (!personalities) {
14954 		goto finish;
14955 	}
14956 
14957 	result = OSArray::withCapacity(personalities->getCount());
14958 	if (!result) {
14959 		goto finish;
14960 	}
14961 
14962 	personalitiesIterator =
14963 	    OSCollectionIterator::withCollection(personalities);
14964 	if (!personalitiesIterator) {
14965 		goto finish;
14966 	}
14967 	while ((personalityName = OSDynamicCast(OSString,
14968 	    personalitiesIterator->getNextObject()))) {
14969 		OSDictionary * personality = OSDynamicCast(OSDictionary,
14970 		    personalities->getObject(personalityName));
14971 
14972 		if (personality) {
14973 			/******
14974 			 * If the personality doesn't have a CFBundleIdentifier, or if it
14975 			 * differs from the kext's, insert the kext's ID so we can find it.
14976 			 * The publisher ID is used to remove personalities from bundles
14977 			 * correctly.
14978 			 */
14979 			personalityBundleIdentifier = OSDynamicCast(OSString,
14980 			    personality->getObject(kCFBundleIdentifierKey));
14981 
14982 			if (!personalityBundleIdentifier) {
14983 				personality->setObject(kCFBundleIdentifierKey, bundleID.get());
14984 			} else if (!personalityBundleIdentifier->isEqualTo(bundleID.get())) {
14985 				personality->setObject(kIOPersonalityPublisherKey, bundleID.get());
14986 			}
14987 		}
14988 
14989 		result->setObject(personality);
14990 	}
14991 
14992 finish:
14993 	return result;
14994 }
14995 
14996 /*********************************************************************
14997 *   Might want to change this to a bool return?
14998 *********************************************************************/
14999 OSReturn
15000 OSKext::sendPersonalitiesToCatalog(
15001 	bool      startMatching,
15002 	OSArray * personalityNames)
15003 {
15004 	OSReturn       result              = kOSReturnSuccess;
15005 	OSSharedPtr<OSArray> personalitiesToSend;
15006 	OSDictionary * kextPersonalities   = NULL;        // do not release
15007 	int            count, i;
15008 
15009 	if (!sLoadEnabled) {
15010 		OSKextLog(this,
15011 		    kOSKextLogErrorLevel |
15012 		    kOSKextLogLoadFlag,
15013 		    "Kext loading is disabled (attempt to start matching for kext %s).",
15014 		    getIdentifierCString());
15015 		result = kOSKextReturnDisabled;
15016 		goto finish;
15017 	}
15018 
15019 	if (sSafeBoot && !isLoadableInSafeBoot()) {
15020 		OSKextLog(this,
15021 		    kOSKextLogErrorLevel |
15022 		    kOSKextLogLoadFlag,
15023 		    "Kext %s is not loadable during safe boot; "
15024 		    "not sending personalities to the IOCatalogue.",
15025 		    getIdentifierCString());
15026 		result = kOSKextReturnNotLoadable;
15027 		goto finish;
15028 	}
15029 
15030 	if (!personalityNames || !personalityNames->getCount()) {
15031 		personalitiesToSend = copyPersonalitiesArray();
15032 	} else {
15033 		kextPersonalities = OSDynamicCast(OSDictionary,
15034 		    getPropertyForHostArch(kIOKitPersonalitiesKey));
15035 		if (!kextPersonalities || !kextPersonalities->getCount()) {
15036 			// not an error
15037 			goto finish;
15038 		}
15039 		personalitiesToSend = OSArray::withCapacity(0);
15040 		if (!personalitiesToSend) {
15041 			result = kOSKextReturnNoMemory;
15042 			goto finish;
15043 		}
15044 		count = personalityNames->getCount();
15045 		for (i = 0; i < count; i++) {
15046 			OSString * name = OSDynamicCast(OSString,
15047 			    personalityNames->getObject(i));
15048 			if (!name) {
15049 				continue;
15050 			}
15051 			OSDictionary * personality = OSDynamicCast(OSDictionary,
15052 			    kextPersonalities->getObject(name));
15053 			if (personality) {
15054 				personalitiesToSend->setObject(personality);
15055 			}
15056 		}
15057 	}
15058 	if (personalitiesToSend) {
15059 		unsigned numPersonalities = personalitiesToSend->getCount();
15060 		OSKextLog(this,
15061 		    kOSKextLogStepLevel |
15062 		    kOSKextLogLoadFlag,
15063 		    "Kext %s sending %d personalit%s to the IOCatalogue%s.",
15064 		    getIdentifierCString(),
15065 		    numPersonalities,
15066 		    numPersonalities > 1 ? "ies" : "y",
15067 		    startMatching ? " and starting matching" : " but not starting matching");
15068 		gIOCatalogue->addDrivers(personalitiesToSend.get(), startMatching);
15069 	}
15070 finish:
15071 	return result;
15072 }
15073 
15074 /*********************************************************************
15075 * xxx - We should allow removing the kext's declared personalities,
15076 * xxx - even with other bundle identifiers.
15077 *********************************************************************/
15078 void
15079 OSKext::removePersonalitiesFromCatalog(void)
15080 {
15081 	OSSharedPtr<OSDictionary> personality;
15082 
15083 	personality = OSDictionary::withCapacity(1);
15084 	if (!personality) {
15085 		goto finish;
15086 	}
15087 	personality->setObject(kCFBundleIdentifierKey, getIdentifier());
15088 
15089 	OSKextLog(this,
15090 	    kOSKextLogStepLevel |
15091 	    kOSKextLogLoadFlag,
15092 	    "Kext %s removing all personalities naming it from the IOCatalogue.",
15093 	    getIdentifierCString());
15094 
15095 	/* Have the IOCatalog remove all personalities matching this kext's
15096 	 * bundle ID and trigger matching anew.
15097 	 */
15098 	gIOCatalogue->removeDrivers(personality.get(), /* startMatching */ true);
15099 
15100 finish:
15101 	return;
15102 }
15103 
15104 void
15105 OSKext::updatePersonalitiesInCatalog(OSArray *upgradedPersonalities)
15106 {
15107 	if (!upgradedPersonalities || upgradedPersonalities->getCount() == 0) {
15108 		return;
15109 	}
15110 
15111 	OSSharedPtr<OSDictionary> personalityToRemove = OSDictionary::withCapacity(1);
15112 	if (!personalityToRemove) {
15113 		return;
15114 	}
15115 
15116 	/*
15117 	 * Create a personality dictionary with just the bundleID.
15118 	 * We will remove any personality that has a matching bundleID,
15119 	 * irrespective of which other keys are present on the dictionary.
15120 	 */
15121 	personalityToRemove->setObject(kCFBundleIdentifierKey, getIdentifier());
15122 	gIOCatalogue->exchangeDrivers(personalityToRemove.get(), upgradedPersonalities, true);
15123 }
15124 
15125 #if PRAGMA_MARK
15126 #pragma mark Logging
15127 #endif
15128 /*********************************************************************
15129 * Do not call any function that takes sKextLock here!
15130 *********************************************************************/
15131 /* static */
15132 OSKextLogSpec
15133 OSKext::setUserSpaceLogFilter(
15134 	OSKextLogSpec   newUserLogFilter,
15135 	bool            captureFlag)
15136 {
15137 	OSKextLogSpec result;
15138 	bool          allocError = false;
15139 
15140 	/* Do not call any function that takes sKextLoggingLock during
15141 	 * this critical block. That means do logging after.
15142 	 */
15143 	IOLockLock(sKextLoggingLock);
15144 
15145 	result = sUserSpaceKextLogFilter;
15146 	sUserSpaceKextLogFilter = newUserLogFilter;
15147 
15148 	if (newUserLogFilter && captureFlag &&
15149 	    !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
15150 		// xxx - do some measurements for a good initial capacity?
15151 		sUserSpaceLogSpecArray = OSArray::withCapacity(0);
15152 		sUserSpaceLogMessageArray = OSArray::withCapacity(0);
15153 
15154 		if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
15155 			allocError = true;
15156 		}
15157 	}
15158 
15159 	IOLockUnlock(sKextLoggingLock);
15160 
15161 	/* If the config flag itself is changing, log the state change
15162 	 * going both ways, before setting up the user-space log arrays,
15163 	 * so that this is only logged in the kernel.
15164 	 */
15165 	if (result != newUserLogFilter) {
15166 		OSKextLog(/* kext */ NULL,
15167 		    kOSKextLogDebugLevel |
15168 		    kOSKextLogGeneralFlag,
15169 		    "User-space log flags changed from 0x%x to 0x%x.",
15170 		    result, newUserLogFilter);
15171 	}
15172 	if (allocError) {
15173 		OSKextLog(/* kext */ NULL,
15174 		    kOSKextLogErrorLevel |
15175 		    kOSKextLogGeneralFlag,
15176 		    "Failed to allocate user-space log message arrays.");
15177 	}
15178 
15179 	return result;
15180 }
15181 
15182 /*********************************************************************
15183 * Do not call any function that takes sKextLock here!
15184 *********************************************************************/
15185 /* static */
15186 OSSharedPtr<OSArray>
15187 OSKext::clearUserSpaceLogFilter(void)
15188 {
15189 	OSSharedPtr<OSArray>       result;
15190 	OSKextLogSpec   oldLogFilter;
15191 	OSKextLogSpec   newLogFilter = kOSKextLogSilentFilter;
15192 
15193 	/* Do not call any function that takes sKextLoggingLock during
15194 	 * this critical block. That means do logging after.
15195 	 */
15196 	IOLockLock(sKextLoggingLock);
15197 
15198 	result = OSArray::withCapacity(2);
15199 	if (result) {
15200 		result->setObject(sUserSpaceLogSpecArray.get());
15201 		result->setObject(sUserSpaceLogMessageArray.get());
15202 	}
15203 	sUserSpaceLogSpecArray.reset();
15204 	sUserSpaceLogMessageArray.reset();
15205 
15206 	oldLogFilter = sUserSpaceKextLogFilter;
15207 	sUserSpaceKextLogFilter = newLogFilter;
15208 
15209 	IOLockUnlock(sKextLoggingLock);
15210 
15211 	/* If the config flag itself is changing, log the state change
15212 	 * going both ways, after tearing down the user-space log
15213 	 * arrays, so this is only logged within the kernel.
15214 	 */
15215 	if (oldLogFilter != newLogFilter) {
15216 		OSKextLog(/* kext */ NULL,
15217 		    kOSKextLogDebugLevel |
15218 		    kOSKextLogGeneralFlag,
15219 		    "User-space log flags changed from 0x%x to 0x%x.",
15220 		    oldLogFilter, newLogFilter);
15221 	}
15222 
15223 	return result;
15224 }
15225 
15226 
15227 /*********************************************************************
15228 * Do not call any function that takes sKextLock here!
15229 *********************************************************************/
15230 /* static */
15231 OSKextLogSpec
15232 OSKext::getUserSpaceLogFilter(void)
15233 {
15234 	OSKextLogSpec result;
15235 
15236 	IOLockLock(sKextLoggingLock);
15237 	result = sUserSpaceKextLogFilter;
15238 	IOLockUnlock(sKextLoggingLock);
15239 
15240 	return result;
15241 }
15242 
15243 /*********************************************************************
15244 * This function is called by OSMetaClass during kernel C++ setup.
15245 * Be careful what you access here; assume only OSKext::initialize()
15246 * has been called.
15247 *
15248 * Do not call any function that takes sKextLock here!
15249 *********************************************************************/
15250 #define VTRESET   "\033[0m"
15251 
15252 #define VTBOLD    "\033[1m"
15253 #define VTUNDER   "\033[4m"
15254 
15255 #define VTRED     "\033[31m"
15256 #define VTGREEN   "\033[32m"
15257 #define VTYELLOW  "\033[33m"
15258 #define VTBLUE    "\033[34m"
15259 #define VTMAGENTA "\033[35m"
15260 #define VTCYAN    "\033[36m"
15261 
15262 inline const char *
15263 colorForFlags(OSKextLogSpec flags)
15264 {
15265 	OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
15266 
15267 	switch (logLevel) {
15268 	case kOSKextLogErrorLevel:
15269 		return VTRED VTBOLD;
15270 	case kOSKextLogWarningLevel:
15271 		return VTRED;
15272 	case kOSKextLogBasicLevel:
15273 		return VTYELLOW VTUNDER;
15274 	case kOSKextLogProgressLevel:
15275 		return VTYELLOW;
15276 	case kOSKextLogStepLevel:
15277 		return VTGREEN;
15278 	case kOSKextLogDetailLevel:
15279 		return VTCYAN;
15280 	case kOSKextLogDebugLevel:
15281 		return VTMAGENTA;
15282 	default:
15283 		return "";         // white
15284 	}
15285 }
15286 
15287 inline bool
15288 logSpecMatch(
15289 	OSKextLogSpec msgLogSpec,
15290 	OSKextLogSpec logFilter)
15291 {
15292 	OSKextLogSpec filterKextGlobal  = logFilter & kOSKextLogKextOrGlobalMask;
15293 	OSKextLogSpec filterLevel       = logFilter & kOSKextLogLevelMask;
15294 	OSKextLogSpec filterFlags       = logFilter & kOSKextLogFlagsMask;
15295 
15296 	OSKextLogSpec msgKextGlobal    = msgLogSpec & kOSKextLogKextOrGlobalMask;
15297 	OSKextLogSpec msgLevel         = msgLogSpec & kOSKextLogLevelMask;
15298 	OSKextLogSpec msgFlags         = msgLogSpec & kOSKextLogFlagsMask;
15299 
15300 	/* Explicit messages always get logged.
15301 	 */
15302 	if (msgLevel == kOSKextLogExplicitLevel) {
15303 		return true;
15304 	}
15305 
15306 	/* Warnings and errors are logged regardless of the flags.
15307 	 */
15308 	if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
15309 		return true;
15310 	}
15311 
15312 	/* A verbose message that isn't for a logging-enabled kext and isn't global
15313 	 * does *not* get logged.
15314 	 */
15315 	if (!msgKextGlobal && !filterKextGlobal) {
15316 		return false;
15317 	}
15318 
15319 	/* Warnings and errors are logged regardless of the flags.
15320 	 * All other messages must fit the flags and
15321 	 * have a level at or below the filter.
15322 	 *
15323 	 */
15324 	if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
15325 		return true;
15326 	}
15327 	return false;
15328 }
15329 
15330 extern "C" {
15331 void
15332 OSKextLog(
15333 	OSKext         * aKext,
15334 	OSKextLogSpec    msgLogSpec,
15335 	const char     * format, ...)
15336 {
15337 	va_list argList;
15338 
15339 	va_start(argList, format);
15340 	OSKextVLog(aKext, msgLogSpec, format, argList);
15341 	va_end(argList);
15342 }
15343 
15344 void
15345 OSKextVLog(
15346 	OSKext         * aKext,
15347 	OSKextLogSpec    msgLogSpec,
15348 	const char     * format,
15349 	va_list          srcArgList)
15350 {
15351 	bool             logForKernel       = false;
15352 	bool             logForUser         = false;
15353 	va_list          argList;
15354 	char             stackBuffer[120];
15355 	uint32_t         length            = 0;
15356 	char           * allocBuffer       = NULL;        // must kfree
15357 	OSSharedPtr<OSNumber> logSpecNum;
15358 	OSSharedPtr<OSString> logString;
15359 	char           * buffer            = stackBuffer;        // do not free
15360 
15361 	IOLockLock(sKextLoggingLock);
15362 
15363 	/* Set the kext/global bit in the message spec if we have no
15364 	 * kext or if the kext requests logging.
15365 	 */
15366 	if (!aKext || aKext->flags.loggingEnabled) {
15367 		msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
15368 	}
15369 
15370 	logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
15371 	if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
15372 		logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
15373 	}
15374 
15375 	if (!(logForKernel || logForUser)) {
15376 		goto finish;
15377 	}
15378 
15379 	/* No goto from here until past va_end()!
15380 	 */
15381 	va_copy(argList, srcArgList);
15382 	length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
15383 	va_end(argList);
15384 
15385 	if (length + 1 >= sizeof(stackBuffer)) {
15386 		allocBuffer = (char *)kalloc_data_tag(length + 1,
15387 		    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
15388 		if (!allocBuffer) {
15389 			goto finish;
15390 		}
15391 
15392 		/* No goto from here until past va_end()!
15393 		 */
15394 		va_copy(argList, srcArgList);
15395 		vsnprintf(allocBuffer, length + 1, format, argList);
15396 		va_end(argList);
15397 
15398 		buffer = allocBuffer;
15399 	}
15400 
15401 	/* If user space wants the log message, queue it up.
15402 	 */
15403 	if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
15404 		logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
15405 		logString = OSString::withCString(buffer);
15406 		if (logSpecNum && logString) {
15407 			sUserSpaceLogSpecArray->setObject(logSpecNum.get());
15408 			sUserSpaceLogMessageArray->setObject(logString.get());
15409 		}
15410 	}
15411 
15412 	/* Always log messages from the kernel according to the kernel's
15413 	 * log flags.
15414 	 */
15415 	if (logForKernel) {
15416 		/* If we are in console mode and have a custom log filter,
15417 		 * colorize the log message.
15418 		 */
15419 		if (sBootArgLogFilterFound) {
15420 			const char * color = "";         // do not free
15421 			color = colorForFlags(msgLogSpec);
15422 			printf("%s%s%s\n", colorForFlags(msgLogSpec),
15423 			    buffer, color[0] ? VTRESET : "");
15424 		} else {
15425 			printf("%s\n", buffer);
15426 		}
15427 	}
15428 
15429 finish:
15430 	IOLockUnlock(sKextLoggingLock);
15431 
15432 	if (allocBuffer) {
15433 		kfree_data(allocBuffer, length + 1);
15434 	}
15435 	return;
15436 }
15437 
15438 #if KASLR_IOREG_DEBUG
15439 
15440 #define IOLOG_INDENT( the_indention ) \
15441 { \
15442     int     i; \
15443     for ( i = 0; i < (the_indention); i++ ) { \
15444 	IOLog(" "); \
15445     } \
15446 }
15447 
15448 extern vm_offset_t       vm_kernel_stext;
15449 extern vm_offset_t       vm_kernel_etext;
15450 extern mach_vm_offset_t kext_alloc_base;
15451 extern mach_vm_offset_t kext_alloc_max;
15452 
15453 bool ScanForAddrInObject(OSObject * theObject,
15454     int indent );
15455 
15456 bool
15457 ScanForAddrInObject(OSObject * theObject,
15458     int indent)
15459 {
15460 	const OSMetaClass *     myTypeID;
15461 	OSSharedPtr<OSCollectionIterator>  myIter;
15462 	OSSymbol *              myKey;
15463 	OSObject *              myValue;
15464 	bool                    myResult = false;
15465 
15466 	if (theObject == NULL) {
15467 		IOLog("%s: theObject is NULL \n",
15468 		    __FUNCTION__);
15469 		return myResult;
15470 	}
15471 
15472 	myTypeID = OSTypeIDInst(theObject);
15473 
15474 	if (myTypeID == OSTypeID(OSDictionary)) {
15475 		OSDictionary *      myDictionary;
15476 
15477 		myDictionary = OSDynamicCast(OSDictionary, theObject);
15478 		myIter = OSCollectionIterator::withCollection( myDictionary );
15479 		if (myIter == NULL) {
15480 			return myResult;
15481 		}
15482 
15483 		// !! reset the iterator
15484 		myIter->reset();
15485 
15486 		while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
15487 			bool    myTempResult;
15488 
15489 			myValue = myDictionary->getObject(myKey);
15490 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
15491 			if (myTempResult) {
15492 				// if we ever get a true result return true
15493 				myResult = true;
15494 				IOLOG_INDENT(indent);
15495 				IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
15496 			}
15497 		}
15498 
15499 		// !! release the iterator
15500 		myIter.reset();
15501 	} else if (myTypeID == OSTypeID(OSArray)) {
15502 		OSArray *   myArray;
15503 
15504 		myArray = OSDynamicCast(OSArray, theObject);
15505 		myIter = OSCollectionIterator::withCollection(myArray);
15506 		if (myIter == NULL) {
15507 			return myResult;
15508 		}
15509 		// !! reset the iterator
15510 		myIter->reset();
15511 
15512 		while ((myValue = myIter->getNextObject())) {
15513 			bool        myTempResult;
15514 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
15515 			if (myTempResult) {
15516 				// if we ever get a true result return true
15517 				myResult = true;
15518 				IOLOG_INDENT(indent);
15519 				IOLog("OSArray: \n");
15520 			}
15521 		}
15522 		// !! release the iterator
15523 		myIter.reset();
15524 	} else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
15525 		// should we look for addresses in strings?
15526 	} else if (myTypeID == OSTypeID(OSData)) {
15527 		void * *        myPtrPtr;
15528 		unsigned int    myLen;
15529 		OSData *        myDataObj;
15530 
15531 		myDataObj =    OSDynamicCast(OSData, theObject);
15532 		myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
15533 		myLen = myDataObj->getLength();
15534 
15535 		if (myPtrPtr && myLen && myLen > 7) {
15536 			int     i;
15537 			int     myPtrCount = (myLen / sizeof(void *));
15538 
15539 			for (i = 0; i < myPtrCount; i++) {
15540 				UInt64 numberValue = (UInt64) * (myPtrPtr);
15541 
15542 				if (kext_alloc_max != 0 &&
15543 				    numberValue >= kext_alloc_base &&
15544 				    numberValue < kext_alloc_max) {
15545 					OSSharedPtr<OSKext> myKext;
15546 					// IOLog("found OSData %p in kext map %p to %p  \n",
15547 					//       *(myPtrPtr),
15548 					//       (void *) kext_alloc_base,
15549 					//       (void *) kext_alloc_max);
15550 
15551 					myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
15552 					if (myKext) {
15553 						IOLog("found addr %p from an OSData obj within kext \"%s\"  \n",
15554 						    *(myPtrPtr),
15555 						    myKext->getIdentifierCString());
15556 					}
15557 					myResult = true;
15558 				}
15559 				if (vm_kernel_etext != 0 &&
15560 				    numberValue >= vm_kernel_stext &&
15561 				    numberValue < vm_kernel_etext) {
15562 					IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n",
15563 					    *(myPtrPtr),
15564 					    (void *) vm_kernel_stext,
15565 					    (void *) vm_kernel_etext);
15566 					myResult = true;
15567 				}
15568 				myPtrPtr++;
15569 			}
15570 		}
15571 	} else if (myTypeID == OSTypeID(OSBoolean)) {
15572 		// do nothing here...
15573 	} else if (myTypeID == OSTypeID(OSNumber)) {
15574 		OSNumber * number = OSDynamicCast(OSNumber, theObject);
15575 
15576 		UInt64 numberValue = number->unsigned64BitValue();
15577 
15578 		if (kext_alloc_max != 0 &&
15579 		    numberValue >= kext_alloc_base &&
15580 		    numberValue < kext_alloc_max) {
15581 			OSSharedPtr<OSKext> myKext;
15582 			IOLog("found OSNumber in kext map %p to %p  \n",
15583 			    (void *) kext_alloc_base,
15584 			    (void *) kext_alloc_max);
15585 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
15586 
15587 			myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
15588 			if (myKext) {
15589 				IOLog("found in kext \"%s\"  \n",
15590 				    myKext->getIdentifierCString());
15591 			}
15592 
15593 			myResult = true;
15594 		}
15595 		if (vm_kernel_etext != 0 &&
15596 		    numberValue >= vm_kernel_stext &&
15597 		    numberValue < vm_kernel_etext) {
15598 			IOLog("found OSNumber in kernel text segment %p to %p  \n",
15599 			    (void *) vm_kernel_stext,
15600 			    (void *) vm_kernel_etext);
15601 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
15602 			myResult = true;
15603 		}
15604 	}
15605 #if 0
15606 	else {
15607 		const OSMetaClass* myMetaClass = NULL;
15608 
15609 		myMetaClass = theObject->getMetaClass();
15610 		if (myMetaClass) {
15611 			IOLog("class %s \n", myMetaClass->getClassName());
15612 		} else {
15613 			IOLog("Unknown object \n" );
15614 		}
15615 	}
15616 #endif
15617 
15618 	return myResult;
15619 }
15620 #endif // KASLR_KEXT_DEBUG
15621 };         /* extern "C" */
15622 
15623 #if PRAGMA_MARK
15624 #pragma mark Backtrace Dump & kmod_get_info() support
15625 #endif
15626 /*********************************************************************
15627 * This function must be safe to call in panic context.
15628 *********************************************************************/
15629 /* static */
15630 void
15631 OSKext::printKextsInBacktrace(
15632 	vm_offset_t  * addr __unused,
15633 	unsigned int   cnt __unused,
15634 	int         (* printf_func)(const char *fmt, ...) __unused,
15635 	uint32_t       flags __unused)
15636 {
15637 	addr64_t    summary_page = 0;
15638 	addr64_t    last_summary_page = 0;
15639 
15640 	if (kPrintKextsLock & flags) {
15641 		if (!sKextSummariesLock) {
15642 			return;
15643 		}
15644 		IOLockLock(sKextSummariesLock);
15645 	}
15646 
15647 	if (!gLoadedKextSummaries) {
15648 		(*printf_func)("         can't perform kext scan: no kext summary");
15649 		goto finish;
15650 	}
15651 
15652 	summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
15653 	last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
15654 	for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
15655 		if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
15656 			(*printf_func)("         can't perform kext scan: "
15657 			    "missing kext summary page %p", summary_page);
15658 			goto finish;
15659 		}
15660 	}
15661 
15662 	foreachKextInBacktrace(addr, cnt, 0, ^(OSKextLoadedKextSummary *summary, uint32_t index) {
15663 		if (index == 0 && !(kPrintKextsTerse & flags)) {
15664 		        (*printf_func)("      Kernel Extensions in backtrace:\n");
15665 		}
15666 
15667 		printSummary(summary, printf_func, flags);
15668 	});
15669 
15670 finish:
15671 	if (kPrintKextsLock & flags) {
15672 		IOLockUnlock(sKextSummariesLock);
15673 	}
15674 
15675 	return;
15676 }
15677 
15678 void
15679 OSKext::foreachKextInBacktrace(
15680 	vm_offset_t   * addr,
15681 	uint32_t        cnt,
15682 	uint32_t        flags,
15683 	void         (^ handler)(OSKextLoadedKextSummary *summary, uint32_t index))
15684 {
15685 	uint32_t n = 0;
15686 
15687 	if (kPrintKextsLock & flags) {
15688 		if (!sKextSummariesLock) {
15689 			return;
15690 		}
15691 		IOLockLock(sKextSummariesLock);
15692 	}
15693 
15694 	for (uint32_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15695 		OSKextLoadedKextSummary * summary;
15696 
15697 		summary = gLoadedKextSummaries->summaries + i;
15698 		if (!summary->address) {
15699 			continue;
15700 		}
15701 
15702 		if (!summaryIsInBacktrace(summary, addr, cnt)) {
15703 			continue;
15704 		}
15705 
15706 		handler(summary, n++);
15707 	}
15708 
15709 	if (kPrintKextsLock & flags) {
15710 		IOLockUnlock(sKextSummariesLock);
15711 	}
15712 }
15713 
15714 /*********************************************************************
15715 * This function must be safe to call in panic context.
15716 *********************************************************************/
15717 /* static */
15718 boolean_t
15719 OSKext::summaryIsInBacktrace(
15720 	OSKextLoadedKextSummary   * summary,
15721 	vm_offset_t               * addr,
15722 	unsigned int                cnt)
15723 {
15724 	u_int i = 0;
15725 
15726 	for (i = 0; i < cnt; i++) {
15727 		vm_offset_t kscan_addr = addr[i];
15728 #if  __has_feature(ptrauth_calls)
15729 		kscan_addr = (vm_offset_t)VM_KERNEL_STRIP_PTR(kscan_addr);
15730 #endif /*  __has_feature(ptrauth_calls) */
15731 		if ((kscan_addr >= summary->text_exec_address) &&
15732 		    (kscan_addr < (summary->text_exec_address + summary->text_exec_size))) {
15733 			return TRUE;
15734 		}
15735 	}
15736 
15737 	return FALSE;
15738 }
15739 
15740 /*
15741  * Get the kext summary object for the kext where 'addr' lies. Must be called with
15742  * sKextSummariesLock held.
15743  */
15744 OSKextLoadedKextSummary *
15745 OSKext::summaryForAddress(uintptr_t addr)
15746 {
15747 #if  __has_feature(ptrauth_calls)
15748 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
15749 #endif /*  __has_feature(ptrauth_calls) */
15750 	for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15751 		OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
15752 		if (!summary->address) {
15753 			continue;
15754 		}
15755 
15756 #if VM_MAPPED_KEXTS
15757 		/* On our platforms that use VM_MAPPED_KEXTS, we currently do not
15758 		 * support split kexts, but we also may unmap the kexts, which can
15759 		 * race with the above codepath (see OSKext::unload).  As such,
15760 		 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
15761 		 */
15762 		if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
15763 			return summary;
15764 		}
15765 #else
15766 		kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
15767 		kernel_segment_command_t *seg;
15768 
15769 		for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
15770 			if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
15771 				return summary;
15772 			}
15773 		}
15774 #endif
15775 	}
15776 
15777 	/* addr did not map to any kext */
15778 	return NULL;
15779 }
15780 
15781 /* static */
15782 void *
15783 OSKext::kextForAddress(const void *address)
15784 {
15785 	OSKextActiveAccount * active;
15786 	OSKext              * kext = NULL;
15787 	uint32_t              baseIdx;
15788 	uint32_t              lim;
15789 	uintptr_t             addr = (uintptr_t) address;
15790 	size_t                i;
15791 
15792 	if (!addr) {
15793 		return NULL;
15794 	}
15795 #if  __has_feature(ptrauth_calls)
15796 	addr = (uintptr_t)VM_KERNEL_STRIP_PTR(addr);
15797 #endif /*  __has_feature(ptrauth_calls) */
15798 
15799 	if (sKextAccountsCount) {
15800 		lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
15801 		// bsearch sKextAccounts list
15802 		for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
15803 			active = &sKextAccounts[baseIdx + (lim >> 1)];
15804 			if ((addr >= active->address) && (addr < active->address_end)) {
15805 				if (active->account &&
15806 				    (kext = active->account->kext) &&
15807 				    kext->kmod_info) {
15808 					lck_ticket_unlock(sKextAccountsLock);
15809 					return (void *)kext->kmod_info->address;
15810 				}
15811 				break;
15812 			} else if (addr > active->address) {
15813 				// move right
15814 				baseIdx += (lim >> 1) + 1;
15815 				lim--;
15816 			}
15817 			// else move left
15818 		}
15819 		lck_ticket_unlock(sKextAccountsLock);
15820 	}
15821 	if (kernel_text_contains(addr)) {
15822 		return (void *)&_mh_execute_header;
15823 	}
15824 	if (gLoadedKextSummaries) {
15825 		IOLockLock(sKextSummariesLock);
15826 		for (i = 0; i < gLoadedKextSummaries->numSummaries; i++) {
15827 			OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
15828 			if (addr >= summary->address && addr < summary->address + summary->size) {
15829 				void *kextAddress = (void *)summary->address;
15830 				IOLockUnlock(sKextSummariesLock);
15831 				return kextAddress;
15832 			}
15833 		}
15834 		IOLockUnlock(sKextSummariesLock);
15835 	}
15836 
15837 	return NULL;
15838 }
15839 
15840 /* static */
15841 kern_return_t
15842 OSKext::summaryForAddressExt(
15843 	const void              * address,
15844 	OSKextLoadedKextSummary * summary)
15845 {
15846 	kern_return_t                   result = KERN_FAILURE;
15847 	const OSKextLoadedKextSummary * foundSummary = NULL;
15848 
15849 	/*
15850 	 * This needs to be safe to call even before the lock has been initialized
15851 	 * in OSKext::initialize(), as we might get here from the ksancov runtime
15852 	 * when instrumenting XNU itself with sanitizer coverage.
15853 	 */
15854 	if (!sKextSummariesLock) {
15855 		return result;
15856 	}
15857 
15858 	IOLockLock(sKextSummariesLock);
15859 	if (gLoadedKextSummaries) {
15860 		foundSummary = summaryForAddress((uintptr_t)address);
15861 		if (foundSummary) {
15862 			memcpy(summary, foundSummary, sizeof(*summary));
15863 			result = KERN_SUCCESS;
15864 		} else {
15865 			result = KERN_NOT_FOUND;
15866 		}
15867 	}
15868 	IOLockUnlock(sKextSummariesLock);
15869 
15870 	return result;
15871 }
15872 
15873 /*
15874  * Find a OSKextLoadedKextSummary given the ID from a kmod_info_t *
15875  * Safe to call in panic context.
15876  */
15877 static OSKextLoadedKextSummary *
15878 findSummary(uint32_t tagID)
15879 {
15880 	OSKextLoadedKextSummary * summary;
15881 	for (size_t i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
15882 		summary = gLoadedKextSummaries->summaries + i;
15883 		if (summary->loadTag == tagID) {
15884 			return summary;
15885 		}
15886 	}
15887 	return NULL;
15888 }
15889 
15890 /*********************************************************************
15891 * This function must be safe to call in panic context.
15892 *********************************************************************/
15893 void
15894 OSKext::printSummary(
15895 	OSKextLoadedKextSummary * summary,
15896 	int                    (* printf_func)(const char *fmt, ...),
15897 	uint32_t                  flags)
15898 {
15899 	kmod_reference_t * kmod_ref = NULL;
15900 	uuid_string_t uuid;
15901 	char version[kOSKextVersionMaxLength];
15902 	uint64_t tmpAddr;
15903 	uint64_t tmpSize;
15904 	OSKextLoadedKextSummary *dependencySummary;
15905 
15906 	if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
15907 		strlcpy(version, "unknown version", sizeof(version));
15908 	}
15909 	(void) uuid_unparse(summary->uuid, uuid);
15910 
15911 #if defined(__arm__) || defined(__arm64__)
15912 	tmpAddr = summary->text_exec_address;
15913 	tmpSize = summary->text_exec_size;
15914 #else
15915 	tmpAddr = summary->address;
15916 	tmpSize = summary->size;
15917 #endif
15918 	if (kPrintKextsUnslide & flags) {
15919 		tmpAddr = ml_static_unslide(tmpAddr);
15920 	}
15921 	(*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
15922 	    (kPrintKextsTerse & flags) ? "" : "         ",
15923 	    summary->name, version, uuid,
15924 	    tmpAddr, tmpAddr + tmpSize - 1);
15925 
15926 	if (kPrintKextsTerse & flags) {
15927 		return;
15928 	}
15929 
15930 	/* print dependency info */
15931 	for (kmod_ref = (kmod_reference_t *) summary->reference_list;
15932 	    kmod_ref;
15933 	    kmod_ref = kmod_ref->next) {
15934 		kmod_info_t * rinfo;
15935 
15936 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
15937 			(*printf_func)("            kmod dependency scan stopped "
15938 			    "due to missing dependency page: %p\n",
15939 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
15940 			break;
15941 		}
15942 		rinfo = kmod_ref->info;
15943 
15944 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
15945 			(*printf_func)("            kmod dependency scan stopped "
15946 			    "due to missing kmod page: %p\n",
15947 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
15948 			break;
15949 		}
15950 
15951 		if (!rinfo->address) {
15952 			continue;         // skip fake entries for built-ins
15953 		}
15954 
15955 		dependencySummary = findSummary(rinfo->id);
15956 		uuid[0] = 0x00;
15957 		tmpAddr = rinfo->address;
15958 		tmpSize = rinfo->size;
15959 		if (dependencySummary) {
15960 			(void) uuid_unparse(dependencySummary->uuid, uuid);
15961 #if defined(__arm__) || defined(__arm64__)
15962 			tmpAddr = dependencySummary->text_exec_address;
15963 			tmpSize = dependencySummary->text_exec_size;
15964 #endif
15965 		}
15966 
15967 		if (kPrintKextsUnslide & flags) {
15968 			tmpAddr = ml_static_unslide(tmpAddr);
15969 		}
15970 		(*printf_func)("            dependency: %s(%s)[%s]@%p->%p\n",
15971 		    rinfo->name, rinfo->version, uuid, tmpAddr, tmpAddr + tmpSize - 1);
15972 	}
15973 	return;
15974 }
15975 
15976 
15977 #if !defined(__arm__) && !defined(__arm64__)
15978 /*******************************************************************************
15979 * substitute() looks at an input string (a pointer within a larger buffer)
15980 * for a match to a substring, and on match it writes the marker & substitution
15981 * character to an output string, updating the scan (from) and
15982 * output (to) indexes as appropriate.
15983 *******************************************************************************/
15984 static int substitute(
15985 	const char * scan_string,
15986 	char       * string_out,
15987 	uint32_t   * to_index,
15988 	uint32_t   * from_index,
15989 	const char * substring,
15990 	char         marker,
15991 	char         substitution);
15992 
15993 /* string_out must be at least KMOD_MAX_NAME bytes.
15994  */
15995 static int
15996 substitute(
15997 	const char * scan_string,
15998 	char       * string_out,
15999 	uint32_t   * to_index,
16000 	uint32_t   * from_index,
16001 	const char * substring,
16002 	char         marker,
16003 	char         substitution)
16004 {
16005 	size_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
16006 
16007 	/* On a substring match, append the marker (if there is one) and then
16008 	 * the substitution character, updating the output (to) index accordingly.
16009 	 * Then update the input (from) length by the length of the substring
16010 	 * that got replaced.
16011 	 */
16012 	if (!strncmp(scan_string, substring, substring_length)) {
16013 		if (marker) {
16014 			string_out[(*to_index)++] = marker;
16015 		}
16016 		string_out[(*to_index)++] = substitution;
16017 		(*from_index) += substring_length;
16018 		return 1;
16019 	}
16020 	return 0;
16021 }
16022 
16023 /*******************************************************************************
16024 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
16025 * KMOD_MAX_NAME characters and performs various substitutions of common
16026 * prefixes & substrings as defined by tables in kext_panic_report.h.
16027 *******************************************************************************/
16028 static void compactIdentifier(
16029 	const char * identifier,
16030 	char       * identifier_out,
16031 	char      ** identifier_out_end);
16032 
16033 static void
16034 compactIdentifier(
16035 	const char * identifier,
16036 	char       * identifier_out,
16037 	char      ** identifier_out_end)
16038 {
16039 	uint32_t       from_index, to_index;
16040 	uint32_t       scan_from_index = 0;
16041 	uint32_t       scan_to_index   = 0;
16042 	subs_entry_t * subs_entry    = NULL;
16043 	int            did_sub       = 0;
16044 
16045 	from_index = to_index = 0;
16046 	identifier_out[0] = '\0';
16047 
16048 	/* Replace certain identifier prefixes with shorter @+character sequences.
16049 	 * Check the return value of substitute() so we only replace the prefix.
16050 	 */
16051 	for (subs_entry = &kext_identifier_prefix_subs[0];
16052 	    subs_entry->substring && !did_sub;
16053 	    subs_entry++) {
16054 		did_sub = substitute(identifier, identifier_out,
16055 		    &scan_to_index, &scan_from_index,
16056 		    subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
16057 	}
16058 	did_sub = 0;
16059 
16060 	/* Now scan through the identifier looking for the common substrings
16061 	 * and replacing them with shorter !+character sequences via substitute().
16062 	 */
16063 	for (/* see above */;
16064 	    scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
16065 	    /* see loop */) {
16066 		const char   * scan_string = &identifier[scan_from_index];
16067 
16068 		did_sub = 0;
16069 
16070 		if (scan_from_index) {
16071 			for (subs_entry = &kext_identifier_substring_subs[0];
16072 			    subs_entry->substring && !did_sub;
16073 			    subs_entry++) {
16074 				did_sub = substitute(scan_string, identifier_out,
16075 				    &scan_to_index, &scan_from_index,
16076 				    subs_entry->substring, '!', subs_entry->substitute);
16077 			}
16078 		}
16079 
16080 		/* If we didn't substitute, copy the input character to the output.
16081 		 */
16082 		if (!did_sub) {
16083 			identifier_out[scan_to_index++] = identifier[scan_from_index++];
16084 		}
16085 	}
16086 
16087 	identifier_out[scan_to_index] = '\0';
16088 	if (identifier_out_end) {
16089 		*identifier_out_end = &identifier_out[scan_to_index];
16090 	}
16091 
16092 	return;
16093 }
16094 #endif /* !defined(__arm__) && !defined(__arm64__) */
16095 
16096 /*******************************************************************************
16097 * assemble_identifier_and_version() adds to a string buffer a compacted
16098 * bundle identifier followed by a version string.
16099 *******************************************************************************/
16100 
16101 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
16102  */
16103 static size_t assemble_identifier_and_version(
16104 	kmod_info_t * kmod_info,
16105 	char        * identPlusVers,
16106 	size_t        bufSize);
16107 
16108 static size_t
16109 assemble_identifier_and_version(
16110 	kmod_info_t * kmod_info,
16111 	char        * identPlusVers,
16112 	size_t        bufSize)
16113 {
16114 	size_t result = 0;
16115 
16116 #if defined(__arm__) || defined(__arm64__)
16117 	result = strlcpy(identPlusVers, kmod_info->name, KMOD_MAX_NAME);
16118 #else
16119 	compactIdentifier(kmod_info->name, identPlusVers, NULL);
16120 	result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
16121 #endif
16122 	identPlusVers[result++] = '\t';         // increment for real char
16123 	identPlusVers[result] = '\0';         // don't increment for nul char
16124 	result = strlcat(identPlusVers, kmod_info->version, bufSize);
16125 	if (result >= bufSize) {
16126 		identPlusVers[bufSize - 1] = '\0';
16127 		result = bufSize - 1;
16128 	}
16129 
16130 	return result;
16131 }
16132 
16133 /*******************************************************************************
16134 * Assumes sKextLock is held.
16135 *******************************************************************************/
16136 /* static */
16137 int
16138 OSKext::saveLoadedKextPanicListTyped(
16139 	const char * prefix,
16140 	int          invertFlag,
16141 	int          libsFlag,
16142 	char       * paniclist,
16143 	uint32_t     list_size)
16144 {
16145 	int             result = -1;
16146 	unsigned int    count, i;
16147 
16148 	count = sLoadedKexts->getCount();
16149 	if (!count) {
16150 		goto finish;
16151 	}
16152 
16153 	i = count - 1;
16154 	do {
16155 		OSObject    * rawKext = sLoadedKexts->getObject(i);
16156 		OSKext      * theKext = OSDynamicCast(OSKext, rawKext);
16157 		int           match;
16158 		size_t        identPlusVersLength;
16159 		size_t        tempLen;
16160 		char          identPlusVers[2 * KMOD_MAX_NAME];
16161 
16162 		if (!rawKext) {
16163 			printf("OSKext::saveLoadedKextPanicListTyped - "
16164 			    "NULL kext in loaded kext list; continuing\n");
16165 			continue;
16166 		}
16167 
16168 		if (!theKext) {
16169 			printf("OSKext::saveLoadedKextPanicListTyped - "
16170 			    "Kext type cast failed in loaded kext list; continuing\n");
16171 			continue;
16172 		}
16173 
16174 		/* Skip all built-in kexts.
16175 		 */
16176 		if (theKext->isKernelComponent()) {
16177 			continue;
16178 		}
16179 
16180 		kmod_info_t * kmod_info = theKext->kmod_info;
16181 
16182 		/* Filter for kmod name (bundle identifier).
16183 		 */
16184 		match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
16185 		if ((match && invertFlag) || (!match && !invertFlag)) {
16186 			continue;
16187 		}
16188 
16189 		/* Filter for libraries (kexts that have a compatible version).
16190 		 */
16191 		if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
16192 		    (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
16193 			continue;
16194 		}
16195 
16196 		if (!kmod_info ||
16197 		    !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
16198 			printf("kext scan stopped due to missing kmod_info page: %p\n",
16199 			    kmod_info);
16200 			goto finish;
16201 		}
16202 
16203 		identPlusVersLength = assemble_identifier_and_version(kmod_info,
16204 		    identPlusVers,
16205 		    sizeof(identPlusVers));
16206 		if (!identPlusVersLength) {
16207 			printf("error saving loaded kext info\n");
16208 			goto finish;
16209 		}
16210 
16211 		/* make sure everything fits and we null terminate.
16212 		 */
16213 		tempLen = strlcat(paniclist, identPlusVers, list_size);
16214 		if (tempLen >= list_size) {
16215 			// panic list is full, keep it and null terminate
16216 			paniclist[list_size - 1] = 0x00;
16217 			result = 0;
16218 			goto finish;
16219 		}
16220 		tempLen = strlcat(paniclist, "\n", list_size);
16221 		if (tempLen >= list_size) {
16222 			// panic list is full, keep it and null terminate
16223 			paniclist[list_size - 1] = 0x00;
16224 			result = 0;
16225 			goto finish;
16226 		}
16227 	} while (i--);
16228 
16229 	result = 0;
16230 finish:
16231 
16232 	return result;
16233 }
16234 
16235 /*********************************************************************
16236 *********************************************************************/
16237 /* static */
16238 void
16239 OSKext::saveLoadedKextPanicList(void)
16240 {
16241 	char     * newlist        = NULL;
16242 	uint32_t   newlist_size   = 0;
16243 
16244 	newlist_size = KEXT_PANICLIST_SIZE;
16245 	newlist = (char *)kalloc_data_tag(newlist_size,
16246 	    Z_WAITOK, VM_KERN_MEMORY_OSKEXT);
16247 
16248 	if (!newlist) {
16249 		OSKextLog(/* kext */ NULL,
16250 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
16251 		    "Couldn't allocate kext panic log buffer.");
16252 		goto finish;
16253 	}
16254 
16255 	newlist[0] = '\0';
16256 
16257 	// non-"com.apple." kexts
16258 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
16259 	    /* libs? */ -1, newlist, newlist_size) != 0) {
16260 		goto finish;
16261 	}
16262 	// "com.apple." nonlibrary kexts
16263 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
16264 	    /* libs? */ 0, newlist, newlist_size) != 0) {
16265 		goto finish;
16266 	}
16267 	// "com.apple." library kexts
16268 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
16269 	    /* libs? */ 1, newlist, newlist_size) != 0) {
16270 		goto finish;
16271 	}
16272 
16273 	if (loaded_kext_paniclist) {
16274 		kfree_data(loaded_kext_paniclist, loaded_kext_paniclist_size);
16275 	}
16276 	loaded_kext_paniclist = newlist;
16277 	newlist = NULL;
16278 	loaded_kext_paniclist_size = newlist_size;
16279 
16280 finish:
16281 	if (newlist) {
16282 		kfree_data(newlist, newlist_size);
16283 	}
16284 	return;
16285 }
16286 
16287 /*********************************************************************
16288 * Assumes sKextLock is held.
16289 *********************************************************************/
16290 void
16291 OSKext::savePanicString(bool isLoading)
16292 {
16293 	u_long len;
16294 
16295 	if (!kmod_info) {
16296 		return;         // do not goto finish here b/c of lock
16297 	}
16298 
16299 	len = assemble_identifier_and_version( kmod_info,
16300 	    (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
16301 	    (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
16302 	if (!len) {
16303 		printf("error saving unloaded kext info\n");
16304 		goto finish;
16305 	}
16306 
16307 	if (isLoading) {
16308 		last_loaded_strlen = len;
16309 		last_loaded_address = (void *)kmod_info->address;
16310 		last_loaded_size = kmod_info->size;
16311 		clock_get_uptime(&last_loaded_timestamp);
16312 	} else {
16313 		last_unloaded_strlen = len;
16314 		last_unloaded_address = (void *)kmod_info->address;
16315 		last_unloaded_size = kmod_info->size;
16316 		clock_get_uptime(&last_unloaded_timestamp);
16317 	}
16318 
16319 finish:
16320 	return;
16321 }
16322 
16323 /*********************************************************************
16324 *********************************************************************/
16325 /* static */
16326 void
16327 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
16328 {
16329 	if (last_loaded_strlen) {
16330 		printf_func("last started kext at %llu: %.*s (addr %p, size %lu)\n",
16331 		    AbsoluteTime_to_scalar(&last_loaded_timestamp),
16332 		    last_loaded_strlen, last_loaded_str_buf,
16333 		    last_loaded_address, last_loaded_size);
16334 	}
16335 
16336 	if (last_unloaded_strlen) {
16337 		printf_func("last stopped kext at %llu: %.*s (addr %p, size %lu)\n",
16338 		    AbsoluteTime_to_scalar(&last_unloaded_timestamp),
16339 		    last_unloaded_strlen, last_unloaded_str_buf,
16340 		    last_unloaded_address, last_unloaded_size);
16341 	}
16342 
16343 	printf_func("loaded kexts:\n");
16344 	if (loaded_kext_paniclist &&
16345 	    pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
16346 	    loaded_kext_paniclist[0]) {
16347 		printf_func("%.*s",
16348 		    strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
16349 		    loaded_kext_paniclist);
16350 	} else {
16351 		printf_func("(none)\n");
16352 	}
16353 	return;
16354 }
16355 
16356 /*********************************************************************
16357 * Assumes sKextLock is held.
16358 *********************************************************************/
16359 /* static */
16360 void
16361 OSKext::updateLoadedKextSummaries(void)
16362 {
16363 	kern_return_t result = KERN_FAILURE;
16364 	OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
16365 	OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
16366 	OSKext *aKext;
16367 	vm_map_offset_t start;
16368 	size_t summarySize = 0;
16369 	size_t size;
16370 	u_int count;
16371 	u_int maxKexts;
16372 	u_int i, j;
16373 	OSKextActiveAccount * accountingList;
16374 	OSKextActiveAccount * prevAccountingList;
16375 	uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
16376 
16377 	prevAccountingList = NULL;
16378 	prevAccountingListCount = 0;
16379 
16380 #if DEVELOPMENT || DEBUG
16381 	if (IORecursiveLockHaveLock(sKextLock) == false) {
16382 		panic("sKextLock must be held");
16383 	}
16384 #endif
16385 
16386 	IOLockLock(sKextSummariesLock);
16387 
16388 	count = sLoadedKexts->getCount();
16389 	for (i = 0, maxKexts = 0; i < count; ++i) {
16390 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16391 		maxKexts += (aKext && (aKext->isExecutable() || aKext->isSpecialKernelBinary()));
16392 	}
16393 
16394 	if (!maxKexts) {
16395 		goto finish;
16396 	}
16397 	if (maxKexts < kOSKextTypicalLoadCount) {
16398 		maxKexts = kOSKextTypicalLoadCount;
16399 	}
16400 
16401 	/* Calculate the size needed for the new summary headers.
16402 	 */
16403 
16404 	size = sizeof(*gLoadedKextSummaries);
16405 	size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
16406 	size = round_page(size);
16407 
16408 	if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
16409 		if (gLoadedKextSummaries) {
16410 			kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
16411 			gLoadedKextSummaries = NULL;
16412 			gLoadedKextSummariesTimestamp = mach_absolute_time();
16413 			sLoadedKextSummariesAllocSize = 0;
16414 		}
16415 		result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size,
16416 		    KMA_DATA, VM_KERN_MEMORY_OSKEXT);
16417 		if (result != KERN_SUCCESS) {
16418 			goto finish;
16419 		}
16420 		summaryHeader = summaryHeaderAlloc;
16421 		summarySize = size;
16422 	} else {
16423 		summaryHeader = gLoadedKextSummaries;
16424 		summarySize = sLoadedKextSummariesAllocSize;
16425 
16426 		start = (vm_map_offset_t) summaryHeader;
16427 		result = mach_vm_protect(kernel_map,
16428 		    start,
16429 		    summarySize,
16430 		    false,
16431 		    VM_PROT_DEFAULT);
16432 		if (result != KERN_SUCCESS) {
16433 			goto finish;
16434 		}
16435 	}
16436 
16437 	/* Populate the summary header.
16438 	 */
16439 
16440 	bzero(summaryHeader, summarySize);
16441 	summaryHeader->version = kOSKextLoadedKextSummaryVersion;
16442 	summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
16443 
16444 	/* Populate each kext summary.
16445 	 */
16446 
16447 	count = sLoadedKexts->getCount();
16448 	accountingListAlloc = 0;
16449 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
16450 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16451 		if (!aKext || (!aKext->isExecutable() && !aKext->isSpecialKernelBinary())) {
16452 			continue;
16453 		}
16454 
16455 		aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
16456 		summaryHeader->numSummaries++;
16457 		accountingListAlloc++;
16458 	}
16459 
16460 	accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
16461 	accountingListCount = 0;
16462 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
16463 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
16464 		if (!aKext || (!aKext->isExecutable() && !aKext->isSpecialKernelBinary())) {
16465 			continue;
16466 		}
16467 
16468 		OSKextActiveAccount activeAccount;
16469 		aKext->updateActiveAccount(&activeAccount);
16470 		// order by address
16471 		for (idx = 0; idx < accountingListCount; idx++) {
16472 			if (activeAccount.address < accountingList[idx].address) {
16473 				break;
16474 			}
16475 		}
16476 		bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
16477 		accountingList[idx] = activeAccount;
16478 		accountingListCount++;
16479 	}
16480 	assert(accountingListCount == accountingListAlloc);
16481 	/* Write protect the buffer and move it into place.
16482 	 */
16483 
16484 	start = (vm_map_offset_t) summaryHeader;
16485 
16486 	result = mach_vm_protect(kernel_map, start, summarySize, false, VM_PROT_READ);
16487 	if (result != KERN_SUCCESS) {
16488 		goto finish;
16489 	}
16490 
16491 	gLoadedKextSummaries = summaryHeader;
16492 	gLoadedKextSummariesTimestamp = mach_absolute_time();
16493 	sLoadedKextSummariesAllocSize = summarySize;
16494 	summaryHeaderAlloc = NULL;
16495 
16496 	/* Call the magic breakpoint function through a static function pointer so
16497 	 * the compiler can't optimize the function away.
16498 	 */
16499 	if (sLoadedKextSummariesUpdated) {
16500 		(*sLoadedKextSummariesUpdated)();
16501 	}
16502 
16503 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16504 	prevAccountingList      = sKextAccounts;
16505 	prevAccountingListCount = sKextAccountsCount;
16506 	sKextAccounts           = accountingList;
16507 	sKextAccountsCount      = accountingListCount;
16508 	lck_ticket_unlock(sKextAccountsLock);
16509 
16510 finish:
16511 	IOLockUnlock(sKextSummariesLock);
16512 
16513 	/* If we had to allocate a new buffer but failed to generate the summaries,
16514 	 * free that now.
16515 	 */
16516 	if (summaryHeaderAlloc) {
16517 		kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
16518 	}
16519 	if (prevAccountingList) {
16520 		IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
16521 	}
16522 
16523 	return;
16524 }
16525 
16526 /*********************************************************************
16527 *********************************************************************/
16528 void
16529 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
16530 {
16531 	OSSharedPtr<OSData> uuid;
16532 
16533 	strlcpy(summary->name, getIdentifierCString(),
16534 	    sizeof(summary->name));
16535 
16536 	uuid = copyUUID();
16537 	if (uuid) {
16538 		memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
16539 	}
16540 
16541 	if (flags.builtin) {
16542 //      this value will stop lldb from parsing the mach-o header
16543 //      summary->address = UINT64_MAX;
16544 //      summary->size = 0;
16545 		summary->address = kmod_info->address;
16546 		summary->size = kmod_info->size;
16547 	} else {
16548 		summary->address = kmod_info->address;
16549 		summary->size = kmod_info->size;
16550 	}
16551 	summary->version = getVersion();
16552 	summary->loadTag = kmod_info->id;
16553 	summary->flags = 0;
16554 	summary->reference_list = (uint64_t) kmod_info->reference_list;
16555 
16556 	summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT_EXEC", &summary->text_exec_size);
16557 	if (summary->text_exec_address == 0) {
16558 		// Fallback to __TEXT
16559 		summary->text_exec_address = (uint64_t) getsegdatafromheader((kernel_mach_header_t *)summary->address, "__TEXT", &summary->text_exec_size);
16560 	}
16561 
16562 	/**
16563 	 * If the addresses within the Mach-O are unslid, then manually slide any
16564 	 * addresses coming from the Mach-O as higher layer software using these
16565 	 * summaries expects a slid address here.
16566 	 */
16567 	if (flags.unslidMachO) {
16568 		summary->text_exec_address = (uint64_t) ml_static_slide((vm_offset_t) summary->text_exec_address);
16569 	}
16570 
16571 	return;
16572 }
16573 
16574 /*********************************************************************
16575 *********************************************************************/
16576 
16577 void
16578 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
16579 {
16580 	kernel_mach_header_t     *hdr = NULL;
16581 	kernel_segment_command_t *seg = NULL;
16582 
16583 	bzero(accountp, sizeof(*accountp));
16584 
16585 	hdr = (kernel_mach_header_t *)kmod_info->address;
16586 	if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO) || isInFileset()) {
16587 		/*
16588 		 * If this kext supports split segments (or is in a new
16589 		 * MH_FILESET kext collection), use the first
16590 		 * executable segment as the range for instructions
16591 		 * (and thus for backtracing.
16592 		 */
16593 		for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
16594 			if (seg->initprot & VM_PROT_EXECUTE) {
16595 				break;
16596 			}
16597 		}
16598 	}
16599 	if (seg) {
16600 		accountp->address = seg->vmaddr;
16601 		if (accountp->address) {
16602 			accountp->address_end = seg->vmaddr + seg->vmsize;
16603 		}
16604 	} else {
16605 		/* For non-split kexts and for kexts without executable
16606 		 * segments, just use the kmod_info range (as the kext
16607 		 * is either all in one range or should not show up in
16608 		 * instruction backtraces).
16609 		 */
16610 		accountp->address = kmod_info->address;
16611 		if (accountp->address) {
16612 			accountp->address_end = kmod_info->address + kmod_info->size;
16613 		}
16614 	}
16615 
16616 	accountp->account = this->account;
16617 }
16618 
16619 bool
16620 OSKext::isDriverKit(void)
16621 {
16622 	OSString *bundleType;
16623 
16624 	if (infoDict) {
16625 		bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey));
16626 		if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) {
16627 			return TRUE;
16628 		}
16629 	}
16630 	return FALSE;
16631 }
16632 
16633 bool
16634 OSKext::isInFileset(void)
16635 {
16636 	if (!kmod_info) {
16637 		goto check_prelinked;
16638 	}
16639 
16640 	if (kmod_info->address && kernel_mach_header_is_in_fileset((kernel_mach_header_t *)kmod_info->address)) {
16641 		return true;
16642 	}
16643 
16644 check_prelinked:
16645 	if (isPrelinked()) {
16646 		/*
16647 		 * If we haven't setup kmod_info yet, but we know
16648 		 * we're loading a prelinked kext in an MH_FILESET KC,
16649 		 * then return true
16650 		 */
16651 		kc_format_t kc_format;
16652 		if (PE_get_primary_kc_format(&kc_format) && kc_format == KCFormatFileset) {
16653 			return true;
16654 		}
16655 	}
16656 	return false;
16657 }
16658 
16659 OSSharedPtr<OSDextStatistics>
16660 OSKext::copyDextStatistics(void)
16661 {
16662 	return dextStatistics;
16663 }
16664 
16665 bool
16666 OSKextSavedMutableSegment::initWithSegment(kernel_segment_command_t *seg)
16667 {
16668 	kern_return_t result;
16669 	if (!super::init()) {
16670 		return false;
16671 	}
16672 	if (seg == nullptr) {
16673 		return false;
16674 	}
16675 	result = kmem_alloc(kernel_map, (vm_offset_t *)&data, seg->vmsize,
16676 	    KMA_PAGEABLE, VM_KERN_MEMORY_KEXT);
16677 	if (result != KERN_SUCCESS) {
16678 		return false;
16679 	}
16680 	memcpy((void *)data, (const void *)seg->vmaddr, seg->vmsize);
16681 	savedSegment = seg;
16682 	vmsize = seg->vmsize;
16683 	vmaddr = seg->vmaddr;
16684 	return true;
16685 }
16686 
16687 OSSharedPtr<OSKextSavedMutableSegment>
16688 OSKextSavedMutableSegment::withSegment(kernel_segment_command_t *seg)
16689 {
16690 	OSSharedPtr<OSKextSavedMutableSegment> me = OSMakeShared<OSKextSavedMutableSegment>();
16691 	if (me && !me->initWithSegment(seg)) {
16692 		return nullptr;
16693 	}
16694 	return me;
16695 }
16696 
16697 void
16698 OSKextSavedMutableSegment::free(void)
16699 {
16700 	if (data) {
16701 		kmem_free(kernel_map, (vm_offset_t)data, vmsize);
16702 	}
16703 }
16704 
16705 vm_offset_t
16706 OSKextSavedMutableSegment::getVMAddr() const
16707 {
16708 	return vmaddr;
16709 }
16710 
16711 vm_offset_t
16712 OSKextSavedMutableSegment::getVMSize() const
16713 {
16714 	return vmsize;
16715 }
16716 
16717 OSReturn
16718 OSKextSavedMutableSegment::restoreContents(kernel_segment_command_t *seg)
16719 {
16720 	if (seg != savedSegment) {
16721 		return kOSKextReturnInvalidArgument;
16722 	}
16723 	if (seg->vmaddr != vmaddr || seg->vmsize != vmsize) {
16724 		return kOSKextReturnInvalidArgument;
16725 	}
16726 	memcpy((void *)seg->vmaddr, data, vmsize);
16727 	return kOSReturnSuccess;
16728 }
16729 
16730 extern "C" kern_return_t
16731 OSKextSetReceiptQueried(void)
16732 {
16733 	OSKextLog(/* kext */ NULL,
16734 	    kOSKextLogStepLevel | kOSKextLogGeneralFlag,
16735 	    "Setting kext receipt as queried");
16736 
16737 	IOService::publishResource(kOSKextReceiptQueried, kOSBooleanTrue);
16738 	return KERN_SUCCESS;
16739 }
16740 
16741 extern "C" const vm_allocation_site_t *
16742 OSKextGetAllocationSiteForCaller(uintptr_t address)
16743 {
16744 	OSKextActiveAccount *  active;
16745 	vm_allocation_site_t * site;
16746 	vm_allocation_site_t * releasesite;
16747 
16748 	uint32_t baseIdx;
16749 	uint32_t lim;
16750 #if  __has_feature(ptrauth_calls)
16751 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
16752 #endif /*  __has_feature(ptrauth_calls) */
16753 
16754 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16755 	site = releasesite = NULL;
16756 
16757 	// bsearch sKextAccounts list
16758 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
16759 		active = &sKextAccounts[baseIdx + (lim >> 1)];
16760 		if ((address >= active->address) && (address < active->address_end)) {
16761 			site = &active->account->site;
16762 			if (!site->tag) {
16763 				vm_tag_alloc_locked(site, &releasesite);
16764 			}
16765 			break;
16766 		} else if (address > active->address) {
16767 			// move right
16768 			baseIdx += (lim >> 1) + 1;
16769 			lim--;
16770 		}
16771 		// else move left
16772 	}
16773 	lck_ticket_unlock(sKextAccountsLock);
16774 	if (releasesite) {
16775 		kern_allocation_name_release(releasesite);
16776 	}
16777 
16778 	return site;
16779 }
16780 
16781 #if DEVELOPMENT || DEBUG
16782 extern "C" void
16783 OSKextGetRefGrpForCaller(uintptr_t address, void (^cb)(struct os_refgrp *))
16784 {
16785 	OSKextActiveAccount *  active;
16786 
16787 	uint32_t baseIdx;
16788 	uint32_t lim;
16789 #if  __has_feature(ptrauth_calls)
16790 	address = (uintptr_t)VM_KERNEL_STRIP_PTR(address);
16791 #endif /*  __has_feature(ptrauth_calls) */
16792 
16793 	lck_ticket_lock(sKextAccountsLock, sKextAccountsLockGrp);
16794 
16795 	// bsearch sKextAccounts list
16796 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
16797 		active = &sKextAccounts[baseIdx + (lim >> 1)];
16798 		if ((address >= active->address) && (address < active->address_end)) {
16799 			cb(&active->account->task_refgrp);
16800 			break;
16801 		} else if (address > active->address) {
16802 			// move right
16803 			baseIdx += (lim >> 1) + 1;
16804 			lim--;
16805 		}
16806 		// else move left
16807 	}
16808 	lck_ticket_unlock(sKextAccountsLock);
16809 }
16810 #endif /* DEVELOPMENT || DEBUG */
16811 
16812 extern "C" uint32_t
16813 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
16814 {
16815 	OSKextAccount * account = (typeof(account))site;
16816 	const char    * kname;
16817 
16818 	if (name) {
16819 		if (account->kext) {
16820 			kname = account->kext->getIdentifierCString();
16821 		} else {
16822 			kname = "<>";
16823 		}
16824 		strlcpy(name, kname, namelen);
16825 	}
16826 
16827 	return account->loadTag;
16828 }
16829 
16830 extern "C" void
16831 OSKextFreeSite(vm_allocation_site_t * site)
16832 {
16833 	OSKextAccount * freeAccount = (typeof(freeAccount))site;
16834 	IOFreeType(freeAccount, OSKextAccount);
16835 }
16836 
16837 /*********************************************************************
16838 *********************************************************************/
16839 
16840 #if CONFIG_IMAGEBOOT
16841 int
16842 OSKextGetUUIDForName(const char *name, uuid_t uuid)
16843 {
16844 	OSSharedPtr<OSKext> kext = OSKext::lookupKextWithIdentifier(name);
16845 	if (!kext) {
16846 		return 1;
16847 	}
16848 
16849 	OSSharedPtr<OSData> uuid_data = kext->copyUUID();
16850 	if (uuid_data) {
16851 		memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
16852 		return 0;
16853 	}
16854 
16855 	return 1;
16856 }
16857 #endif
16858 
16859 
16860 
16861 class OSDextCrash : public OSObject {
16862 	OSDeclareDefaultStructors(OSDextCrash);
16863 public:
16864 	static OSPtr<OSDextCrash> withTimestamp(uint64_t timestamp);
16865 	uint64_t getTimestamp();
16866 
16867 private:
16868 	virtual bool initWithTimestamp(uint64_t timestamp);
16869 	uint64_t fTimestamp;
16870 };
16871 
16872 OSDefineMetaClassAndStructors(OSDextCrash, OSObject);
16873 
16874 OSSharedPtr<OSDextCrash>
16875 OSDextCrash::withTimestamp(uint64_t timestamp)
16876 {
16877 	OSSharedPtr<OSDextCrash> result = OSMakeShared<OSDextCrash>();
16878 	if (!result->initWithTimestamp(timestamp)) {
16879 		return NULL;
16880 	}
16881 	return result;
16882 }
16883 
16884 bool
16885 OSDextCrash::initWithTimestamp(uint64_t timestamp)
16886 {
16887 	if (!OSObject::init()) {
16888 		return false;
16889 	}
16890 	fTimestamp = timestamp;
16891 	return true;
16892 }
16893 
16894 uint64_t
16895 OSDextCrash::getTimestamp()
16896 {
16897 	return fTimestamp;
16898 }
16899 
16900 OSSharedPtr<OSDextStatistics>
16901 OSDextStatistics::create()
16902 {
16903 	OSSharedPtr<OSDextStatistics> result = OSMakeShared<OSDextStatistics>();
16904 	if (!result->init()) {
16905 		return NULL;
16906 	}
16907 	return result;
16908 }
16909 
16910 bool
16911 OSDextStatistics::init()
16912 {
16913 	if (!OSObject::init()) {
16914 		return false;
16915 	}
16916 
16917 	lock = IOLockAlloc();
16918 	crashes = OSArray::withCapacity(kMaxDextCrashesInOneDay);
16919 	return true;
16920 }
16921 
16922 void
16923 OSDextStatistics::free()
16924 {
16925 	if (lock) {
16926 		IOLockFree(lock);
16927 	}
16928 	crashes.reset();
16929 	OSObject::free();
16930 }
16931 
16932 OSDextCrashPolicy
16933 OSDextStatistics::recordCrash()
16934 {
16935 	size_t i = 0;
16936 	uint64_t timestamp = mach_continuous_time();
16937 	uint64_t interval;
16938 	nanoseconds_to_absolutetime(86400 * NSEC_PER_SEC /* 1 day */, &interval);
16939 	uint64_t lastTimestamp = timestamp > interval ? timestamp - interval : 0;
16940 	OSDextCrashPolicy policy;
16941 
16942 	IOLockLock(lock);
16943 	OSSharedPtr<OSDextCrash> crash = OSDextCrash::withTimestamp(timestamp);
16944 	for (i = 0; i < crashes->getCount();) {
16945 		OSDextCrash * current = OSDynamicCast(OSDextCrash, crashes->getObject(i));
16946 		assert(current != NULL);
16947 		if (current->getTimestamp() < lastTimestamp) {
16948 			crashes->removeObject(i);
16949 		} else {
16950 			i++;
16951 		}
16952 	}
16953 
16954 	crashes->setObject(crash);
16955 
16956 	if (crashes->getCount() > kMaxDextCrashesInOneDay) {
16957 		policy = kOSDextCrashPolicyReboot;
16958 	} else {
16959 		policy = kOSDextCrashPolicyNone;
16960 	}
16961 
16962 	IOLockUnlock(lock);
16963 
16964 	return policy;
16965 }
16966 
16967 size_t
16968 OSDextStatistics::getCrashCount()
16969 {
16970 	size_t result = 0;
16971 	IOLockLock(lock);
16972 	result = crashes->getCount();
16973 	IOLockUnlock(lock);
16974 	return result;
16975 }
16976 
16977 static int
16978 sysctl_willuserspacereboot
16979 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
16980 {
16981 	int new_value = 0, old_value = 0, changed = 0;
16982 	int error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
16983 	if (error) {
16984 		return error;
16985 	}
16986 	if (changed) {
16987 		OSKext::willUserspaceReboot();
16988 	}
16989 	return 0;
16990 }
16991 
16992 static SYSCTL_PROC(_kern, OID_AUTO, willuserspacereboot,
16993     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
16994     NULL, 0, sysctl_willuserspacereboot, "I", "");
16995