xref: /xnu-11215/libkern/c++/OSKext.cpp (revision a5e72196)
1 /*
2  * Copyright (c) 2008-2016 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 extern "C" {
30 #include <string.h>
31 #include <kern/clock.h>
32 #include <kern/host.h>
33 #include <kern/kext_alloc.h>
34 #include <firehose/tracepoint_private.h>
35 #include <firehose/chunk_private.h>
36 #include <os/firehose_buffer_private.h>
37 #include <vm/vm_kern.h>
38 #include <kextd/kextd_mach.h>
39 #include <libkern/kernel_mach_header.h>
40 #include <libkern/kext_panic_report.h>
41 #include <libkern/kext_request_keys.h>
42 #include <libkern/mkext.h>
43 #include <libkern/prelink.h>
44 #include <libkern/version.h>
45 #include <libkern/zlib.h>
46 #include <mach/host_special_ports.h>
47 #include <mach/mach_vm.h>
48 #include <mach/mach_time.h>
49 #include <sys/sysctl.h>
50 #include <uuid/uuid.h>
51 #include <sys/random.h>
52 
53 #include <sys/pgo.h>
54 
55 #if CONFIG_MACF
56 #include <sys/kauth.h>
57 #include <security/mac_framework.h>
58 #endif
59 };
60 
61 #include <libkern/OSKextLibPrivate.h>
62 #include <libkern/c++/OSKext.h>
63 #include <libkern/c++/OSLib.h>
64 
65 #include <IOKit/IOLib.h>
66 #include <IOKit/IOCatalogue.h>
67 #include <IOKit/IORegistryEntry.h>
68 #include <IOKit/IOService.h>
69 
70 #include <IOKit/IOStatisticsPrivate.h>
71 #include <IOKit/IOBSD.h>
72 
73 #include <san/kasan.h>
74 
75 #if PRAGMA_MARK
76 #pragma mark External & Internal Function Protos
77 #endif
78 /*********************************************************************
79 *********************************************************************/
80 extern "C" {
81 extern int  IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
82 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
83 
84 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
85 extern int dtrace_keep_kernel_symbols(void);
86 }
87 
88 extern unsigned long gVirtBase;
89 extern unsigned long gPhysBase;
90 #if CONFIG_EMBEDDED
91 extern vm_offset_t   segLOWESTTEXT;
92 #endif /* CONFIG_EMBEDDED */
93 
94 static OSReturn _OSKextCreateRequest(
95 	const char    * predicate,
96 	OSDictionary ** requestP);
97 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
98 static OSObject * _OSKextGetRequestArgument(
99 	OSDictionary * requestDict,
100 	const char   * argName);
101 static bool _OSKextSetRequestArgument(
102 	OSDictionary * requestDict,
103 	const char   * argName,
104 	OSObject     * value);
105 static void * _OSKextExtractPointer(OSData * wrapper);
106 static OSReturn _OSDictionarySetCStringValue(
107 	OSDictionary * dict,
108 	const char   * key,
109 	const char   * value);
110 static bool _OSKextInPrelinkRebuildWindow(void);
111 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
112 
113 // We really should add containsObject() & containsCString to OSCollection & subclasses.
114 // So few pad slots, though....
115 static bool _OSArrayContainsCString(OSArray * array, const char * cString);
116 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code);
117 
118 /* Prelinked arm kexts do not have VM entries because the method we use to
119  * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
120  * not work on ARM.  To get around that, we must free prelinked kext
121  * executables with ml_static_mfree() instead of kext_free().
122  */
123 #if __i386__ || __x86_64__
124 #define VM_MAPPED_KEXTS 1
125 #define KASLR_KEXT_DEBUG 0
126 #define KASLR_IOREG_DEBUG 0
127 #elif __arm__ || __arm64__
128 #define VM_MAPPED_KEXTS 0
129 #define KASLR_KEXT_DEBUG 0
130 #else
131 #error Unsupported architecture
132 #endif
133 
134 #if PRAGMA_MARK
135 #pragma mark Constants & Macros
136 #endif
137 /*********************************************************************
138 * Constants & Macros
139 *********************************************************************/
140 
141 /* Use this number to create containers.
142  */
143 #define kOSKextTypicalLoadCount      (150)
144 
145 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
146  * A loaded kext will no dependents or external retains will have 2 retains.
147  */
148 #define kOSKextMinRetainCount        (1)
149 #define kOSKextMinLoadedRetainCount  (2)
150 
151 /**********
152  * Strings and substrings used in dependency resolution.
153  */
154 #define APPLE_KEXT_PREFIX            "com.apple."
155 #define KERNEL_LIB                   "com.apple.kernel"
156 
157 #define PRIVATE_KPI                  "com.apple.kpi.private"
158 
159 /* Version for compatbility pseudokexts (com.apple.kernel.*),
160  * compatible back to v6.0.
161  */
162 #define KERNEL6_LIB                  "com.apple.kernel.6.0"
163 #define KERNEL6_VERSION              "7.9.9"
164 
165 #define KERNEL_LIB_PREFIX            "com.apple.kernel."
166 #define KPI_LIB_PREFIX               "com.apple.kpi."
167 
168 #define STRING_HAS_PREFIX(s, p)      (strncmp((s), (p), strlen(p)) == 0)
169 
170 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
171 #define MINIMUM_WAKEUP_SECONDS (30)
172 
173 /*********************************************************************
174 * infoDict keys for internally-stored data. Saves on ivar slots for
175 * objects we don't keep around past boot time or during active load.
176 *********************************************************************/
177 
178 /* A usable, uncompressed file is stored under this key.
179  */
180 #define _kOSKextExecutableKey                "_OSKextExecutable"
181 
182 /* An indirect reference to the executable file from an mkext
183  * is stored under this key.
184  */
185 #define _kOSKextMkextExecutableReferenceKey  "_OSKextMkextExecutableReference"
186 
187 /* If the file is contained in a larger buffer laid down by the booter or
188  * sent from user space, the OSKext stores that OSData under this key so that
189  * references are properly tracked. This is always an mkext, right now.
190  */
191 #define _kOSKextExecutableExternalDataKey    "_OSKextExecutableExternalData"
192 
193 #define OS_LOG_HDR_VERSION  1
194 #define NUM_OS_LOG_SECTIONS 2
195 
196 #define OS_LOG_SECT_IDX     0
197 #define CSTRING_SECT_IDX    1
198 
199 #if PRAGMA_MARK
200 #pragma mark Typedefs
201 #endif
202 /*********************************************************************
203 * Typedefs
204 *********************************************************************/
205 
206 /*********************************************************************
207 * osLogDataHeaderRef describes the header information of an OSData
208 * object that is returned when querying for kOSBundleLogStringsKey.
209 * We currently return information regarding 2 sections - os_log and
210 * cstring. In the case that the os_log section doesn't exist, we just
211 * return an offset and length of 0 for that section.
212 *********************************************************************/
213 typedef struct osLogDataHeader {
214 	uint32_t version;
215 	uint32_t sect_count;
216 	struct {
217 		uint32_t sect_offset;
218 		uint32_t sect_size;
219 	} sections[0];
220 } osLogDataHeaderRef;
221 
222 /*********************************************************************
223 * MkextEntryRef describes the contents of an OSData object
224 * referencing a file entry from an mkext so that we can uncompress
225 * (if necessary) and extract it on demand.
226 *
227 * It contains the mkextVersion in case we ever wind up supporting
228 * multiple mkext formats. Mkext format 1 is officially retired as of
229 * Snow Leopard.
230 *********************************************************************/
231 typedef struct MkextEntryRef {
232 	mkext_basic_header * mkext; // beginning of whole mkext file
233 	void               * fileinfo;// mkext2_file_entry or equiv; see mkext.h
234 } MkextEntryRef;
235 
236 #if PRAGMA_MARK
237 #pragma mark Global and static Module Variables
238 #endif
239 /*********************************************************************
240 * Global & static variables, used to keep track of kexts.
241 *********************************************************************/
242 
243 static  bool                sPrelinkBoot               = false;
244 static  bool                sSafeBoot                  = false;
245 static  bool                sKeepSymbols               = false;
246 
247 /*********************************************************************
248  * sKextLock is the principal lock for OSKext, and guards all static
249  * and global variables not owned by other locks (declared further
250  * below). It must be taken by any entry-point method or function,
251  * including internal functions called on scheduled threads.
252  *
253  * sKextLock and sKextInnerLock are recursive due to multiple functions
254  * that are called both externally and internally. The other locks are
255  * nonrecursive.
256  *
257  * Which locks are taken depends on what they protect, but if more than
258  * one must be taken, they must always be locked in this order
259  * (and unlocked in reverse order) to prevent deadlocks:
260  *
261  *    1. sKextLock
262  *    2. sKextInnerLock
263  *    3. sKextSummariesLock
264  *    4. sKextLoggingLock
265  */
266 static IORecursiveLock    * sKextLock                  = NULL;
267 
268 static OSDictionary       * sKextsByID                 = NULL;
269 static OSDictionary       * sExcludeListByID           = NULL;
270 static OSKextVersion        sExcludeListVersion        = 0;
271 static OSArray            * sLoadedKexts               = NULL;
272 static OSArray            * sUnloadedPrelinkedKexts    = NULL;
273 static OSArray            * sLoadedDriverKitKexts      = NULL;
274 
275 // Requests to kextd waiting to be picked up.
276 static OSArray            * sKernelRequests            = NULL;
277 // Identifier of kext load requests in sKernelRequests
278 static OSSet              * sPostedKextLoadIdentifiers = NULL;
279 static OSArray            * sRequestCallbackRecords    = NULL;
280 
281 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
282 static OSSet              * sAllKextLoadIdentifiers    = NULL;
283 static KXLDContext        * sKxldContext               = NULL;
284 static uint32_t             sNextLoadTag               = 0;
285 static uint32_t             sNextRequestTag            = 0;
286 
287 static bool                 sUserLoadsActive           = false;
288 static bool                 sKextdActive               = false;
289 static bool                 sDeferredLoadSucceeded     = false;
290 static bool                 sConsiderUnloadsExecuted   = false;
291 
292 #if NO_KEXTD
293 static bool                 sKernelRequestsEnabled     = false;
294 #else
295 static bool                 sKernelRequestsEnabled     = true;
296 #endif
297 static bool                 sLoadEnabled               = true;
298 static bool                 sUnloadEnabled             = true;
299 
300 /*********************************************************************
301  * Stuff for the OSKext representing the kernel itself.
302  **********/
303 static OSKext          * sKernelKext             = NULL;
304 
305 /* Set up a fake kmod_info struct for the kernel.
306  * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
307  * before OSKext is initialized; that call only needs the name
308  * and address to be set correctly.
309  *
310  * We don't do much else with the kerne's kmod_info; we never
311  * put it into the kmod list, never adjust the reference count,
312  * and never have kernel components reference it.
313  * For that matter, we don't do much with kmod_info structs
314  * at all anymore! We just keep them filled in for gdb and
315  * binary compability.
316  */
317 kmod_info_t g_kernel_kmod_info = {
318 	.next =            NULL,
319 	.info_version =    KMOD_INFO_VERSION,
320 	.id =              0,             // loadTag: kernel is always 0
321 	.name =            kOSKextKernelIdentifier,// bundle identifier
322 	.version =         "0",           // filled in in OSKext::initialize()
323 	.reference_count = -1,            // never adjusted; kernel never unloads
324 	.reference_list =  NULL,
325 	.address =         0,
326 	.size =            0,             // filled in in OSKext::initialize()
327 	.hdr_size =        0,
328 	.start =           NULL,
329 	.stop =            NULL
330 };
331 
332 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
333 
334 kmod_info_t invalid_kmod_info = {
335 	.next =            NULL,
336 	.info_version =    KMOD_INFO_VERSION,
337 	.id =              UINT32_MAX,
338 	.name =            "invalid",
339 	.version =         "0",
340 	.reference_count = -1,
341 	.reference_list =  NULL,
342 	.address =         0,
343 	.size =            0,
344 	.hdr_size =        0,
345 	.start =           NULL,
346 	.stop =            NULL
347 };
348 
349 extern "C" {
350 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
351 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
352 // misc_protos.h, db_low_trace.c, kgmacros
353 // 'kmod' is a holdover from the old kmod system, we can't rename it.
354 kmod_info_t * kmod = NULL;
355 
356 #define KEXT_PANICLIST_SIZE  (2 * PAGE_SIZE)
357 
358 
359 static char     * loaded_kext_paniclist         = NULL;
360 static uint32_t   loaded_kext_paniclist_size    = 0;
361 
362 AbsoluteTime      last_loaded_timestamp;
363 static char       last_loaded_str_buf[2 * KMOD_MAX_NAME];
364 static u_long     last_loaded_strlen            = 0;
365 static void     * last_loaded_address           = NULL;
366 static u_long     last_loaded_size              = 0;
367 
368 AbsoluteTime      last_unloaded_timestamp;
369 static char       last_unloaded_str_buf[2 * KMOD_MAX_NAME];
370 static u_long     last_unloaded_strlen          = 0;
371 static void     * last_unloaded_address         = NULL;
372 static u_long     last_unloaded_size            = 0;
373 
374 // Statically linked kmods described by several mach-o sections:
375 //
376 // kPrelinkInfoSegment:kBuiltinInfoSection
377 // Array of pointers to kmod_info_t structs.
378 //
379 // kPrelinkInfoSegment:kBuiltinInfoSection
380 // Array of pointers to an embedded mach-o header.
381 //
382 // __DATA:kBuiltinInitSection, kBuiltinTermSection
383 // Structors for all kmods. Has to be filtered by proc address.
384 //
385 
386 static uint32_t gBuiltinKmodsCount;
387 static kernel_section_t * gBuiltinKmodsSectionInfo;
388 static kernel_section_t * gBuiltinKmodsSectionStart;
389 
390 static const OSSymbol       * gIOSurfaceIdentifier;
391 vm_tag_t                      gIOSurfaceTag;
392 
393 /*********************************************************************
394  * sKextInnerLock protects against cross-calls with IOService and
395  * IOCatalogue, and owns the variables declared immediately below.
396  *
397  * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
398  *
399  * When both sKextLock and sKextInnerLock need to be taken,
400  * always lock sKextLock first and unlock it second. Never take both
401  * locks in an entry point to OSKext; if you need to do so, you must
402  * spawn an independent thread to avoid potential deadlocks for threads
403  * calling into OSKext.
404  **********/
405 static IORecursiveLock *    sKextInnerLock             = NULL;
406 
407 static bool                 sAutounloadEnabled         = true;
408 static bool                 sConsiderUnloadsCalled     = false;
409 static bool                 sConsiderUnloadsPending    = false;
410 
411 static unsigned int         sConsiderUnloadDelay       = 60;     // seconds
412 static thread_call_t        sUnloadCallout             = NULL;
413 static thread_call_t        sDestroyLinkContextThread  = NULL;   // one-shot, one-at-a-time thread
414 static bool                 sSystemSleep               = false;  // true when system going to sleep
415 static AbsoluteTime         sLastWakeTime;                       // last time we woke up
416 
417 /*********************************************************************
418  * Backtraces can be printed at various times so we need a tight lock
419  * on data used for that. sKextSummariesLock protects the variables
420  * declared immediately below.
421  *
422  * gLoadedKextSummaries is accessed by other modules, but only during
423  * a panic so the lock isn't needed then.
424  *
425  * gLoadedKextSummaries has the "used" attribute in order to ensure
426  * that it remains visible even when we are performing extremely
427  * aggressive optimizations, as it is needed to allow the debugger
428  * to automatically parse the list of loaded kexts.
429  **********/
430 static IOLock                 * sKextSummariesLock                = NULL;
431 extern "C" lck_spin_t           vm_allocation_sites_lock;
432 static IOSimpleLock           * sKextAccountsLock = &vm_allocation_sites_lock;
433 
434 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
435 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
436 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
437 static size_t sLoadedKextSummariesAllocSize = 0;
438 
439 static OSKextActiveAccount * sKextAccounts;
440 static uint32_t                 sKextAccountsCount;
441 };
442 
443 /*********************************************************************
444  * sKextLoggingLock protects the logging variables declared immediately below.
445  **********/
446 static IOLock             * sKextLoggingLock           = NULL;
447 
448 static  const OSKextLogSpec kDefaultKernelLogFilter    = kOSKextLogBasicLevel |
449     kOSKextLogVerboseFlagsMask;
450 static  OSKextLogSpec       sKernelLogFilter           = kDefaultKernelLogFilter;
451 static  bool                sBootArgLogFilterFound     = false;
452 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
453     0, "kernel kext logging");
454 
455 static  OSKextLogSpec       sUserSpaceKextLogFilter    = kOSKextLogSilentFilter;
456 static  OSArray           * sUserSpaceLogSpecArray     = NULL;
457 static  OSArray           * sUserSpaceLogMessageArray  = NULL;
458 
459 /*********
460  * End scope for sKextInnerLock-protected variables.
461  *********************************************************************/
462 
463 
464 /*********************************************************************
465  *  helper function used for collecting PGO data upon unload of a kext
466  */
467 
468 static int OSKextGrabPgoDataLocked(OSKext *kext,
469     bool metadata,
470     uuid_t instance_uuid,
471     uint64_t *pSize,
472     char *pBuffer,
473     uint64_t bufferSize);
474 
475 /**********************************************************************/
476 
477 
478 
479 #if PRAGMA_MARK
480 #pragma mark OSData callbacks (need to move to OSData)
481 #endif
482 /*********************************************************************
483 * C functions used for callbacks.
484 *********************************************************************/
485 extern "C" {
486 void
487 osdata_kmem_free(void * ptr, unsigned int length)
488 {
489 	kmem_free(kernel_map, (vm_address_t)ptr, length);
490 	return;
491 }
492 
493 void
494 osdata_phys_free(void * ptr, unsigned int length)
495 {
496 	ml_static_mfree((vm_offset_t)ptr, length);
497 	return;
498 }
499 
500 void
501 osdata_vm_deallocate(void * ptr, unsigned int length)
502 {
503 	(void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
504 	return;
505 }
506 
507 void
508 osdata_kext_free(void * ptr, unsigned int length)
509 {
510 	(void)kext_free((vm_offset_t)ptr, length);
511 }
512 };
513 
514 #if PRAGMA_MARK
515 #pragma mark KXLD Allocation Callback
516 #endif
517 /*********************************************************************
518 * KXLD Allocation Callback
519 *********************************************************************/
520 kxld_addr_t
521 kern_allocate(
522 	u_long              size,
523 	KXLDAllocateFlags * flags,
524 	void              * user_data)
525 {
526 	vm_address_t  result       = 0; // returned
527 	kern_return_t mach_result  = KERN_FAILURE;
528 	bool          success      = false;
529 	OSKext      * theKext      = (OSKext *)user_data;
530 	u_long        roundSize    = round_page(size);
531 	OSData      * linkBuffer   = NULL;// must release
532 
533 	mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
534 	if (mach_result != KERN_SUCCESS) {
535 		OSKextLog(theKext,
536 		    kOSKextLogErrorLevel |
537 		    kOSKextLogGeneralFlag,
538 		    "Can't allocate kernel memory to link %s.",
539 		    theKext->getIdentifierCString());
540 		goto finish;
541 	}
542 
543 	/* Create an OSData wrapper for the allocated buffer.
544 	 */
545 	linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
546 	if (!linkBuffer) {
547 		OSKextLog(theKext,
548 		    kOSKextLogErrorLevel |
549 		    kOSKextLogGeneralFlag,
550 		    "Can't allocate linked executable wrapper for %s.",
551 		    theKext->getIdentifierCString());
552 		goto finish;
553 	}
554 	linkBuffer->setDeallocFunction(osdata_kext_free);
555 	OSKextLog(theKext,
556 	    kOSKextLogProgressLevel |
557 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
558 	    "Allocated link buffer for kext %s at %p (%lu bytes).",
559 	    theKext->getIdentifierCString(),
560 	    (void *)result, (unsigned long)roundSize);
561 
562 	theKext->setLinkedExecutable(linkBuffer);
563 
564 	*flags = kKxldAllocateWritable;
565 	success = true;
566 
567 finish:
568 	if (!success && result) {
569 		kext_free(result, roundSize);
570 		result = 0;
571 	}
572 
573 	OSSafeReleaseNULL(linkBuffer);
574 
575 	return (kxld_addr_t)result;
576 }
577 
578 /*********************************************************************
579 *********************************************************************/
580 void
581 kxld_log_callback(
582 	KXLDLogSubsystem    subsystem,
583 	KXLDLogLevel        level,
584 	const char        * format,
585 	va_list             argList,
586 	void              * user_data)
587 {
588 	OSKext *theKext = (OSKext *) user_data;
589 	OSKextLogSpec logSpec = 0;
590 
591 	switch (subsystem) {
592 	case kKxldLogLinking:
593 		logSpec |= kOSKextLogLinkFlag;
594 		break;
595 	case kKxldLogPatching:
596 		logSpec |= kOSKextLogPatchFlag;
597 		break;
598 	}
599 
600 	switch (level) {
601 	case kKxldLogExplicit:
602 		logSpec |= kOSKextLogExplicitLevel;
603 		break;
604 	case kKxldLogErr:
605 		logSpec |= kOSKextLogErrorLevel;
606 		break;
607 	case kKxldLogWarn:
608 		logSpec |= kOSKextLogWarningLevel;
609 		break;
610 	case kKxldLogBasic:
611 		logSpec |= kOSKextLogProgressLevel;
612 		break;
613 	case kKxldLogDetail:
614 		logSpec |= kOSKextLogDetailLevel;
615 		break;
616 	case kKxldLogDebug:
617 		logSpec |= kOSKextLogDebugLevel;
618 		break;
619 	}
620 
621 	OSKextVLog(theKext, logSpec, format, argList);
622 }
623 
624 #if PRAGMA_MARK
625 #pragma mark IOStatistics defines
626 #endif
627 
628 #if IOKITSTATS
629 
630 #define notifyKextLoadObservers(kext, kmod_info) \
631 do { \
632     IOStatistics::onKextLoad(kext, kmod_info); \
633 } while (0)
634 
635 #define notifyKextUnloadObservers(kext) \
636 do { \
637     IOStatistics::onKextUnload(kext); \
638 } while (0)
639 
640 #define notifyAddClassObservers(kext, addedClass, flags) \
641 do { \
642     IOStatistics::onClassAdded(kext, addedClass); \
643 } while (0)
644 
645 #define notifyRemoveClassObservers(kext, removedClass, flags) \
646 do { \
647     IOStatistics::onClassRemoved(kext, removedClass); \
648 } while (0)
649 
650 #else
651 
652 #define notifyKextLoadObservers(kext, kmod_info)
653 #define notifyKextUnloadObservers(kext)
654 #define notifyAddClassObservers(kext, addedClass, flags)
655 #define notifyRemoveClassObservers(kext, removedClass, flags)
656 
657 #endif /* IOKITSTATS */
658 
659 #if PRAGMA_MARK
660 #pragma mark Module Config (Startup & Shutdown)
661 #endif
662 /*********************************************************************
663 * Module Config (Class Definition & Class Methods)
664 *********************************************************************/
665 #define super OSObject
666 OSDefineMetaClassAndStructors(OSKext, OSObject)
667 
668 /*********************************************************************
669 *********************************************************************/
670 /* static */
671 void
672 OSKext::initialize(void)
673 {
674 	OSData          * kernelExecutable   = NULL;// do not release
675 	u_char          * kernelStart        = NULL;// do not free
676 	size_t            kernelLength       = 0;
677 	OSString        * scratchString      = NULL;// must release
678 	IORegistryEntry * registryRoot       = NULL;// do not release
679 	OSNumber        * kernelCPUType      = NULL;// must release
680 	OSNumber        * kernelCPUSubtype   = NULL;// must release
681 	OSKextLogSpec     bootLogFilter      = kOSKextLogSilentFilter;
682 	bool              setResult          = false;
683 	uint64_t        * timestamp          = NULL;
684 	char              bootArgBuffer[16];// for PE_parse_boot_argn w/strings
685 
686 	/* This must be the first thing allocated. Everything else grabs this lock.
687 	 */
688 	sKextLock = IORecursiveLockAlloc();
689 	sKextInnerLock = IORecursiveLockAlloc();
690 	sKextSummariesLock = IOLockAlloc();
691 	sKextLoggingLock = IOLockAlloc();
692 	assert(sKextLock);
693 	assert(sKextInnerLock);
694 	assert(sKextSummariesLock);
695 	assert(sKextLoggingLock);
696 
697 	sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
698 	sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
699 	sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
700 	sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
701 	sKernelRequests = OSArray::withCapacity(0);
702 	sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
703 	sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
704 	sRequestCallbackRecords = OSArray::withCapacity(0);
705 	assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests &&
706 	    sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
707 	    sRequestCallbackRecords && sUnloadedPrelinkedKexts);
708 
709 	/* Read the log flag boot-args and set the log flags.
710 	 */
711 	if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
712 		sBootArgLogFilterFound = true;
713 		sKernelLogFilter = bootLogFilter;
714 		// log this if any flags are set
715 		OSKextLog(/* kext */ NULL,
716 		    kOSKextLogBasicLevel |
717 		    kOSKextLogFlagsMask,
718 		    "Kernel kext log filter 0x%x per kextlog boot arg.",
719 		    (unsigned)sKernelLogFilter);
720 	}
721 
722 	sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
723 	    sizeof(bootArgBuffer)) ? true : false;
724 
725 	if (sSafeBoot) {
726 		OSKextLog(/* kext */ NULL,
727 		    kOSKextLogWarningLevel |
728 		    kOSKextLogGeneralFlag,
729 		    "SAFE BOOT DETECTED - "
730 		    "only valid OSBundleRequired kexts will be loaded.");
731 	}
732 
733 	PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
734 #if CONFIG_DTRACE
735 	if (dtrace_keep_kernel_symbols()) {
736 		sKeepSymbols = true;
737 	}
738 #endif /* CONFIG_DTRACE */
739 #if KASAN_DYNAMIC_BLACKLIST
740 	/* needed for function lookup */
741 	sKeepSymbols = true;
742 #endif
743 
744 	/* Set up an OSKext instance to represent the kernel itself.
745 	 */
746 	sKernelKext = new OSKext;
747 	assert(sKernelKext);
748 
749 	kernelStart = (u_char *)&_mh_execute_header;
750 	kernelLength = getlastaddr() - (vm_offset_t)kernelStart;
751 	kernelExecutable = OSData::withBytesNoCopy(
752 		kernelStart, kernelLength);
753 	assert(kernelExecutable);
754 
755 #if KASLR_KEXT_DEBUG
756 	IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %lu (0x%016lx) \n",
757 	    (unsigned long)kernelStart,
758 	    (unsigned long)getlastaddr(),
759 	    kernelLength,
760 	    (unsigned long)vm_kernel_slide,
761 	    (unsigned long)vm_kernel_slide);
762 #endif
763 
764 	sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0
765 	sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier);
766 
767 	sKernelKext->version = OSKextParseVersionString(osrelease);
768 	sKernelKext->compatibleVersion = sKernelKext->version;
769 	sKernelKext->linkedExecutable = kernelExecutable;
770 	sKernelKext->interfaceUUID = sKernelKext->copyUUID();
771 
772 	sKernelKext->flags.hasAllDependencies = 1;
773 	sKernelKext->flags.kernelComponent = 1;
774 	sKernelKext->flags.prelinked = 0;
775 	sKernelKext->flags.loaded = 1;
776 	sKernelKext->flags.started = 1;
777 	sKernelKext->flags.CPPInitialized = 0;
778 	sKernelKext->flags.jettisonLinkeditSeg = 0;
779 
780 	sKernelKext->kmod_info = &g_kernel_kmod_info;
781 	strlcpy(g_kernel_kmod_info.version, osrelease,
782 	    sizeof(g_kernel_kmod_info.version));
783 	g_kernel_kmod_info.size = kernelLength;
784 	g_kernel_kmod_info.id = sKernelKext->loadTag;
785 
786 	/* Cons up an info dict, so we don't have to have special-case
787 	 * checking all over.
788 	 */
789 	sKernelKext->infoDict = OSDictionary::withCapacity(5);
790 	assert(sKernelKext->infoDict);
791 	setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey,
792 	    sKernelKext->bundleID);
793 	assert(setResult);
794 	setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey,
795 	    kOSBooleanTrue);
796 	assert(setResult);
797 
798 	scratchString = OSString::withCStringNoCopy(osrelease);
799 	assert(scratchString);
800 	setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey,
801 	    scratchString);
802 	assert(setResult);
803 	OSSafeReleaseNULL(scratchString);
804 
805 	scratchString = OSString::withCStringNoCopy("mach_kernel");
806 	assert(scratchString);
807 	setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey,
808 	    scratchString);
809 	assert(setResult);
810 	OSSafeReleaseNULL(scratchString);
811 
812 	/* Add the kernel kext to the bookkeeping dictionaries. Note that
813 	 * the kernel kext doesn't have a kmod_info struct. copyInfo()
814 	 * gathers info from other places anyhow.
815 	 */
816 	setResult = sKextsByID->setObject(sKernelKext->bundleID, sKernelKext);
817 	assert(setResult);
818 	setResult = sLoadedKexts->setObject(sKernelKext);
819 	assert(setResult);
820 	sKernelKext->release();
821 
822 	registryRoot = IORegistryEntry::getRegistryRoot();
823 	kernelCPUType = OSNumber::withNumber(
824 		(long long unsigned int)_mh_execute_header.cputype,
825 		8 * sizeof(_mh_execute_header.cputype));
826 	kernelCPUSubtype = OSNumber::withNumber(
827 		(long long unsigned int)_mh_execute_header.cpusubtype,
828 		8 * sizeof(_mh_execute_header.cpusubtype));
829 	assert(registryRoot && kernelCPUSubtype && kernelCPUType);
830 
831 	registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType);
832 	registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype);
833 
834 	OSSafeReleaseNULL(kernelCPUType);
835 	OSSafeReleaseNULL(kernelCPUSubtype);
836 
837 	gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
838 	if (gBuiltinKmodsSectionInfo) {
839 		uint32_t count;
840 
841 		assert(gBuiltinKmodsSectionInfo->addr);
842 		assert(gBuiltinKmodsSectionInfo->size);
843 		gBuiltinKmodsCount = (gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
844 
845 		gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
846 		assert(gBuiltinKmodsSectionStart);
847 		assert(gBuiltinKmodsSectionStart->addr);
848 		assert(gBuiltinKmodsSectionStart->size);
849 		count = (gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
850 		// one extra pointer for the end of last kmod
851 		assert(count == (gBuiltinKmodsCount + 1));
852 
853 		vm_kernel_builtinkmod_text     = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
854 		vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
855 	}
856 	gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface");
857 
858 	timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
859 	*timestamp = 0;
860 	timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
861 	*timestamp = 0;
862 	timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
863 	*timestamp = 0;
864 
865 	OSKextLog(/* kext */ NULL,
866 	    kOSKextLogProgressLevel |
867 	    kOSKextLogGeneralFlag,
868 	    "Kext system initialized.");
869 
870 	notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
871 
872 	return;
873 }
874 
875 /*********************************************************************
876 * This is expected to be called exactly once, from exactly one thread
877 * context, during kernel bootstrap.
878 *********************************************************************/
879 /* static */
880 OSReturn
881 OSKext::removeKextBootstrap(void)
882 {
883 	OSReturn                   result                = kOSReturnError;
884 
885 	const char               * dt_kernel_header_name = "Kernel-__HEADER";
886 	const char               * dt_kernel_symtab_name = "Kernel-__SYMTAB";
887 	kernel_mach_header_t     * dt_mach_header        = NULL;
888 	int                        dt_mach_header_size   = 0;
889 	struct symtab_command    * dt_symtab             = NULL;
890 	int                        dt_symtab_size        = 0;
891 	int                        dt_result             = 0;
892 
893 	kernel_segment_command_t * seg_to_remove         = NULL;
894 
895 #if __arm__ || __arm64__
896 	const char               * dt_segment_name       = NULL;
897 	void                     * segment_paddress      = NULL;
898 	int                        segment_size          = 0;
899 #endif
900 
901 	OSKextLog(/* kext */ NULL,
902 	    kOSKextLogProgressLevel |
903 	    kOSKextLogGeneralFlag,
904 	    "Jettisoning kext bootstrap segments.");
905 
906 	/*****
907 	 * Dispose of unnecessary stuff that the booter didn't need to load.
908 	 */
909 	dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
910 	    (void **)&dt_mach_header, &dt_mach_header_size);
911 	if (dt_result == 0 && dt_mach_header) {
912 		IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
913 		    round_page_32(dt_mach_header_size));
914 	}
915 	dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
916 	    (void **)&dt_symtab, &dt_symtab_size);
917 	if (dt_result == 0 && dt_symtab) {
918 		IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
919 		    round_page_32(dt_symtab_size));
920 	}
921 
922 	/*****
923 	 * KLD bootstrap segment.
924 	 */
925 	// xxx - should rename KLD segment
926 	seg_to_remove = getsegbyname("__KLD");
927 	if (seg_to_remove) {
928 		OSRuntimeUnloadCPPForSegment(seg_to_remove);
929 	}
930 
931 #if __arm__ || __arm64__
932 	/* Free the memory that was set up by bootx.
933 	 */
934 	dt_segment_name = "Kernel-__KLD";
935 	if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
936 		/* We cannot free this with KTRR enabled, as we cannot
937 		 * update the permissions on the KLD range this late
938 		 * in the boot process.
939 		 */
940 		IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
941 		    (int)segment_size);
942 	}
943 #elif __i386__ || __x86_64__
944 	/* On x86, use the mapping data from the segment load command to
945 	 * unload KLD directly.
946 	 * This may invalidate any assumptions about  "avail_start"
947 	 * defining the lower bound for valid physical addresses.
948 	 */
949 	if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) {
950 		// 04/18/11 - gab: <rdar://problem/9236163>
951 		// overwrite memory occupied by KLD segment with random data before
952 		// releasing it.
953 		read_frandom((void *) seg_to_remove->vmaddr, seg_to_remove->vmsize);
954 		ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize);
955 	}
956 #else
957 #error arch
958 #endif
959 
960 	seg_to_remove = NULL;
961 
962 	/*****
963 	 * Prelinked kernel's symtab (if there is one).
964 	 */
965 	kernel_section_t * sect;
966 	sect = getsectbyname("__PRELINK", "__symtab");
967 	if (sect && sect->addr && sect->size) {
968 		ml_static_mfree(sect->addr, sect->size);
969 	}
970 
971 	seg_to_remove = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
972 
973 	/* kxld always needs the kernel's __LINKEDIT segment, but we can make it
974 	 * pageable, unless keepsyms is set.  To do that, we have to copy it from
975 	 * its booter-allocated memory, free the booter memory, reallocate proper
976 	 * managed memory, then copy the segment back in.
977 	 */
978 #if CONFIG_KXLD
979 #if (__arm__ || __arm64__)
980 #error CONFIG_KXLD not expected for this arch
981 #endif
982 	if (!sKeepSymbols) {
983 		kern_return_t mem_result;
984 		void *seg_copy = NULL;
985 		void *seg_data = NULL;
986 		vm_map_offset_t seg_offset = 0;
987 		vm_map_offset_t seg_copy_offset = 0;
988 		vm_map_size_t seg_length = 0;
989 
990 		seg_data = (void *) seg_to_remove->vmaddr;
991 		seg_offset = (vm_map_offset_t) seg_to_remove->vmaddr;
992 		seg_length = (vm_map_size_t) seg_to_remove->vmsize;
993 
994 		/* Allocate space for the LINKEDIT copy.
995 		 */
996 		mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
997 		    seg_length, VM_KERN_MEMORY_KEXT);
998 		if (mem_result != KERN_SUCCESS) {
999 			OSKextLog(/* kext */ NULL,
1000 			    kOSKextLogErrorLevel |
1001 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1002 			    "Can't copy __LINKEDIT segment for VM reassign.");
1003 			return result;
1004 		}
1005 		seg_copy_offset = (vm_map_offset_t) seg_copy;
1006 
1007 		/* Copy it out.
1008 		 */
1009 		memcpy(seg_copy, seg_data, seg_length);
1010 
1011 		/* Dump the booter memory.
1012 		 */
1013 		ml_static_mfree(seg_offset, seg_length);
1014 
1015 		/* Set up the VM region.
1016 		 */
1017 		mem_result = vm_map_enter_mem_object(
1018 			kernel_map,
1019 			&seg_offset,
1020 			seg_length, /* mask */ 0,
1021 			VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
1022 			VM_MAP_KERNEL_FLAGS_NONE,
1023 			VM_KERN_MEMORY_NONE,
1024 			(ipc_port_t)NULL,
1025 			(vm_object_offset_t) 0,
1026 			/* copy */ FALSE,
1027 			/* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
1028 			/* max_protection */ VM_PROT_ALL,
1029 			/* inheritance */ VM_INHERIT_DEFAULT);
1030 		if ((mem_result != KERN_SUCCESS) ||
1031 		    (seg_offset != (vm_map_offset_t) seg_data)) {
1032 			OSKextLog(/* kext */ NULL,
1033 			    kOSKextLogErrorLevel |
1034 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1035 			    "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1036 			    seg_data, seg_length, mem_result);
1037 			return result;
1038 		}
1039 
1040 		/* And copy it back.
1041 		 */
1042 		memcpy(seg_data, seg_copy, seg_length);
1043 
1044 		/* Free the copy.
1045 		 */
1046 		kmem_free(kernel_map, seg_copy_offset, seg_length);
1047 	}
1048 #else /* we are not CONFIG_KXLD */
1049 #if !(__arm__ || __arm64__)
1050 #error CONFIG_KXLD is expected for this arch
1051 #endif
1052 
1053 	/*****
1054 	 * Dump the LINKEDIT segment, unless keepsyms is set.
1055 	 */
1056 	if (!sKeepSymbols) {
1057 		dt_segment_name = "Kernel-__LINKEDIT";
1058 		if (0 == IODTGetLoaderInfo(dt_segment_name,
1059 		    &segment_paddress, &segment_size)) {
1060 #ifdef SECURE_KERNEL
1061 			vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
1062 			bzero((void*)vmaddr, segment_size);
1063 #endif
1064 			IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1065 			    (int)segment_size);
1066 		}
1067 	} else {
1068 		OSKextLog(/* kext */ NULL,
1069 		    kOSKextLogBasicLevel |
1070 		    kOSKextLogGeneralFlag,
1071 		    "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1072 	}
1073 #endif /* CONFIG_KXLD */
1074 
1075 	seg_to_remove = NULL;
1076 
1077 	result = kOSReturnSuccess;
1078 
1079 	return result;
1080 }
1081 
1082 /*********************************************************************
1083 *********************************************************************/
1084 void
1085 OSKext::flushNonloadedKexts(
1086 	Boolean flushPrelinkedKexts)
1087 {
1088 	OSSet                * keepKexts       = NULL;// must release
1089 
1090 	IORecursiveLockLock(sKextLock);
1091 
1092 	OSKextLog(/* kext */ NULL,
1093 	    kOSKextLogProgressLevel |
1094 	    kOSKextLogKextBookkeepingFlag,
1095 	    "Flushing nonloaded kexts and other unused data.");
1096 
1097 	OSKext::considerDestroyingLinkContext();
1098 
1099 	/* If we aren't flushing unused prelinked kexts, we have to put them
1100 	 * aside while we flush everything else so make a container for them.
1101 	 */
1102 	keepKexts = OSSet::withCapacity(16);
1103 	if (!keepKexts) {
1104 		goto finish;
1105 	}
1106 
1107 	/* Set aside prelinked kexts (in-use or not) and break
1108 	 * any lingering inter-kext references for nonloaded kexts
1109 	 * so they have min. retain counts.
1110 	 */
1111 	sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1112 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1113 		if (!thisKext) {
1114 		        return false;
1115 		}
1116 		if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
1117 		        keepKexts->setObject(thisKext);
1118 		}
1119 		if (!thisKext->declaresExecutable()) {
1120 		        /*
1121 		         * Don't unload codeless kexts, because they never appear in the loadedKexts array.
1122 		         * Requesting one from kextd will load it and then immediately remove it by calling
1123 		         * flushNonloadedKexts().
1124 		         * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
1125 		         */
1126 		        keepKexts->setObject(thisKext);
1127 		}
1128 
1129 		thisKext->flushDependencies(/* forceIfLoaded */ false);
1130 		return false;
1131 	});
1132 
1133 	/* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1134 	 */
1135 	sKextsByID->flushCollection();
1136 
1137 	/* Now put the loaded kexts back into the ID dictionary.
1138 	 */
1139 	sLoadedKexts->iterateObjects(^bool (OSObject * obj) {
1140 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1141 		if (!thisKext) {
1142 		        return false;
1143 		}
1144 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1145 		return false;
1146 	});
1147 
1148 	/* Finally, put back the kept kexts if we saved any.
1149 	 */
1150 	keepKexts->iterateObjects(^bool (OSObject * obj) {
1151 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
1152 		if (!thisKext) {
1153 		        return false;
1154 		}
1155 		sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1156 		return false;
1157 	});
1158 
1159 finish:
1160 	IORecursiveLockUnlock(sKextLock);
1161 
1162 	OSSafeReleaseNULL(keepKexts);
1163 
1164 	return;
1165 }
1166 
1167 /*********************************************************************
1168 *********************************************************************/
1169 /* static */
1170 void
1171 OSKext::setKextdActive(Boolean active)
1172 {
1173 	IORecursiveLockLock(sKextLock);
1174 	sKextdActive = active;
1175 	if (sKernelRequests->getCount()) {
1176 		OSKext::pingKextd();
1177 	}
1178 	IORecursiveLockUnlock(sKextLock);
1179 
1180 	return;
1181 }
1182 
1183 /*********************************************************************
1184 * OSKextLib.cpp might need access to this someday but for now it's
1185 * private.
1186 *********************************************************************/
1187 extern "C" {
1188 extern void ipc_port_release_send(ipc_port_t);
1189 };
1190 
1191 /* static */
1192 OSReturn
1193 OSKext::pingKextd(void)
1194 {
1195 	OSReturn    result     = kOSReturnError;
1196 #if !NO_KEXTD
1197 	mach_port_t kextd_port = IPC_PORT_NULL;
1198 
1199 	if (!sKextdActive) {
1200 		result = kOSKextReturnDisabled; // basically unavailable
1201 		goto finish;
1202 	}
1203 
1204 	result = host_get_kextd_port(host_priv_self(), &kextd_port);
1205 	if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1206 		OSKextLog(/* kext */ NULL,
1207 		    kOSKextLogErrorLevel |
1208 		    kOSKextLogIPCFlag,
1209 		    "Can't get kextd port.");
1210 		goto finish;
1211 	}
1212 
1213 	result = kextd_ping(kextd_port);
1214 	if (result != KERN_SUCCESS) {
1215 		OSKextLog(/* kext */ NULL,
1216 		    kOSKextLogErrorLevel |
1217 		    kOSKextLogIPCFlag,
1218 		    "kextd ping failed (0x%x).", (int)result);
1219 		goto finish;
1220 	}
1221 
1222 finish:
1223 	if (IPC_PORT_VALID(kextd_port)) {
1224 		ipc_port_release_send(kextd_port);
1225 	}
1226 #endif
1227 
1228 	return result;
1229 }
1230 
1231 /*********************************************************************
1232 *********************************************************************/
1233 /* static */
1234 void
1235 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1236 {
1237 	IORecursiveLockLock(sKextLock);
1238 	sDeferredLoadSucceeded = succeeded;
1239 	IORecursiveLockUnlock(sKextLock);
1240 
1241 	return;
1242 }
1243 
1244 /*********************************************************************
1245 * Called from IOSystemShutdownNotification.
1246 *********************************************************************/
1247 /* static */
1248 void
1249 OSKext::willShutdown(void)
1250 {
1251 #if !NO_KEXTD
1252 	OSReturn       checkResult = kOSReturnError;
1253 #endif
1254 	OSDictionary * exitRequest = NULL; // must release
1255 
1256 	IORecursiveLockLock(sKextLock);
1257 
1258 	OSKext::setLoadEnabled(false);
1259 	OSKext::setUnloadEnabled(false);
1260 	OSKext::setAutounloadsEnabled(false);
1261 	OSKext::setKernelRequestsEnabled(false);
1262 
1263 #if !NO_KEXTD
1264 	OSKextLog(/* kext */ NULL,
1265 	    kOSKextLogProgressLevel |
1266 	    kOSKextLogGeneralFlag,
1267 	    "System shutdown; requesting immediate kextd exit.");
1268 
1269 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit,
1270 	    &exitRequest);
1271 	if (checkResult != kOSReturnSuccess) {
1272 		goto finish;
1273 	}
1274 	if (!sKernelRequests->setObject(exitRequest)) {
1275 		goto finish;
1276 	}
1277 
1278 	OSKext::pingKextd();
1279 
1280 finish:
1281 #endif
1282 
1283 	IORecursiveLockUnlock(sKextLock);
1284 
1285 	OSSafeReleaseNULL(exitRequest);
1286 	return;
1287 }
1288 
1289 /*********************************************************************
1290 *********************************************************************/
1291 /* static */
1292 bool
1293 OSKext::getLoadEnabled(void)
1294 {
1295 	bool result;
1296 
1297 	IORecursiveLockLock(sKextLock);
1298 	result = sLoadEnabled;
1299 	IORecursiveLockUnlock(sKextLock);
1300 	return result;
1301 }
1302 
1303 /*********************************************************************
1304 *********************************************************************/
1305 /* static */
1306 bool
1307 OSKext::setLoadEnabled(bool flag)
1308 {
1309 	bool result;
1310 
1311 	IORecursiveLockLock(sKextLock);
1312 	result = sLoadEnabled;
1313 	sLoadEnabled = (flag ? true : false);
1314 
1315 	if (sLoadEnabled != result) {
1316 		OSKextLog(/* kext */ NULL,
1317 		    kOSKextLogBasicLevel |
1318 		    kOSKextLogLoadFlag,
1319 		    "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1320 	}
1321 
1322 	IORecursiveLockUnlock(sKextLock);
1323 
1324 	return result;
1325 }
1326 
1327 /*********************************************************************
1328 *********************************************************************/
1329 /* static */
1330 bool
1331 OSKext::getUnloadEnabled(void)
1332 {
1333 	bool result;
1334 
1335 	IORecursiveLockLock(sKextLock);
1336 	result = sUnloadEnabled;
1337 	IORecursiveLockUnlock(sKextLock);
1338 	return result;
1339 }
1340 
1341 /*********************************************************************
1342 *********************************************************************/
1343 /* static */
1344 bool
1345 OSKext::setUnloadEnabled(bool flag)
1346 {
1347 	bool result;
1348 
1349 	IORecursiveLockLock(sKextLock);
1350 	result = sUnloadEnabled;
1351 	sUnloadEnabled = (flag ? true : false);
1352 	IORecursiveLockUnlock(sKextLock);
1353 
1354 	if (sUnloadEnabled != result) {
1355 		OSKextLog(/* kext */ NULL,
1356 		    kOSKextLogBasicLevel |
1357 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1358 		    "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1359 	}
1360 
1361 	return result;
1362 }
1363 
1364 /*********************************************************************
1365 * Do not call any function that takes sKextLock here!
1366 *********************************************************************/
1367 /* static */
1368 bool
1369 OSKext::getAutounloadEnabled(void)
1370 {
1371 	bool result;
1372 
1373 	IORecursiveLockLock(sKextInnerLock);
1374 	result = sAutounloadEnabled ? true : false;
1375 	IORecursiveLockUnlock(sKextInnerLock);
1376 	return result;
1377 }
1378 
1379 /*********************************************************************
1380 * Do not call any function that takes sKextLock here!
1381 *********************************************************************/
1382 /* static */
1383 bool
1384 OSKext::setAutounloadsEnabled(bool flag)
1385 {
1386 	bool result;
1387 
1388 	IORecursiveLockLock(sKextInnerLock);
1389 
1390 	result = sAutounloadEnabled;
1391 	sAutounloadEnabled = (flag ? true : false);
1392 	if (!sAutounloadEnabled && sUnloadCallout) {
1393 		thread_call_cancel(sUnloadCallout);
1394 	}
1395 
1396 	if (sAutounloadEnabled != result) {
1397 		OSKextLog(/* kext */ NULL,
1398 		    kOSKextLogBasicLevel |
1399 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1400 		    "Kext autounloading now %sabled.",
1401 		    sAutounloadEnabled ? "en" : "dis");
1402 	}
1403 
1404 	IORecursiveLockUnlock(sKextInnerLock);
1405 
1406 	return result;
1407 }
1408 
1409 /*********************************************************************
1410 *********************************************************************/
1411 /* instance method operating on OSKext field */
1412 bool
1413 OSKext::setAutounloadEnabled(bool flag)
1414 {
1415 	bool result = flags.autounloadEnabled ? true : false;
1416 	flags.autounloadEnabled = flag ? 1 : 0;
1417 
1418 	if (result != (flag ? true : false)) {
1419 		OSKextLog(this,
1420 		    kOSKextLogProgressLevel |
1421 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1422 		    "Autounloading for kext %s now %sabled.",
1423 		    getIdentifierCString(),
1424 		    flags.autounloadEnabled ? "en" : "dis");
1425 	}
1426 	return result;
1427 }
1428 
1429 /*********************************************************************
1430 *********************************************************************/
1431 /* static */
1432 bool
1433 OSKext::setKernelRequestsEnabled(bool flag)
1434 {
1435 	bool result;
1436 
1437 	IORecursiveLockLock(sKextLock);
1438 	result = sKernelRequestsEnabled;
1439 	sKernelRequestsEnabled = flag ? true : false;
1440 
1441 	if (sKernelRequestsEnabled != result) {
1442 		OSKextLog(/* kext */ NULL,
1443 		    kOSKextLogBasicLevel |
1444 		    kOSKextLogGeneralFlag,
1445 		    "Kernel requests now %sabled.",
1446 		    sKernelRequestsEnabled ? "en" : "dis");
1447 	}
1448 	IORecursiveLockUnlock(sKextLock);
1449 	return result;
1450 }
1451 
1452 /*********************************************************************
1453 *********************************************************************/
1454 /* static */
1455 bool
1456 OSKext::getKernelRequestsEnabled(void)
1457 {
1458 	bool result;
1459 
1460 	IORecursiveLockLock(sKextLock);
1461 	result = sKernelRequestsEnabled;
1462 	IORecursiveLockUnlock(sKextLock);
1463 	return result;
1464 }
1465 
1466 #if PRAGMA_MARK
1467 #pragma mark Kext Life Cycle
1468 #endif
1469 /*********************************************************************
1470 *********************************************************************/
1471 OSKext *
1472 OSKext::withPrelinkedInfoDict(
1473 	OSDictionary * anInfoDict,
1474 	bool doCoalesedSlides)
1475 {
1476 	OSKext * newKext = new OSKext;
1477 
1478 	if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalesedSlides)) {
1479 		newKext->release();
1480 		return NULL;
1481 	}
1482 
1483 	return newKext;
1484 }
1485 
1486 /*********************************************************************
1487 *********************************************************************/
1488 bool
1489 OSKext::initWithPrelinkedInfoDict(
1490 	OSDictionary * anInfoDict,
1491 	bool doCoalesedSlides)
1492 {
1493 	bool            result              = false;
1494 	OSString      * kextPath            = NULL;// do not release
1495 	OSNumber      * addressNum          = NULL;// reused; do not release
1496 	OSNumber      * lengthNum           = NULL;// reused; do not release
1497 	void          * data                = NULL;// do not free
1498 	void          * srcData             = NULL;// do not free
1499 	OSData        * prelinkedExecutable = NULL;// must release
1500 	uint32_t        length              = 0; // reused
1501 
1502 	if (!super::init()) {
1503 		goto finish;
1504 	}
1505 
1506 	/* Get the path. Don't look for an arch-specific path property.
1507 	 */
1508 	kextPath = OSDynamicCast(OSString,
1509 	    anInfoDict->getObject(kPrelinkBundlePathKey));
1510 
1511 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
1512 		goto finish;
1513 	}
1514 #if KASLR_KEXT_DEBUG
1515 	IOLog("kaslr: doCoalesedSlides %d kext %s \n", doCoalesedSlides, getIdentifierCString());
1516 #endif
1517 
1518 	/* Also get the executable's bundle-relative path if present.
1519 	 * Don't look for an arch-specific path property.
1520 	 */
1521 	executableRelPath = OSDynamicCast(OSString,
1522 	    anInfoDict->getObject(kPrelinkExecutableRelativePathKey));
1523 	if (executableRelPath) {
1524 		executableRelPath->retain();
1525 	}
1526 
1527 	userExecutableRelPath = OSDynamicCast(OSString,
1528 	    anInfoDict->getObject("CFBundleUEXTExecutable"));
1529 	if (userExecutableRelPath) {
1530 		userExecutableRelPath->retain();
1531 	}
1532 
1533 	/* Don't need the paths to be in the info dictionary any more.
1534 	 */
1535 	anInfoDict->removeObject(kPrelinkBundlePathKey);
1536 	anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
1537 
1538 	/* Create an OSData wrapper around the linked executable.
1539 	 */
1540 	addressNum = OSDynamicCast(OSNumber,
1541 	    anInfoDict->getObject(kPrelinkExecutableLoadKey));
1542 	if (addressNum) {
1543 		lengthNum = OSDynamicCast(OSNumber,
1544 		    anInfoDict->getObject(kPrelinkExecutableSizeKey));
1545 		if (!lengthNum) {
1546 			OSKextLog(this,
1547 			    kOSKextLogErrorLevel |
1548 			    kOSKextLogArchiveFlag,
1549 			    "Kext %s can't find prelinked kext executable size.",
1550 			    getIdentifierCString());
1551 			goto finish;
1552 		}
1553 
1554 		data = (void *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
1555 		length = (uint32_t) (lengthNum->unsigned32BitValue());
1556 
1557 #if KASLR_KEXT_DEBUG
1558 		IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1559 		    (unsigned long)ml_static_unslide((vm_offset_t)data),
1560 		    (unsigned long)data,
1561 		    length);
1562 #endif
1563 
1564 		anInfoDict->removeObject(kPrelinkExecutableLoadKey);
1565 		anInfoDict->removeObject(kPrelinkExecutableSizeKey);
1566 
1567 		/* If the kext's load address differs from its source address, allocate
1568 		 * space in the kext map at the load address and copy the kext over.
1569 		 */
1570 		addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
1571 		if (addressNum) {
1572 			srcData = (void *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
1573 
1574 #if KASLR_KEXT_DEBUG
1575 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1576 			    (unsigned long)ml_static_unslide((vm_offset_t)srcData),
1577 			    (unsigned long)srcData);
1578 #endif
1579 
1580 			if (data != srcData) {
1581 #if __LP64__
1582 				kern_return_t alloc_result;
1583 
1584 				alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
1585 				if (alloc_result != KERN_SUCCESS) {
1586 					OSKextLog(this,
1587 					    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1588 					    "Failed to allocate space for prelinked kext %s.",
1589 					    getIdentifierCString());
1590 					goto finish;
1591 				}
1592 				memcpy(data, srcData, length);
1593 #else
1594 				OSKextLog(this,
1595 				    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1596 				    "Error: prelinked kext %s - source and load addresses "
1597 				    "differ on ILP32 architecture.",
1598 				    getIdentifierCString());
1599 				goto finish;
1600 #endif /* __LP64__ */
1601 			}
1602 
1603 			anInfoDict->removeObject(kPrelinkExecutableSourceKey);
1604 		}
1605 
1606 		prelinkedExecutable = OSData::withBytesNoCopy(data, length);
1607 		if (!prelinkedExecutable) {
1608 			OSKextLog(this,
1609 			    kOSKextLogErrorLevel |
1610 			    kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1611 			    "Kext %s failed to create executable wrapper.",
1612 			    getIdentifierCString());
1613 			goto finish;
1614 		}
1615 
1616 #if VM_MAPPED_KEXTS
1617 		prelinkedExecutable->setDeallocFunction(osdata_kext_free);
1618 #else
1619 		prelinkedExecutable->setDeallocFunction(osdata_phys_free);
1620 #endif
1621 		setLinkedExecutable(prelinkedExecutable);
1622 		addressNum = OSDynamicCast(OSNumber,
1623 		    anInfoDict->getObject(kPrelinkKmodInfoKey));
1624 		if (!addressNum) {
1625 			OSKextLog(this,
1626 			    kOSKextLogErrorLevel |
1627 			    kOSKextLogArchiveFlag,
1628 			    "Kext %s can't find prelinked kext kmod_info address.",
1629 			    getIdentifierCString());
1630 			goto finish;
1631 		}
1632 
1633 		if (addressNum->unsigned64BitValue() != 0) {
1634 			kmod_info = (kmod_info_t *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
1635 			kmod_info->address = ml_static_slide(kmod_info->address);
1636 #if KASLR_KEXT_DEBUG
1637 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1638 			    (unsigned long)ml_static_unslide((vm_offset_t)kmod_info),
1639 			    (unsigned long)kmod_info);
1640 			IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1641 			    (unsigned long)ml_static_unslide(kmod_info->address),
1642 			    (unsigned long)kmod_info->address);
1643  #endif
1644 		}
1645 
1646 		anInfoDict->removeObject(kPrelinkKmodInfoKey);
1647 	}
1648 
1649 	if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) {
1650 		uintptr_t builtinTextStart;
1651 		uintptr_t builtinTextEnd;
1652 
1653 		flags.builtin = true;
1654 		builtinKmodIdx = addressNum->unsigned32BitValue();
1655 		assert(builtinKmodIdx < gBuiltinKmodsCount);
1656 
1657 		builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx];
1658 		builtinTextEnd   = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1];
1659 
1660 		kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx];
1661 		kmod_info->address = builtinTextStart;
1662 		kmod_info->size    = builtinTextEnd - builtinTextStart;
1663 	}
1664 
1665 	/* If the plist has a UUID for an interface, save that off.
1666 	 */
1667 	if (isInterface()) {
1668 		interfaceUUID = OSDynamicCast(OSData,
1669 		    anInfoDict->getObject(kPrelinkInterfaceUUIDKey));
1670 		if (interfaceUUID) {
1671 			interfaceUUID->retain();
1672 			anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
1673 		}
1674 	}
1675 
1676 	result = slidePrelinkedExecutable(doCoalesedSlides);
1677 	if (result != kOSReturnSuccess) {
1678 		goto finish;
1679 	}
1680 
1681 	if (doCoalesedSlides == false) {
1682 		/* set VM protections now, wire later at kext load */
1683 		result = setVMAttributes(true, false);
1684 		if (result != KERN_SUCCESS) {
1685 			goto finish;
1686 		}
1687 	}
1688 
1689 	flags.prelinked = true;
1690 
1691 	/* If we created a kext from prelink info,
1692 	 * we must be booting from a prelinked kernel.
1693 	 */
1694 	sPrelinkBoot = true;
1695 
1696 	result = registerIdentifier();
1697 
1698 finish:
1699 	OSSafeReleaseNULL(prelinkedExecutable);
1700 
1701 	return result;
1702 }
1703 
1704 /*********************************************************************
1705 *********************************************************************/
1706 /* static */
1707 void
1708 OSKext::setAllVMAttributes(void)
1709 {
1710 	OSCollectionIterator * kextIterator     = NULL;// must release
1711 	const OSSymbol * thisID                 = NULL;// do not release
1712 
1713 	IORecursiveLockLock(sKextLock);
1714 
1715 	kextIterator = OSCollectionIterator::withCollection(sKextsByID);
1716 	if (!kextIterator) {
1717 		goto finish;
1718 	}
1719 
1720 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
1721 		OSKext *    thisKext;// do not release
1722 
1723 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
1724 		if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
1725 			continue;
1726 		}
1727 
1728 		/* set VM protections now, wire later at kext load */
1729 		thisKext->setVMAttributes(true, false);
1730 	}
1731 
1732 finish:
1733 	IORecursiveLockUnlock(sKextLock);
1734 	OSSafeReleaseNULL(kextIterator);
1735 
1736 	return;
1737 }
1738 
1739 /*********************************************************************
1740 *********************************************************************/
1741 OSKext *
1742 OSKext::withBooterData(
1743 	OSString * deviceTreeName,
1744 	OSData   * booterData)
1745 {
1746 	OSKext * newKext = new OSKext;
1747 
1748 	if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
1749 		newKext->release();
1750 		return NULL;
1751 	}
1752 
1753 	return newKext;
1754 }
1755 
1756 /*********************************************************************
1757 *********************************************************************/
1758 typedef struct _BooterKextFileInfo {
1759 	uint32_t  infoDictPhysAddr;
1760 	uint32_t  infoDictLength;
1761 	uint32_t  executablePhysAddr;
1762 	uint32_t  executableLength;
1763 	uint32_t  bundlePathPhysAddr;
1764 	uint32_t  bundlePathLength;
1765 } _BooterKextFileInfo;
1766 
1767 bool
1768 OSKext::initWithBooterData(
1769 	OSString * deviceTreeName,
1770 	OSData   * booterData)
1771 {
1772 	bool                  result         = false;
1773 	_BooterKextFileInfo * kextFileInfo   = NULL;// do not free
1774 	char                * infoDictAddr   = NULL;// do not free
1775 	void                * executableAddr = NULL;// do not free
1776 	char                * bundlePathAddr = NULL;// do not free
1777 
1778 	OSObject            * parsedXML      = NULL;// must release
1779 	OSDictionary        * theInfoDict    = NULL;// do not release
1780 	OSString            * kextPath       = NULL;// must release
1781 	OSString            * errorString    = NULL;// must release
1782 	OSData              * executable     = NULL;// must release
1783 
1784 	if (!super::init()) {
1785 		goto finish;
1786 	}
1787 
1788 	kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
1789 	if (!kextFileInfo) {
1790 		OSKextLog(this,
1791 		    kOSKextLogErrorLevel |
1792 		    kOSKextLogGeneralFlag,
1793 		    "No booter-provided data for kext device tree entry %s.",
1794 		    deviceTreeName->getCStringNoCopy());
1795 		goto finish;
1796 	}
1797 
1798 	/* The info plist must exist or we can't read the kext.
1799 	 */
1800 	if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
1801 		OSKextLog(this,
1802 		    kOSKextLogErrorLevel |
1803 		    kOSKextLogGeneralFlag,
1804 		    "No kext info dictionary for booter device tree entry %s.",
1805 		    deviceTreeName->getCStringNoCopy());
1806 		goto finish;
1807 	}
1808 
1809 	infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
1810 	if (!infoDictAddr) {
1811 		OSKextLog(this,
1812 		    kOSKextLogErrorLevel |
1813 		    kOSKextLogGeneralFlag,
1814 		    "Can't translate physical address 0x%x of kext info dictionary "
1815 		    "for device tree entry %s.",
1816 		    (int)kextFileInfo->infoDictPhysAddr,
1817 		    deviceTreeName->getCStringNoCopy());
1818 		goto finish;
1819 	}
1820 
1821 	parsedXML = OSUnserializeXML(infoDictAddr, &errorString);
1822 	if (parsedXML) {
1823 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
1824 	}
1825 	if (!theInfoDict) {
1826 		const char * errorCString = "(unknown error)";
1827 
1828 		if (errorString && errorString->getCStringNoCopy()) {
1829 			errorCString = errorString->getCStringNoCopy();
1830 		} else if (parsedXML) {
1831 			errorCString = "not a dictionary";
1832 		}
1833 		OSKextLog(this,
1834 		    kOSKextLogErrorLevel |
1835 		    kOSKextLogGeneralFlag,
1836 		    "Error unserializing info dictionary for device tree entry %s: %s.",
1837 		    deviceTreeName->getCStringNoCopy(), errorCString);
1838 		goto finish;
1839 	}
1840 
1841 	/* A bundle path is not mandatory.
1842 	 */
1843 	if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
1844 		bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
1845 		if (!bundlePathAddr) {
1846 			OSKextLog(this,
1847 			    kOSKextLogErrorLevel |
1848 			    kOSKextLogGeneralFlag,
1849 			    "Can't translate physical address 0x%x of kext bundle path "
1850 			    "for device tree entry %s.",
1851 			    (int)kextFileInfo->bundlePathPhysAddr,
1852 			    deviceTreeName->getCStringNoCopy());
1853 			goto finish;
1854 		}
1855 		bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0'; // just in case!
1856 
1857 		kextPath = OSString::withCString(bundlePathAddr);
1858 		if (!kextPath) {
1859 			OSKextLog(this,
1860 			    kOSKextLogErrorLevel |
1861 			    kOSKextLogGeneralFlag,
1862 			    "Failed to create wrapper for device tree entry %s kext path %s.",
1863 			    deviceTreeName->getCStringNoCopy(), bundlePathAddr);
1864 			goto finish;
1865 		}
1866 	}
1867 
1868 	if (!setInfoDictionaryAndPath(theInfoDict, kextPath)) {
1869 		goto finish;
1870 	}
1871 
1872 	/* An executable is not mandatory.
1873 	 */
1874 	if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
1875 		executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
1876 		if (!executableAddr) {
1877 			OSKextLog(this,
1878 			    kOSKextLogErrorLevel |
1879 			    kOSKextLogGeneralFlag,
1880 			    "Can't translate physical address 0x%x of kext executable "
1881 			    "for device tree entry %s.",
1882 			    (int)kextFileInfo->executablePhysAddr,
1883 			    deviceTreeName->getCStringNoCopy());
1884 			goto finish;
1885 		}
1886 
1887 		executable = OSData::withBytesNoCopy(executableAddr,
1888 		    kextFileInfo->executableLength);
1889 		if (!executable) {
1890 			OSKextLog(this,
1891 			    kOSKextLogErrorLevel |
1892 			    kOSKextLogGeneralFlag,
1893 			    "Failed to create executable wrapper for device tree entry %s.",
1894 			    deviceTreeName->getCStringNoCopy());
1895 			goto finish;
1896 		}
1897 
1898 		/* A kext with an executable needs to retain the whole booterData
1899 		 * object to keep the executable in memory.
1900 		 */
1901 		if (!setExecutable(executable, booterData)) {
1902 			OSKextLog(this,
1903 			    kOSKextLogErrorLevel |
1904 			    kOSKextLogGeneralFlag,
1905 			    "Failed to set kext executable for device tree entry %s.",
1906 			    deviceTreeName->getCStringNoCopy());
1907 			goto finish;
1908 		}
1909 	}
1910 
1911 	result = registerIdentifier();
1912 
1913 finish:
1914 	OSSafeReleaseNULL(parsedXML);
1915 	OSSafeReleaseNULL(kextPath);
1916 	OSSafeReleaseNULL(errorString);
1917 	OSSafeReleaseNULL(executable);
1918 
1919 	return result;
1920 }
1921 
1922 /*********************************************************************
1923 *********************************************************************/
1924 bool
1925 OSKext::registerIdentifier(void)
1926 {
1927 	bool            result              = false;
1928 	OSKext        * existingKext        = NULL;// do not release
1929 	bool            existingIsLoaded    = false;
1930 	bool            existingIsPrelinked = false;
1931 	OSKextVersion   newVersion          = -1;
1932 	OSKextVersion   existingVersion     = -1;
1933 	char            newVersionCString[kOSKextVersionMaxLength];
1934 	char            existingVersionCString[kOSKextVersionMaxLength];
1935 	OSData        * newUUID             = NULL;// must release
1936 	OSData        * existingUUID        = NULL;// must release
1937 
1938 	IORecursiveLockLock(sKextLock);
1939 
1940 	/* Get the new kext's version for checks & log messages.
1941 	 */
1942 	newVersion = getVersion();
1943 	OSKextVersionGetString(newVersion, newVersionCString,
1944 	    kOSKextVersionMaxLength);
1945 
1946 	/* If we don't have an existing kext with this identifier,
1947 	 * just record the new kext and we're done!
1948 	 */
1949 	existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID));
1950 	if (!existingKext) {
1951 		sKextsByID->setObject(bundleID, this);
1952 		result = true;
1953 		goto finish;
1954 	}
1955 
1956 	/* Get the existing kext's version for checks & log messages.
1957 	 */
1958 	existingVersion = existingKext->getVersion();
1959 	OSKextVersionGetString(existingVersion,
1960 	    existingVersionCString, kOSKextVersionMaxLength);
1961 
1962 	existingIsLoaded = existingKext->isLoaded();
1963 	existingIsPrelinked = existingKext->isPrelinked();
1964 
1965 	/* If we have a kext with this identifier that's already loaded/prelinked,
1966 	 * we can't use the new one, but let's be really thorough and check how
1967 	 * the two are related for a precise diagnostic log message.
1968 	 *
1969 	 * Note that user space can't find out about nonloaded prelinked kexts,
1970 	 * so in this case we log a message when new & existing are equivalent
1971 	 * at the step rather than warning level, because we are always going
1972 	 * be getting a copy of the kext in the user load request mkext.
1973 	 */
1974 	if (existingIsLoaded || existingIsPrelinked) {
1975 		bool sameVersion = (newVersion == existingVersion);
1976 		bool sameExecutable = true; // assume true unless we have UUIDs
1977 
1978 		/* Only get the UUID if the existing kext is loaded. Doing so
1979 		 * might have to uncompress an mkext executable and we shouldn't
1980 		 * take that hit when neither kext is loaded.
1981 		 */
1982 		newUUID = copyUUID();
1983 		existingUUID = existingKext->copyUUID();
1984 
1985 		/* I'm entirely too paranoid about checking equivalence of executables,
1986 		 * but I remember nasty problems with it in the past.
1987 		 *
1988 		 * - If we have UUIDs for both kexts, compare them.
1989 		 * - If only one kext has a UUID, they're definitely different.
1990 		 */
1991 		if (newUUID && existingUUID) {
1992 			sameExecutable = newUUID->isEqualTo(existingUUID);
1993 		} else if (newUUID || existingUUID) {
1994 			sameExecutable = false;
1995 		}
1996 
1997 		if (!newUUID && !existingUUID) {
1998 			/* If there are no UUIDs, we can't really tell that the executables
1999 			 * are *different* without a lot of work; the loaded kext's
2000 			 * unrelocated executable is no longer around (and we never had it
2001 			 * in-kernel for a prelinked kext). We certainly don't want to do
2002 			 * a whole fake link for the new kext just to compare, either.
2003 			 */
2004 
2005 			OSKextVersionGetString(version, newVersionCString,
2006 			    sizeof(newVersionCString));
2007 			OSKextLog(this,
2008 			    kOSKextLogWarningLevel |
2009 			    kOSKextLogKextBookkeepingFlag,
2010 			    "Notice - new kext %s, v%s matches %s kext "
2011 			    "but can't determine if executables are the same (no UUIDs).",
2012 			    getIdentifierCString(),
2013 			    newVersionCString,
2014 			    (existingIsLoaded ? "loaded" : "prelinked"));
2015 		}
2016 
2017 		if (sameVersion && sameExecutable) {
2018 			OSKextLog(this,
2019 			    (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
2020 			    kOSKextLogKextBookkeepingFlag,
2021 			    "Refusing new kext %s, v%s: a %s copy is already present "
2022 			    "(same version and executable).",
2023 			    getIdentifierCString(), newVersionCString,
2024 			    (existingIsLoaded ? "loaded" : "prelinked"));
2025 		} else {
2026 			if (!sameVersion) {
2027 				/* This condition is significant so log it under warnings.
2028 				 */
2029 				OSKextLog(this,
2030 				    kOSKextLogWarningLevel |
2031 				    kOSKextLogKextBookkeepingFlag,
2032 				    "Refusing new kext %s, v%s: already have %s v%s.",
2033 				    getIdentifierCString(),
2034 				    newVersionCString,
2035 				    (existingIsLoaded ? "loaded" : "prelinked"),
2036 				    existingVersionCString);
2037 			} else {
2038 				/* This condition is significant so log it under warnings.
2039 				 */
2040 				OSKextLog(this,
2041 				    kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2042 				    "Refusing new kext %s, v%s: a %s copy with a different "
2043 				    "executable UUID is already present.",
2044 				    getIdentifierCString(), newVersionCString,
2045 				    (existingIsLoaded ? "loaded" : "prelinked"));
2046 			}
2047 		}
2048 		goto finish;
2049 	} /* if (existingIsLoaded || existingIsPrelinked) */
2050 
2051 	/* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2052 	 * user loads are happening or if we're still in early boot. User agents are
2053 	 * supposed to resolve dependencies topside and include only the exact
2054 	 * kexts needed; so we always accept the new kext (in fact we should never
2055 	 * see an older unloaded copy hanging around).
2056 	 */
2057 	if (sUserLoadsActive) {
2058 		sKextsByID->setObject(bundleID, this);
2059 		result = true;
2060 
2061 		OSKextLog(this,
2062 		    kOSKextLogStepLevel |
2063 		    kOSKextLogKextBookkeepingFlag,
2064 		    "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2065 		    getIdentifierCString(),
2066 		    existingVersionCString,
2067 		    newVersionCString);
2068 
2069 		goto finish;
2070 	}
2071 
2072 	/* During early boot, the kext with the highest version always wins out.
2073 	 * Prelinked kernels will never hit this, but mkexts and booter-read
2074 	 * kexts might have duplicates.
2075 	 */
2076 	if (newVersion > existingVersion) {
2077 		sKextsByID->setObject(bundleID, this);
2078 		result = true;
2079 
2080 		OSKextLog(this,
2081 		    kOSKextLogStepLevel |
2082 		    kOSKextLogKextBookkeepingFlag,
2083 		    "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2084 		    existingVersionCString,
2085 		    getIdentifierCString(),
2086 		    newVersionCString);
2087 	} else {
2088 		OSKextLog(this,
2089 		    kOSKextLogStepLevel |
2090 		    kOSKextLogKextBookkeepingFlag,
2091 		    "Kext %s is already registered with a higher/same version (v%s); "
2092 		    "dropping newly-added (v%s).",
2093 		    getIdentifierCString(),
2094 		    existingVersionCString,
2095 		    newVersionCString);
2096 	}
2097 
2098 	/* result has been set appropriately by now. */
2099 
2100 finish:
2101 
2102 	IORecursiveLockUnlock(sKextLock);
2103 
2104 	if (result) {
2105 		OSKextLog(this,
2106 		    kOSKextLogStepLevel |
2107 		    kOSKextLogKextBookkeepingFlag,
2108 		    "Kext %s, v%s registered and available for loading.",
2109 		    getIdentifierCString(), newVersionCString);
2110 	}
2111 
2112 	OSSafeReleaseNULL(newUUID);
2113 	OSSafeReleaseNULL(existingUUID);
2114 
2115 	return result;
2116 }
2117 
2118 /*********************************************************************
2119  * Does the bare minimum validation to look up a kext.
2120  * All other validation is done on the spot as needed.
2121  **********************************************************************/
2122 bool
2123 OSKext::setInfoDictionaryAndPath(
2124 	OSDictionary * aDictionary,
2125 	OSString     * aPath)
2126 {
2127 	bool           result                   = false;
2128 	OSString     * bundleIDString           = NULL;// do not release
2129 	OSString     * versionString            = NULL;// do not release
2130 	OSString     * compatibleVersionString  = NULL;// do not release
2131 	const char   * versionCString           = NULL;// do not free
2132 	const char   * compatibleVersionCString = NULL;// do not free
2133 	OSBoolean    * scratchBool              = NULL;// do not release
2134 	OSDictionary * scratchDict              = NULL;// do not release
2135 
2136 	if (infoDict) {
2137 		panic("Attempt to set info dictionary on a kext "
2138 		    "that already has one (%s).",
2139 		    getIdentifierCString());
2140 	}
2141 
2142 	if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
2143 		goto finish;
2144 	}
2145 
2146 	infoDict = aDictionary;
2147 	infoDict->retain();
2148 
2149 	/* Check right away if the info dictionary has any log flags.
2150 	 */
2151 	scratchBool = OSDynamicCast(OSBoolean,
2152 	    getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
2153 	if (scratchBool == kOSBooleanTrue) {
2154 		flags.loggingEnabled = 1;
2155 	}
2156 
2157 	/* The very next thing to get is the bundle identifier. Unlike
2158 	 * in user space, a kext with no bundle identifier gets axed
2159 	 * immediately.
2160 	 */
2161 	bundleIDString = OSDynamicCast(OSString,
2162 	    getPropertyForHostArch(kCFBundleIdentifierKey));
2163 	if (!bundleIDString) {
2164 		OSKextLog(this,
2165 		    kOSKextLogErrorLevel |
2166 		    kOSKextLogValidationFlag,
2167 		    "CFBundleIdentifier missing/invalid type in kext %s.",
2168 		    aPath ? aPath->getCStringNoCopy() : "(unknown)");
2169 		goto finish;
2170 	}
2171 	bundleID = OSSymbol::withString(bundleIDString);
2172 	if (!bundleID) {
2173 		OSKextLog(this,
2174 		    kOSKextLogErrorLevel |
2175 		    kOSKextLogValidationFlag,
2176 		    "Can't copy bundle identifier as symbol for kext %s.",
2177 		    bundleIDString->getCStringNoCopy());
2178 		goto finish;
2179 	}
2180 
2181 	/* Save the path if we got one (it should always be available but it's
2182 	 * just something nice to have for bookkeeping).
2183 	 */
2184 	if (aPath) {
2185 		path = aPath;
2186 		path->retain();
2187 	}
2188 
2189 	/*****
2190 	 * Minimal validation to initialize. We'll do other validation on the spot.
2191 	 */
2192 	if (bundleID->getLength() >= KMOD_MAX_NAME) {
2193 		OSKextLog(this,
2194 		    kOSKextLogErrorLevel |
2195 		    kOSKextLogValidationFlag,
2196 		    "Kext %s error - CFBundleIdentifier over max length %d.",
2197 		    getIdentifierCString(), KMOD_MAX_NAME - 1);
2198 		goto finish;
2199 	}
2200 
2201 	version = compatibleVersion = -1;
2202 
2203 	versionString = OSDynamicCast(OSString,
2204 	    getPropertyForHostArch(kCFBundleVersionKey));
2205 	if (!versionString) {
2206 		OSKextLog(this,
2207 		    kOSKextLogErrorLevel |
2208 		    kOSKextLogValidationFlag,
2209 		    "Kext %s error - CFBundleVersion missing/invalid type.",
2210 		    getIdentifierCString());
2211 		goto finish;
2212 	}
2213 	versionCString = versionString->getCStringNoCopy();
2214 	version = OSKextParseVersionString(versionCString);
2215 	if (version < 0) {
2216 		OSKextLog(this,
2217 		    kOSKextLogErrorLevel |
2218 		    kOSKextLogValidationFlag,
2219 		    "Kext %s error - CFBundleVersion bad value '%s'.",
2220 		    getIdentifierCString(), versionCString);
2221 		goto finish;
2222 	}
2223 
2224 	compatibleVersion = -1; // set to illegal value for kexts that don't have
2225 
2226 	compatibleVersionString = OSDynamicCast(OSString,
2227 	    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
2228 	if (compatibleVersionString) {
2229 		compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
2230 		compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
2231 		if (compatibleVersion < 0) {
2232 			OSKextLog(this,
2233 			    kOSKextLogErrorLevel |
2234 			    kOSKextLogValidationFlag,
2235 			    "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2236 			    getIdentifierCString(), compatibleVersionCString);
2237 			goto finish;
2238 		}
2239 
2240 		if (compatibleVersion > version) {
2241 			OSKextLog(this,
2242 			    kOSKextLogErrorLevel |
2243 			    kOSKextLogValidationFlag,
2244 			    "Kext %s error - %s %s > %s %s (must be <=).",
2245 			    getIdentifierCString(),
2246 			    kOSBundleCompatibleVersionKey, compatibleVersionCString,
2247 			    kCFBundleVersionKey, versionCString);
2248 			goto finish;
2249 		}
2250 	}
2251 
2252 	/* Check to see if this kext is in exclude list */
2253 	if (isInExcludeList()) {
2254 		OSKextLog(this,
2255 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2256 		    "Kext %s is in exclude list, not loadable",
2257 		    getIdentifierCString());
2258 		goto finish;
2259 	}
2260 
2261 	/* Set flags for later use if the infoDict gets flushed. We only
2262 	 * check for true values, not false ones(!)
2263 	 */
2264 	scratchBool = OSDynamicCast(OSBoolean,
2265 	    getPropertyForHostArch(kOSBundleIsInterfaceKey));
2266 	if (scratchBool == kOSBooleanTrue) {
2267 		flags.interface = 1;
2268 	}
2269 
2270 	scratchBool = OSDynamicCast(OSBoolean,
2271 	    getPropertyForHostArch(kOSKernelResourceKey));
2272 	if (scratchBool == kOSBooleanTrue) {
2273 		flags.kernelComponent = 1;
2274 		flags.interface = 1; // xxx - hm. the kernel itself isn't an interface...
2275 		flags.started = 1;
2276 
2277 		/* A kernel component has one implicit dependency on the kernel.
2278 		 */
2279 		flags.hasAllDependencies = 1;
2280 	}
2281 
2282 	/* Make sure common string values in personalities are uniqued to OSSymbols.
2283 	 */
2284 	scratchDict = OSDynamicCast(OSDictionary,
2285 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
2286 	if (scratchDict) {
2287 		uniquePersonalityProperties(scratchDict);
2288 	}
2289 
2290 	result = true;
2291 
2292 finish:
2293 
2294 	return result;
2295 }
2296 
2297 /*********************************************************************
2298 * Not used for prelinked kernel boot as there is no unrelocated
2299 * executable.
2300 *********************************************************************/
2301 bool
2302 OSKext::setExecutable(
2303 	OSData * anExecutable,
2304 	OSData * externalData,
2305 	bool     externalDataIsMkext)
2306 {
2307 	bool         result        = false;
2308 	const char * executableKey = NULL; // do not free
2309 
2310 	if (!anExecutable) {
2311 		infoDict->removeObject(_kOSKextExecutableKey);
2312 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
2313 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
2314 		result = true;
2315 		goto finish;
2316 	}
2317 
2318 	if (infoDict->getObject(_kOSKextExecutableKey) ||
2319 	    infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
2320 		panic("Attempt to set an executable on a kext "
2321 		    "that already has one (%s).",
2322 		    getIdentifierCString());
2323 		goto finish;
2324 	}
2325 
2326 	if (externalDataIsMkext) {
2327 		executableKey = _kOSKextMkextExecutableReferenceKey;
2328 	} else {
2329 		executableKey = _kOSKextExecutableKey;
2330 	}
2331 
2332 	if (anExecutable) {
2333 		infoDict->setObject(executableKey, anExecutable);
2334 		if (externalData) {
2335 			infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
2336 		}
2337 	}
2338 
2339 	result = true;
2340 
2341 finish:
2342 	return result;
2343 }
2344 
2345 /*********************************************************************
2346 *********************************************************************/
2347 static void
2348 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
2349 {
2350 	OSString       * stringValue = NULL;// do not release
2351 	const OSSymbol * symbolValue = NULL; // must release
2352 
2353 	stringValue = OSDynamicCast(OSString, dict->getObject(key));
2354 	if (!stringValue) {
2355 		goto finish;
2356 	}
2357 
2358 	symbolValue = OSSymbol::withString(stringValue);
2359 	if (!symbolValue) {
2360 		goto finish;
2361 	}
2362 
2363 	dict->setObject(key, symbolValue);
2364 
2365 finish:
2366 	if (symbolValue) {
2367 		symbolValue->release();
2368 	}
2369 
2370 	return;
2371 }
2372 
2373 /*********************************************************************
2374 *********************************************************************/
2375 static void
2376 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
2377 {
2378 	OSString       * stringValue = NULL;// do not release
2379 	const OSSymbol * symbolValue = NULL; // must release
2380 
2381 	stringValue = OSDynamicCast(OSString, dict->getObject(key));
2382 	if (!stringValue) {
2383 		goto finish;
2384 	}
2385 
2386 	symbolValue = OSSymbol::withString(stringValue);
2387 	if (!symbolValue) {
2388 		goto finish;
2389 	}
2390 
2391 	dict->setObject(key, symbolValue);
2392 
2393 finish:
2394 	if (symbolValue) {
2395 		symbolValue->release();
2396 	}
2397 
2398 	return;
2399 }
2400 
2401 /*********************************************************************
2402 * Replace common personality property values with uniqued instances
2403 * to save on wired memory.
2404 *********************************************************************/
2405 /* static */
2406 void
2407 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
2408 {
2409 	/* Properties every personality has.
2410 	 */
2411 	uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
2412 	uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
2413 	uniqueStringPlistProperty(personalityDict, gIOClassKey);
2414 	if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) {
2415 		uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey);
2416 	} else {
2417 		personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey));
2418 	}
2419 
2420 	/* Other commonly used properties.
2421 	 */
2422 	uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
2423 	uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
2424 	uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
2425 
2426 	uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
2427 	uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
2428 	uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
2429 	uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
2430 	uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
2431 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
2432 	uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
2433 	uniqueStringPlistProperty(personalityDict, "Vendor");
2434 	uniqueStringPlistProperty(personalityDict, "Vendor Identification");
2435 	uniqueStringPlistProperty(personalityDict, "Vendor Name");
2436 	uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
2437 	uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
2438 	uniqueStringPlistProperty(personalityDict, "idProduct");
2439 
2440 	return;
2441 }
2442 
2443 /*********************************************************************
2444 *********************************************************************/
2445 void
2446 OSKext::free(void)
2447 {
2448 	if (isLoaded()) {
2449 		panic("Attempt to free loaded kext %s.", getIdentifierCString());
2450 	}
2451 
2452 	OSSafeReleaseNULL(infoDict);
2453 	OSSafeReleaseNULL(bundleID);
2454 	OSSafeReleaseNULL(path);
2455 	OSSafeReleaseNULL(executableRelPath);
2456 	OSSafeReleaseNULL(userExecutableRelPath);
2457 	OSSafeReleaseNULL(dependencies);
2458 	OSSafeReleaseNULL(linkedExecutable);
2459 	OSSafeReleaseNULL(metaClasses);
2460 	OSSafeReleaseNULL(interfaceUUID);
2461 	OSSafeReleaseNULL(driverKitUUID);
2462 
2463 	if (isInterface() && kmod_info) {
2464 		kfree(kmod_info, sizeof(kmod_info_t));
2465 	}
2466 
2467 	super::free();
2468 	return;
2469 }
2470 
2471 #if PRAGMA_MARK
2472 #pragma mark Mkext files
2473 #endif
2474 /*********************************************************************
2475 *********************************************************************/
2476 OSReturn
2477 OSKext::readMkextArchive(OSData * mkextData,
2478     uint32_t * checksumPtr)
2479 {
2480 	OSReturn       result       = kOSKextReturnBadData;
2481 	uint32_t       mkextLength  = 0;
2482 	mkext_header * mkextHeader  = NULL;// do not free
2483 	uint32_t       mkextVersion = 0;
2484 
2485 	/* Note default return of kOSKextReturnBadData above.
2486 	 */
2487 	mkextLength = mkextData->getLength();
2488 	if (mkextLength < sizeof(mkext_basic_header)) {
2489 		OSKextLog(/* kext */ NULL,
2490 		    kOSKextLogErrorLevel |
2491 		    kOSKextLogArchiveFlag,
2492 		    "Mkext archive too small to be valid.");
2493 		goto finish;
2494 	}
2495 
2496 	mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
2497 
2498 	if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
2499 	    MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
2500 		OSKextLog(/* kext */ NULL,
2501 		    kOSKextLogErrorLevel |
2502 		    kOSKextLogArchiveFlag,
2503 		    "Mkext archive has invalid magic or signature.");
2504 		goto finish;
2505 	}
2506 
2507 	if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
2508 		OSKextLog(/* kext */ NULL,
2509 		    kOSKextLogErrorLevel |
2510 		    kOSKextLogArchiveFlag,
2511 		    "Mkext archive recorded length doesn't match actual file length.");
2512 		goto finish;
2513 	}
2514 
2515 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2516 
2517 	if (mkextVersion == MKEXT_VERS_2) {
2518 		result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
2519 	} else {
2520 		OSKextLog(/* kext */ NULL,
2521 		    kOSKextLogErrorLevel |
2522 		    kOSKextLogArchiveFlag,
2523 		    "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
2524 		result = kOSKextReturnUnsupported;
2525 	}
2526 
2527 finish:
2528 	return result;
2529 }
2530 
2531 /*********************************************************************
2532 * Assumes magic, signature, version, length have been checked.
2533 * xxx - need to add further bounds checking for each file entry
2534 *
2535 * Should keep track of all kexts created so far, and if we hit a
2536 * fatal error halfway through, remove those kexts. If we've dropped
2537 * an older version that had already been read, whoops! Might want to
2538 * add a level of buffering?
2539 *********************************************************************/
2540 /* static */
2541 OSReturn
2542 OSKext::readMkext2Archive(
2543 	OSData        * mkextData,
2544 	OSDictionary ** mkextPlistOut,
2545 	uint32_t      * checksumPtr)
2546 {
2547 	OSReturn        result                     = kOSReturnError;
2548 	uint32_t        mkextLength;
2549 	mkext2_header * mkextHeader                = NULL;// do not free
2550 	void          * mkextEnd                   = NULL;// do not free
2551 	uint32_t        mkextVersion;
2552 	uint8_t       * crc_address                = NULL;
2553 	uint32_t        checksum;
2554 	uint32_t        mkextPlistOffset;
2555 	uint32_t        mkextPlistCompressedSize;
2556 	char          * mkextPlistEnd              = NULL;// do not free
2557 	uint32_t        mkextPlistFullSize;
2558 	OSString      * errorString                = NULL;// must release
2559 	OSData        * mkextPlistUncompressedData = NULL;// must release
2560 	const char    * mkextPlistDataBuffer       = NULL;// do not free
2561 	OSObject      * parsedXML                  = NULL;// must release
2562 	OSDictionary  * mkextPlist                 = NULL;// do not release
2563 	OSArray       * mkextInfoDictArray         = NULL;// do not release
2564 	uint32_t        count, i;
2565 
2566 	mkextLength = mkextData->getLength();
2567 	mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
2568 	mkextEnd = (char *)mkextHeader + mkextLength;
2569 	mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2570 
2571 	crc_address = (u_int8_t *)&mkextHeader->version;
2572 	checksum = mkext_adler32(crc_address,
2573 	    (uintptr_t)mkextHeader +
2574 	    MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address);
2575 
2576 	if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
2577 		OSKextLog(/* kext */ NULL,
2578 		    kOSKextLogErrorLevel |
2579 		    kOSKextLogArchiveFlag,
2580 		    "Mkext archive has bad checksum.");
2581 		result = kOSKextReturnBadData;
2582 		goto finish;
2583 	}
2584 
2585 	if (checksumPtr) {
2586 		*checksumPtr = checksum;
2587 	}
2588 
2589 	/* Check that the CPU type & subtype match that of the running kernel. */
2590 	if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
2591 		OSKextLog(/* kext */ NULL,
2592 		    kOSKextLogErrorLevel |
2593 		    kOSKextLogArchiveFlag,
2594 		    "Mkext archive must have a specific CPU type.");
2595 		result = kOSKextReturnBadData;
2596 		goto finish;
2597 	} else {
2598 		if ((UInt32)_mh_execute_header.cputype !=
2599 		    MKEXT_GET_CPUTYPE(mkextHeader)) {
2600 			OSKextLog(/* kext */ NULL,
2601 			    kOSKextLogErrorLevel |
2602 			    kOSKextLogArchiveFlag,
2603 			    "Mkext archive does not match the running kernel's CPU type.");
2604 			result = kOSKextReturnArchNotFound;
2605 			goto finish;
2606 		}
2607 	}
2608 
2609 	mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
2610 	mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
2611 	mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
2612 	    mkextPlistCompressedSize;
2613 	if (mkextPlistEnd > mkextEnd) {
2614 		OSKextLog(/* kext */ NULL,
2615 		    kOSKextLogErrorLevel |
2616 		    kOSKextLogArchiveFlag,
2617 		    "Mkext archive file overrun.");
2618 		result = kOSKextReturnBadData;
2619 	}
2620 
2621 	mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
2622 	if (mkextPlistCompressedSize) {
2623 		mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
2624 			(UInt8 *)mkextHeader + mkextPlistOffset,
2625 			"plist",
2626 			mkextPlistCompressedSize, mkextPlistFullSize);
2627 		if (!mkextPlistUncompressedData) {
2628 			goto finish;
2629 		}
2630 		mkextPlistDataBuffer = (const char *)
2631 		    mkextPlistUncompressedData->getBytesNoCopy();
2632 	} else {
2633 		mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
2634 	}
2635 
2636 	/* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2637 	 */
2638 	parsedXML = OSUnserializeXML(mkextPlistDataBuffer, &errorString);
2639 	if (parsedXML) {
2640 		mkextPlist = OSDynamicCast(OSDictionary, parsedXML);
2641 	}
2642 	if (!mkextPlist) {
2643 		const char * errorCString = "(unknown error)";
2644 
2645 		if (errorString && errorString->getCStringNoCopy()) {
2646 			errorCString = errorString->getCStringNoCopy();
2647 		} else if (parsedXML) {
2648 			errorCString = "not a dictionary";
2649 		}
2650 		OSKextLog(/* kext */ NULL,
2651 		    kOSKextLogErrorLevel |
2652 		    kOSKextLogArchiveFlag,
2653 		    "Error unserializing mkext plist: %s.", errorCString);
2654 		goto finish;
2655 	}
2656 
2657 	/* If the caller needs the plist, hand it back and retain it.
2658 	 * (This function releases it at the end.)
2659 	 */
2660 	if (mkextPlistOut) {
2661 		*mkextPlistOut = mkextPlist;
2662 		(*mkextPlistOut)->retain();
2663 	}
2664 
2665 	mkextInfoDictArray = OSDynamicCast(OSArray,
2666 	    mkextPlist->getObject(kMKEXTInfoDictionariesKey));
2667 	if (!mkextInfoDictArray) {
2668 		OSKextLog(/* kext */ NULL,
2669 		    kOSKextLogErrorLevel |
2670 		    kOSKextLogArchiveFlag,
2671 		    "Mkext archive contains no kext info dictionaries.");
2672 		goto finish;
2673 	}
2674 
2675 	count = mkextInfoDictArray->getCount();
2676 	for (i = 0; i < count; i++) {
2677 		OSDictionary * infoDict;
2678 
2679 
2680 		infoDict = OSDynamicCast(OSDictionary,
2681 		    mkextInfoDictArray->getObject(i));
2682 
2683 		/* Create the kext for the entry, then release it, because the
2684 		 * kext system keeps them around until explicitly removed.
2685 		 * Any creation/registration failures are already logged for us.
2686 		 */
2687 		if (infoDict) {
2688 			OSKext * newKext = OSKext::withMkext2Info(infoDict, mkextData);
2689 			OSSafeReleaseNULL(newKext);
2690 		}
2691 	}
2692 
2693 	/* Even if we didn't keep any kexts from the mkext, we may have a load
2694 	 * request to process, so we are successful (no errors occurred).
2695 	 */
2696 	result = kOSReturnSuccess;
2697 
2698 finish:
2699 
2700 	OSSafeReleaseNULL(parsedXML);
2701 	OSSafeReleaseNULL(mkextPlistUncompressedData);
2702 	OSSafeReleaseNULL(errorString);
2703 
2704 	return result;
2705 }
2706 
2707 /*********************************************************************
2708 *********************************************************************/
2709 /* static */
2710 OSKext *
2711 OSKext::withMkext2Info(
2712 	OSDictionary * anInfoDict,
2713 	OSData       * mkextData)
2714 {
2715 	OSKext * newKext = new OSKext;
2716 
2717 	if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
2718 		newKext->release();
2719 		return NULL;
2720 	}
2721 
2722 	return newKext;
2723 }
2724 
2725 /*********************************************************************
2726 *********************************************************************/
2727 bool
2728 OSKext::initWithMkext2Info(
2729 	OSDictionary * anInfoDict,
2730 	OSData       * mkextData)
2731 {
2732 	bool                   result              = false;
2733 	OSString             * kextPath            = NULL;// do not release
2734 	OSNumber             * executableOffsetNum = NULL;// do not release
2735 	OSCollectionIterator * iterator            = NULL;// must release
2736 	OSData               * executable          = NULL;// must release
2737 
2738 	if (anInfoDict == NULL || !super::init()) {
2739 		goto finish;
2740 	}
2741 
2742 	/* Get the path. Don't look for an arch-specific path property.
2743 	 */
2744 	kextPath = OSDynamicCast(OSString,
2745 	    anInfoDict->getObject(kMKEXTBundlePathKey));
2746 
2747 	if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2748 		goto finish;
2749 	}
2750 
2751 	/* If we have a path to the executable, save it.
2752 	 */
2753 	executableRelPath = OSDynamicCast(OSString,
2754 	    anInfoDict->getObject(kMKEXTExecutableRelativePathKey));
2755 	if (executableRelPath) {
2756 		executableRelPath->retain();
2757 	}
2758 
2759 	/* Don't need the paths to be in the info dictionary any more.
2760 	 */
2761 	anInfoDict->removeObject(kMKEXTBundlePathKey);
2762 	anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
2763 
2764 	executableOffsetNum = OSDynamicCast(OSNumber,
2765 	    infoDict->getObject(kMKEXTExecutableKey));
2766 	if (executableOffsetNum) {
2767 		executable = createMkext2FileEntry(mkextData,
2768 		    executableOffsetNum, "executable");
2769 		infoDict->removeObject(kMKEXTExecutableKey);
2770 		if (!executable) {
2771 			goto finish;
2772 		}
2773 		if (!setExecutable(executable, mkextData, true)) {
2774 			goto finish;
2775 		}
2776 	}
2777 
2778 	result = registerIdentifier();
2779 
2780 finish:
2781 
2782 	OSSafeReleaseNULL(executable);
2783 	OSSafeReleaseNULL(iterator);
2784 	return result;
2785 }
2786 
2787 /*********************************************************************
2788 *********************************************************************/
2789 OSData *
2790 OSKext::createMkext2FileEntry(
2791 	OSData     * mkextData,
2792 	OSNumber   * offsetNum,
2793 	const char * name)
2794 {
2795 	OSData        * result      = NULL;
2796 	MkextEntryRef   entryRef;
2797 	uint8_t       * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
2798 	uint32_t        entryOffset = offsetNum->unsigned32BitValue();
2799 
2800 	result = OSData::withCapacity(sizeof(entryRef));
2801 	if (!result) {
2802 		goto finish;
2803 	}
2804 
2805 	entryRef.mkext = (mkext_basic_header *)mkextBuffer;
2806 	entryRef.fileinfo = mkextBuffer + entryOffset;
2807 	if (!result->appendBytes(&entryRef, sizeof(entryRef))) {
2808 		OSSafeReleaseNULL(result);
2809 		goto finish;
2810 	}
2811 
2812 finish:
2813 	if (!result) {
2814 		OSKextLog(this,
2815 		    kOSKextLogErrorLevel |
2816 		    kOSKextLogArchiveFlag,
2817 		    "Can't create wrapper for mkext file entry '%s' of kext %s.",
2818 		    name, getIdentifierCString());
2819 	}
2820 	return result;
2821 }
2822 
2823 /*********************************************************************
2824 *********************************************************************/
2825 extern "C" {
2826 static void * z_alloc(void *, u_int items, u_int size);
2827 static void   z_free(void *, void *ptr);
2828 
2829 typedef struct z_mem {
2830 	uint32_t alloc_size;
2831 	uint8_t  data[0];
2832 } z_mem;
2833 
2834 /*
2835  * Space allocation and freeing routines for use by zlib routines.
2836  */
2837 void *
2838 z_alloc(void * notused __unused, u_int num_items, u_int size)
2839 {
2840 	void     * result = NULL;
2841 	z_mem    * zmem = NULL;
2842 
2843 	uint64_t   total = ((uint64_t)num_items) * ((uint64_t)size);
2844 	//Check for overflow due to multiplication
2845 	if (total > UINT32_MAX) {
2846 		panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
2847 		    notused, num_items, size, num_items, size);
2848 	}
2849 
2850 	uint64_t   allocSize64 =  total + ((uint64_t)sizeof(zmem));
2851 	//Check for overflow due to addition
2852 	if (allocSize64 > UINT32_MAX) {
2853 		panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
2854 		    notused, num_items, size, (uint32_t)total, sizeof(zmem));
2855 	}
2856 	uint32_t allocSize = (uint32_t)allocSize64;
2857 
2858 	zmem = (z_mem *)kalloc_tag(allocSize, VM_KERN_MEMORY_OSKEXT);
2859 	if (!zmem) {
2860 		goto finish;
2861 	}
2862 	zmem->alloc_size = allocSize;
2863 	result = (void *)&(zmem->data);
2864 finish:
2865 	return result;
2866 }
2867 
2868 void
2869 z_free(void * notused __unused, void * ptr)
2870 {
2871 	uint32_t * skipper = (uint32_t *)ptr - 1;
2872 	z_mem    * zmem = (z_mem *)skipper;
2873 	kfree(zmem, zmem->alloc_size);
2874 	return;
2875 }
2876 };
2877 
2878 OSData *
2879 OSKext::extractMkext2FileData(
2880 	UInt8      * data,
2881 	const char * name,
2882 	uint32_t     compressedSize,
2883 	uint32_t     fullSize)
2884 {
2885 	OSData      * result = NULL;
2886 
2887 	OSData      * uncompressedData = NULL;// release on error
2888 
2889 	uint8_t     * uncompressedDataBuffer = NULL;// do not free
2890 	unsigned long uncompressedSize;
2891 	z_stream      zstream;
2892 	bool          zstream_inited = false;
2893 	int           zlib_result;
2894 
2895 	/* If the file isn't compressed, we want to make a copy
2896 	 * so that we don't have the tie to the larger mkext file buffer any more.
2897 	 */
2898 	if (!compressedSize) {
2899 		uncompressedData = OSData::withBytes(data, fullSize);
2900 		// xxx - no check for failure?
2901 		result = uncompressedData;
2902 		goto finish;
2903 	}
2904 
2905 	if (KERN_SUCCESS != kmem_alloc(kernel_map,
2906 	    (vm_offset_t*)&uncompressedDataBuffer, fullSize, VM_KERN_MEMORY_OSKEXT)) {
2907 		/* How's this for cheesy? The kernel is only asked to extract
2908 		 * kext plists so we tailor the log messages.
2909 		 */
2910 		if (isKernel()) {
2911 			OSKextLog(this,
2912 			    kOSKextLogErrorLevel |
2913 			    kOSKextLogArchiveFlag,
2914 			    "Allocation failure extracting %s from mkext.", name);
2915 		} else {
2916 			OSKextLog(this,
2917 			    kOSKextLogErrorLevel |
2918 			    kOSKextLogArchiveFlag,
2919 			    "Allocation failure extracting %s from mkext for kext %s.",
2920 			    name, getIdentifierCString());
2921 		}
2922 
2923 		goto finish;
2924 	}
2925 	uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
2926 	if (!uncompressedData) {
2927 		if (isKernel()) {
2928 			OSKextLog(this,
2929 			    kOSKextLogErrorLevel |
2930 			    kOSKextLogArchiveFlag,
2931 			    "Allocation failure extracting %s from mkext.", name);
2932 		} else {
2933 			OSKextLog(this,
2934 			    kOSKextLogErrorLevel |
2935 			    kOSKextLogArchiveFlag,
2936 			    "Allocation failure extracting %s from mkext for kext %s.",
2937 			    name, getIdentifierCString());
2938 		}
2939 		goto finish;
2940 	}
2941 	uncompressedData->setDeallocFunction(&osdata_kmem_free);
2942 
2943 	if (isKernel()) {
2944 		OSKextLog(this,
2945 		    kOSKextLogDetailLevel |
2946 		    kOSKextLogArchiveFlag,
2947 		    "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2948 		    name, compressedSize, fullSize);
2949 	} else {
2950 		OSKextLog(this,
2951 		    kOSKextLogDetailLevel |
2952 		    kOSKextLogArchiveFlag,
2953 		    "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2954 		    getIdentifierCString(), name, compressedSize, fullSize);
2955 	}
2956 
2957 	bzero(&zstream, sizeof(zstream));
2958 	zstream.next_in   = (UInt8 *)data;
2959 	zstream.avail_in  = compressedSize;
2960 
2961 	zstream.next_out  = uncompressedDataBuffer;
2962 	zstream.avail_out = fullSize;
2963 
2964 	zstream.zalloc    = z_alloc;
2965 	zstream.zfree     = z_free;
2966 
2967 	zlib_result = inflateInit(&zstream);
2968 	if (Z_OK != zlib_result) {
2969 		if (isKernel()) {
2970 			OSKextLog(this,
2971 			    kOSKextLogErrorLevel |
2972 			    kOSKextLogArchiveFlag,
2973 			    "Mkext error; zlib inflateInit failed (%d) for %s.",
2974 			    zlib_result, name);
2975 		} else {
2976 			OSKextLog(this,
2977 			    kOSKextLogErrorLevel |
2978 			    kOSKextLogArchiveFlag,
2979 			    "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2980 			    getIdentifierCString(), zlib_result, name);
2981 		}
2982 		goto finish;
2983 	} else {
2984 		zstream_inited = true;
2985 	}
2986 
2987 	zlib_result = inflate(&zstream, Z_FINISH);
2988 
2989 	if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
2990 		uncompressedSize = zstream.total_out;
2991 	} else {
2992 		if (isKernel()) {
2993 			OSKextLog(this,
2994 			    kOSKextLogErrorLevel |
2995 			    kOSKextLogArchiveFlag,
2996 			    "Mkext error; zlib inflate failed (%d) for %s.",
2997 			    zlib_result, name);
2998 		} else {
2999 			OSKextLog(this,
3000 			    kOSKextLogErrorLevel |
3001 			    kOSKextLogArchiveFlag,
3002 			    "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3003 			    getIdentifierCString(), zlib_result, name);
3004 		}
3005 		if (zstream.msg) {
3006 			OSKextLog(this,
3007 			    kOSKextLogErrorLevel |
3008 			    kOSKextLogArchiveFlag,
3009 			    "zlib error: %s.", zstream.msg);
3010 		}
3011 		goto finish;
3012 	}
3013 
3014 	if (uncompressedSize != fullSize) {
3015 		if (isKernel()) {
3016 			OSKextLog(this,
3017 			    kOSKextLogErrorLevel |
3018 			    kOSKextLogArchiveFlag,
3019 			    "Mkext error; zlib inflate discrepancy for %s, "
3020 			    "uncompressed size != original size.", name);
3021 		} else {
3022 			OSKextLog(this,
3023 			    kOSKextLogErrorLevel |
3024 			    kOSKextLogArchiveFlag,
3025 			    "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3026 			    "uncompressed size != original size.",
3027 			    getIdentifierCString(), name);
3028 		}
3029 		goto finish;
3030 	}
3031 
3032 	result = uncompressedData;
3033 
3034 finish:
3035 	/* Don't bother checking return, nothing we can do on fail.
3036 	 */
3037 	if (zstream_inited) {
3038 		inflateEnd(&zstream);
3039 	}
3040 
3041 	if (!result) {
3042 		OSSafeReleaseNULL(uncompressedData);
3043 	}
3044 
3045 	return result;
3046 }
3047 
3048 /*********************************************************************
3049 *********************************************************************/
3050 /* static */
3051 OSReturn
3052 OSKext::loadFromMkext(
3053 	OSKextLogSpec   clientLogFilter,
3054 	char          * mkextBuffer,
3055 	uint32_t        mkextBufferLength,
3056 	char         ** logInfoOut,
3057 	uint32_t      * logInfoLengthOut)
3058 {
3059 	OSReturn         result                      = kOSReturnError;
3060 	OSReturn         tempResult                  = kOSReturnError;
3061 
3062 	OSData         * mkextData                   = NULL;// must release
3063 	OSDictionary   * mkextPlist                  = NULL;// must release
3064 
3065 	OSArray        * logInfoArray                = NULL;// must release
3066 	OSSerialize    * serializer                  = NULL;// must release
3067 
3068 	OSString       * predicate                   = NULL;// do not release
3069 	OSDictionary   * requestArgs                 = NULL;// do not release
3070 
3071 	OSString       * kextIdentifier              = NULL;// do not release
3072 	OSNumber       * startKextExcludeNum         = NULL;// do not release
3073 	OSNumber       * startMatchingExcludeNum     = NULL;// do not release
3074 	OSBoolean      * delayAutounloadBool         = NULL;// do not release
3075 	OSArray        * personalityNames            = NULL;// do not release
3076 
3077 	/* Default values for these two options: regular autounload behavior,
3078 	 * load all kexts, send no personalities.
3079 	 */
3080 	Boolean            delayAutounload           = false;
3081 	OSKextExcludeLevel startKextExcludeLevel     = kOSKextExcludeNone;
3082 	OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3083 
3084 	IORecursiveLockLock(sKextLock);
3085 
3086 	if (logInfoOut) {
3087 		*logInfoOut = NULL;
3088 		*logInfoLengthOut = 0;
3089 	}
3090 
3091 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3092 
3093 	OSKextLog(/* kext */ NULL,
3094 	    kOSKextLogDebugLevel |
3095 	    kOSKextLogIPCFlag,
3096 	    "Received kext load request from user space.");
3097 
3098 	/* Regardless of processing, the fact that we have gotten here means some
3099 	 * user-space program is up and talking to us, so we'll switch our kext
3100 	 * registration to reflect that.
3101 	 */
3102 	if (!sUserLoadsActive) {
3103 		OSKextLog(/* kext */ NULL,
3104 		    kOSKextLogProgressLevel |
3105 		    kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3106 		    "Switching to late startup (user-space) kext loading policy.");
3107 
3108 		sUserLoadsActive = true;
3109 	}
3110 
3111 	if (!sLoadEnabled) {
3112 		OSKextLog(/* kext */ NULL,
3113 		    kOSKextLogErrorLevel |
3114 		    kOSKextLogLoadFlag,
3115 		    "Kext loading is disabled.");
3116 		result = kOSKextReturnDisabled;
3117 		goto finish;
3118 	}
3119 
3120 	/* Note that we do not set a dealloc function on this OSData
3121 	 * object! No references to it can remain after the loadFromMkext()
3122 	 * call since we are in a MIG function, and will vm_deallocate()
3123 	 * the buffer.
3124 	 */
3125 	mkextData = OSData::withBytesNoCopy(mkextBuffer,
3126 	    mkextBufferLength);
3127 	if (!mkextData) {
3128 		OSKextLog(/* kext */ NULL,
3129 		    kOSKextLogErrorLevel |
3130 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3131 		    "Failed to create wrapper for kext load request.");
3132 		result = kOSKextReturnNoMemory;
3133 		goto finish;
3134 	}
3135 
3136 	result = readMkext2Archive(mkextData, &mkextPlist, NULL);
3137 	if (result != kOSReturnSuccess) {
3138 		OSKextLog(/* kext */ NULL,
3139 		    kOSKextLogErrorLevel |
3140 		    kOSKextLogLoadFlag,
3141 		    "Failed to read kext load request.");
3142 		goto finish;
3143 	}
3144 
3145 	predicate = _OSKextGetRequestPredicate(mkextPlist);
3146 	if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3147 		OSKextLog(/* kext */ NULL,
3148 		    kOSKextLogErrorLevel |
3149 		    kOSKextLogLoadFlag,
3150 		    "Received kext load request with no predicate; skipping.");
3151 		result = kOSKextReturnInvalidArgument;
3152 		goto finish;
3153 	}
3154 
3155 	requestArgs = OSDynamicCast(OSDictionary,
3156 	    mkextPlist->getObject(kKextRequestArgumentsKey));
3157 	if (!requestArgs || !requestArgs->getCount()) {
3158 		OSKextLog(/* kext */ NULL,
3159 		    kOSKextLogErrorLevel |
3160 		    kOSKextLogLoadFlag,
3161 		    "Received kext load request with no arguments.");
3162 		result = kOSKextReturnInvalidArgument;
3163 		goto finish;
3164 	}
3165 
3166 	kextIdentifier = OSDynamicCast(OSString,
3167 	    requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3168 
3169 	if (!kextIdentifier) {
3170 		OSKextLog(/* kext */ NULL,
3171 		    kOSKextLogErrorLevel |
3172 		    kOSKextLogLoadFlag,
3173 		    "Received kext load request with no kext identifier.");
3174 		result = kOSKextReturnInvalidArgument;
3175 		goto finish;
3176 	}
3177 
3178 	startKextExcludeNum = OSDynamicCast(OSNumber,
3179 	    requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3180 	startMatchingExcludeNum = OSDynamicCast(OSNumber,
3181 	    requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3182 	delayAutounloadBool = OSDynamicCast(OSBoolean,
3183 	    requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3184 	personalityNames = OSDynamicCast(OSArray,
3185 	    requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3186 
3187 	if (delayAutounloadBool) {
3188 		delayAutounload = delayAutounloadBool->getValue();
3189 	}
3190 	if (startKextExcludeNum) {
3191 		startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3192 	}
3193 	if (startMatchingExcludeNum) {
3194 		startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3195 	}
3196 
3197 	OSKextLog(/* kext */ NULL,
3198 	    kOSKextLogProgressLevel |
3199 	    kOSKextLogIPCFlag,
3200 	    "Received request from user space to load kext %s.",
3201 	    kextIdentifier->getCStringNoCopy());
3202 
3203 	/* Load the kext, with no deferral, since this is a load from outside
3204 	 * the kernel.
3205 	 * xxx - Would like a better way to handle the default values for the
3206 	 * xxx - start/match opt args.
3207 	 */
3208 	result = OSKext::loadKextWithIdentifier(
3209 		kextIdentifier,
3210 		/* kextRef */ NULL,
3211 		/* allowDefer */ false,
3212 		delayAutounload,
3213 		startKextExcludeLevel,
3214 		startMatchingExcludeLevel,
3215 		personalityNames);
3216 	if (result != kOSReturnSuccess) {
3217 		goto finish;
3218 	}
3219 	/* If the load came down from kextd, it will shortly inform IOCatalogue
3220 	 * for matching via a separate IOKit calldown.
3221 	 */
3222 
3223 finish:
3224 
3225 	/* Gather up the collected log messages for user space. Any
3226 	 * error messages past this call will not make it up as log messages
3227 	 * but will be in the system log.
3228 	 */
3229 	logInfoArray = OSKext::clearUserSpaceLogFilter();
3230 
3231 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
3232 		tempResult = OSKext::serializeLogInfo(logInfoArray,
3233 		    logInfoOut, logInfoLengthOut);
3234 		if (tempResult != kOSReturnSuccess) {
3235 			result = tempResult;
3236 		}
3237 	}
3238 
3239 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3240 
3241 	/* Note: mkextDataObject will have been retained by every kext w/an
3242 	 * executable in it. That should all have been flushed out at the
3243 	 * and of the load operation, but you never know....
3244 	 */
3245 	if (mkextData && mkextData->getRetainCount() > 1) {
3246 		OSKextLog(/* kext */ NULL,
3247 		    kOSKextLogErrorLevel |
3248 		    kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3249 		    "Kext load request buffer from user space still retained by a kext; "
3250 		    "probable memory leak.");
3251 	}
3252 
3253 	IORecursiveLockUnlock(sKextLock);
3254 
3255 	OSSafeReleaseNULL(mkextData);
3256 	OSSafeReleaseNULL(mkextPlist);
3257 	OSSafeReleaseNULL(serializer);
3258 	OSSafeReleaseNULL(logInfoArray);
3259 
3260 	return result;
3261 }
3262 
3263 /*********************************************************************
3264 *********************************************************************/
3265 /* static */
3266 OSReturn
3267 OSKext::serializeLogInfo(
3268 	OSArray   * logInfoArray,
3269 	char     ** logInfoOut,
3270 	uint32_t  * logInfoLengthOut)
3271 {
3272 	OSReturn        result      = kOSReturnError;
3273 	char          * buffer      = NULL;
3274 	kern_return_t   kmem_result = KERN_FAILURE;
3275 	OSSerialize  * serializer   = NULL;// must release; reused
3276 	char         * logInfo            = NULL;// returned by reference
3277 	uint32_t       logInfoLength      = 0;
3278 
3279 	if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
3280 		OSKextLog(/* kext */ NULL,
3281 		    kOSKextLogErrorLevel |
3282 		    kOSKextLogIPCFlag,
3283 		    "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3284 		/* Bad programmer. */
3285 		result = kOSKextReturnInvalidArgument;
3286 		goto finish;
3287 	}
3288 
3289 	serializer = OSSerialize::withCapacity(0);
3290 	if (!serializer) {
3291 		OSKextLog(/* kext */ NULL,
3292 		    kOSKextLogErrorLevel |
3293 		    kOSKextLogIPCFlag,
3294 		    "Failed to create serializer on log info for request from user space.");
3295 		/* Incidental error; we're going to (try to) allow the request
3296 		 * itself to succeed. */
3297 	}
3298 
3299 	if (!logInfoArray->serialize(serializer)) {
3300 		OSKextLog(/* kext */ NULL,
3301 		    kOSKextLogErrorLevel |
3302 		    kOSKextLogIPCFlag,
3303 		    "Failed to serialize log info for request from user space.");
3304 		/* Incidental error; we're going to (try to) allow the request
3305 		 * itself to succeed. */
3306 	} else {
3307 		logInfo = serializer->text();
3308 		logInfoLength = serializer->getLength();
3309 
3310 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), VM_KERN_MEMORY_OSKEXT);
3311 		if (kmem_result != KERN_SUCCESS) {
3312 			OSKextLog(/* kext */ NULL,
3313 			    kOSKextLogErrorLevel |
3314 			    kOSKextLogIPCFlag,
3315 			    "Failed to copy log info for request from user space.");
3316 			/* Incidental error; we're going to (try to) allow the request
3317 			 * to succeed. */
3318 		} else {
3319 			/* 11981737 - clear uninitialized data in last page */
3320 			bzero((void *)(buffer + logInfoLength),
3321 			    (round_page(logInfoLength) - logInfoLength));
3322 			memcpy(buffer, logInfo, logInfoLength);
3323 			*logInfoOut = buffer;
3324 			*logInfoLengthOut = logInfoLength;
3325 		}
3326 	}
3327 
3328 	result = kOSReturnSuccess;
3329 finish:
3330 	OSSafeReleaseNULL(serializer);
3331 	return result;
3332 }
3333 
3334 #if PRAGMA_MARK
3335 #pragma mark Instance Management Methods
3336 #endif
3337 /*********************************************************************
3338 *********************************************************************/
3339 OSKext *
3340 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
3341 {
3342 	OSKext * foundKext = NULL;
3343 
3344 	IORecursiveLockLock(sKextLock);
3345 	foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
3346 	if (foundKext) {
3347 		foundKext->retain();
3348 	}
3349 	IORecursiveLockUnlock(sKextLock);
3350 
3351 	return foundKext;
3352 }
3353 
3354 /*********************************************************************
3355 *********************************************************************/
3356 OSKext *
3357 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
3358 {
3359 	return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
3360 }
3361 
3362 /*********************************************************************
3363 *********************************************************************/
3364 OSKext *
3365 OSKext::lookupKextWithLoadTag(uint32_t aTag)
3366 {
3367 	OSKext * foundKext = NULL;             // returned
3368 	uint32_t i, j;
3369 	OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
3370 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
3371 
3372 	IORecursiveLockLock(sKextLock);
3373 
3374 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
3375 		for (i = 0; i < count[j]; i++) {
3376 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
3377 			if (thisKext->getLoadTag() == aTag) {
3378 				foundKext = thisKext;
3379 				foundKext->retain();
3380 				goto finish;
3381 			}
3382 		}
3383 	}
3384 
3385 finish:
3386 	IORecursiveLockUnlock(sKextLock);
3387 
3388 	return foundKext;
3389 }
3390 
3391 /*********************************************************************
3392 *********************************************************************/
3393 OSKext *
3394 OSKext::lookupKextWithAddress(vm_address_t address)
3395 {
3396 	OSKext * foundKext = NULL;             // returned
3397 	uint32_t count, i;
3398 
3399 	IORecursiveLockLock(sKextLock);
3400 
3401 	count = sLoadedKexts->getCount();
3402 	for (i = 0; i < count; i++) {
3403 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3404 		if (thisKext->linkedExecutable) {
3405 			vm_address_t kext_start =
3406 			    (vm_address_t)thisKext->linkedExecutable->getBytesNoCopy();
3407 			vm_address_t kext_end = kext_start +
3408 			    thisKext->linkedExecutable->getLength();
3409 			if ((kext_start <= address) && (address < kext_end)) {
3410 				foundKext = thisKext;
3411 				foundKext->retain();
3412 				goto finish;
3413 			}
3414 		}
3415 	}
3416 
3417 	count = sLoadedDriverKitKexts->getCount();
3418 	for (i = 0; i < count; i++) {
3419 		OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
3420 		/*
3421 		 * DriverKitKexts do not have a linkedExecutable,
3422 		 * so we "fake" their address with the LoadTag
3423 		 */
3424 		if (thisKext->getLoadTag() == address) {
3425 			foundKext = thisKext;
3426 			foundKext->retain();
3427 		}
3428 	}
3429 
3430 finish:
3431 	IORecursiveLockUnlock(sKextLock);
3432 
3433 	return foundKext;
3434 }
3435 
3436 OSData *
3437 OSKext::copyKextUUIDForAddress(OSNumber *address)
3438 {
3439 	OSData              * uuid = NULL;
3440 	OSKextActiveAccount * active;
3441 	OSKext              * kext = NULL;
3442 	uint32_t              baseIdx;
3443 	uint32_t              lim;
3444 	uint32_t            count, i;
3445 
3446 	if (!address) {
3447 		return NULL;
3448 	}
3449 
3450 	uintptr_t addr = ml_static_slide((uintptr_t)address->unsigned64BitValue());
3451 
3452 #if CONFIG_MACF
3453 	/* Is the calling process allowed to query kext info? */
3454 	if (current_task() != kernel_task) {
3455 		int macCheckResult = 0;
3456 		kauth_cred_t cred = NULL;
3457 
3458 		cred = kauth_cred_get_with_ref();
3459 		macCheckResult = mac_kext_check_query(cred);
3460 		kauth_cred_unref(&cred);
3461 
3462 		if (macCheckResult != 0) {
3463 			OSKextLog(/* kext */ NULL,
3464 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
3465 			    "Failed to query kext UUID (MAC policy error 0x%x).",
3466 			    macCheckResult);
3467 			return NULL;
3468 		}
3469 	}
3470 #endif
3471 
3472 	IOSimpleLockLock(sKextAccountsLock);
3473 	// bsearch sKextAccounts list
3474 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
3475 		active = &sKextAccounts[baseIdx + (lim >> 1)];
3476 		if ((addr >= active->address) && (addr < active->address_end)) {
3477 			kext = active->account->kext;
3478 			if (kext) {
3479 				kext->retain();
3480 			}
3481 			break;
3482 		} else if (addr > active->address) {
3483 			// move right
3484 			baseIdx += (lim >> 1) + 1;
3485 			lim--;
3486 		}
3487 		// else move left
3488 	}
3489 	IOSimpleLockUnlock(sKextAccountsLock);
3490 
3491 	if (!kext) {
3492 		/*
3493 		 * Maybe it is a Dext.
3494 		 * DriverKit userspace executables do not have a kernel linkedExecutable,
3495 		 * so we "fake" their address range with the LoadTag.
3496 		 *
3497 		 * This is supposed to be used for logging reasons only. When logd
3498 		 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
3499 		 * remove it here before checking it against the LoadTag.
3500 		 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
3501 		 */
3502 		addr = (uintptr_t)address->unsigned64BitValue() & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
3503 		IORecursiveLockLock(sKextLock);
3504 		count = sLoadedDriverKitKexts->getCount();
3505 		for (i = 0; i < count; i++) {
3506 			OSKext   * thisKext     = NULL;
3507 
3508 			thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
3509 			if (!thisKext) {
3510 				continue;
3511 			}
3512 			if (thisKext->getLoadTag() == addr) {
3513 				kext = thisKext;
3514 				kext->retain();
3515 				break;
3516 			}
3517 		}
3518 		IORecursiveLockUnlock(sKextLock);
3519 	}
3520 
3521 	if (kext) {
3522 		uuid = kext->copyTextUUID();
3523 		kext->release();
3524 	} else if (((vm_offset_t)addr >= vm_kernel_stext) && ((vm_offset_t)addr < vm_kernel_etext)) {
3525 		uuid = sKernelKext->copyTextUUID();
3526 	}
3527 
3528 	return uuid;
3529 }
3530 
3531 /*********************************************************************
3532 *********************************************************************/
3533 OSKext *
3534 OSKext::lookupKextWithUUID(uuid_t wanted)
3535 {
3536 	OSKext * foundKext = NULL;             // returned
3537 	uint32_t j, i;
3538 	OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
3539 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
3540 
3541 
3542 	IORecursiveLockLock(sKextLock);
3543 
3544 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
3545 		for (i = 0; i < count[j]; i++) {
3546 			OSKext   * thisKext     = NULL;
3547 
3548 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
3549 			if (!thisKext) {
3550 				continue;
3551 			}
3552 
3553 			OSData *uuid_data = thisKext->copyUUID();
3554 			if (!uuid_data) {
3555 				continue;
3556 			}
3557 
3558 			uuid_t uuid;
3559 			memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
3560 			uuid_data->release();
3561 
3562 			if (0 == uuid_compare(wanted, uuid)) {
3563 				foundKext = thisKext;
3564 				foundKext->retain();
3565 				goto finish;
3566 			}
3567 		}
3568 	}
3569 finish:
3570 	IORecursiveLockUnlock(sKextLock);
3571 
3572 	return foundKext;
3573 }
3574 
3575 
3576 
3577 
3578 /*********************************************************************
3579 *********************************************************************/
3580 /* static */
3581 bool
3582 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
3583 {
3584 	bool result = false;
3585 	OSKext * foundKext = NULL;             // returned
3586 
3587 	IORecursiveLockLock(sKextLock);
3588 
3589 	foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
3590 	if (foundKext && foundKext->isLoaded()) {
3591 		result = true;
3592 	}
3593 
3594 	IORecursiveLockUnlock(sKextLock);
3595 
3596 	return result;
3597 }
3598 
3599 /*********************************************************************
3600 * xxx - should spawn a separate thread so a kext can safely have
3601 * xxx - itself unloaded.
3602 *********************************************************************/
3603 /* static */
3604 OSReturn
3605 OSKext::removeKext(
3606 	OSKext * aKext,
3607 #if CONFIG_EMBEDDED
3608 	__unused
3609 #endif
3610 	bool     terminateServicesAndRemovePersonalitiesFlag)
3611 {
3612 #if CONFIG_EMBEDDED
3613 	OSKextLog(aKext,
3614 	    kOSKextLogErrorLevel |
3615 	    kOSKextLogKextBookkeepingFlag,
3616 	    "removeKext() called for %s, not supported on embedded",
3617 	    aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
3618 
3619 	return kOSReturnSuccess;
3620 #else /* CONFIG_EMBEDDED */
3621 
3622 	OSReturn result    = kOSKextReturnInUse;
3623 	OSKext * checkKext = NULL; // do not release
3624 #if CONFIG_MACF
3625 	int macCheckResult = 0;
3626 	kauth_cred_t cred  = NULL;
3627 #endif
3628 
3629 	IORecursiveLockLock(sKextLock);
3630 
3631 	/* If the kext has no identifier, it failed to init
3632 	 * so isn't in sKextsByID and it isn't loaded.
3633 	 */
3634 	if (!aKext->getIdentifier()) {
3635 		result = kOSReturnSuccess;
3636 		goto finish;
3637 	}
3638 
3639 	checkKext = OSDynamicCast(OSKext,
3640 	    sKextsByID->getObject(aKext->getIdentifier()));
3641 	if (checkKext != aKext) {
3642 		result = kOSKextReturnNotFound;
3643 		goto finish;
3644 	}
3645 
3646 	if (aKext->isLoaded()) {
3647 #if CONFIG_MACF
3648 		if (current_task() != kernel_task) {
3649 			cred = kauth_cred_get_with_ref();
3650 			macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
3651 			kauth_cred_unref(&cred);
3652 		}
3653 
3654 		if (macCheckResult != 0) {
3655 			result = kOSReturnError;
3656 			OSKextLog(aKext,
3657 			    kOSKextLogErrorLevel |
3658 			    kOSKextLogKextBookkeepingFlag,
3659 			    "Failed to remove kext %s (MAC policy error 0x%x).",
3660 			    aKext->getIdentifierCString(), macCheckResult);
3661 			goto finish;
3662 		}
3663 #endif
3664 
3665 		/* make sure there are no resource requests in flight - 17187548 */
3666 		if (aKext->countRequestCallbacks()) {
3667 			goto finish;
3668 		}
3669 
3670 		/* If we are terminating, send the request to the IOCatalogue
3671 		 * (which will actually call us right back but that's ok we have
3672 		 * a recursive lock don't you know) but do not ask the IOCatalogue
3673 		 * to call back with an unload, we'll do that right here.
3674 		 */
3675 		if (terminateServicesAndRemovePersonalitiesFlag) {
3676 			result = gIOCatalogue->terminateDriversForModule(
3677 				aKext->getIdentifierCString(), /* unload */ false);
3678 			if (result != kOSReturnSuccess) {
3679 				OSKextLog(aKext,
3680 				    kOSKextLogErrorLevel |
3681 				    kOSKextLogKextBookkeepingFlag,
3682 				    "Can't remove kext %s; services failed to terminate - 0x%x.",
3683 				    aKext->getIdentifierCString(), result);
3684 				goto finish;
3685 			}
3686 		}
3687 
3688 		result = aKext->unload();
3689 		if (result != kOSReturnSuccess) {
3690 			goto finish;
3691 		}
3692 	}
3693 
3694 	/* Remove personalities as requested. This is a bit redundant for a loaded
3695 	 * kext as IOCatalogue::terminateDriversForModule() removes driver
3696 	 * personalities, but it doesn't restart matching, which we always want
3697 	 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3698 	 * that happens.
3699 	 */
3700 	if (terminateServicesAndRemovePersonalitiesFlag) {
3701 		aKext->removePersonalitiesFromCatalog();
3702 	}
3703 
3704 	OSKextLog(aKext,
3705 	    kOSKextLogProgressLevel |
3706 	    kOSKextLogKextBookkeepingFlag,
3707 	    "Removing kext %s.",
3708 	    aKext->getIdentifierCString());
3709 
3710 	sKextsByID->removeObject(aKext->getIdentifier());
3711 	result = kOSReturnSuccess;
3712 
3713 finish:
3714 	IORecursiveLockUnlock(sKextLock);
3715 	return result;
3716 #endif /* CONFIG_EMBEDDED */
3717 }
3718 
3719 /*********************************************************************
3720 *********************************************************************/
3721 /* static */
3722 OSReturn
3723 OSKext::removeKextWithIdentifier(
3724 	const char * kextIdentifier,
3725 	bool         terminateServicesAndRemovePersonalitiesFlag)
3726 {
3727 	OSReturn result = kOSReturnError;
3728 
3729 	IORecursiveLockLock(sKextLock);
3730 
3731 	OSKext * aKext = OSDynamicCast(OSKext,
3732 	    sKextsByID->getObject(kextIdentifier));
3733 	if (!aKext) {
3734 		result = kOSKextReturnNotFound;
3735 		OSKextLog(/* kext */ NULL,
3736 		    kOSKextLogErrorLevel |
3737 		    kOSKextLogKextBookkeepingFlag,
3738 		    "Can't remove kext %s - not found.",
3739 		    kextIdentifier);
3740 		goto finish;
3741 	}
3742 
3743 	result = OSKext::removeKext(aKext,
3744 	    terminateServicesAndRemovePersonalitiesFlag);
3745 
3746 finish:
3747 	IORecursiveLockUnlock(sKextLock);
3748 
3749 	return result;
3750 }
3751 
3752 /*********************************************************************
3753 *********************************************************************/
3754 /* static */
3755 OSReturn
3756 OSKext::removeKextWithLoadTag(
3757 	OSKextLoadTag loadTag,
3758 	bool          terminateServicesAndRemovePersonalitiesFlag)
3759 {
3760 	OSReturn result    = kOSReturnError;
3761 	OSKext * foundKext = NULL;
3762 	uint32_t i, j;
3763 	OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
3764 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
3765 
3766 
3767 	IORecursiveLockLock(sKextLock);
3768 
3769 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
3770 		for (i = 0; i < count[j]; i++) {
3771 			OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
3772 			if (thisKext->loadTag == loadTag) {
3773 				foundKext = thisKext;
3774 				break;
3775 			}
3776 		}
3777 	}
3778 
3779 	if (!foundKext) {
3780 		result = kOSKextReturnNotFound;
3781 		OSKextLog(/* kext */ NULL,
3782 		    kOSKextLogErrorLevel |
3783 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
3784 		    "Can't remove kext with load tag %d - not found.",
3785 		    loadTag);
3786 		goto finish;
3787 	}
3788 
3789 	result = OSKext::removeKext(foundKext,
3790 	    terminateServicesAndRemovePersonalitiesFlag);
3791 
3792 finish:
3793 	IORecursiveLockUnlock(sKextLock);
3794 
3795 	return result;
3796 }
3797 
3798 /*********************************************************************
3799 *********************************************************************/
3800 OSDictionary *
3801 OSKext::copyKexts(void)
3802 {
3803 	OSDictionary * result;
3804 
3805 	IORecursiveLockLock(sKextLock);
3806 	result = OSDynamicCast(OSDictionary, sKextsByID->copyCollection());
3807 	IORecursiveLockUnlock(sKextLock);
3808 
3809 	return result;
3810 }
3811 
3812 /*********************************************************************
3813 *********************************************************************/
3814 #define BOOTER_KEXT_PREFIX   "Driver-"
3815 
3816 typedef struct _DeviceTreeBuffer {
3817 	uint32_t paddr;
3818 	uint32_t length;
3819 } _DeviceTreeBuffer;
3820 
3821 /*********************************************************************
3822 * Create a dictionary of excluded kexts from the given booter data.
3823 *********************************************************************/
3824 /* static */
3825 void
3826 OSKext::createExcludeListFromBooterData(
3827 	OSDictionary *          theDictionary,
3828 	OSCollectionIterator *  theIterator )
3829 {
3830 	OSString                  * deviceTreeName      = NULL;// do not release
3831 	const _DeviceTreeBuffer   * deviceTreeBuffer    = NULL;// do not release
3832 	char                      * booterDataPtr       = NULL;// do not release
3833 	_BooterKextFileInfo       * kextFileInfo        = NULL;// do not release
3834 	char                      * infoDictAddr        = NULL;// do not release
3835 	OSObject                  * parsedXML           = NULL;// must release
3836 	OSDictionary              * theInfoDict         = NULL;// do not release
3837 
3838 	theIterator->reset();
3839 
3840 	/* look for AppleKextExcludeList.kext */
3841 	while ((deviceTreeName =
3842 	    OSDynamicCast(OSString, theIterator->getNextObject()))) {
3843 		const char *    devTreeNameCString;
3844 		OSData *        deviceTreeEntry;
3845 		OSString *      myBundleID;// do not release
3846 
3847 		OSSafeReleaseNULL(parsedXML);
3848 
3849 		deviceTreeEntry =
3850 		    OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
3851 		if (!deviceTreeEntry) {
3852 			continue;
3853 		}
3854 
3855 		/* Make sure it is a kext */
3856 		devTreeNameCString = deviceTreeName->getCStringNoCopy();
3857 		if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
3858 		    (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
3859 			OSKextLog(NULL,
3860 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3861 			    "\"%s\" not a kext",
3862 			    devTreeNameCString);
3863 			continue;
3864 		}
3865 
3866 		deviceTreeBuffer = (const _DeviceTreeBuffer *)
3867 		    deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
3868 		if (!deviceTreeBuffer) {
3869 			continue;
3870 		}
3871 
3872 		booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
3873 		if (!booterDataPtr) {
3874 			continue;
3875 		}
3876 
3877 		kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
3878 		if (!kextFileInfo->infoDictPhysAddr ||
3879 		    !kextFileInfo->infoDictLength) {
3880 			continue;
3881 		}
3882 
3883 		infoDictAddr = (char *)
3884 		    ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
3885 		if (!infoDictAddr) {
3886 			continue;
3887 		}
3888 
3889 		parsedXML = OSUnserializeXML(infoDictAddr);
3890 		if (!parsedXML) {
3891 			continue;
3892 		}
3893 
3894 		theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
3895 		if (!theInfoDict) {
3896 			continue;
3897 		}
3898 
3899 		myBundleID =
3900 		    OSDynamicCast(OSString,
3901 		    theInfoDict->getObject(kCFBundleIdentifierKey));
3902 		if (myBundleID &&
3903 		    strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
3904 			boolean_t updated = updateExcludeList(theInfoDict);
3905 			if (!updated) {
3906 				/* 25322874 */
3907 				panic("Missing OSKextExcludeList dictionary\n");
3908 			}
3909 			break;
3910 		}
3911 	} // while ( (deviceTreeName = ...) )
3912 
3913 	OSSafeReleaseNULL(parsedXML);
3914 	return;
3915 }
3916 
3917 /*********************************************************************
3918 * Create a dictionary of excluded kexts from the given prelink
3919 * info (kernelcache).
3920 *********************************************************************/
3921 /* static */
3922 void
3923 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
3924 {
3925 	OSDictionary *  myInfoDict = NULL;// do not release
3926 	OSString *      myBundleID;     // do not release
3927 	u_int           i;
3928 
3929 	/* Find com.apple.driver.KextExcludeList. */
3930 	for (i = 0; i < theInfoArray->getCount(); i++) {
3931 		myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
3932 		if (!myInfoDict) {
3933 			continue;
3934 		}
3935 		myBundleID =
3936 		    OSDynamicCast(OSString,
3937 		    myInfoDict->getObject(kCFBundleIdentifierKey));
3938 		if (myBundleID &&
3939 		    strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
3940 			boolean_t updated = updateExcludeList(myInfoDict);
3941 			if (!updated) {
3942 				/* 25322874 */
3943 				panic("Missing OSKextExcludeList dictionary\n");
3944 			}
3945 			break;
3946 		}
3947 	} // for (i = 0; i < theInfoArray->getCount()...
3948 
3949 	return;
3950 }
3951 
3952 /* static */
3953 boolean_t
3954 OSKext::updateExcludeList(OSDictionary *infoDict)
3955 {
3956 	OSDictionary *myTempDict = NULL; // do not free
3957 	OSString     *myTempString = NULL;// do not free
3958 	OSKextVersion newVersion = 0;
3959 	boolean_t updated = false;
3960 
3961 	if (!infoDict) {
3962 		return false;
3963 	}
3964 
3965 	myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
3966 	if (!myTempDict) {
3967 		return false;
3968 	}
3969 
3970 	myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
3971 	if (!myTempString) {
3972 		return false;
3973 	}
3974 
3975 	newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
3976 	if (newVersion == 0) {
3977 		return false;
3978 	}
3979 
3980 	IORecursiveLockLock(sKextLock);
3981 
3982 	if (newVersion > sExcludeListVersion) {
3983 		OSSafeReleaseNULL(sExcludeListByID);
3984 		sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
3985 		sExcludeListVersion = newVersion;
3986 		updated = true;
3987 	}
3988 
3989 	IORecursiveLockUnlock(sKextLock);
3990 	return updated;
3991 }
3992 
3993 #if PRAGMA_MARK
3994 #pragma mark Accessors
3995 #endif
3996 /*********************************************************************
3997 *********************************************************************/
3998 const OSSymbol *
3999 OSKext::getIdentifier(void)
4000 {
4001 	return bundleID;
4002 }
4003 
4004 /*********************************************************************
4005 * A kext must have a bundle identifier to even survive initialization;
4006 * this is guaranteed to exist past then.
4007 *********************************************************************/
4008 const char *
4009 OSKext::getIdentifierCString(void)
4010 {
4011 	return bundleID->getCStringNoCopy();
4012 }
4013 
4014 /*********************************************************************
4015 *********************************************************************/
4016 OSKextVersion
4017 OSKext::getVersion(void)
4018 {
4019 	return version;
4020 }
4021 
4022 /*********************************************************************
4023 *********************************************************************/
4024 OSKextVersion
4025 OSKext::getCompatibleVersion(void)
4026 {
4027 	return compatibleVersion;
4028 }
4029 
4030 /*********************************************************************
4031 *********************************************************************/
4032 bool
4033 OSKext::isLibrary(void)
4034 {
4035 	return getCompatibleVersion() > 0;
4036 }
4037 
4038 /*********************************************************************
4039 *********************************************************************/
4040 bool
4041 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
4042 {
4043 	if ((compatibleVersion > -1 && version > -1) &&
4044 	    (compatibleVersion <= version && aVersion <= version)) {
4045 		return true;
4046 	}
4047 	return false;
4048 }
4049 
4050 /*********************************************************************
4051 *********************************************************************/
4052 bool
4053 OSKext::declaresExecutable(void)
4054 {
4055 	if (isDriverKit()) {
4056 		return false;
4057 	}
4058 	return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
4059 }
4060 
4061 /*********************************************************************
4062 *********************************************************************/
4063 OSData *
4064 OSKext::getExecutable(void)
4065 {
4066 	OSData * result              = NULL;
4067 	OSData * extractedExecutable = NULL; // must release
4068 	OSData * mkextExecutableRef  = NULL;// do not release
4069 
4070 	if (flags.builtin) {
4071 		return sKernelKext->linkedExecutable;
4072 	}
4073 
4074 	result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
4075 	if (result) {
4076 		goto finish;
4077 	}
4078 
4079 	mkextExecutableRef = OSDynamicCast(OSData,
4080 	    getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
4081 
4082 	if (mkextExecutableRef) {
4083 		MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
4084 		    mkextExecutableRef->getBytesNoCopy();
4085 		uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
4086 		if (mkextVersion == MKEXT_VERS_2) {
4087 			mkext2_file_entry * fileinfo =
4088 			    (mkext2_file_entry *)mkextEntryRef->fileinfo;
4089 			uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
4090 			uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
4091 			extractedExecutable = extractMkext2FileData(
4092 				MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
4093 				compressedSize, fullSize);
4094 		} else {
4095 			OSKextLog(this, kOSKextLogErrorLevel |
4096 			    kOSKextLogArchiveFlag,
4097 			    "Kext %s - unknown mkext version 0x%x for executable.",
4098 			    getIdentifierCString(), mkextVersion);
4099 		}
4100 
4101 		/* Regardless of success, remove the mkext executable,
4102 		 * and drop one reference on the mkext.  (setExecutable() does not
4103 		 * replace, it removes, or panics if asked to replace.)
4104 		 */
4105 		infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4106 		infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4107 
4108 		if (extractedExecutable && extractedExecutable->getLength()) {
4109 			if (!setExecutable(extractedExecutable)) {
4110 				goto finish;
4111 			}
4112 			result = extractedExecutable;
4113 		} else {
4114 			goto finish;
4115 		}
4116 	}
4117 
4118 finish:
4119 
4120 	OSSafeReleaseNULL(extractedExecutable);
4121 
4122 	return result;
4123 }
4124 
4125 /*********************************************************************
4126 *********************************************************************/
4127 bool
4128 OSKext::isInterface(void)
4129 {
4130 	return flags.interface;
4131 }
4132 
4133 /*********************************************************************
4134 *********************************************************************/
4135 bool
4136 OSKext::isKernel(void)
4137 {
4138 	return this == sKernelKext;
4139 }
4140 
4141 /*********************************************************************
4142 *********************************************************************/
4143 bool
4144 OSKext::isKernelComponent(void)
4145 {
4146 	return flags.kernelComponent ? true : false;
4147 }
4148 
4149 /*********************************************************************
4150 *********************************************************************/
4151 bool
4152 OSKext::isExecutable(void)
4153 {
4154 	return !isKernel() && !isInterface() && declaresExecutable();
4155 }
4156 
4157 /*********************************************************************
4158 * We might want to check this recursively for all dependencies,
4159 * since a subtree of dependencies could get loaded before we hit
4160 * a dependency that isn't safe-boot-loadable.
4161 *
4162 * xxx - Might want to return false if OSBundleEnableKextLogging or
4163 * OSBundleDebugLevel
4164 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4165 * the point except it's usually development drivers, which might
4166 * cause panics on startup, that have those properties). Heh; could
4167 * use a "kx" boot-arg!
4168 *********************************************************************/
4169 bool
4170 OSKext::isLoadableInSafeBoot(void)
4171 {
4172 	bool       result   = false;
4173 	OSString * required = NULL; // do not release
4174 
4175 	if (isKernel()) {
4176 		result = true;
4177 		goto finish;
4178 	}
4179 
4180 	required = OSDynamicCast(OSString,
4181 	    getPropertyForHostArch(kOSBundleRequiredKey));
4182 	if (!required) {
4183 		goto finish;
4184 	}
4185 	if (required->isEqualTo(kOSBundleRequiredRoot) ||
4186 	    required->isEqualTo(kOSBundleRequiredLocalRoot) ||
4187 	    required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
4188 	    required->isEqualTo(kOSBundleRequiredSafeBoot) ||
4189 	    required->isEqualTo(kOSBundleRequiredConsole)) {
4190 		result = true;
4191 	}
4192 
4193 finish:
4194 	return result;
4195 }
4196 
4197 /*********************************************************************
4198 *********************************************************************/
4199 bool
4200 OSKext::isPrelinked(void)
4201 {
4202 	return flags.prelinked ? true : false;
4203 }
4204 
4205 /*********************************************************************
4206 *********************************************************************/
4207 bool
4208 OSKext::isLoaded(void)
4209 {
4210 	return flags.loaded ? true : false;
4211 }
4212 
4213 /*********************************************************************
4214 *********************************************************************/
4215 bool
4216 OSKext::isStarted(void)
4217 {
4218 	return flags.started ? true : false;
4219 }
4220 
4221 /*********************************************************************
4222 *********************************************************************/
4223 bool
4224 OSKext::isCPPInitialized(void)
4225 {
4226 	return flags.CPPInitialized;
4227 }
4228 
4229 /*********************************************************************
4230 *********************************************************************/
4231 void
4232 OSKext::setCPPInitialized(bool initialized)
4233 {
4234 	flags.CPPInitialized = initialized;
4235 }
4236 
4237 /*********************************************************************
4238 *********************************************************************/
4239 uint32_t
4240 OSKext::getLoadTag(void)
4241 {
4242 	return loadTag;
4243 }
4244 
4245 /*********************************************************************
4246 *********************************************************************/
4247 void
4248 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
4249 {
4250 	if (linkedExecutable) {
4251 		*loadSize = linkedExecutable->getLength();
4252 
4253 		/* If we have a kmod_info struct, calculated the wired size
4254 		 * from that. Otherwise it's the full load size.
4255 		 */
4256 		if (kmod_info) {
4257 			*wiredSize = *loadSize - kmod_info->hdr_size;
4258 		} else {
4259 			*wiredSize = *loadSize;
4260 		}
4261 	} else {
4262 		*wiredSize = 0;
4263 		*loadSize = 0;
4264 	}
4265 }
4266 
4267 /*********************************************************************
4268 *********************************************************************/
4269 OSData *
4270 OSKext::copyUUID(void)
4271 {
4272 	OSData                     * result        = NULL;
4273 	OSData                     * theExecutable = NULL;// do not release
4274 	const kernel_mach_header_t * header;
4275 
4276 	/* An interface kext doesn't have a linked executable with an LC_UUID,
4277 	 * we create one when it's linked.
4278 	 */
4279 	if (interfaceUUID) {
4280 		result = interfaceUUID;
4281 		result->retain();
4282 		goto finish;
4283 	}
4284 
4285 	if (flags.builtin || isInterface()) {
4286 		return sKernelKext->copyUUID();
4287 	}
4288 
4289 	if (isDriverKit() && infoDict) {
4290 		if (driverKitUUID) {
4291 			driverKitUUID->retain();
4292 			return driverKitUUID;
4293 		} else {
4294 			return NULL;
4295 		}
4296 	}
4297 
4298 	/* For real kexts, try to get the UUID from the linked executable,
4299 	 * or if is hasn't been linked yet, the unrelocated executable.
4300 	 */
4301 	theExecutable = linkedExecutable;
4302 	if (!theExecutable) {
4303 		theExecutable = getExecutable();
4304 	}
4305 
4306 	if (!theExecutable) {
4307 		goto finish;
4308 	}
4309 
4310 	header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
4311 	result = copyMachoUUID(header);
4312 
4313 finish:
4314 	return result;
4315 }
4316 
4317 /*********************************************************************
4318 *********************************************************************/
4319 OSData *
4320 OSKext::copyTextUUID(void)
4321 {
4322 	if (flags.builtin) {
4323 		return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
4324 	}
4325 	return copyUUID();
4326 }
4327 
4328 /*********************************************************************
4329 *********************************************************************/
4330 OSData *
4331 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
4332 {
4333 	OSData                     * result        = NULL;
4334 	const struct load_command  * load_cmd      = NULL;
4335 	const struct uuid_command  * uuid_cmd      = NULL;
4336 	uint32_t                     i;
4337 
4338 	load_cmd = (const struct load_command *)&header[1];
4339 
4340 	if (header->magic != MH_MAGIC_KERNEL) {
4341 		OSKextLog(NULL,
4342 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4343 		    "%s: bad header %p",
4344 		    __func__,
4345 		    header);
4346 		goto finish;
4347 	}
4348 
4349 	for (i = 0; i < header->ncmds; i++) {
4350 		if (load_cmd->cmd == LC_UUID) {
4351 			uuid_cmd = (struct uuid_command *)load_cmd;
4352 			result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid));
4353 			goto finish;
4354 		}
4355 		load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
4356 	}
4357 
4358 finish:
4359 	return result;
4360 }
4361 
4362 void
4363 OSKext::setDriverKitUUID(OSData *uuid)
4364 {
4365 	if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
4366 		OSSafeReleaseNULL(uuid);
4367 	}
4368 }
4369 
4370 /*********************************************************************
4371 *********************************************************************/
4372 #if defined (__arm__)
4373 #include <arm/arch.h>
4374 #endif
4375 
4376 #if   defined (__x86_64__)
4377 #define ARCHNAME "x86_64"
4378 #elif defined (__arm64__)
4379 #define ARCHNAME "arm64"
4380 #elif defined (__arm__)
4381 
4382 #if defined (__ARM_ARCH_7S__)
4383 #define ARCHNAME "armv7s"
4384 #elif defined (__ARM_ARCH_7F__)
4385 #define ARCHNAME "armv7f"
4386 #elif defined (__ARM_ARCH_7K__)
4387 #define ARCHNAME "armv7k"
4388 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
4389 #define ARCHNAME "armv7"
4390 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
4391 #define ARCHNAME "armv6"
4392 #endif
4393 
4394 #elif defined (__arm64__)
4395 #define ARCHNAME "arm64"
4396 #else
4397 #error architecture not supported
4398 #endif
4399 
4400 #define ARCH_SEPARATOR_CHAR  '_'
4401 
4402 static char *
4403 makeHostArchKey(const char * key, uint32_t * keySizeOut)
4404 {
4405 	char     * result = NULL;
4406 	uint32_t   keyLength = strlen(key);
4407 	uint32_t   keySize;
4408 
4409 	/* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4410 	 */
4411 	keySize = 1 + 1 + strlen(key) + strlen(ARCHNAME);
4412 	result = (char *)kalloc_tag(keySize, VM_KERN_MEMORY_OSKEXT);
4413 	if (!result) {
4414 		goto finish;
4415 	}
4416 	strlcpy(result, key, keySize);
4417 	result[keyLength++] = ARCH_SEPARATOR_CHAR;
4418 	result[keyLength] = '\0';
4419 	strlcat(result, ARCHNAME, keySize);
4420 	*keySizeOut = keySize;
4421 
4422 finish:
4423 	return result;
4424 }
4425 
4426 /*********************************************************************
4427 *********************************************************************/
4428 OSObject *
4429 OSKext::getPropertyForHostArch(const char * key)
4430 {
4431 	OSObject * result           = NULL;// do not release
4432 	uint32_t   hostArchKeySize  = 0;
4433 	char     * hostArchKey      = NULL;// must kfree
4434 
4435 	if (!key || !infoDict) {
4436 		goto finish;
4437 	}
4438 
4439 	/* Some properties are not allowed to be arch-variant:
4440 	 * - Any CFBundle... property.
4441 	 * - OSBundleIsInterface.
4442 	 * - OSKernelResource.
4443 	 */
4444 	if (STRING_HAS_PREFIX(key, "OS") ||
4445 	    STRING_HAS_PREFIX(key, "IO")) {
4446 		hostArchKey = makeHostArchKey(key, &hostArchKeySize);
4447 		if (!hostArchKey) {
4448 			OSKextLog(/* kext (this isn't about a kext) */ NULL,
4449 			    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4450 			    "Allocation failure.");
4451 			goto finish;
4452 		}
4453 		result = infoDict->getObject(hostArchKey);
4454 	}
4455 
4456 	if (!result) {
4457 		result = infoDict->getObject(key);
4458 	}
4459 
4460 finish:
4461 	if (hostArchKey) {
4462 		kfree(hostArchKey, hostArchKeySize);
4463 	}
4464 	return result;
4465 }
4466 
4467 #if PRAGMA_MARK
4468 #pragma mark Load/Start/Stop/Unload
4469 #endif
4470 
4471 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4472 
4473 /*********************************************************************
4474 * sExcludeListByID is a dictionary with keys / values of:
4475 *  key = bundleID string of kext we will not allow to load
4476 *  value = version string(s) of the kext that is to be denied loading.
4477 *      The version strings can be comma delimited.  For example if kext
4478 *      com.foocompany.fookext has two versions that we want to deny
4479 *      loading then the version strings might look like:
4480 *      1.0.0, 1.0.1
4481 *      If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4482 *      not load the kext.
4483 *
4484 *      Value may also be in the form of "LE 2.0.0" (version numbers
4485 *      less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4486 *      number less than 2.0.0 will not load)
4487 *
4488 *      NOTE - we cannot use the characters "<=" or "<" because we have code
4489 *      that serializes plists and treats '<' as a special character.
4490 *********************************************************************/
4491 bool
4492 OSKext::isInExcludeList(void)
4493 {
4494 	OSString *      versionString           = NULL;// do not release
4495 	char *          versionCString          = NULL;// do not free
4496 	size_t          i;
4497 	boolean_t       wantLessThan = false;
4498 	boolean_t       wantLessThanEqualTo = false;
4499 	boolean_t       isInExcludeList = true;
4500 	char            myBuffer[32];
4501 
4502 	IORecursiveLockLock(sKextLock);
4503 
4504 	if (!sExcludeListByID) {
4505 		isInExcludeList = false;
4506 	} else {
4507 		/* look up by bundleID in our exclude list and if found get version
4508 		 * string (or strings) that we will not allow to load
4509 		 */
4510 		versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID));
4511 		if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
4512 			isInExcludeList = false;
4513 		}
4514 	}
4515 
4516 	IORecursiveLockUnlock(sKextLock);
4517 
4518 	if (!isInExcludeList) {
4519 		return false;
4520 	}
4521 
4522 	/* parse version strings */
4523 	versionCString = (char *) versionString->getCStringNoCopy();
4524 
4525 	/* look for "LT" or "LE" form of version string, must be in first two
4526 	 * positions.
4527 	 */
4528 	if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
4529 		wantLessThan = true;
4530 		versionCString += 2;
4531 	} else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
4532 		wantLessThanEqualTo = true;
4533 		versionCString += 2;
4534 	}
4535 
4536 	for (i = 0; *versionCString != 0x00; versionCString++) {
4537 		/* skip whitespace */
4538 		if (isWhiteSpace(*versionCString)) {
4539 			continue;
4540 		}
4541 
4542 		/* peek ahead for version string separator or null terminator */
4543 		if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
4544 			/* OK, we have a version string */
4545 			myBuffer[i++] = *versionCString;
4546 			myBuffer[i] = 0x00;
4547 
4548 			OSKextVersion excludeVers;
4549 			excludeVers = OSKextParseVersionString(myBuffer);
4550 
4551 			if (wantLessThanEqualTo) {
4552 				if (version <= excludeVers) {
4553 					return true;
4554 				}
4555 			} else if (wantLessThan) {
4556 				if (version < excludeVers) {
4557 					return true;
4558 				}
4559 			} else if (version == excludeVers) {
4560 				return true;
4561 			}
4562 
4563 			/* reset for the next (if any) version string */
4564 			i = 0;
4565 			wantLessThan = false;
4566 			wantLessThanEqualTo = false;
4567 		} else {
4568 			/* save valid version character */
4569 			myBuffer[i++] = *versionCString;
4570 
4571 			/* make sure bogus version string doesn't overrun local buffer */
4572 			if (i >= sizeof(myBuffer)) {
4573 				break;
4574 			}
4575 		}
4576 	}
4577 
4578 	return false;
4579 }
4580 
4581 /*********************************************************************
4582 *********************************************************************/
4583 /* static */
4584 OSReturn
4585 OSKext::loadKextWithIdentifier(
4586 	const char       * kextIdentifierCString,
4587 	Boolean            allowDeferFlag,
4588 	Boolean            delayAutounloadFlag,
4589 	OSKextExcludeLevel startOpt,
4590 	OSKextExcludeLevel startMatchingOpt,
4591 	OSArray          * personalityNames)
4592 {
4593 	OSReturn   result         = kOSReturnError;
4594 	OSString * kextIdentifier = NULL; // must release
4595 
4596 	kextIdentifier = OSString::withCString(kextIdentifierCString);
4597 	if (!kextIdentifier) {
4598 		result = kOSKextReturnNoMemory;
4599 		goto finish;
4600 	}
4601 	result = OSKext::loadKextWithIdentifier(kextIdentifier,
4602 	    NULL /* kextRef */,
4603 	    allowDeferFlag, delayAutounloadFlag,
4604 	    startOpt, startMatchingOpt, personalityNames);
4605 
4606 finish:
4607 	OSSafeReleaseNULL(kextIdentifier);
4608 	return result;
4609 }
4610 
4611 /*********************************************************************
4612 *********************************************************************/
4613 OSReturn
4614 OSKext::loadKextWithIdentifier(
4615 	OSString          * kextIdentifier,
4616 	OSObject         ** kextRef,
4617 	Boolean             allowDeferFlag,
4618 	Boolean             delayAutounloadFlag,
4619 	OSKextExcludeLevel  startOpt,
4620 	OSKextExcludeLevel  startMatchingOpt,
4621 	OSArray           * personalityNames)
4622 {
4623 	OSReturn          result               = kOSReturnError;
4624 	OSReturn          pingResult           = kOSReturnError;
4625 	OSKext          * theKext              = NULL;// do not release
4626 	OSDictionary    * loadRequest          = NULL;// must release
4627 	const OSSymbol  * kextIdentifierSymbol = NULL;// must release
4628 
4629 	if (kextRef) {
4630 		*kextRef = NULL;
4631 	}
4632 
4633 	IORecursiveLockLock(sKextLock);
4634 
4635 	if (!kextIdentifier) {
4636 		result = kOSKextReturnInvalidArgument;
4637 		goto finish;
4638 	}
4639 
4640 	OSKext::recordIdentifierRequest(kextIdentifier);
4641 
4642 	theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4643 	if (!theKext) {
4644 		if (!allowDeferFlag) {
4645 			OSKextLog(/* kext */ NULL,
4646 			    kOSKextLogErrorLevel |
4647 			    kOSKextLogLoadFlag,
4648 			    "Can't load kext %s - not found.",
4649 			    kextIdentifier->getCStringNoCopy());
4650 			goto finish;
4651 		}
4652 
4653 		if (!sKernelRequestsEnabled) {
4654 			OSKextLog(theKext,
4655 			    kOSKextLogErrorLevel |
4656 			    kOSKextLogLoadFlag,
4657 			    "Can't load kext %s - requests to user space are disabled.",
4658 			    kextIdentifier->getCStringNoCopy());
4659 			result = kOSKextReturnDisabled;
4660 			goto finish;
4661 		}
4662 
4663 		/* Create a new request unless one is already sitting
4664 		 * in sKernelRequests for this bundle identifier
4665 		 */
4666 		kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
4667 		if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
4668 			result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
4669 			    &loadRequest);
4670 			if (result != kOSReturnSuccess) {
4671 				goto finish;
4672 			}
4673 			if (!_OSKextSetRequestArgument(loadRequest,
4674 			    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
4675 				result = kOSKextReturnNoMemory;
4676 				goto finish;
4677 			}
4678 			if (!sKernelRequests->setObject(loadRequest)) {
4679 				result = kOSKextReturnNoMemory;
4680 				goto finish;
4681 			}
4682 
4683 			if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
4684 				result = kOSKextReturnNoMemory;
4685 				goto finish;
4686 			}
4687 
4688 			OSKextLog(theKext,
4689 			    kOSKextLogDebugLevel |
4690 			    kOSKextLogLoadFlag,
4691 			    "Kext %s not found; queued load request to user space.",
4692 			    kextIdentifier->getCStringNoCopy());
4693 		}
4694 
4695 		pingResult = OSKext::pingKextd();
4696 		if (pingResult == kOSKextReturnDisabled) {
4697 			OSKextLog(/* kext */ NULL,
4698 			    ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
4699 			    kOSKextLogLoadFlag,
4700 			    "Kext %s might not load - kextd is currently unavailable.",
4701 			    kextIdentifier->getCStringNoCopy());
4702 		}
4703 
4704 		result = kOSKextReturnDeferred;
4705 		goto finish;
4706 	}
4707 
4708 	result = theKext->load(startOpt, startMatchingOpt, personalityNames);
4709 
4710 	if (result != kOSReturnSuccess) {
4711 		OSKextLog(theKext,
4712 		    kOSKextLogErrorLevel |
4713 		    kOSKextLogLoadFlag,
4714 		    "Failed to load kext %s (error 0x%x).",
4715 		    kextIdentifier->getCStringNoCopy(), (int)result);
4716 
4717 		OSKext::removeKext(theKext,
4718 		    /* terminateService/removePersonalities */ true);
4719 		goto finish;
4720 	}
4721 
4722 	if (delayAutounloadFlag) {
4723 		OSKextLog(theKext,
4724 		    kOSKextLogProgressLevel |
4725 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4726 		    "Setting delayed autounload for %s.",
4727 		    kextIdentifier->getCStringNoCopy());
4728 		theKext->flags.delayAutounload = 1;
4729 	}
4730 
4731 finish:
4732 	OSSafeReleaseNULL(loadRequest);
4733 	OSSafeReleaseNULL(kextIdentifierSymbol);
4734 
4735 	if ((kOSReturnSuccess == result) && kextRef) {
4736 		theKext->retain();
4737 		theKext->matchingRefCount++;
4738 		*kextRef = theKext;
4739 	}
4740 
4741 	IORecursiveLockUnlock(sKextLock);
4742 
4743 	return result;
4744 }
4745 /*********************************************************************
4746 *********************************************************************/
4747 /* static */
4748 void
4749 OSKext::dropMatchingReferences(
4750 	OSSet * kexts)
4751 {
4752 	IORecursiveLockLock(sKextLock);
4753 	kexts->iterateObjects(^bool (OSObject * obj) {
4754 		OSKext * thisKext = OSDynamicCast(OSKext, obj);
4755 		if (!thisKext) {
4756 		        return false;
4757 		}
4758 		thisKext->matchingRefCount--;
4759 		return false;
4760 	});
4761 	IORecursiveLockUnlock(sKextLock);
4762 }
4763 
4764 /*********************************************************************
4765 *********************************************************************/
4766 /* static */
4767 void
4768 OSKext::recordIdentifierRequest(
4769 	OSString * kextIdentifier)
4770 {
4771 	const OSSymbol * kextIdentifierSymbol = NULL; // must release
4772 	bool             fail                 = false;
4773 
4774 	if (!sAllKextLoadIdentifiers || !kextIdentifier) {
4775 		goto finish;
4776 	}
4777 
4778 	kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
4779 	if (!kextIdentifierSymbol) {
4780 		// xxx - this is really a basic alloc failure
4781 		fail = true;
4782 		goto finish;
4783 	}
4784 
4785 	IORecursiveLockLock(sKextLock);
4786 	if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
4787 		if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
4788 			fail = true;
4789 		} else {
4790 			// xxx - need to find a way to associate this whole func w/the kext
4791 			OSKextLog(/* kext */ NULL,
4792 			    // xxx - check level
4793 			    kOSKextLogStepLevel |
4794 			    kOSKextLogArchiveFlag,
4795 			    "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4796 			    kextIdentifier->getCStringNoCopy());
4797 		}
4798 	}
4799 	IORecursiveLockUnlock(sKextLock);
4800 
4801 finish:
4802 
4803 	if (fail) {
4804 		OSKextLog(/* kext */ NULL,
4805 		    kOSKextLogErrorLevel |
4806 		    kOSKextLogArchiveFlag,
4807 		    "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4808 		    kextIdentifier->getCStringNoCopy());
4809 	}
4810 	OSSafeReleaseNULL(kextIdentifierSymbol);
4811 	return;
4812 }
4813 
4814 /*********************************************************************
4815 *********************************************************************/
4816 OSReturn
4817 OSKext::load(
4818 	OSKextExcludeLevel   startOpt,
4819 	OSKextExcludeLevel   startMatchingOpt,
4820 	OSArray            * personalityNames)
4821 {
4822 	OSReturn             result                       = kOSReturnError;
4823 	kern_return_t        kxldResult;
4824 	OSKextExcludeLevel   dependenciesStartOpt         = startOpt;
4825 	OSKextExcludeLevel   dependenciesStartMatchingOpt = startMatchingOpt;
4826 	unsigned int         i, count;
4827 	Boolean              alreadyLoaded                = false;
4828 	OSKext             * lastLoadedKext               = NULL;
4829 
4830 	if (isInExcludeList()) {
4831 		OSKextLog(this,
4832 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
4833 		    kOSKextLogLoadFlag,
4834 		    "Kext %s is in exclude list, not loadable",
4835 		    getIdentifierCString());
4836 
4837 		result = kOSKextReturnNotLoadable;
4838 		goto finish;
4839 	}
4840 
4841 	if (isLoaded()) {
4842 		alreadyLoaded = true;
4843 		result = kOSReturnSuccess;
4844 
4845 		OSKextLog(this,
4846 		    kOSKextLogDebugLevel |
4847 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4848 		    "Kext %s is already loaded.",
4849 		    getIdentifierCString());
4850 		goto loaded;
4851 	}
4852 
4853 #if CONFIG_MACF
4854 	if (current_task() != kernel_task) {
4855 		int                 macCheckResult      = 0;
4856 		kauth_cred_t        cred                = NULL;
4857 
4858 		cred = kauth_cred_get_with_ref();
4859 		macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
4860 		kauth_cred_unref(&cred);
4861 
4862 		if (macCheckResult != 0) {
4863 			result = kOSReturnError;
4864 			OSKextLog(this,
4865 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
4866 			    "Failed to load kext %s (MAC policy error 0x%x).",
4867 			    getIdentifierCString(), macCheckResult);
4868 			goto finish;
4869 		}
4870 	}
4871 #endif
4872 
4873 	if (!sLoadEnabled) {
4874 		OSKextLog(this,
4875 		    kOSKextLogErrorLevel |
4876 		    kOSKextLogLoadFlag,
4877 		    "Kext loading is disabled (attempt to load kext %s).",
4878 		    getIdentifierCString());
4879 		result = kOSKextReturnDisabled;
4880 		goto finish;
4881 	}
4882 
4883 	/* If we've pushed the next available load tag to the invalid value,
4884 	 * we can't load any more kexts.
4885 	 */
4886 	if (sNextLoadTag == kOSKextInvalidLoadTag) {
4887 		OSKextLog(this,
4888 		    kOSKextLogErrorLevel |
4889 		    kOSKextLogLoadFlag,
4890 		    "Can't load kext %s - no more load tags to assign.",
4891 		    getIdentifierCString());
4892 		result = kOSKextReturnNoResources;
4893 		goto finish;
4894 	}
4895 
4896 	/* This is a bit of a hack, because we shouldn't be handling
4897 	 * personalities within the load function.
4898 	 */
4899 	if (!declaresExecutable()) {
4900 		/* There is a special case where a non-executable kext can be loaded: the
4901 		 * AppleKextExcludeList.  Detect that special kext by bundle identifier and
4902 		 * load its metadata into the global data structures, if appropriate
4903 		 */
4904 		if (strcmp(getIdentifierCString(), "com.apple.driver.KextExcludeList") == 0) {
4905 			boolean_t updated = updateExcludeList(infoDict);
4906 			if (updated) {
4907 				OSKextLog(this,
4908 				    kOSKextLogDebugLevel | kOSKextLogLoadFlag,
4909 				    "KextExcludeList was updated to version: %lld", sExcludeListVersion);
4910 			}
4911 		}
4912 
4913 		if (isDriverKit()) {
4914 			if (loadTag == 0) {
4915 				sLoadedDriverKitKexts->setObject(this);
4916 				loadTag = sNextLoadTag++;
4917 			}
4918 		}
4919 		result = kOSReturnSuccess;
4920 		goto loaded;
4921 	}
4922 
4923 	/* Are we in safe boot?
4924 	 */
4925 	if (sSafeBoot && !isLoadableInSafeBoot()) {
4926 		OSKextLog(this,
4927 		    kOSKextLogErrorLevel |
4928 		    kOSKextLogLoadFlag,
4929 		    "Can't load kext %s - not loadable during safe boot.",
4930 		    getIdentifierCString());
4931 		result = kOSKextReturnBootLevel;
4932 		goto finish;
4933 	}
4934 
4935 	OSKextLog(this,
4936 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
4937 	    "Loading kext %s.",
4938 	    getIdentifierCString());
4939 
4940 	if (!sKxldContext) {
4941 		kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
4942 		    &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
4943 		    /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
4944 		if (kxldResult) {
4945 			OSKextLog(this,
4946 			    kOSKextLogErrorLevel |
4947 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
4948 			    "Can't load kext %s - failed to create link context.",
4949 			    getIdentifierCString());
4950 			result = kOSKextReturnNoMemory;
4951 			goto finish;
4952 		}
4953 	}
4954 
4955 	/* We only need to resolve dependencies once for the whole graph, but
4956 	 * resolveDependencies will just return if there's no work to do, so it's
4957 	 * safe to call it more than once.
4958 	 */
4959 	if (!resolveDependencies()) {
4960 		// xxx - check resolveDependencies() for log msg
4961 		OSKextLog(this,
4962 		    kOSKextLogErrorLevel |
4963 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4964 		    "Can't load kext %s - failed to resolve library dependencies.",
4965 		    getIdentifierCString());
4966 		result = kOSKextReturnDependencies;
4967 		goto finish;
4968 	}
4969 
4970 	/* If we are excluding just the kext being loaded now (and not its
4971 	 * dependencies), drop the exclusion level to none so dependencies
4972 	 * start and/or add their personalities.
4973 	 */
4974 	if (dependenciesStartOpt == kOSKextExcludeKext) {
4975 		dependenciesStartOpt = kOSKextExcludeNone;
4976 	}
4977 
4978 	if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
4979 		dependenciesStartMatchingOpt = kOSKextExcludeNone;
4980 	}
4981 
4982 	/* Load the dependencies, recursively.
4983 	 */
4984 	count = getNumDependencies();
4985 	for (i = 0; i < count; i++) {
4986 		OSKext * dependency = OSDynamicCast(OSKext,
4987 		    dependencies->getObject(i));
4988 		if (dependency == NULL) {
4989 			OSKextLog(this,
4990 			    kOSKextLogErrorLevel |
4991 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4992 			    "Internal error loading kext %s; dependency disappeared.",
4993 			    getIdentifierCString());
4994 			result = kOSKextReturnInternalError;
4995 			goto finish;
4996 		}
4997 
4998 		/* Dependencies must be started accorting to the opt,
4999 		 * but not given the personality names of the main kext.
5000 		 */
5001 		result = dependency->load(dependenciesStartOpt,
5002 		    dependenciesStartMatchingOpt,
5003 		    /* personalityNames */ NULL);
5004 		if (result != KERN_SUCCESS) {
5005 			OSKextLog(this,
5006 			    kOSKextLogErrorLevel |
5007 			    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5008 			    "Dependency %s of kext %s failed to load.",
5009 			    dependency->getIdentifierCString(),
5010 			    getIdentifierCString());
5011 
5012 			OSKext::removeKext(dependency,
5013 			    /* terminateService/removePersonalities */ true);
5014 			result = kOSKextReturnDependencyLoadError;
5015 
5016 			goto finish;
5017 		}
5018 	}
5019 
5020 	result = loadExecutable();
5021 	if (result != KERN_SUCCESS) {
5022 		goto finish;
5023 	}
5024 
5025 	pendingPgoHead.next = &pendingPgoHead;
5026 	pendingPgoHead.prev = &pendingPgoHead;
5027 
5028 	// The kernel PRNG is not initialized when the first kext is
5029 	// loaded, so use early random
5030 	uuid_generate_early_random(instance_uuid);
5031 	account = IONew(OSKextAccount, 1);
5032 	if (!account) {
5033 		result = KERN_MEMORY_ERROR;
5034 		goto finish;
5035 	}
5036 	bzero(account, sizeof(*account));
5037 	account->loadTag = kmod_info->id;
5038 	account->site.refcount = 0;
5039 	account->site.flags = VM_TAG_KMOD;
5040 	account->kext = this;
5041 	if (gIOSurfaceIdentifier == bundleID) {
5042 		vm_tag_alloc(&account->site);
5043 		gIOSurfaceTag = account->site.tag;
5044 	}
5045 
5046 	flags.loaded = true;
5047 
5048 	/* Add the kext to the list of loaded kexts and update the kmod_info
5049 	 * struct to point to that of the last loaded kext (which is the way
5050 	 * it's always been done, though I'd rather do them in order now).
5051 	 */
5052 	lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
5053 	sLoadedKexts->setObject(this);
5054 
5055 	/* Keep the kernel itself out of the kmod list.
5056 	 */
5057 	if (lastLoadedKext->isKernel()) {
5058 		lastLoadedKext = NULL;
5059 	}
5060 
5061 	if (lastLoadedKext) {
5062 		kmod_info->next = lastLoadedKext->kmod_info;
5063 	}
5064 
5065 	notifyKextLoadObservers(this, kmod_info);
5066 
5067 	/* Make the global kmod list point at the just-loaded kext. Note that the
5068 	 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
5069 	 * although we do report it in kextstat these days by using the newer
5070 	 * OSArray of loaded kexts, which does contain it.
5071 	 *
5072 	 * (The OSKext object representing the kernel doesn't even have a kmod_info
5073 	 * struct, though I suppose we could stick a pointer to it from the
5074 	 * static struct in OSRuntime.cpp.)
5075 	 */
5076 	kmod = kmod_info;
5077 
5078 	/* Save the list of loaded kexts in case we panic.
5079 	 */
5080 	OSKext::saveLoadedKextPanicList();
5081 
5082 	if (isExecutable()) {
5083 		OSKext::updateLoadedKextSummaries();
5084 		savePanicString(/* isLoading */ true);
5085 
5086 #if CONFIG_DTRACE
5087 		registerWithDTrace();
5088 #else
5089 		jettisonLinkeditSegment();
5090 #endif /* CONFIG_DTRACE */
5091 
5092 #if !VM_MAPPED_KEXTS
5093 		/* If there is a page (or more) worth of padding after the end
5094 		 * of the last data section but before the end of the data segment
5095 		 * then free it in the same manner the LinkeditSegment is freed
5096 		 */
5097 		jettisonDATASegmentPadding();
5098 #endif
5099 	}
5100 
5101 loaded:
5102 	if (isExecutable() && !flags.started) {
5103 		if (startOpt == kOSKextExcludeNone) {
5104 			result = start();
5105 			if (result != kOSReturnSuccess) {
5106 				OSKextLog(this,
5107 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5108 				    "Kext %s start failed (result 0x%x).",
5109 				    getIdentifierCString(), result);
5110 				result = kOSKextReturnStartStopError;
5111 			}
5112 		}
5113 	}
5114 
5115 	/* If not excluding matching, send the personalities to the kernel.
5116 	 * This never affects the result of the load operation.
5117 	 * This is a bit of a hack, because we shouldn't be handling
5118 	 * personalities within the load function.
5119 	 */
5120 	if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
5121 		result = sendPersonalitiesToCatalog(true, personalityNames);
5122 	}
5123 
5124 finish:
5125 
5126 	if (result != kOSReturnSuccess) {
5127 		OSKextLog(this,
5128 		    kOSKextLogErrorLevel |
5129 		    kOSKextLogLoadFlag,
5130 		    "Kext %s failed to load (0x%x).",
5131 		    getIdentifierCString(), (int)result);
5132 	} else if (!alreadyLoaded) {
5133 		OSKextLog(this,
5134 		    kOSKextLogProgressLevel |
5135 		    kOSKextLogLoadFlag,
5136 		    "Kext %s loaded.",
5137 		    getIdentifierCString());
5138 
5139 		queueKextNotification(kKextRequestPredicateLoadNotification,
5140 		    OSDynamicCast(OSString, bundleID));
5141 	}
5142 	return result;
5143 }
5144 
5145 /*********************************************************************
5146 *
5147 *********************************************************************/
5148 static char *
5149 strdup(const char * string)
5150 {
5151 	char * result = NULL;
5152 	size_t size;
5153 
5154 	if (!string) {
5155 		goto finish;
5156 	}
5157 
5158 	size = 1 + strlen(string);
5159 	result = (char *)kalloc_tag(size, VM_KERN_MEMORY_OSKEXT);
5160 	if (!result) {
5161 		goto finish;
5162 	}
5163 
5164 	memcpy(result, string, size);
5165 
5166 finish:
5167 	return result;
5168 }
5169 
5170 /*********************************************************************
5171 *
5172 *********************************************************************/
5173 
5174 kernel_section_t *
5175 OSKext::lookupSection(const char *segname, const char *secname)
5176 {
5177 	kernel_section_t         * found_section = NULL;
5178 	kernel_mach_header_t     * mh            = NULL;
5179 	kernel_segment_command_t * seg           = NULL;
5180 	kernel_section_t         * sec           = NULL;
5181 
5182 	if (!linkedExecutable) {
5183 		return NULL;
5184 	}
5185 
5186 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
5187 
5188 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
5189 		if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) {
5190 			continue;
5191 		}
5192 
5193 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
5194 			if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) {
5195 				found_section = sec;
5196 				goto out;
5197 			}
5198 		}
5199 	}
5200 
5201 out:
5202 	return found_section;
5203 }
5204 
5205 /*********************************************************************
5206 *
5207 *********************************************************************/
5208 
5209 OSReturn
5210 OSKext::slidePrelinkedExecutable(bool doCoalesedSlides)
5211 {
5212 	OSReturn                       result           = kOSKextReturnBadData;
5213 	kernel_mach_header_t         * mh               = NULL;
5214 	kernel_segment_command_t     * seg              = NULL;
5215 	kernel_segment_command_t     * linkeditSeg      = NULL;
5216 	kernel_section_t             * sec              = NULL;
5217 	char                         * linkeditBase     = NULL;
5218 	bool                           haveLinkeditBase = false;
5219 	char                         * relocBase        = NULL;
5220 	bool                           haveRelocBase    = false;
5221 	struct dysymtab_command      * dysymtab         = NULL;
5222 	struct linkedit_data_command * segmentSplitInfo = NULL;
5223 	struct symtab_command        * symtab           = NULL;
5224 	kernel_nlist_t               * sym              = NULL;
5225 	struct relocation_info       * reloc            = NULL;
5226 	uint32_t                       i                = 0;
5227 	int                            reloc_size;
5228 	vm_offset_t                    new_kextsize;
5229 
5230 	if (linkedExecutable == NULL || flags.builtin) {
5231 		result = kOSReturnSuccess;
5232 		goto finish;
5233 	}
5234 
5235 	mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
5236 	segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
5237 
5238 	for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
5239 		if (!seg->vmaddr) {
5240 			continue;
5241 		}
5242 
5243 		seg->vmaddr = ml_static_slide(seg->vmaddr);
5244 
5245 #if KASLR_KEXT_DEBUG
5246 		IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
5247 		    seg->segname,
5248 		    (unsigned long)ml_static_unslide(seg->vmaddr),
5249 		    (unsigned long)seg->vmaddr);
5250 #endif
5251 
5252 		if (!haveRelocBase) {
5253 			relocBase = (char *) seg->vmaddr;
5254 			haveRelocBase = true;
5255 		}
5256 		if (!strcmp(seg->segname, "__LINKEDIT")) {
5257 			linkeditBase = (char *) seg->vmaddr - seg->fileoff;
5258 			haveLinkeditBase = true;
5259 			linkeditSeg = seg;
5260 		}
5261 		for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
5262 			sec->addr = ml_static_slide(sec->addr);
5263 
5264 #if KASLR_KEXT_DEBUG
5265 			IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
5266 			    sec->sectname,
5267 			    (unsigned long)ml_static_unslide(sec->addr),
5268 			    (unsigned long)sec->addr);
5269 #endif
5270 		}
5271 	}
5272 
5273 	dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
5274 
5275 	symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
5276 
5277 	if (symtab != NULL && doCoalesedSlides == false) {
5278 		/* Some pseudo-kexts have symbol tables without segments.
5279 		 * Ignore them. */
5280 		if (symtab->nsyms > 0 && haveLinkeditBase) {
5281 			sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
5282 			for (i = 0; i < symtab->nsyms; i++) {
5283 				if (sym[i].n_type & N_STAB) {
5284 					continue;
5285 				}
5286 				sym[i].n_value = ml_static_slide(sym[i].n_value);
5287 
5288 #if KASLR_KEXT_DEBUG
5289 #define MAX_SYMS_TO_LOG 5
5290 				if (i < MAX_SYMS_TO_LOG) {
5291 					IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
5292 					    (unsigned long)ml_static_unslide(sym[i].n_value),
5293 					    (unsigned long)sym[i].n_value);
5294 				}
5295 #endif
5296 			}
5297 		}
5298 	}
5299 
5300 	if (dysymtab != NULL && doCoalesedSlides == false) {
5301 		if (dysymtab->nextrel > 0) {
5302 			OSKextLog(this,
5303 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5304 			    kOSKextLogLinkFlag,
5305 			    "Sliding kext %s: External relocations found.",
5306 			    getIdentifierCString());
5307 			goto finish;
5308 		}
5309 
5310 		if (dysymtab->nlocrel > 0) {
5311 			if (!haveLinkeditBase) {
5312 				OSKextLog(this,
5313 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5314 				    kOSKextLogLinkFlag,
5315 				    "Sliding kext %s: No linkedit segment.",
5316 				    getIdentifierCString());
5317 				goto finish;
5318 			}
5319 
5320 			if (!haveRelocBase) {
5321 				OSKextLog(this,
5322 				    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5323 				    kOSKextLogLinkFlag,
5324 #if __x86_64__
5325 				    "Sliding kext %s: No writable segments.",
5326 #else
5327 				    "Sliding kext %s: No segments.",
5328 #endif
5329 				    getIdentifierCString());
5330 				goto finish;
5331 			}
5332 
5333 			reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
5334 			reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
5335 
5336 			for (i = 0; i < dysymtab->nlocrel; i++) {
5337 				if (reloc[i].r_extern != 0
5338 				    || reloc[i].r_type != 0
5339 				    || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
5340 				    ) {
5341 					OSKextLog(this,
5342 					    kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5343 					    kOSKextLogLinkFlag,
5344 					    "Sliding kext %s: Unexpected relocation found.",
5345 					    getIdentifierCString());
5346 					goto finish;
5347 				}
5348 				if (reloc[i].r_pcrel != 0) {
5349 					continue;
5350 				}
5351 				uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
5352 				*relocAddr = ml_static_slide(*relocAddr);
5353 
5354 #if KASLR_KEXT_DEBUG
5355 #define MAX_DYSYMS_TO_LOG 5
5356 				if (i < MAX_DYSYMS_TO_LOG) {
5357 					IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
5358 					    (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
5359 					    (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
5360 				}
5361 #endif
5362 			}
5363 
5364 			/* We should free these relocations, not just delete the reference to them.
5365 			 * <rdar://problem/10535549> Free relocations from PIE kexts.
5366 			 *
5367 			 * For now, we do not free LINKEDIT for kexts with split segments.
5368 			 */
5369 			new_kextsize = round_page(kmod_info->size - reloc_size);
5370 			if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
5371 				vm_offset_t     endofkext = kmod_info->address + kmod_info->size;
5372 				vm_offset_t     new_endofkext = kmod_info->address + new_kextsize;
5373 				vm_offset_t     endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
5374 				int             bytes_remaining = endofkext - endofrelocInfo;
5375 				OSData *        new_osdata = NULL;
5376 
5377 				/* fix up symbol offsets if they are after the dsymtab local relocs */
5378 				if (symtab) {
5379 					if (dysymtab->locreloff < symtab->symoff) {
5380 						symtab->symoff -= reloc_size;
5381 					}
5382 					if (dysymtab->locreloff < symtab->stroff) {
5383 						symtab->stroff -= reloc_size;
5384 					}
5385 				}
5386 				if (dysymtab->locreloff < dysymtab->extreloff) {
5387 					dysymtab->extreloff -= reloc_size;
5388 				}
5389 
5390 				/* move data behind reloc info down to new offset */
5391 				if (endofrelocInfo < endofkext) {
5392 					memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
5393 				}
5394 
5395 				/* Create a new OSData for the smaller kext object and reflect
5396 				 * new linkedit segment size.
5397 				 */
5398 				linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
5399 				linkeditSeg->filesize = linkeditSeg->vmsize;
5400 
5401 				new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, new_kextsize);
5402 				if (new_osdata) {
5403 					/* Fix up kmod info and linkedExecutable.
5404 					 */
5405 					kmod_info->size = new_kextsize;
5406 #if VM_MAPPED_KEXTS
5407 					new_osdata->setDeallocFunction(osdata_kext_free);
5408 #else
5409 					new_osdata->setDeallocFunction(osdata_phys_free);
5410 #endif
5411 					linkedExecutable->setDeallocFunction(NULL);
5412 					linkedExecutable->release();
5413 					linkedExecutable = new_osdata;
5414 
5415 #if VM_MAPPED_KEXTS
5416 					kext_free(new_endofkext, (endofkext - new_endofkext));
5417 #else
5418 					ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
5419 #endif
5420 				}
5421 			}
5422 			dysymtab->nlocrel = 0;
5423 			dysymtab->locreloff = 0;
5424 		}
5425 	}
5426 
5427 	result = kOSReturnSuccess;
5428 finish:
5429 	return result;
5430 }
5431 
5432 /*********************************************************************
5433 * called only by load()
5434 *********************************************************************/
5435 OSReturn
5436 OSKext::loadExecutable()
5437 {
5438 	OSReturn              result             = kOSReturnError;
5439 	kern_return_t         kxldResult;
5440 	KXLDDependency     *  kxlddeps           = NULL;// must kfree
5441 	uint32_t              num_kxlddeps       = 0;
5442 	OSArray            *  linkDependencies   = NULL;// must release
5443 	uint32_t              numDirectDependencies   = 0;
5444 	uint32_t              num_kmod_refs      = 0;
5445 	struct mach_header ** kxldHeaderPtr      = NULL;// do not free
5446 	struct mach_header  * kxld_header        = NULL;// xxx - need to free here?
5447 	OSData              * theExecutable      = NULL;// do not release
5448 	OSString            * versString         = NULL;// do not release
5449 	const char          * versCString        = NULL;// do not free
5450 	const char          * string             = NULL;// do not free
5451 	unsigned int          i;
5452 
5453 	/* We need the version string for a variety of bits below.
5454 	 */
5455 	versString = OSDynamicCast(OSString,
5456 	    getPropertyForHostArch(kCFBundleVersionKey));
5457 	if (!versString) {
5458 		goto finish;
5459 	}
5460 	versCString = versString->getCStringNoCopy();
5461 
5462 	if (isKernelComponent()) {
5463 		if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
5464 			if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
5465 				OSKextLog(this,
5466 				    kOSKextLogErrorLevel |
5467 				    kOSKextLogLoadFlag,
5468 				    "Kernel component %s has incorrect version %s; "
5469 				    "expected %s.",
5470 				    getIdentifierCString(),
5471 				    versCString, KERNEL6_VERSION);
5472 				result = kOSKextReturnInternalError;
5473 				goto finish;
5474 			} else if (strcmp(versCString, osrelease)) {
5475 				OSKextLog(this,
5476 				    kOSKextLogErrorLevel |
5477 				    kOSKextLogLoadFlag,
5478 				    "Kernel component %s has incorrect version %s; "
5479 				    "expected %s.",
5480 				    getIdentifierCString(),
5481 				    versCString, osrelease);
5482 				result = kOSKextReturnInternalError;
5483 				goto finish;
5484 			}
5485 		}
5486 	}
5487 
5488 	if (isPrelinked()) {
5489 		goto register_kmod;
5490 	}
5491 
5492 	/* <rdar://problem/21444003> all callers must be entitled */
5493 	if (FALSE == IOTaskHasEntitlement(current_task(), kOSKextManagementEntitlement)) {
5494 		OSKextLog(this,
5495 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5496 		    "Not entitled to link kext '%s'",
5497 		    getIdentifierCString());
5498 		result = kOSKextReturnNotPrivileged;
5499 		goto finish;
5500 	}
5501 
5502 	theExecutable = getExecutable();
5503 	if (!theExecutable) {
5504 		if (declaresExecutable()) {
5505 			OSKextLog(this,
5506 			    kOSKextLogErrorLevel |
5507 			    kOSKextLogLoadFlag,
5508 			    "Can't load kext %s - executable is missing.",
5509 			    getIdentifierCString());
5510 			result = kOSKextReturnValidation;
5511 			goto finish;
5512 		}
5513 		goto register_kmod;
5514 	}
5515 
5516 	if (isInterface()) {
5517 		OSData *executableCopy = OSData::withData(theExecutable);
5518 		setLinkedExecutable(executableCopy);
5519 		executableCopy->release();
5520 		goto register_kmod;
5521 	}
5522 
5523 	numDirectDependencies = getNumDependencies();
5524 
5525 	if (flags.hasBleedthrough) {
5526 		linkDependencies = dependencies;
5527 		linkDependencies->retain();
5528 	} else {
5529 		linkDependencies = OSArray::withArray(dependencies);
5530 		if (!linkDependencies) {
5531 			OSKextLog(this,
5532 			    kOSKextLogErrorLevel |
5533 			    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5534 			    "Can't allocate link dependencies to load kext %s.",
5535 			    getIdentifierCString());
5536 			goto finish;
5537 		}
5538 
5539 		for (i = 0; i < numDirectDependencies; ++i) {
5540 			OSKext * dependencyKext = OSDynamicCast(OSKext,
5541 			    dependencies->getObject(i));
5542 			dependencyKext->addBleedthroughDependencies(linkDependencies);
5543 		}
5544 	}
5545 
5546 	num_kxlddeps = linkDependencies->getCount();
5547 	if (!num_kxlddeps) {
5548 		OSKextLog(this,
5549 		    kOSKextLogErrorLevel |
5550 		    kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5551 		    "Can't load kext %s - it has no library dependencies.",
5552 		    getIdentifierCString());
5553 		goto finish;
5554 	}
5555 
5556 	kxlddeps = (KXLDDependency *)kalloc_tag(num_kxlddeps * sizeof(*kxlddeps), VM_KERN_MEMORY_OSKEXT);
5557 	if (!kxlddeps) {
5558 		OSKextLog(this,
5559 		    kOSKextLogErrorLevel |
5560 		    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5561 		    "Can't allocate link context to load kext %s.",
5562 		    getIdentifierCString());
5563 		goto finish;
5564 	}
5565 	bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
5566 
5567 	for (i = 0; i < num_kxlddeps; ++i) {
5568 		OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
5569 
5570 		if (dependency->isInterface()) {
5571 			OSKext *interfaceTargetKext = NULL;
5572 			OSData * interfaceTarget = NULL;
5573 
5574 			if (dependency->isKernelComponent()) {
5575 				interfaceTargetKext = sKernelKext;
5576 				interfaceTarget = sKernelKext->linkedExecutable;
5577 			} else {
5578 				interfaceTargetKext = OSDynamicCast(OSKext,
5579 				    dependency->dependencies->getObject(0));
5580 
5581 				interfaceTarget = interfaceTargetKext->linkedExecutable;
5582 			}
5583 
5584 			if (!interfaceTarget) {
5585 				// panic?
5586 				goto finish;
5587 			}
5588 
5589 			/* The names set here aren't actually logged yet <rdar://problem/7941514>,
5590 			 * it will be useful to have them in the debugger.
5591 			 * strdup() failing isn't critical right here so we don't check that.
5592 			 */
5593 			kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
5594 			kxlddeps[i].kext_size = interfaceTarget->getLength();
5595 			kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
5596 
5597 			kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
5598 			kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
5599 			kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
5600 		} else {
5601 			kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
5602 			kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
5603 			kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
5604 		}
5605 
5606 		kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
5607 	}
5608 
5609 	kxldHeaderPtr = &kxld_header;
5610 
5611 #if DEBUG
5612 	OSKextLog(this,
5613 	    kOSKextLogExplicitLevel |
5614 	    kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5615 	    "Kext %s - calling kxld_link_file:\n"
5616 	    "    kxld_context: %p\n"
5617 	    "    executable: %p    executable_length: %d\n"
5618 	    "    user_data: %p\n"
5619 	    "    kxld_dependencies: %p    num_dependencies: %d\n"
5620 	    "    kxld_header_ptr: %p    kmod_info_ptr: %p\n",
5621 	    getIdentifierCString(), sKxldContext,
5622 	    theExecutable->getBytesNoCopy(), theExecutable->getLength(),
5623 	    this, kxlddeps, num_kxlddeps,
5624 	    kxldHeaderPtr, &kmod_info);
5625 #endif
5626 
5627 	/* After this call, the linkedExecutable instance variable
5628 	 * should exist.
5629 	 */
5630 	kxldResult = kxld_link_file(sKxldContext,
5631 	    (u_char *)theExecutable->getBytesNoCopy(),
5632 	    theExecutable->getLength(),
5633 	    getIdentifierCString(), this, kxlddeps, num_kxlddeps,
5634 	    (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
5635 
5636 	if (kxldResult != KERN_SUCCESS) {
5637 		// xxx - add kxldResult here?
5638 		OSKextLog(this,
5639 		    kOSKextLogErrorLevel |
5640 		    kOSKextLogLoadFlag,
5641 		    "Can't load kext %s - link failed.",
5642 		    getIdentifierCString());
5643 		result = kOSKextReturnLinkError;
5644 		goto finish;
5645 	}
5646 
5647 	/* We've written data & instructions into kernel memory, so flush the data
5648 	 * cache and invalidate the instruction cache.
5649 	 * I/D caches are coherent on x86
5650 	 */
5651 #if !defined(__i386__) && !defined(__x86_64__)
5652 	flush_dcache(kmod_info->address, kmod_info->size, false);
5653 	invalidate_icache(kmod_info->address, kmod_info->size, false);
5654 #endif
5655 register_kmod:
5656 
5657 	if (isInterface()) {
5658 		/* Whip up a fake kmod_info entry for the interface kext.
5659 		 */
5660 		kmod_info = (kmod_info_t *)kalloc_tag(sizeof(kmod_info_t), VM_KERN_MEMORY_OSKEXT);
5661 		if (!kmod_info) {
5662 			result = KERN_MEMORY_ERROR;
5663 			goto finish;
5664 		}
5665 
5666 		/* A pseudokext has almost nothing in its kmod_info struct.
5667 		 */
5668 		bzero(kmod_info, sizeof(kmod_info_t));
5669 
5670 		kmod_info->info_version = KMOD_INFO_VERSION;
5671 
5672 		/* An interface kext doesn't have a linkedExecutable, so save a
5673 		 * copy of the UUID out of the original executable via copyUUID()
5674 		 * while we still have the original executable.
5675 		 */
5676 		interfaceUUID = copyUUID();
5677 	}
5678 
5679 	kmod_info->id = loadTag = sNextLoadTag++;
5680 	kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid).
5681 
5682 	/* Stamp the bundle ID and version from the OSKext over anything
5683 	 * resident inside the kmod_info.
5684 	 */
5685 	string = getIdentifierCString();
5686 	strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
5687 
5688 	string = versCString;
5689 	strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
5690 
5691 	/* Add the dependencies' kmod_info structs as kmod_references.
5692 	 */
5693 	num_kmod_refs = getNumDependencies();
5694 	if (num_kmod_refs) {
5695 		kmod_info->reference_list = (kmod_reference_t *)kalloc_tag(
5696 			num_kmod_refs * sizeof(kmod_reference_t), VM_KERN_MEMORY_OSKEXT);
5697 		if (!kmod_info->reference_list) {
5698 			result = KERN_MEMORY_ERROR;
5699 			goto finish;
5700 		}
5701 		bzero(kmod_info->reference_list,
5702 		    num_kmod_refs * sizeof(kmod_reference_t));
5703 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
5704 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
5705 			OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
5706 			ref->info = refKext->kmod_info;
5707 			ref->info->reference_count++;
5708 
5709 			if (refIndex + 1 < num_kmod_refs) {
5710 				ref->next = kmod_info->reference_list + refIndex + 1;
5711 			}
5712 		}
5713 	}
5714 
5715 	if (!isInterface() && linkedExecutable) {
5716 		OSKextLog(this,
5717 		    kOSKextLogProgressLevel |
5718 		    kOSKextLogLoadFlag,
5719 		    "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5720 		    kmod_info->name,
5721 		    (unsigned)kmod_info->size / PAGE_SIZE,
5722 		    (unsigned long)ml_static_unslide(kmod_info->address),
5723 		    (unsigned)kmod_info->id);
5724 	}
5725 
5726 	/* if prelinked, VM protections are already set */
5727 	result = setVMAttributes(!isPrelinked(), true);
5728 	if (result != KERN_SUCCESS) {
5729 		goto finish;
5730 	}
5731 
5732 #if KASAN
5733 	if (linkedExecutable) {
5734 		kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
5735 		    linkedExecutable->getLength(), getIdentifierCString());
5736 	}
5737 #else
5738 	if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
5739 		OSKextLog(this,
5740 		    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5741 		    "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
5742 		    getIdentifierCString()
5743 		    );
5744 		result = KERN_FAILURE;
5745 		goto finish;
5746 	}
5747 #endif
5748 
5749 	result = kOSReturnSuccess;
5750 
5751 finish:
5752 	OSSafeReleaseNULL(linkDependencies);
5753 
5754 	/* Clear up locally allocated dependency info.
5755 	 */
5756 	for (i = 0; i < num_kxlddeps; ++i) {
5757 		size_t size;
5758 
5759 		if (kxlddeps[i].kext_name) {
5760 			size = 1 + strlen(kxlddeps[i].kext_name);
5761 			kfree(kxlddeps[i].kext_name, size);
5762 		}
5763 		if (kxlddeps[i].interface_name) {
5764 			size = 1 + strlen(kxlddeps[i].interface_name);
5765 			kfree(kxlddeps[i].interface_name, size);
5766 		}
5767 	}
5768 	if (kxlddeps) {
5769 		kfree(kxlddeps, (num_kxlddeps * sizeof(*kxlddeps)));
5770 	}
5771 
5772 	/* We no longer need the unrelocated executable (which the linker
5773 	 * has altered anyhow).
5774 	 */
5775 	setExecutable(NULL);
5776 
5777 	if (result != kOSReturnSuccess) {
5778 		OSKextLog(this,
5779 		    kOSKextLogErrorLevel |
5780 		    kOSKextLogLoadFlag,
5781 		    "Failed to load executable for kext %s.",
5782 		    getIdentifierCString());
5783 
5784 		if (kmod_info && kmod_info->reference_list) {
5785 			kfree(kmod_info->reference_list,
5786 			    num_kmod_refs * sizeof(kmod_reference_t));
5787 		}
5788 		if (isInterface()) {
5789 			kfree(kmod_info, sizeof(kmod_info_t));
5790 		}
5791 		kmod_info = NULL;
5792 		if (linkedExecutable) {
5793 			linkedExecutable->release();
5794 			linkedExecutable = NULL;
5795 		}
5796 	}
5797 
5798 	return result;
5799 }
5800 
5801 /*********************************************************************
5802 * The linkedit segment is used by the kext linker for dependency
5803 * resolution, and by dtrace for probe initialization. We can free it
5804 * for non-library kexts, since no kexts depend on non-library kexts
5805 * by definition, once dtrace has been initialized.
5806 *********************************************************************/
5807 void
5808 OSKext::jettisonLinkeditSegment(void)
5809 {
5810 	kernel_mach_header_t     * machhdr = (kernel_mach_header_t *)kmod_info->address;
5811 	kernel_segment_command_t * linkedit = NULL;
5812 	vm_offset_t                start;
5813 	vm_size_t                  linkeditsize, kextsize;
5814 	OSData                   * data = NULL;
5815 
5816 #if NO_KEXTD
5817 	/* We can free symbol tables for all embedded kexts because we don't
5818 	 * support runtime kext linking.
5819 	 */
5820 	if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
5821 #else
5822 	if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
5823 #endif
5824 		goto finish;
5825 	}
5826 
5827 	/* Find the linkedit segment.  If it's not the last segment, then freeing
5828 	 * it will fragment the kext into multiple VM regions, which OSKext is not
5829 	 * designed to handle, so we'll have to skip it.
5830 	 */
5831 	linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
5832 	if (!linkedit) {
5833 		goto finish;
5834 	}
5835 
5836 	if (round_page(kmod_info->address + kmod_info->size) !=
5837 	    round_page(linkedit->vmaddr + linkedit->vmsize)) {
5838 		goto finish;
5839 	}
5840 
5841 	/* Create a new OSData for the smaller kext object.
5842 	 */
5843 	linkeditsize = round_page(linkedit->vmsize);
5844 	kextsize = kmod_info->size - linkeditsize;
5845 	start = linkedit->vmaddr;
5846 
5847 	data = OSData::withBytesNoCopy((void *)kmod_info->address, kextsize);
5848 	if (!data) {
5849 		goto finish;
5850 	}
5851 
5852 	/* Fix the kmod info and linkedExecutable.
5853 	 */
5854 	kmod_info->size = kextsize;
5855 
5856 #if VM_MAPPED_KEXTS
5857 	data->setDeallocFunction(osdata_kext_free);
5858 #else
5859 	data->setDeallocFunction(osdata_phys_free);
5860 #endif
5861 	linkedExecutable->setDeallocFunction(NULL);
5862 	linkedExecutable->release();
5863 	linkedExecutable = data;
5864 	flags.jettisonLinkeditSeg = 1;
5865 
5866 	/* Free the linkedit segment.
5867 	 */
5868 #if VM_MAPPED_KEXTS
5869 	kext_free(start, linkeditsize);
5870 #else
5871 	ml_static_mfree(start, linkeditsize);
5872 #endif
5873 
5874 finish:
5875 	return;
5876 }
5877 
5878 /*********************************************************************
5879 * If there are whole pages that are unused betweem the last section
5880 * of the DATA segment and the end of the DATA segment then we can free
5881 * them
5882 *********************************************************************/
5883 void
5884 OSKext::jettisonDATASegmentPadding(void)
5885 {
5886 	kernel_mach_header_t * mh;
5887 	kernel_segment_command_t * dataSeg;
5888 	kernel_section_t * sec, * lastSec;
5889 	vm_offset_t dataSegEnd, lastSecEnd;
5890 	vm_size_t padSize;
5891 
5892 	if (flags.builtin) {
5893 		return;
5894 	}
5895 	mh = (kernel_mach_header_t *)kmod_info->address;
5896 
5897 	dataSeg = getsegbynamefromheader(mh, SEG_DATA);
5898 	if (dataSeg == NULL) {
5899 		return;
5900 	}
5901 
5902 	lastSec = NULL;
5903 	sec = firstsect(dataSeg);
5904 	while (sec != NULL) {
5905 		lastSec = sec;
5906 		sec = nextsect(dataSeg, sec);
5907 	}
5908 
5909 	if (lastSec == NULL) {
5910 		return;
5911 	}
5912 
5913 	if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
5914 	    (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
5915 		return;
5916 	}
5917 
5918 	dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
5919 	lastSecEnd = round_page(lastSec->addr + lastSec->size);
5920 
5921 	if (dataSegEnd <= lastSecEnd) {
5922 		return;
5923 	}
5924 
5925 	padSize = dataSegEnd - lastSecEnd;
5926 
5927 	if (padSize >= PAGE_SIZE) {
5928 #if VM_MAPPED_KEXTS
5929 		kext_free(lastSecEnd, padSize);
5930 #else
5931 		ml_static_mfree(lastSecEnd, padSize);
5932 #endif
5933 	}
5934 }
5935 
5936 /*********************************************************************
5937 *********************************************************************/
5938 void
5939 OSKext::setLinkedExecutable(OSData * anExecutable)
5940 {
5941 	if (linkedExecutable) {
5942 		panic("Attempt to set linked executable on kext "
5943 		    "that already has one (%s).\n",
5944 		    getIdentifierCString());
5945 	}
5946 	linkedExecutable = anExecutable;
5947 	linkedExecutable->retain();
5948 	return;
5949 }
5950 
5951 #if CONFIG_DTRACE
5952 /*********************************************************************
5953 * Go through all loaded kexts and tell them to register with dtrace.
5954 * The instance method only registers if necessary.
5955 *********************************************************************/
5956 /* static */
5957 void
5958 OSKext::registerKextsWithDTrace(void)
5959 {
5960 	uint32_t count = sLoadedKexts->getCount();
5961 	uint32_t i;
5962 
5963 	IORecursiveLockLock(sKextLock);
5964 
5965 	for (i = 0; i < count; i++) {
5966 		OSKext   * thisKext     = NULL;// do not release
5967 
5968 		thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
5969 		if (!thisKext || !thisKext->isExecutable()) {
5970 			continue;
5971 		}
5972 
5973 		thisKext->registerWithDTrace();
5974 	}
5975 
5976 	IORecursiveLockUnlock(sKextLock);
5977 
5978 	return;
5979 }
5980 
5981 extern "C" {
5982 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
5983 extern int (*dtrace_modunload)(struct kmod_info *);
5984 };
5985 
5986 /*********************************************************************
5987 *********************************************************************/
5988 void
5989 OSKext::registerWithDTrace(void)
5990 {
5991 	/* Register kext with dtrace. A dtrace_modload failure should not
5992 	 * prevent a kext from loading, so we ignore the return code.
5993 	 */
5994 	if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
5995 		uint32_t modflag = 0;
5996 		OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
5997 		if (forceInit == kOSBooleanTrue) {
5998 			modflag |= KMOD_DTRACE_FORCE_INIT;
5999 		}
6000 		if (flags.builtin) {
6001 			modflag |= KMOD_DTRACE_STATIC_KEXT;
6002 		}
6003 
6004 		(void)(*dtrace_modload)(kmod_info, modflag);
6005 		flags.dtraceInitialized = true;
6006 		jettisonLinkeditSegment();
6007 	}
6008 	return;
6009 }
6010 /*********************************************************************
6011 *********************************************************************/
6012 void
6013 OSKext::unregisterWithDTrace(void)
6014 {
6015 	/* Unregister kext with dtrace. A dtrace_modunload failure should not
6016 	 * prevent a kext from loading, so we ignore the return code.
6017 	 */
6018 	if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
6019 		(void)(*dtrace_modunload)(kmod_info);
6020 		flags.dtraceInitialized = false;
6021 	}
6022 	return;
6023 }
6024 #endif /* CONFIG_DTRACE */
6025 
6026 
6027 /*********************************************************************
6028 * called only by loadExecutable()
6029 *********************************************************************/
6030 #if !VM_MAPPED_KEXTS
6031 #if defined(__arm__) || defined(__arm64__)
6032 static inline kern_return_t
6033 OSKext_protect(
6034 	vm_map_t   map,
6035 	vm_map_offset_t    start,
6036 	vm_map_offset_t    end,
6037 	vm_prot_t  new_prot,
6038 	boolean_t  set_max)
6039 {
6040 #pragma unused(map)
6041 	assert(map == kernel_map); // we can handle KEXTs arising from the PRELINK segment and no others
6042 	assert(start <= end);
6043 	if (start >= end) {
6044 		return KERN_SUCCESS; // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
6045 	} else if (set_max) {
6046 		return KERN_SUCCESS; // Punt set_max, as there's no mechanism to record that state
6047 	} else {
6048 		return ml_static_protect(start, end - start, new_prot);
6049 	}
6050 }
6051 
6052 static inline kern_return_t
6053 OSKext_wire(
6054 	vm_map_t   map,
6055 	vm_map_offset_t    start,
6056 	vm_map_offset_t    end,
6057 	vm_prot_t  access_type,
6058 	boolean_t       user_wire)
6059 {
6060 #pragma unused(map,start,end,access_type,user_wire)
6061 	return KERN_SUCCESS; // No-op as PRELINK kexts are cemented into physical memory at boot
6062 }
6063 #else
6064 #error Unrecognized architecture
6065 #endif
6066 #else
6067 static inline kern_return_t
6068 OSKext_protect(
6069 	vm_map_t   map,
6070 	vm_map_offset_t    start,
6071 	vm_map_offset_t    end,
6072 	vm_prot_t  new_prot,
6073 	boolean_t  set_max)
6074 {
6075 	if (start == end) { // 10538581
6076 		return KERN_SUCCESS;
6077 	}
6078 	return vm_map_protect(map, start, end, new_prot, set_max);
6079 }
6080 
6081 static inline kern_return_t
6082 OSKext_wire(
6083 	vm_map_t   map,
6084 	vm_map_offset_t    start,
6085 	vm_map_offset_t    end,
6086 	vm_prot_t  access_type,
6087 	boolean_t       user_wire)
6088 {
6089 	return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
6090 }
6091 #endif
6092 
6093 OSReturn
6094 OSKext::setVMAttributes(bool protect, bool wire)
6095 {
6096 	vm_map_t                    kext_map        = NULL;
6097 	kernel_segment_command_t  * seg             = NULL;
6098 	vm_map_offset_t             start           = 0;
6099 	vm_map_offset_t             end             = 0;
6100 	OSReturn                    result          = kOSReturnError;
6101 
6102 	if (isInterface() || !declaresExecutable() || flags.builtin) {
6103 		result = kOSReturnSuccess;
6104 		goto finish;
6105 	}
6106 
6107 	/* Get the kext's vm map */
6108 	kext_map = kext_get_vm_map(kmod_info);
6109 	if (!kext_map) {
6110 		result = KERN_MEMORY_ERROR;
6111 		goto finish;
6112 	}
6113 
6114 #if !VM_MAPPED_KEXTS
6115 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
6116 		/* This is a split kext in a prelinked kernelcache; we'll let the
6117 		 * platform code take care of protecting it.  It is already wired.
6118 		 */
6119 		/* TODO: Should this still allow protections for the first segment
6120 		 * to go through, in the event that we have a mix of split and
6121 		 * unsplit kexts?
6122 		 */
6123 		result = KERN_SUCCESS;
6124 		goto finish;
6125 	}
6126 #endif
6127 
6128 	/* Protect the headers as read-only; they do not need to be wired */
6129 	result = (protect) ? OSKext_protect(kext_map, kmod_info->address,
6130 	    kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE)
6131 	    : KERN_SUCCESS;
6132 	if (result != KERN_SUCCESS) {
6133 		goto finish;
6134 	}
6135 
6136 	/* Set the VM protections and wire down each of the segments */
6137 	seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6138 	while (seg) {
6139 #if __arm__
6140 		/* We build all ARM kexts, so we can ensure they are aligned */
6141 		assert((seg->vmaddr & PAGE_MASK) == 0);
6142 		assert((seg->vmsize & PAGE_MASK) == 0);
6143 #endif
6144 
6145 		start = round_page(seg->vmaddr);
6146 		end = trunc_page(seg->vmaddr + seg->vmsize);
6147 
6148 		if (protect) {
6149 			result = OSKext_protect(kext_map, start, end, seg->maxprot, TRUE);
6150 			if (result != KERN_SUCCESS) {
6151 				OSKextLog(this,
6152 				    kOSKextLogErrorLevel |
6153 				    kOSKextLogLoadFlag,
6154 				    "Kext %s failed to set maximum VM protections "
6155 				    "for segment %s - 0x%x.",
6156 				    getIdentifierCString(), seg->segname, (int)result);
6157 				goto finish;
6158 			}
6159 
6160 			result = OSKext_protect(kext_map, start, end, seg->initprot, FALSE);
6161 			if (result != KERN_SUCCESS) {
6162 				OSKextLog(this,
6163 				    kOSKextLogErrorLevel |
6164 				    kOSKextLogLoadFlag,
6165 				    "Kext %s failed to set initial VM protections "
6166 				    "for segment %s - 0x%x.",
6167 				    getIdentifierCString(), seg->segname, (int)result);
6168 				goto finish;
6169 			}
6170 		}
6171 
6172 		if (segmentShouldBeWired(seg) && wire) {
6173 			result = OSKext_wire(kext_map, start, end, seg->initprot, FALSE);
6174 			if (result != KERN_SUCCESS) {
6175 				goto finish;
6176 			}
6177 		}
6178 
6179 		seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
6180 	}
6181 
6182 finish:
6183 	return result;
6184 }
6185 
6186 /*********************************************************************
6187 *********************************************************************/
6188 boolean_t
6189 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
6190 {
6191 	return sKeepSymbols || strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname));
6192 }
6193 
6194 /*********************************************************************
6195 *********************************************************************/
6196 OSReturn
6197 OSKext::validateKextMapping(bool startFlag)
6198 {
6199 	OSReturn                              result      = kOSReturnError;
6200 	const char                          * whichOp = startFlag ? "start" : "stop";
6201 	kern_return_t                         kern_result = 0;
6202 	vm_map_t                              kext_map    = NULL;
6203 	kernel_segment_command_t            * seg         = NULL;
6204 	mach_vm_address_t                     address     = 0;
6205 	mach_vm_size_t                        size        = 0;
6206 	uint32_t                              depth       = 0;
6207 	mach_msg_type_number_t                count;
6208 	vm_region_submap_short_info_data_64_t info;
6209 
6210 	if (flags.builtin) {
6211 		return kOSReturnSuccess;
6212 	}
6213 
6214 	count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
6215 	bzero(&info, sizeof(info));
6216 
6217 	// xxx - do we need a distinct OSReturn value for these or is "bad data"
6218 	// xxx - sufficient?
6219 
6220 	/* Verify that the kmod_info and start/stop pointers are non-NULL.
6221 	 */
6222 	if (!kmod_info) {
6223 		OSKextLog(this,
6224 		    kOSKextLogErrorLevel |
6225 		    kOSKextLogLoadFlag,
6226 		    "Kext %s - NULL kmod_info pointer.",
6227 		    getIdentifierCString());
6228 		result = kOSKextReturnBadData;
6229 		goto finish;
6230 	}
6231 
6232 	if (startFlag) {
6233 		address = (mach_vm_address_t)kmod_info->start;
6234 	} else {
6235 		address = (mach_vm_address_t)kmod_info->stop;
6236 	}
6237 
6238 	if (!address) {
6239 		OSKextLog(this,
6240 		    kOSKextLogErrorLevel |
6241 		    kOSKextLogLoadFlag,
6242 		    "Kext %s - NULL module %s pointer.",
6243 		    getIdentifierCString(), whichOp);
6244 		result = kOSKextReturnBadData;
6245 		goto finish;
6246 	}
6247 
6248 	kext_map = kext_get_vm_map(kmod_info);
6249 	depth = (kernel_map == kext_map) ? 1 : 2;
6250 
6251 	/* Verify that the start/stop function lies within the kext's address range.
6252 	 */
6253 	if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
6254 		/* This will likely be how we deal with split kexts; walk the segments to
6255 		 * check that the function lies inside one of the segments of this kext.
6256 		 */
6257 		for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6258 		    seg != NULL;
6259 		    seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
6260 			if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
6261 				break;
6262 			}
6263 		}
6264 
6265 		if (!seg) {
6266 			OSKextLog(this,
6267 			    kOSKextLogErrorLevel |
6268 			    kOSKextLogLoadFlag,
6269 			    "Kext %s module %s pointer is outside of kext range "
6270 			    "(%s %p - kext starts at %p).",
6271 			    getIdentifierCString(),
6272 			    whichOp,
6273 			    whichOp,
6274 			    (void *)ml_static_unslide(address),
6275 			    (void *)ml_static_unslide(kmod_info->address));
6276 			result = kOSKextReturnBadData;
6277 			goto finish;
6278 		}
6279 
6280 		seg = NULL;
6281 	} else {
6282 		if (address < kmod_info->address + kmod_info->hdr_size ||
6283 		    kmod_info->address + kmod_info->size <= address) {
6284 			OSKextLog(this,
6285 			    kOSKextLogErrorLevel |
6286 			    kOSKextLogLoadFlag,
6287 			    "Kext %s module %s pointer is outside of kext range "
6288 			    "(%s %p - kext at %p-%p).",
6289 			    getIdentifierCString(),
6290 			    whichOp,
6291 			    whichOp,
6292 			    (void *)ml_static_unslide(address),
6293 			    (void *)ml_static_unslide(kmod_info->address),
6294 			    (void *)(ml_static_unslide(kmod_info->address) + kmod_info->size));
6295 			result = kOSKextReturnBadData;
6296 			goto finish;
6297 		}
6298 	}
6299 
6300 	/* Only do these checks before calling the start function;
6301 	 * If anything goes wrong with the mapping while the kext is running,
6302 	 * we'll likely have panicked well before any attempt to stop the kext.
6303 	 */
6304 	if (startFlag) {
6305 		/* Verify that the start/stop function is executable.
6306 		 */
6307 		kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
6308 		    (vm_region_recurse_info_t)&info, &count);
6309 		if (kern_result != KERN_SUCCESS) {
6310 			OSKextLog(this,
6311 			    kOSKextLogErrorLevel |
6312 			    kOSKextLogLoadFlag,
6313 			    "Kext %s - bad %s pointer %p.",
6314 			    getIdentifierCString(),
6315 			    whichOp, (void *)ml_static_unslide(address));
6316 			result = kOSKextReturnBadData;
6317 			goto finish;
6318 		}
6319 
6320 #if VM_MAPPED_KEXTS
6321 		if (!(info.protection & VM_PROT_EXECUTE)) {
6322 			OSKextLog(this,
6323 			    kOSKextLogErrorLevel |
6324 			    kOSKextLogLoadFlag,
6325 			    "Kext %s - memory region containing module %s function "
6326 			    "is not executable.",
6327 			    getIdentifierCString(), whichOp);
6328 			result = kOSKextReturnBadData;
6329 			goto finish;
6330 		}
6331 #endif
6332 
6333 		/* Verify that the kext's segments are backed by physical memory.
6334 		 */
6335 		seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6336 		while (seg) {
6337 			if (!verifySegmentMapping(seg)) {
6338 				result = kOSKextReturnBadData;
6339 				goto finish;
6340 			}
6341 
6342 			seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
6343 		}
6344 	}
6345 
6346 	result = kOSReturnSuccess;
6347 finish:
6348 	return result;
6349 }
6350 
6351 /*********************************************************************
6352 *********************************************************************/
6353 boolean_t
6354 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
6355 {
6356 	mach_vm_address_t address = 0;
6357 
6358 	if (!segmentShouldBeWired(seg)) {
6359 		return true;
6360 	}
6361 
6362 	for (address = seg->vmaddr;
6363 	    address < round_page(seg->vmaddr + seg->vmsize);
6364 	    address += PAGE_SIZE) {
6365 		if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
6366 			OSKextLog(this,
6367 			    kOSKextLogErrorLevel |
6368 			    kOSKextLogLoadFlag,
6369 			    "Kext %s - page %p is not backed by physical memory.",
6370 			    getIdentifierCString(),
6371 			    (void *)address);
6372 			return false;
6373 		}
6374 	}
6375 
6376 	return true;
6377 }
6378 
6379 /*********************************************************************
6380 *********************************************************************/
6381 static void
6382 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
6383 {
6384 	uint64_t                            stamp = 0;
6385 	firehose_tracepoint_id_u            trace_id;
6386 	struct firehose_trace_uuid_info_s   uuid_info_s;
6387 	firehose_trace_uuid_info_t          uuid_info = &uuid_info_s;
6388 	size_t                              uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
6389 	OSData                              *uuid_data;
6390 
6391 	stamp = firehose_tracepoint_time(firehose_activity_flags_default);
6392 	trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
6393 
6394 	uuid_data = aKext->copyTextUUID();
6395 	if (uuid_data) {
6396 		memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
6397 		OSSafeReleaseNULL(uuid_data);
6398 	}
6399 
6400 	uuid_info->ftui_size    = size;
6401 	if (aKext->isDriverKit()) {
6402 		uuid_info->ftui_address = address;
6403 	} else {
6404 		uuid_info->ftui_address = ml_static_unslide(address);
6405 	}
6406 	firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len);
6407 	return;
6408 }
6409 
6410 void
6411 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext)
6412 {
6413 	OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load);
6414 }
6415 
6416 /*********************************************************************
6417 *********************************************************************/
6418 OSReturn
6419 OSKext::start(bool startDependenciesFlag)
6420 {
6421 	OSReturn                            result = kOSReturnError;
6422 	kern_return_t                       (* startfunc)(kmod_info_t *, void *);
6423 	unsigned int                        i, count;
6424 	void                              * kmodStartData = NULL;
6425 
6426 	if (isStarted() || isInterface() || isKernelComponent()) {
6427 		result = kOSReturnSuccess;
6428 		goto finish;
6429 	}
6430 
6431 	if (!isLoaded()) {
6432 		OSKextLog(this,
6433 		    kOSKextLogErrorLevel |
6434 		    kOSKextLogLoadFlag,
6435 		    "Attempt to start nonloaded kext %s.",
6436 		    getIdentifierCString());
6437 		result = kOSKextReturnInvalidArgument;
6438 		goto finish;
6439 	}
6440 
6441 	if (!sLoadEnabled) {
6442 		OSKextLog(this,
6443 		    kOSKextLogErrorLevel |
6444 		    kOSKextLogLoadFlag,
6445 		    "Kext loading is disabled (attempt to start kext %s).",
6446 		    getIdentifierCString());
6447 		result = kOSKextReturnDisabled;
6448 		goto finish;
6449 	}
6450 
6451 	result = validateKextMapping(/* start? */ true);
6452 	if (result != kOSReturnSuccess) {
6453 		goto finish;
6454 	}
6455 
6456 	startfunc = kmod_info->start;
6457 
6458 	count = getNumDependencies();
6459 	for (i = 0; i < count; i++) {
6460 		OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
6461 		if (dependency == NULL) {
6462 			OSKextLog(this,
6463 			    kOSKextLogErrorLevel |
6464 			    kOSKextLogLoadFlag,
6465 			    "Kext %s start - internal error, dependency disappeared.",
6466 			    getIdentifierCString());
6467 			goto finish;
6468 		}
6469 		if (!dependency->isStarted()) {
6470 			if (startDependenciesFlag) {
6471 				OSReturn dependencyResult =
6472 				    dependency->start(startDependenciesFlag);
6473 				if (dependencyResult != KERN_SUCCESS) {
6474 					OSKextLog(this,
6475 					    kOSKextLogErrorLevel |
6476 					    kOSKextLogLoadFlag,
6477 					    "Kext %s start - dependency %s failed to start (error 0x%x).",
6478 					    getIdentifierCString(),
6479 					    dependency->getIdentifierCString(),
6480 					    dependencyResult);
6481 					goto finish;
6482 				}
6483 			} else {
6484 				OSKextLog(this,
6485 				    kOSKextLogErrorLevel |
6486 				    kOSKextLogLoadFlag,
6487 				    "Not starting %s - dependency %s not started yet.",
6488 				    getIdentifierCString(),
6489 				    dependency->getIdentifierCString());
6490 				result = kOSKextReturnStartStopError; // xxx - make new return?
6491 				goto finish;
6492 			}
6493 		}
6494 	}
6495 
6496 	OSKextLog(this,
6497 	    kOSKextLogDetailLevel |
6498 	    kOSKextLogLoadFlag,
6499 	    "Kext %s calling module start function.",
6500 	    getIdentifierCString());
6501 
6502 	flags.starting = 1;
6503 
6504 	// Drop a log message so logd can grab the needed information to decode this kext
6505 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
6506 	result = OSRuntimeInitializeCPP(this);
6507 	if (result == KERN_SUCCESS) {
6508 		result = startfunc(kmod_info, kmodStartData);
6509 	}
6510 
6511 	flags.starting = 0;
6512 
6513 	/* On success overlap the setting of started/starting. On failure just
6514 	 * clear starting.
6515 	 */
6516 	if (result == KERN_SUCCESS) {
6517 		flags.started = 1;
6518 
6519 		// xxx - log start error from kernel?
6520 		OSKextLog(this,
6521 		    kOSKextLogProgressLevel |
6522 		    kOSKextLogLoadFlag,
6523 		    "Kext %s is now started.",
6524 		    getIdentifierCString());
6525 	} else {
6526 		invokeOrCancelRequestCallbacks(
6527 			/* result not actually used */ kOSKextReturnStartStopError,
6528 			/* invokeFlag */ false);
6529 		OSKextLog(this,
6530 		    kOSKextLogProgressLevel |
6531 		    kOSKextLogLoadFlag,
6532 		    "Kext %s did not start (return code 0x%x).",
6533 		    getIdentifierCString(), result);
6534 	}
6535 
6536 finish:
6537 	return result;
6538 }
6539 
6540 /*********************************************************************
6541 *********************************************************************/
6542 /* static */
6543 bool
6544 OSKext::canUnloadKextWithIdentifier(
6545 	OSString * kextIdentifier,
6546 	bool       checkClassesFlag)
6547 {
6548 	bool     result = false;
6549 	OSKext * aKext  = NULL;// do not release
6550 
6551 	IORecursiveLockLock(sKextLock);
6552 
6553 	aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
6554 
6555 	if (!aKext) {
6556 		goto finish; // can't unload what's not loaded
6557 	}
6558 
6559 	if (aKext->isLoaded()) {
6560 		if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
6561 			goto finish;
6562 		}
6563 		if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
6564 			goto finish;
6565 		}
6566 	}
6567 
6568 	result = true;
6569 
6570 finish:
6571 	IORecursiveLockUnlock(sKextLock);
6572 	return result;
6573 }
6574 
6575 /*********************************************************************
6576 *********************************************************************/
6577 OSReturn
6578 OSKext::stop(void)
6579 {
6580 	OSReturn result = kOSReturnError;
6581 	kern_return_t (*stopfunc)(kmod_info_t *, void *);
6582 
6583 	if (!isStarted() || isInterface()) {
6584 		result = kOSReturnSuccess;
6585 		goto finish;
6586 	}
6587 
6588 	if (!isLoaded()) {
6589 		OSKextLog(this,
6590 		    kOSKextLogErrorLevel |
6591 		    kOSKextLogLoadFlag,
6592 		    "Attempt to stop nonloaded kext %s.",
6593 		    getIdentifierCString());
6594 		result = kOSKextReturnInvalidArgument;
6595 		goto finish;
6596 	}
6597 
6598 	/* Refuse to stop if we have clients or instances. It is up to
6599 	 * the caller to make sure those aren't true.
6600 	 */
6601 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6602 		OSKextLog(this,
6603 		    kOSKextLogErrorLevel |
6604 		    kOSKextLogLoadFlag,
6605 		    "Kext %s - C++ instances; can't stop.",
6606 		    getIdentifierCString());
6607 		result = kOSKextReturnInUse;
6608 		goto finish;
6609 	}
6610 
6611 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6612 		OSKextLog(this,
6613 		    kOSKextLogErrorLevel |
6614 		    kOSKextLogLoadFlag,
6615 		    "Kext %s - has references (linkage or tracking object); "
6616 		    "can't stop.",
6617 		    getIdentifierCString());
6618 		result = kOSKextReturnInUse;
6619 		goto finish;
6620 	}
6621 
6622 	/* Note: If validateKextMapping fails on the stop & unload path,
6623 	 * we are in serious trouble and a kernel panic is likely whether
6624 	 * we stop & unload the kext or not.
6625 	 */
6626 	result = validateKextMapping(/* start? */ false);
6627 	if (result != kOSReturnSuccess) {
6628 		goto finish;
6629 	}
6630 
6631 	stopfunc = kmod_info->stop;
6632 	if (stopfunc) {
6633 		OSKextLog(this,
6634 		    kOSKextLogDetailLevel |
6635 		    kOSKextLogLoadFlag,
6636 		    "Kext %s calling module stop function.",
6637 		    getIdentifierCString());
6638 
6639 		flags.stopping = 1;
6640 
6641 		result = stopfunc(kmod_info, /* userData */ NULL);
6642 		if (result == KERN_SUCCESS) {
6643 			result = OSRuntimeFinalizeCPP(this);
6644 		}
6645 
6646 		flags.stopping = 0;
6647 
6648 		if (result == KERN_SUCCESS) {
6649 			flags.started = 0;
6650 
6651 			OSKextLog(this,
6652 			    kOSKextLogDetailLevel |
6653 			    kOSKextLogLoadFlag,
6654 			    "Kext %s is now stopped and ready to unload.",
6655 			    getIdentifierCString());
6656 		} else {
6657 			OSKextLog(this,
6658 			    kOSKextLogErrorLevel |
6659 			    kOSKextLogLoadFlag,
6660 			    "Kext %s did not stop (return code 0x%x).",
6661 			    getIdentifierCString(), result);
6662 			result = kOSKextReturnStartStopError;
6663 		}
6664 	}
6665 
6666 finish:
6667 	// Drop a log message so logd can update this kext's metadata
6668 	OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
6669 	return result;
6670 }
6671 
6672 /*********************************************************************
6673 *********************************************************************/
6674 OSReturn
6675 OSKext::unload(void)
6676 {
6677 	OSReturn        result = kOSReturnError;
6678 	unsigned int    index;
6679 	uint32_t        num_kmod_refs = 0;
6680 	OSKextAccount * freeAccount;
6681 
6682 	if (!sUnloadEnabled) {
6683 		OSKextLog(this,
6684 		    kOSKextLogErrorLevel |
6685 		    kOSKextLogLoadFlag,
6686 		    "Kext unloading is disabled (%s).",
6687 		    this->getIdentifierCString());
6688 
6689 		result = kOSKextReturnDisabled;
6690 		goto finish;
6691 	}
6692 
6693 	/* Refuse to unload if we have clients or instances. It is up to
6694 	 * the caller to make sure those aren't true.
6695 	 */
6696 	if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6697 		// xxx - Don't log under errors? this is more of an info thing
6698 		OSKextLog(this,
6699 		    kOSKextLogErrorLevel |
6700 		    kOSKextLogKextBookkeepingFlag,
6701 		    "Can't unload kext %s; outstanding references (linkage or tracking object).",
6702 		    getIdentifierCString());
6703 		result = kOSKextReturnInUse;
6704 		goto finish;
6705 	}
6706 
6707 	if (isDriverKit()) {
6708 		index = sLoadedKexts->getNextIndexOfObject(this, 0);
6709 		if (index != (unsigned int)-1) {
6710 			sLoadedDriverKitKexts->removeObject(index);
6711 			OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
6712 			loadTag = 0;
6713 		}
6714 	}
6715 
6716 	if (!isLoaded()) {
6717 		result = kOSReturnSuccess;
6718 		goto finish;
6719 	}
6720 
6721 	if (isKernelComponent()) {
6722 		result = kOSKextReturnInvalidArgument;
6723 		goto finish;
6724 	}
6725 
6726 	if (metaClasses && !OSMetaClass::removeClasses(metaClasses)) {
6727 		OSKextLog(this,
6728 		    kOSKextLogErrorLevel |
6729 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6730 		    "Can't unload kext %s; classes have instances:",
6731 		    getIdentifierCString());
6732 		reportOSMetaClassInstances(kOSKextLogErrorLevel |
6733 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
6734 		result = kOSKextReturnInUse;
6735 		goto finish;
6736 	}
6737 
6738 	/* Note that the kext is unloading before running any code that
6739 	 * might be in the kext (request callbacks, module stop function).
6740 	 * We will deny certain requests made against a kext in the process
6741 	 * of unloading.
6742 	 */
6743 	flags.unloading = 1;
6744 
6745 	/* Update the string describing the last kext to unload in case we panic.
6746 	 */
6747 	savePanicString(/* isLoading */ false);
6748 
6749 	if (isStarted()) {
6750 		result = stop();
6751 		if (result != KERN_SUCCESS) {
6752 			OSKextLog(this,
6753 			    kOSKextLogErrorLevel |
6754 			    kOSKextLogLoadFlag,
6755 			    "Kext %s can't unload - module stop returned 0x%x.",
6756 			    getIdentifierCString(), (unsigned)result);
6757 			result = kOSKextReturnStartStopError;
6758 			goto finish;
6759 		}
6760 	}
6761 
6762 	OSKextLog(this,
6763 	    kOSKextLogProgressLevel |
6764 	    kOSKextLogLoadFlag,
6765 	    "Kext %s unloading.",
6766 	    getIdentifierCString());
6767 
6768 	{
6769 		struct list_head *p;
6770 		struct list_head *prev;
6771 		struct list_head *next;
6772 		for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
6773 			OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
6774 			s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
6775 			prev = p->prev;
6776 			next = p->next;
6777 			prev->next = next;
6778 			next->prev = prev;
6779 			p->prev = p;
6780 			p->next = p;
6781 			IORecursiveLockWakeup(sKextLock, s, false);
6782 		}
6783 	}
6784 
6785 
6786 	/* Even if we don't call the stop function, we want to be sure we
6787 	 * have no OSMetaClass references before unloading the kext executable
6788 	 * from memory. OSMetaClasses may have pointers into the kext executable
6789 	 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6790 	 */
6791 	if (metaClasses) {
6792 		metaClasses->flushCollection();
6793 	}
6794 	(void) OSRuntimeFinalizeCPP(this);
6795 
6796 	/* Remove the kext from the list of loaded kexts, patch the gap
6797 	 * in the kmod_info_t linked list, and reset "kmod" to point to the
6798 	 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6799 	 */
6800 	index = sLoadedKexts->getNextIndexOfObject(this, 0);
6801 	if (index != (unsigned int)-1) {
6802 		sLoadedKexts->removeObject(index);
6803 
6804 		OSKext * nextKext = OSDynamicCast(OSKext,
6805 		    sLoadedKexts->getObject(index));
6806 
6807 		if (nextKext) {
6808 			if (index > 0) {
6809 				OSKext * gapKext = OSDynamicCast(OSKext,
6810 				    sLoadedKexts->getObject(index - 1));
6811 
6812 				nextKext->kmod_info->next = gapKext->kmod_info;
6813 			} else { /* index == 0 */
6814 				nextKext->kmod_info->next = NULL;
6815 			}
6816 		}
6817 
6818 		OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
6819 		if (lastKext && !lastKext->isKernel()) {
6820 			kmod = lastKext->kmod_info;
6821 		} else {
6822 			kmod = NULL; // clear the global kmod variable
6823 		}
6824 	}
6825 
6826 	/* Clear out the kmod references that we're keeping for compatibility
6827 	 * with current panic backtrace code & kgmacros.
6828 	 * xxx - will want to update those bits sometime and remove this.
6829 	 */
6830 	num_kmod_refs = getNumDependencies();
6831 	if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
6832 		for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
6833 			kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
6834 			ref->info->reference_count--;
6835 		}
6836 		kfree(kmod_info->reference_list,
6837 		    num_kmod_refs * sizeof(kmod_reference_t));
6838 	}
6839 
6840 #if CONFIG_DTRACE
6841 	unregisterWithDTrace();
6842 #endif /* CONFIG_DTRACE */
6843 
6844 	notifyKextUnloadObservers(this);
6845 
6846 	freeAccount = NULL;
6847 	IOSimpleLockLock(sKextAccountsLock);
6848 	account->kext = NULL;
6849 	if (account->site.tag) {
6850 		account->site.flags |= VM_TAG_UNLOAD;
6851 	} else {
6852 		freeAccount = account;
6853 	}
6854 	IOSimpleLockUnlock(sKextAccountsLock);
6855 	if (freeAccount) {
6856 		IODelete(freeAccount, OSKextAccount, 1);
6857 	}
6858 
6859 	/* Unwire and free the linked executable.
6860 	 */
6861 	if (linkedExecutable) {
6862 #if KASAN
6863 		kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
6864 #endif
6865 
6866 #if VM_MAPPED_KEXTS
6867 		if (!isInterface()) {
6868 			kernel_segment_command_t *seg = NULL;
6869 			vm_map_t kext_map = kext_get_vm_map(kmod_info);
6870 
6871 			if (!kext_map) {
6872 				OSKextLog(this,
6873 				    kOSKextLogErrorLevel |
6874 				    kOSKextLogLoadFlag,
6875 				    "Failed to free kext %s; couldn't find the kext map.",
6876 				    getIdentifierCString());
6877 				result = kOSKextReturnInternalError;
6878 				goto finish;
6879 			}
6880 
6881 			OSKextLog(this,
6882 			    kOSKextLogProgressLevel |
6883 			    kOSKextLogLoadFlag,
6884 			    "Kext %s unwiring and unmapping linked executable.",
6885 			    getIdentifierCString());
6886 
6887 			seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6888 			while (seg) {
6889 				if (segmentShouldBeWired(seg)) {
6890 					result = vm_map_unwire(kext_map, seg->vmaddr,
6891 					    seg->vmaddr + seg->vmsize, FALSE);
6892 					if (result != KERN_SUCCESS) {
6893 						OSKextLog(this,
6894 						    kOSKextLogErrorLevel |
6895 						    kOSKextLogLoadFlag,
6896 						    "Failed to unwire kext %s.",
6897 						    getIdentifierCString());
6898 						result = kOSKextReturnInternalError;
6899 						goto finish;
6900 					}
6901 				}
6902 
6903 				seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
6904 			}
6905 		}
6906 #endif
6907 		OSSafeReleaseNULL(linkedExecutable);
6908 	}
6909 
6910 	/* An interface kext has a fake kmod_info that was allocated,
6911 	 * so we have to free it.
6912 	 */
6913 	if (isInterface()) {
6914 		kfree(kmod_info, sizeof(kmod_info_t));
6915 	}
6916 
6917 	kmod_info = NULL;
6918 
6919 	flags.loaded = false;
6920 	flushDependencies();
6921 
6922 	/* save a copy of the bundle ID for us to check when deciding to
6923 	 * rebuild the kernel cache file.  If a kext was already in the kernel
6924 	 * cache and unloaded then later loaded we do not need to rebuild the
6925 	 * kernel cache.  9055303
6926 	 */
6927 	if (isPrelinked()) {
6928 		if (!_OSKextInUnloadedPrelinkedKexts(bundleID)) {
6929 			IORecursiveLockLock(sKextLock);
6930 			if (sUnloadedPrelinkedKexts) {
6931 				sUnloadedPrelinkedKexts->setObject(bundleID);
6932 			}
6933 			IORecursiveLockUnlock(sKextLock);
6934 		}
6935 	}
6936 
6937 	OSKextLog(this,
6938 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
6939 	    "Kext %s unloaded.", getIdentifierCString());
6940 
6941 	queueKextNotification(kKextRequestPredicateUnloadNotification,
6942 	    OSDynamicCast(OSString, bundleID));
6943 
6944 finish:
6945 	OSKext::saveLoadedKextPanicList();
6946 	OSKext::updateLoadedKextSummaries();
6947 
6948 	flags.unloading = 0;
6949 	return result;
6950 }
6951 
6952 /*********************************************************************
6953 * Assumes sKextLock is held.
6954 *********************************************************************/
6955 /* static */
6956 OSReturn
6957 OSKext::queueKextNotification(
6958 	const char * notificationName,
6959 	OSString   * kextIdentifier)
6960 {
6961 	OSReturn          result               = kOSReturnError;
6962 	OSDictionary    * loadRequest          = NULL;// must release
6963 
6964 	if (!kextIdentifier) {
6965 		result = kOSKextReturnInvalidArgument;
6966 		goto finish;
6967 	}
6968 
6969 	/* Create a new request unless one is already sitting
6970 	 * in sKernelRequests for this bundle identifier
6971 	 */
6972 	result = _OSKextCreateRequest(notificationName, &loadRequest);
6973 	if (result != kOSReturnSuccess) {
6974 		goto finish;
6975 	}
6976 	if (!_OSKextSetRequestArgument(loadRequest,
6977 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
6978 		result = kOSKextReturnNoMemory;
6979 		goto finish;
6980 	}
6981 	if (!sKernelRequests->setObject(loadRequest)) {
6982 		result = kOSKextReturnNoMemory;
6983 		goto finish;
6984 	}
6985 
6986 	/* We might want to only queue the notification if kextd is active,
6987 	 * but that wouldn't work for embedded. Note that we don't care if
6988 	 * the ping immediately succeeds here so don't do anything with the
6989 	 * result of this call.
6990 	 */
6991 	OSKext::pingKextd();
6992 
6993 	result = kOSReturnSuccess;
6994 
6995 finish:
6996 	OSSafeReleaseNULL(loadRequest);
6997 
6998 	return result;
6999 }
7000 
7001 /*********************************************************************
7002 *********************************************************************/
7003 static void
7004 _OSKextConsiderDestroyingLinkContext(
7005 	__unused thread_call_param_t p0,
7006 	__unused thread_call_param_t p1)
7007 {
7008 	/* Take multiple locks in the correct order.
7009 	 */
7010 	IORecursiveLockLock(sKextLock);
7011 	IORecursiveLockLock(sKextInnerLock);
7012 
7013 	/* The first time we destroy the kxldContext is in the first
7014 	 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
7015 	 * before calling this function. Thereafter any call to this function
7016 	 * will actually destroy the context.
7017 	 */
7018 	if (sConsiderUnloadsCalled && sKxldContext) {
7019 		kxld_destroy_context(sKxldContext);
7020 		sKxldContext = NULL;
7021 	}
7022 
7023 	/* Free the thread_call that was allocated to execute this function.
7024 	 */
7025 	if (sDestroyLinkContextThread) {
7026 		if (!thread_call_free(sDestroyLinkContextThread)) {
7027 			OSKextLog(/* kext */ NULL,
7028 			    kOSKextLogErrorLevel |
7029 			    kOSKextLogGeneralFlag,
7030 			    "thread_call_free() failed for kext link context.");
7031 		}
7032 		sDestroyLinkContextThread = NULL;
7033 	}
7034 
7035 	IORecursiveLockUnlock(sKextInnerLock);
7036 	IORecursiveLockUnlock(sKextLock);
7037 
7038 	return;
7039 }
7040 
7041 /*********************************************************************
7042 * Destroying the kxldContext requires checking variables under both
7043 * sKextInnerLock and sKextLock, so we do it on a separate thread
7044 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
7045 * call relationship.
7046 *
7047 * This function must be invoked with sKextInnerLock held.
7048 * Do not call any function that takes sKextLock here!
7049 *********************************************************************/
7050 /* static */
7051 void
7052 OSKext::considerDestroyingLinkContext(void)
7053 {
7054 	IORecursiveLockLock(sKextInnerLock);
7055 
7056 	/* If we have already queued a thread to destroy the link context,
7057 	 * don't bother resetting; that thread will take care of it.
7058 	 */
7059 	if (sDestroyLinkContextThread) {
7060 		goto finish;
7061 	}
7062 
7063 	/* The function to be invoked in the thread will deallocate
7064 	 * this thread_call, so don't share it around.
7065 	 */
7066 	sDestroyLinkContextThread = thread_call_allocate(
7067 		&_OSKextConsiderDestroyingLinkContext, NULL);
7068 	if (!sDestroyLinkContextThread) {
7069 		OSKextLog(/* kext */ NULL,
7070 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
7071 		    "Can't create thread to destroy kext link context.");
7072 		goto finish;
7073 	}
7074 
7075 	thread_call_enter(sDestroyLinkContextThread);
7076 
7077 finish:
7078 	IORecursiveLockUnlock(sKextInnerLock);
7079 	return;
7080 }
7081 
7082 #if PRAGMA_MARK
7083 #pragma mark Autounload
7084 #endif
7085 /*********************************************************************
7086 * This is a static method because the kext will be deallocated if it
7087 * does unload!
7088 *********************************************************************/
7089 /* static */
7090 OSReturn
7091 OSKext::autounloadKext(OSKext * aKext)
7092 {
7093 	OSReturn result = kOSKextReturnInUse;
7094 
7095 	/* Check for external references to this kext (usu. dependents),
7096 	 * instances of defined classes (or classes derived from them),
7097 	 * outstanding requests.
7098 	 */
7099 	if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
7100 	    !aKext->flags.autounloadEnabled ||
7101 	    aKext->isKernelComponent()) {
7102 		goto finish;
7103 	}
7104 
7105 	/* Skip a delay-autounload kext, once.
7106 	 */
7107 	if (aKext->flags.delayAutounload) {
7108 		OSKextLog(aKext,
7109 		    kOSKextLogProgressLevel |
7110 		    kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
7111 		    "Kext %s has delayed autounload set; skipping and clearing flag.",
7112 		    aKext->getIdentifierCString());
7113 		aKext->flags.delayAutounload = 0;
7114 		goto finish;
7115 	}
7116 
7117 	if (aKext->hasOSMetaClassInstances() ||
7118 	    aKext->countRequestCallbacks()) {
7119 		goto finish;
7120 	}
7121 
7122 	result = OSKext::removeKext(aKext);
7123 
7124 finish:
7125 	return result;
7126 }
7127 
7128 /*********************************************************************
7129 *********************************************************************/
7130 void
7131 _OSKextConsiderUnloads(
7132 	__unused thread_call_param_t p0,
7133 	__unused thread_call_param_t p1)
7134 {
7135 	bool         didUnload = false;
7136 	unsigned int count, i;
7137 
7138 	/* Take multiple locks in the correct order
7139 	 * (note also sKextSummaries lock further down).
7140 	 */
7141 	IORecursiveLockLock(sKextLock);
7142 	IORecursiveLockLock(sKextInnerLock);
7143 
7144 	OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
7145 
7146 	/* If the system is powering down, don't try to unload anything.
7147 	 */
7148 	if (sSystemSleep) {
7149 		goto finish;
7150 	}
7151 
7152 	OSKextLog(/* kext */ NULL,
7153 	    kOSKextLogProgressLevel | kOSKextLogLoadFlag,
7154 	    "Checking for unused kexts to autounload.");
7155 
7156 	/*****
7157 	 * Remove any request callbacks marked as stale,
7158 	 * and mark as stale any currently in flight.
7159 	 */
7160 	count = sRequestCallbackRecords->getCount();
7161 	if (count) {
7162 		i = count - 1;
7163 		do {
7164 			OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
7165 			    sRequestCallbackRecords->getObject(i));
7166 			OSBoolean * stale = OSDynamicCast(OSBoolean,
7167 			    callbackRecord->getObject(kKextRequestStaleKey));
7168 
7169 			if (stale == kOSBooleanTrue) {
7170 				OSKext::invokeRequestCallback(callbackRecord,
7171 				    kOSKextReturnTimeout);
7172 			} else {
7173 				callbackRecord->setObject(kKextRequestStaleKey,
7174 				    kOSBooleanTrue);
7175 			}
7176 		} while (i--);
7177 	}
7178 
7179 	/*****
7180 	 * Make multiple passes through the array of loaded kexts until
7181 	 * we don't unload any. This handles unwinding of dependency
7182 	 * chains. We have to go *backwards* through the array because
7183 	 * kexts are removed from it when unloaded, and we cannot make
7184 	 * a copy or we'll mess up the retain counts we rely on to
7185 	 * check whether a kext will unload. If only we could have
7186 	 * nonretaining collections like CF has....
7187 	 */
7188 	do {
7189 		didUnload = false;
7190 
7191 		count = sLoadedKexts->getCount();
7192 		if (count) {
7193 			i = count - 1;
7194 			do {
7195 				OSKext * thisKext = OSDynamicCast(OSKext,
7196 				    sLoadedKexts->getObject(i));
7197 				didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
7198 			} while (i--);
7199 		}
7200 	} while (didUnload);
7201 
7202 finish:
7203 	sConsiderUnloadsPending = false;
7204 	sConsiderUnloadsExecuted = true;
7205 
7206 	(void) OSKext::considerRebuildOfPrelinkedKernel();
7207 
7208 	IORecursiveLockUnlock(sKextInnerLock);
7209 	IORecursiveLockUnlock(sKextLock);
7210 
7211 	return;
7212 }
7213 
7214 /*********************************************************************
7215 * Do not call any function that takes sKextLock here!
7216 *********************************************************************/
7217 void
7218 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
7219 {
7220 	AbsoluteTime when;
7221 
7222 	IORecursiveLockLock(sKextInnerLock);
7223 
7224 	if (!sUnloadCallout) {
7225 		sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL);
7226 	}
7227 
7228 	/* we only reset delay value for unloading if we already have something
7229 	 * pending.  rescheduleOnlyFlag should not start the count down.
7230 	 */
7231 	if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
7232 		goto finish;
7233 	}
7234 
7235 	thread_call_cancel(sUnloadCallout);
7236 	if (OSKext::getAutounloadEnabled() && !sSystemSleep) {
7237 		clock_interval_to_deadline(sConsiderUnloadDelay,
7238 		    1000 * 1000 * 1000, &when);
7239 
7240 		OSKextLog(/* kext */ NULL,
7241 		    kOSKextLogProgressLevel |
7242 		    kOSKextLogLoadFlag,
7243 		    "%scheduling %sscan for unused kexts in %lu seconds.",
7244 		    sConsiderUnloadsPending ? "Res" : "S",
7245 		    sConsiderUnloadsCalled ? "" : "initial ",
7246 		    (unsigned long)sConsiderUnloadDelay);
7247 
7248 		sConsiderUnloadsPending = true;
7249 		thread_call_enter_delayed(sUnloadCallout, when);
7250 	}
7251 
7252 finish:
7253 	/* The kxld context should be reused throughout boot.  We mark the end of
7254 	 * period as the first time considerUnloads() is called, and we destroy
7255 	 * the first kxld context in that function.  Afterwards, it will be
7256 	 * destroyed in flushNonloadedKexts.
7257 	 */
7258 	if (!sConsiderUnloadsCalled) {
7259 		sConsiderUnloadsCalled = true;
7260 		OSKext::considerDestroyingLinkContext();
7261 	}
7262 
7263 	IORecursiveLockUnlock(sKextInnerLock);
7264 	return;
7265 }
7266 
7267 /*********************************************************************
7268 * Do not call any function that takes sKextLock here!
7269 *********************************************************************/
7270 extern "C" {
7271 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
7272 IOReturn
7273 OSKextSystemSleepOrWake(UInt32 messageType)
7274 {
7275 	IORecursiveLockLock(sKextInnerLock);
7276 
7277 	/* If the system is going to sleep, cancel the reaper thread timer,
7278 	 * and note that we're in a sleep state in case it just fired but hasn't
7279 	 * taken the lock yet. If we are coming back from sleep, just
7280 	 * clear the sleep flag; IOService's normal operation will cause
7281 	 * unloads to be considered soon enough.
7282 	 */
7283 	if (messageType == kIOMessageSystemWillSleep) {
7284 		if (sUnloadCallout) {
7285 			thread_call_cancel(sUnloadCallout);
7286 		}
7287 		sSystemSleep = true;
7288 		AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
7289 	} else if (messageType == kIOMessageSystemHasPoweredOn) {
7290 		sSystemSleep = false;
7291 		clock_get_uptime(&sLastWakeTime);
7292 	}
7293 	IORecursiveLockUnlock(sKextInnerLock);
7294 
7295 	return kIOReturnSuccess;
7296 }
7297 };
7298 
7299 
7300 #if PRAGMA_MARK
7301 #pragma mark Prelinked Kernel
7302 #endif
7303 /*********************************************************************
7304 * Do not access sConsiderUnloads... variables other than
7305 * sConsiderUnloadsExecuted in this function. They are guarded by a
7306 * different lock.
7307 *********************************************************************/
7308 /* static */
7309 void
7310 OSKext::considerRebuildOfPrelinkedKernel(void)
7311 {
7312 	static bool     requestedPrelink        = false;
7313 	OSReturn        checkResult             = kOSReturnError;
7314 	OSDictionary *  prelinkRequest          = NULL;// must release
7315 	OSCollectionIterator * kextIterator     = NULL;// must release
7316 	const OSSymbol * thisID                 = NULL;// do not release
7317 	bool            doRebuild               = false;
7318 	AbsoluteTime    my_abstime;
7319 	UInt64          my_ns;
7320 	SInt32          delta_secs;
7321 
7322 	/* Only one auto rebuild per boot and only on boot from prelinked kernel */
7323 	if (requestedPrelink || !sPrelinkBoot) {
7324 		return;
7325 	}
7326 
7327 	/* no direct return from this point */
7328 	IORecursiveLockLock(sKextLock);
7329 
7330 	/* We need to wait for kextd to get up and running with unloads already done
7331 	 * and any new startup kexts loaded.
7332 	 */
7333 	if (!sConsiderUnloadsExecuted ||
7334 	    !sDeferredLoadSucceeded) {
7335 		goto finish;
7336 	}
7337 
7338 	/* we really only care about boot / system start up related kexts so bail
7339 	 * if we're here after REBUILD_MAX_TIME.
7340 	 */
7341 	if (!_OSKextInPrelinkRebuildWindow()) {
7342 		OSKextLog(/* kext */ NULL,
7343 		    kOSKextLogArchiveFlag,
7344 		    "%s prebuild rebuild has expired",
7345 		    __FUNCTION__);
7346 		requestedPrelink = true;
7347 		goto finish;
7348 	}
7349 
7350 	/* we do not want to trigger a rebuild if we get here too close to waking
7351 	 * up.  (see radar 10233768)
7352 	 */
7353 	IORecursiveLockLock(sKextInnerLock);
7354 
7355 	clock_get_uptime(&my_abstime);
7356 	delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
7357 	if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
7358 		SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
7359 		absolutetime_to_nanoseconds(my_abstime, &my_ns);
7360 		delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
7361 	}
7362 	IORecursiveLockUnlock(sKextInnerLock);
7363 
7364 	if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
7365 		/* too close to time of last wake from sleep */
7366 		goto finish;
7367 	}
7368 	requestedPrelink = true;
7369 
7370 	/* Now it's time to see if we have a reason to rebuild.  We may have done
7371 	 * some loads and unloads but the kernel cache didn't actually change.
7372 	 * We will rebuild if any kext is not marked prelinked AND is not in our
7373 	 * list of prelinked kexts that got unloaded.  (see radar 9055303)
7374 	 */
7375 	kextIterator = OSCollectionIterator::withCollection(sKextsByID);
7376 	if (!kextIterator) {
7377 		goto finish;
7378 	}
7379 
7380 	while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
7381 		OSKext *    thisKext;// do not release
7382 
7383 		thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
7384 		if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
7385 			continue;
7386 		}
7387 
7388 		if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID)) {
7389 			continue;
7390 		}
7391 		/* kext is loaded and was not in current kernel cache so let's rebuild
7392 		 */
7393 		doRebuild = true;
7394 		OSKextLog(/* kext */ NULL,
7395 		    kOSKextLogArchiveFlag,
7396 		    "considerRebuildOfPrelinkedKernel %s triggered rebuild",
7397 		    thisKext->bundleID->getCStringNoCopy());
7398 		break;
7399 	}
7400 	sUnloadedPrelinkedKexts->flushCollection();
7401 
7402 	if (!doRebuild) {
7403 		goto finish;
7404 	}
7405 
7406 	checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
7407 	    &prelinkRequest);
7408 	if (checkResult != kOSReturnSuccess) {
7409 		goto finish;
7410 	}
7411 
7412 	if (!sKernelRequests->setObject(prelinkRequest)) {
7413 		goto finish;
7414 	}
7415 
7416 	OSKext::pingKextd();
7417 
7418 finish:
7419 	IORecursiveLockUnlock(sKextLock);
7420 	OSSafeReleaseNULL(prelinkRequest);
7421 	OSSafeReleaseNULL(kextIterator);
7422 
7423 	return;
7424 }
7425 
7426 #if PRAGMA_MARK
7427 #pragma mark Dependencies
7428 #endif
7429 /*********************************************************************
7430 *********************************************************************/
7431 bool
7432 OSKext::resolveDependencies(
7433 	OSArray * loopStack)
7434 {
7435 	bool                   result                   = false;
7436 	OSArray              * localLoopStack           = NULL;// must release
7437 	bool                   addedToLoopStack         = false;
7438 	OSDictionary         * libraries                = NULL;// do not release
7439 	OSCollectionIterator * libraryIterator          = NULL;// must release
7440 	OSString             * libraryID                = NULL;// do not release
7441 	OSString             * infoString               = NULL;// do not release
7442 	OSString             * readableString           = NULL;// do not release
7443 	OSKext               * libraryKext              = NULL;// do not release
7444 	bool                   hasRawKernelDependency   = false;
7445 	bool                   hasKernelDependency      = false;
7446 	bool                   hasKPIDependency         = false;
7447 	bool                   hasPrivateKPIDependency  = false;
7448 	unsigned int           count;
7449 
7450 	/* A kernel component will automatically have this flag set,
7451 	 * and a loaded kext should also have it set (as should all its
7452 	 * loaded dependencies).
7453 	 */
7454 	if (flags.hasAllDependencies) {
7455 		result = true;
7456 		goto finish;
7457 	}
7458 
7459 	/* Check for loops in the dependency graph.
7460 	 */
7461 	if (loopStack) {
7462 		if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
7463 			OSKextLog(this,
7464 			    kOSKextLogErrorLevel |
7465 			    kOSKextLogDependenciesFlag,
7466 			    "Kext %s has a dependency loop; can't resolve dependencies.",
7467 			    getIdentifierCString());
7468 			goto finish;
7469 		}
7470 	} else {
7471 		OSKextLog(this,
7472 		    kOSKextLogStepLevel |
7473 		    kOSKextLogDependenciesFlag,
7474 		    "Kext %s resolving dependencies.",
7475 		    getIdentifierCString());
7476 
7477 		loopStack = OSArray::withCapacity(6); // any small capacity will do
7478 		if (!loopStack) {
7479 			OSKextLog(this,
7480 			    kOSKextLogErrorLevel |
7481 			    kOSKextLogDependenciesFlag,
7482 			    "Kext %s can't create bookkeeping stack to resolve dependencies.",
7483 			    getIdentifierCString());
7484 			goto finish;
7485 		}
7486 		localLoopStack = loopStack;
7487 	}
7488 	if (!loopStack->setObject(this)) {
7489 		OSKextLog(this,
7490 		    kOSKextLogErrorLevel |
7491 		    kOSKextLogDependenciesFlag,
7492 		    "Kext %s - internal error resolving dependencies.",
7493 		    getIdentifierCString());
7494 		goto finish;
7495 	}
7496 	addedToLoopStack = true;
7497 
7498 	/* Purge any existing kexts in the dependency list and start over.
7499 	 */
7500 	flushDependencies();
7501 	if (dependencies) {
7502 		OSKextLog(this,
7503 		    kOSKextLogErrorLevel |
7504 		    kOSKextLogDependenciesFlag,
7505 		    "Kext %s - internal error resolving dependencies.",
7506 		    getIdentifierCString());
7507 	}
7508 
7509 	libraries = OSDynamicCast(OSDictionary,
7510 	    getPropertyForHostArch(kOSBundleLibrariesKey));
7511 	if (libraries == NULL || libraries->getCount() == 0) {
7512 		OSKextLog(this,
7513 		    kOSKextLogErrorLevel |
7514 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7515 		    "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7516 		    getIdentifierCString(), kOSBundleLibrariesKey);
7517 		goto finish;
7518 	}
7519 
7520 	/* Make a new array to hold the dependencies (flush freed the old one).
7521 	 */
7522 	dependencies = OSArray::withCapacity(libraries->getCount());
7523 	if (!dependencies) {
7524 		OSKextLog(this,
7525 		    kOSKextLogErrorLevel |
7526 		    kOSKextLogDependenciesFlag,
7527 		    "Kext %s - can't allocate dependencies array.",
7528 		    getIdentifierCString());
7529 		goto finish;
7530 	}
7531 
7532 	// xxx - compat: We used to add an implicit dependency on kernel 6.0
7533 	// xxx - compat: if none were declared.
7534 
7535 	libraryIterator = OSCollectionIterator::withCollection(libraries);
7536 	if (!libraryIterator) {
7537 		OSKextLog(this,
7538 		    kOSKextLogErrorLevel |
7539 		    kOSKextLogDependenciesFlag,
7540 		    "Kext %s - can't allocate dependencies iterator.",
7541 		    getIdentifierCString());
7542 		goto finish;
7543 	}
7544 
7545 	while ((libraryID = OSDynamicCast(OSString,
7546 	    libraryIterator->getNextObject()))) {
7547 		const char * library_id = libraryID->getCStringNoCopy();
7548 
7549 		OSString * libraryVersion = OSDynamicCast(OSString,
7550 		    libraries->getObject(libraryID));
7551 		if (libraryVersion == NULL) {
7552 			OSKextLog(this,
7553 			    kOSKextLogErrorLevel |
7554 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7555 			    "Kext %s - illegal type in OSBundleLibraries.",
7556 			    getIdentifierCString());
7557 			goto finish;
7558 		}
7559 
7560 		OSKextVersion libraryVers =
7561 		    OSKextParseVersionString(libraryVersion->getCStringNoCopy());
7562 		if (libraryVers == -1) {
7563 			OSKextLog(this,
7564 			    kOSKextLogErrorLevel |
7565 			    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7566 			    "Kext %s - invalid library version %s.",
7567 			    getIdentifierCString(),
7568 			    libraryVersion->getCStringNoCopy());
7569 			goto finish;
7570 		}
7571 
7572 		libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
7573 		if (libraryKext == NULL) {
7574 			OSKextLog(this,
7575 			    kOSKextLogErrorLevel |
7576 			    kOSKextLogDependenciesFlag,
7577 			    "Kext %s - library kext %s not found.",
7578 			    getIdentifierCString(), library_id);
7579 			goto finish;
7580 		}
7581 
7582 		if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
7583 			OSKextLog(this,
7584 			    kOSKextLogErrorLevel |
7585 			    kOSKextLogDependenciesFlag,
7586 			    "Kext %s - library kext %s not compatible "
7587 			    "with requested version %s.",
7588 			    getIdentifierCString(), library_id,
7589 			    libraryVersion->getCStringNoCopy());
7590 			goto finish;
7591 		}
7592 
7593 		/* If a nonprelinked library somehow got into the mix for a
7594 		 * prelinked kext, at any point in the chain, we must fail
7595 		 * because the prelinked relocs for the library will be all wrong.
7596 		 */
7597 		if (this->isPrelinked() &&
7598 		    libraryKext->declaresExecutable() &&
7599 		    !libraryKext->isPrelinked()) {
7600 			OSKextLog(this,
7601 			    kOSKextLogErrorLevel |
7602 			    kOSKextLogDependenciesFlag,
7603 			    "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7604 			    getIdentifierCString(), library_id,
7605 			    libraryVersion->getCStringNoCopy());
7606 			goto finish;
7607 		}
7608 
7609 		if (!libraryKext->resolveDependencies(loopStack)) {
7610 			goto finish;
7611 		}
7612 
7613 		/* Add the library directly only if it has an executable to link.
7614 		 * Otherwise it's just used to collect other dependencies, so put
7615 		 * *its* dependencies on the list for this kext.
7616 		 */
7617 		// xxx - We are losing info here; would like to make fake entries or
7618 		// xxx - keep these in the dependency graph for loaded kexts.
7619 		// xxx - I really want to make kernel components not a special case!
7620 		if (libraryKext->declaresExecutable() ||
7621 		    libraryKext->isInterface()) {
7622 			if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
7623 				dependencies->setObject(libraryKext);
7624 
7625 				OSKextLog(this,
7626 				    kOSKextLogDetailLevel |
7627 				    kOSKextLogDependenciesFlag,
7628 				    "Kext %s added dependency %s.",
7629 				    getIdentifierCString(),
7630 				    libraryKext->getIdentifierCString());
7631 			}
7632 		} else {
7633 			int       numLibDependencies  = libraryKext->getNumDependencies();
7634 			OSArray * libraryDependencies = libraryKext->getDependencies();
7635 			int       index;
7636 
7637 			if (numLibDependencies) {
7638 				// xxx - this msg level should be 1 lower than the per-kext one
7639 				OSKextLog(this,
7640 				    kOSKextLogDetailLevel |
7641 				    kOSKextLogDependenciesFlag,
7642 				    "Kext %s pulling %d dependencies from codeless library %s.",
7643 				    getIdentifierCString(),
7644 				    numLibDependencies,
7645 				    libraryKext->getIdentifierCString());
7646 			}
7647 			for (index = 0; index < numLibDependencies; index++) {
7648 				OSKext * thisLibDependency = OSDynamicCast(OSKext,
7649 				    libraryDependencies->getObject(index));
7650 				if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
7651 					dependencies->setObject(thisLibDependency);
7652 					OSKextLog(this,
7653 					    kOSKextLogDetailLevel |
7654 					    kOSKextLogDependenciesFlag,
7655 					    "Kext %s added dependency %s from codeless library %s.",
7656 					    getIdentifierCString(),
7657 					    thisLibDependency->getIdentifierCString(),
7658 					    libraryKext->getIdentifierCString());
7659 				}
7660 			}
7661 		}
7662 
7663 		if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
7664 		    0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
7665 			hasRawKernelDependency = true;
7666 		} else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
7667 			hasKernelDependency = true;
7668 		} else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
7669 			hasKPIDependency = true;
7670 			if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
7671 				hasPrivateKPIDependency = true;
7672 			}
7673 		}
7674 	}
7675 
7676 	if (hasRawKernelDependency) {
7677 		OSKextLog(this,
7678 		    kOSKextLogErrorLevel |
7679 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7680 		    "Error - kext %s declares a dependency on %s, which is not permitted.",
7681 		    getIdentifierCString(), KERNEL_LIB);
7682 		goto finish;
7683 	}
7684 #if __LP64__
7685 	if (hasKernelDependency) {
7686 		OSKextLog(this,
7687 		    kOSKextLogErrorLevel |
7688 		    kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7689 		    "Error - kext %s declares %s dependencies. "
7690 		    "Only %s* dependencies are supported for 64-bit kexts.",
7691 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
7692 		goto finish;
7693 	}
7694 	if (!hasKPIDependency) {
7695 		OSKextLog(this,
7696 		    kOSKextLogWarningLevel |
7697 		    kOSKextLogDependenciesFlag,
7698 		    "Warning - kext %s declares no %s* dependencies. "
7699 		    "If it uses any KPIs, the link may fail with undefined symbols.",
7700 		    getIdentifierCString(), KPI_LIB_PREFIX);
7701 	}
7702 #else /* __LP64__ */
7703 	// xxx - will change to flatly disallow "kernel" dependencies at some point
7704 	// xxx - is it invalid to do both "com.apple.kernel" and any
7705 	// xxx - "com.apple.kernel.*"?
7706 
7707 	if (hasKernelDependency && hasKPIDependency) {
7708 		OSKextLog(this,
7709 		    kOSKextLogWarningLevel |
7710 		    kOSKextLogDependenciesFlag,
7711 		    "Warning - kext %s has immediate dependencies on both "
7712 		    "%s* and %s* components; use only one style.",
7713 		    getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
7714 	}
7715 
7716 	if (!hasKernelDependency && !hasKPIDependency) {
7717 		// xxx - do we want to use validation flag for these too?
7718 		OSKextLog(this,
7719 		    kOSKextLogWarningLevel |
7720 		    kOSKextLogDependenciesFlag,
7721 		    "Warning - %s declares no kernel dependencies; using %s.",
7722 		    getIdentifierCString(), KERNEL6_LIB);
7723 		OSKext * kernelKext = OSDynamicCast(OSKext,
7724 		    sKextsByID->getObject(KERNEL6_LIB));
7725 		if (kernelKext) {
7726 			dependencies->setObject(kernelKext);
7727 		} else {
7728 			OSKextLog(this,
7729 			    kOSKextLogErrorLevel |
7730 			    kOSKextLogDependenciesFlag,
7731 			    "Error - Library %s not found for %s.",
7732 			    KERNEL6_LIB, getIdentifierCString());
7733 		}
7734 	}
7735 
7736 	/* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7737 	 * its indirect dependencies to simulate old-style linking.  XXX - Should
7738 	 * check for duplicates.
7739 	 */
7740 	if (!hasKPIDependency) {
7741 		unsigned int i;
7742 
7743 		flags.hasBleedthrough = true;
7744 
7745 		count = getNumDependencies();
7746 
7747 		/* We add to the dependencies array in this loop, but do not iterate
7748 		 * past its original count.
7749 		 */
7750 		for (i = 0; i < count; i++) {
7751 			OSKext * dependencyKext = OSDynamicCast(OSKext,
7752 			    dependencies->getObject(i));
7753 			dependencyKext->addBleedthroughDependencies(dependencies);
7754 		}
7755 	}
7756 #endif /* __LP64__ */
7757 
7758 	if (hasPrivateKPIDependency) {
7759 		bool hasApplePrefix = false;
7760 		bool infoCopyrightIsValid = false;
7761 		bool readableCopyrightIsValid = false;
7762 
7763 		hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
7764 		    APPLE_KEXT_PREFIX);
7765 
7766 		infoString = OSDynamicCast(OSString,
7767 		    getPropertyForHostArch("CFBundleGetInfoString"));
7768 		if (infoString) {
7769 			infoCopyrightIsValid =
7770 			    kxld_validate_copyright_string(infoString->getCStringNoCopy());
7771 		}
7772 
7773 		readableString = OSDynamicCast(OSString,
7774 		    getPropertyForHostArch("NSHumanReadableCopyright"));
7775 		if (readableString) {
7776 			readableCopyrightIsValid =
7777 			    kxld_validate_copyright_string(readableString->getCStringNoCopy());
7778 		}
7779 
7780 		if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
7781 			OSKextLog(this,
7782 			    kOSKextLogErrorLevel |
7783 			    kOSKextLogDependenciesFlag,
7784 			    "Error - kext %s declares a dependency on %s. "
7785 			    "Only Apple kexts may declare a dependency on %s.",
7786 			    getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
7787 			goto finish;
7788 		}
7789 	}
7790 
7791 	result = true;
7792 	flags.hasAllDependencies = 1;
7793 
7794 finish:
7795 
7796 	if (addedToLoopStack) {
7797 		count = loopStack->getCount();
7798 		if (count > 0 && (this == loopStack->getObject(count - 1))) {
7799 			loopStack->removeObject(count - 1);
7800 		} else {
7801 			OSKextLog(this,
7802 			    kOSKextLogErrorLevel |
7803 			    kOSKextLogDependenciesFlag,
7804 			    "Kext %s - internal error resolving dependencies.",
7805 			    getIdentifierCString());
7806 		}
7807 	}
7808 
7809 	if (result && localLoopStack) {
7810 		OSKextLog(this,
7811 		    kOSKextLogStepLevel |
7812 		    kOSKextLogDependenciesFlag,
7813 		    "Kext %s successfully resolved dependencies.",
7814 		    getIdentifierCString());
7815 	}
7816 
7817 	OSSafeReleaseNULL(localLoopStack);
7818 	OSSafeReleaseNULL(libraryIterator);
7819 
7820 	return result;
7821 }
7822 
7823 /*********************************************************************
7824 *********************************************************************/
7825 bool
7826 OSKext::addBleedthroughDependencies(OSArray * anArray)
7827 {
7828 	bool result = false;
7829 	unsigned int dependencyIndex, dependencyCount;
7830 
7831 	dependencyCount = getNumDependencies();
7832 
7833 	for (dependencyIndex = 0;
7834 	    dependencyIndex < dependencyCount;
7835 	    dependencyIndex++) {
7836 		OSKext * dependency = OSDynamicCast(OSKext,
7837 		    dependencies->getObject(dependencyIndex));
7838 		if (!dependency) {
7839 			OSKextLog(this,
7840 			    kOSKextLogErrorLevel |
7841 			    kOSKextLogDependenciesFlag,
7842 			    "Kext %s - internal error propagating compatibility dependencies.",
7843 			    getIdentifierCString());
7844 			goto finish;
7845 		}
7846 		if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
7847 			anArray->setObject(dependency);
7848 		}
7849 		dependency->addBleedthroughDependencies(anArray);
7850 	}
7851 
7852 	result = true;
7853 
7854 finish:
7855 	return result;
7856 }
7857 
7858 /*********************************************************************
7859 *********************************************************************/
7860 bool
7861 OSKext::flushDependencies(bool forceFlag)
7862 {
7863 	bool result = false;
7864 
7865 	/* Only clear the dependencies if the kext isn't loaded;
7866 	 * we need the info for loaded kexts to track references.
7867 	 */
7868 	if (!isLoaded() || forceFlag) {
7869 		if (dependencies) {
7870 			// xxx - check level
7871 			OSKextLog(this,
7872 			    kOSKextLogProgressLevel |
7873 			    kOSKextLogDependenciesFlag,
7874 			    "Kext %s flushing dependencies.",
7875 			    getIdentifierCString());
7876 			OSSafeReleaseNULL(dependencies);
7877 		}
7878 		if (!isKernelComponent()) {
7879 			flags.hasAllDependencies = 0;
7880 		}
7881 		result = true;
7882 	}
7883 
7884 	return result;
7885 }
7886 
7887 /*********************************************************************
7888 *********************************************************************/
7889 uint32_t
7890 OSKext::getNumDependencies(void)
7891 {
7892 	if (!dependencies) {
7893 		return 0;
7894 	}
7895 	return dependencies->getCount();
7896 }
7897 
7898 /*********************************************************************
7899 *********************************************************************/
7900 OSArray *
7901 OSKext::getDependencies(void)
7902 {
7903 	return dependencies;
7904 }
7905 
7906 #if PRAGMA_MARK
7907 #pragma mark OSMetaClass Support
7908 #endif
7909 /*********************************************************************
7910 *********************************************************************/
7911 OSReturn
7912 OSKext::addClass(
7913 	OSMetaClass * aClass,
7914 	uint32_t      numClasses)
7915 {
7916 	OSReturn result = kOSMetaClassNoInsKModSet;
7917 
7918 	if (!metaClasses) {
7919 		metaClasses = OSSet::withCapacity(numClasses);
7920 		if (!metaClasses) {
7921 			goto finish;
7922 		}
7923 	}
7924 
7925 	if (metaClasses->containsObject(aClass)) {
7926 		OSKextLog(this,
7927 		    kOSKextLogWarningLevel |
7928 		    kOSKextLogLoadFlag,
7929 		    "Notice - kext %s has already registered class %s.",
7930 		    getIdentifierCString(),
7931 		    aClass->getClassName());
7932 		result = kOSReturnSuccess;
7933 		goto finish;
7934 	}
7935 
7936 	if (!metaClasses->setObject(aClass)) {
7937 		goto finish;
7938 	} else {
7939 		OSKextLog(this,
7940 		    kOSKextLogDetailLevel |
7941 		    kOSKextLogLoadFlag,
7942 		    "Kext %s registered class %s.",
7943 		    getIdentifierCString(),
7944 		    aClass->getClassName());
7945 	}
7946 
7947 	if (!flags.autounloadEnabled) {
7948 		const OSMetaClass * metaScan  = NULL;// do not release
7949 
7950 		for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
7951 			if (metaScan == OSTypeID(IOService)) {
7952 				OSKextLog(this,
7953 				    kOSKextLogProgressLevel |
7954 				    kOSKextLogLoadFlag,
7955 				    "Kext %s has IOService subclass %s; enabling autounload.",
7956 				    getIdentifierCString(),
7957 				    aClass->getClassName());
7958 
7959 				flags.autounloadEnabled = 1;
7960 				break;
7961 			}
7962 		}
7963 	}
7964 
7965 	notifyAddClassObservers(this, aClass, flags);
7966 
7967 	result = kOSReturnSuccess;
7968 
7969 finish:
7970 	if (result != kOSReturnSuccess) {
7971 		OSKextLog(this,
7972 		    kOSKextLogErrorLevel |
7973 		    kOSKextLogLoadFlag,
7974 		    "Kext %s failed to register class %s.",
7975 		    getIdentifierCString(),
7976 		    aClass->getClassName());
7977 	}
7978 
7979 	return result;
7980 }
7981 
7982 /*********************************************************************
7983 *********************************************************************/
7984 OSReturn
7985 OSKext::removeClass(
7986 	OSMetaClass * aClass)
7987 {
7988 	OSReturn result = kOSMetaClassNoKModSet;
7989 
7990 	if (!metaClasses) {
7991 		goto finish;
7992 	}
7993 
7994 	if (!metaClasses->containsObject(aClass)) {
7995 		OSKextLog(this,
7996 		    kOSKextLogWarningLevel |
7997 		    kOSKextLogLoadFlag,
7998 		    "Notice - kext %s asked to unregister unknown class %s.",
7999 		    getIdentifierCString(),
8000 		    aClass->getClassName());
8001 		result = kOSReturnSuccess;
8002 		goto finish;
8003 	}
8004 
8005 	OSKextLog(this,
8006 	    kOSKextLogDetailLevel |
8007 	    kOSKextLogLoadFlag,
8008 	    "Kext %s unregistering class %s.",
8009 	    getIdentifierCString(),
8010 	    aClass->getClassName());
8011 
8012 	metaClasses->removeObject(aClass);
8013 
8014 	notifyRemoveClassObservers(this, aClass, flags);
8015 
8016 	result = kOSReturnSuccess;
8017 
8018 finish:
8019 	if (result != kOSReturnSuccess) {
8020 		OSKextLog(this,
8021 		    kOSKextLogErrorLevel |
8022 		    kOSKextLogLoadFlag,
8023 		    "Failed to unregister kext %s class %s.",
8024 		    getIdentifierCString(),
8025 		    aClass->getClassName());
8026 	}
8027 	return result;
8028 }
8029 
8030 /*********************************************************************
8031 *********************************************************************/
8032 OSSet *
8033 OSKext::getMetaClasses(void)
8034 {
8035 	return metaClasses;
8036 }
8037 
8038 /*********************************************************************
8039 *********************************************************************/
8040 bool
8041 OSKext::hasOSMetaClassInstances(void)
8042 {
8043 	bool                   result        = false;
8044 	OSCollectionIterator * classIterator = NULL; // must release
8045 	OSMetaClass          * checkClass    = NULL;// do not release
8046 
8047 	if (!metaClasses) {
8048 		goto finish;
8049 	}
8050 
8051 	classIterator = OSCollectionIterator::withCollection(metaClasses);
8052 	if (!classIterator) {
8053 		// xxx - log alloc failure?
8054 		goto finish;
8055 	}
8056 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
8057 		if (checkClass->getInstanceCount()) {
8058 			result = true;
8059 			goto finish;
8060 		}
8061 	}
8062 
8063 finish:
8064 
8065 	OSSafeReleaseNULL(classIterator);
8066 	return result;
8067 }
8068 
8069 /*********************************************************************
8070 *********************************************************************/
8071 /* static */
8072 void
8073 OSKext::reportOSMetaClassInstances(
8074 	const char     * kextIdentifier,
8075 	OSKextLogSpec    msgLogSpec)
8076 {
8077 	OSKext * theKext = NULL; // must release
8078 
8079 	theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
8080 	if (!theKext) {
8081 		goto finish;
8082 	}
8083 
8084 	theKext->reportOSMetaClassInstances(msgLogSpec);
8085 finish:
8086 	OSSafeReleaseNULL(theKext);
8087 	return;
8088 }
8089 
8090 /*********************************************************************
8091 *********************************************************************/
8092 void
8093 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
8094 {
8095 	OSCollectionIterator * classIterator = NULL; // must release
8096 	OSMetaClass          * checkClass    = NULL;// do not release
8097 
8098 	if (!metaClasses) {
8099 		goto finish;
8100 	}
8101 
8102 	classIterator = OSCollectionIterator::withCollection(metaClasses);
8103 	if (!classIterator) {
8104 		goto finish;
8105 	}
8106 	while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
8107 		if (checkClass->getInstanceCount()) {
8108 			OSKextLog(this,
8109 			    msgLogSpec,
8110 			    "    Kext %s class %s has %d instance%s.",
8111 			    getIdentifierCString(),
8112 			    checkClass->getClassName(),
8113 			    checkClass->getInstanceCount(),
8114 			    checkClass->getInstanceCount() == 1 ? "" : "s");
8115 		}
8116 	}
8117 
8118 finish:
8119 	OSSafeReleaseNULL(classIterator);
8120 	return;
8121 }
8122 
8123 #if PRAGMA_MARK
8124 #pragma mark User-Space Requests
8125 #endif
8126 /*********************************************************************
8127 * XXX - this function is a big ugly mess
8128 *********************************************************************/
8129 /* static */
8130 OSReturn
8131 OSKext::handleRequest(
8132 	host_priv_t     hostPriv,
8133 	OSKextLogSpec   clientLogFilter,
8134 	char          * requestBuffer,
8135 	uint32_t        requestLength,
8136 	char         ** responseOut,
8137 	uint32_t      * responseLengthOut,
8138 	char         ** logInfoOut,
8139 	uint32_t      * logInfoLengthOut)
8140 {
8141 	OSReturn       result             = kOSReturnError;
8142 	kern_return_t  kmem_result        = KERN_FAILURE;
8143 
8144 	char         * response           = NULL;// returned by reference
8145 	uint32_t       responseLength     = 0;
8146 
8147 	OSObject     * parsedXML          = NULL;// must release
8148 	OSDictionary * requestDict        = NULL;// do not release
8149 	OSString     * errorString        = NULL;// must release
8150 
8151 	OSObject     * responseObject     = NULL;// must release
8152 
8153 	OSSerialize  * serializer         = NULL;// must release
8154 
8155 	OSArray      * logInfoArray       = NULL;// must release
8156 
8157 	OSString     * predicate          = NULL;// do not release
8158 	OSString     * kextIdentifier     = NULL;// do not release
8159 	OSArray      * kextIdentifiers    = NULL;// do not release
8160 	OSKext       * theKext            = NULL;// do not release
8161 	OSBoolean    * boolArg            = NULL;// do not release
8162 
8163 	IORecursiveLockLock(sKextLock);
8164 
8165 	if (responseOut) {
8166 		*responseOut = NULL;
8167 		*responseLengthOut = 0;
8168 	}
8169 	if (logInfoOut) {
8170 		*logInfoOut = NULL;
8171 		*logInfoLengthOut = 0;
8172 	}
8173 
8174 	OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
8175 
8176 	/* XML must be nul-terminated.
8177 	 */
8178 	if (requestBuffer[requestLength - 1] != '\0') {
8179 		OSKextLog(/* kext */ NULL,
8180 		    kOSKextLogErrorLevel |
8181 		    kOSKextLogIPCFlag,
8182 		    "Invalid request from user space (not nul-terminated).");
8183 		result = kOSKextReturnBadData;
8184 		goto finish;
8185 	}
8186 	parsedXML = OSUnserializeXML((const char *)requestBuffer, &errorString);
8187 	if (parsedXML) {
8188 		requestDict = OSDynamicCast(OSDictionary, parsedXML);
8189 	}
8190 	if (!requestDict) {
8191 		const char * errorCString = "(unknown error)";
8192 
8193 		if (errorString && errorString->getCStringNoCopy()) {
8194 			errorCString = errorString->getCStringNoCopy();
8195 		} else if (parsedXML) {
8196 			errorCString = "not a dictionary";
8197 		}
8198 		OSKextLog(/* kext */ NULL,
8199 		    kOSKextLogErrorLevel |
8200 		    kOSKextLogIPCFlag,
8201 		    "Error unserializing request from user space: %s.",
8202 		    errorCString);
8203 		result = kOSKextReturnSerialization;
8204 		goto finish;
8205 	}
8206 
8207 	predicate = _OSKextGetRequestPredicate(requestDict);
8208 	if (!predicate) {
8209 		OSKextLog(/* kext */ NULL,
8210 		    kOSKextLogErrorLevel |
8211 		    kOSKextLogIPCFlag,
8212 		    "Recieved kext request from user space with no predicate.");
8213 		result = kOSKextReturnInvalidArgument;
8214 		goto finish;
8215 	}
8216 
8217 	OSKextLog(/* kext */ NULL,
8218 	    kOSKextLogDebugLevel |
8219 	    kOSKextLogIPCFlag,
8220 	    "Received '%s' request from user space.",
8221 	    predicate->getCStringNoCopy());
8222 
8223 	result = kOSKextReturnNotPrivileged;
8224 	if (hostPriv == HOST_PRIV_NULL) {
8225 		/* must be root to use these kext requests */
8226 		if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
8227 		    predicate->isEqualTo(kKextRequestPredicateStart) ||
8228 		    predicate->isEqualTo(kKextRequestPredicateStop) ||
8229 		    predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
8230 		    predicate->isEqualTo(kKextRequestPredicateSendResource)) {
8231 			OSKextLog(/* kext */ NULL,
8232 			    kOSKextLogErrorLevel |
8233 			    kOSKextLogIPCFlag,
8234 			    "Access Failure - must be root user.");
8235 			goto finish;
8236 		}
8237 	}
8238 
8239 	/* Get common args in anticipation of use.
8240 	 */
8241 	kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
8242 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
8243 	kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
8244 		    requestDict, kKextRequestArgumentBundleIdentifierKey));
8245 	if (kextIdentifier) {
8246 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
8247 	}
8248 	boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
8249 		    requestDict, kKextRequestArgumentValueKey));
8250 
8251 	result = kOSKextReturnInvalidArgument;
8252 
8253 	if (predicate->isEqualTo(kKextRequestPredicateStart)) {
8254 		if (!kextIdentifier) {
8255 			OSKextLog(/* kext */ NULL,
8256 			    kOSKextLogErrorLevel |
8257 			    kOSKextLogIPCFlag,
8258 			    "Invalid arguments to kext start request.");
8259 		} else if (!theKext) {
8260 			OSKextLog(/* kext */ NULL,
8261 			    kOSKextLogErrorLevel |
8262 			    kOSKextLogIPCFlag,
8263 			    "Kext %s not found for start request.",
8264 			    kextIdentifier->getCStringNoCopy());
8265 			result = kOSKextReturnNotFound;
8266 		} else {
8267 			result = theKext->start();
8268 		}
8269 	} else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
8270 		if (!kextIdentifier) {
8271 			OSKextLog(/* kext */ NULL,
8272 			    kOSKextLogErrorLevel |
8273 			    kOSKextLogIPCFlag,
8274 			    "Invalid arguments to kext stop request.");
8275 		} else if (!theKext) {
8276 			OSKextLog(/* kext */ NULL,
8277 			    kOSKextLogErrorLevel |
8278 			    kOSKextLogIPCFlag,
8279 			    "Kext %s not found for stop request.",
8280 			    kextIdentifier->getCStringNoCopy());
8281 			result = kOSKextReturnNotFound;
8282 		} else {
8283 			result = theKext->stop();
8284 		}
8285 	} else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
8286 		if (!kextIdentifier) {
8287 			OSKextLog(/* kext */ NULL,
8288 			    kOSKextLogErrorLevel |
8289 			    kOSKextLogIPCFlag,
8290 			    "Invalid arguments to kext unload request.");
8291 		} else if (!theKext) {
8292 			OSKextLog(/* kext */ NULL,
8293 			    kOSKextLogErrorLevel |
8294 			    kOSKextLogIPCFlag,
8295 			    "Kext %s not found for unload request.",
8296 			    kextIdentifier->getCStringNoCopy());
8297 			result = kOSKextReturnNotFound;
8298 		} else {
8299 			OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
8300 			    _OSKextGetRequestArgument(requestDict,
8301 			    kKextRequestArgumentTerminateIOServicesKey));
8302 			result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
8303 		}
8304 	} else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
8305 		result = OSKext::dispatchResource(requestDict);
8306 	} else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
8307 		OSNumber     *lookupNum   = NULL;
8308 		lookupNum = OSDynamicCast(OSNumber,
8309 		    _OSKextGetRequestArgument(requestDict,
8310 		    kKextRequestArgumentLookupAddressKey));
8311 
8312 		responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
8313 		if (responseObject) {
8314 			result = kOSReturnSuccess;
8315 		} else {
8316 			goto finish;
8317 		}
8318 	} else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
8319 	    predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
8320 		OSBoolean    * delayAutounloadBool = NULL;
8321 		OSObject     * infoKeysRaw         = NULL;
8322 		OSArray      * infoKeys            = NULL;
8323 		uint32_t       infoKeysCount       = 0;
8324 
8325 		delayAutounloadBool = OSDynamicCast(OSBoolean,
8326 		    _OSKextGetRequestArgument(requestDict,
8327 		    kKextRequestArgumentDelayAutounloadKey));
8328 
8329 		/* If asked to delay autounload, reset the timer if it's currently set.
8330 		 * (That is, don't schedule an unload if one isn't already pending.
8331 		 */
8332 		if (delayAutounloadBool == kOSBooleanTrue) {
8333 			OSKext::considerUnloads(/* rescheduleOnly? */ true);
8334 		}
8335 
8336 		infoKeysRaw = _OSKextGetRequestArgument(requestDict,
8337 		    kKextRequestArgumentInfoKeysKey);
8338 		infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
8339 		if (infoKeysRaw && !infoKeys) {
8340 			OSKextLog(/* kext */ NULL,
8341 			    kOSKextLogErrorLevel |
8342 			    kOSKextLogIPCFlag,
8343 			    "Invalid arguments to kext info request.");
8344 			goto finish;
8345 		}
8346 
8347 		if (infoKeys) {
8348 			infoKeysCount = infoKeys->getCount();
8349 			for (uint32_t i = 0; i < infoKeysCount; i++) {
8350 				if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
8351 					OSKextLog(/* kext */ NULL,
8352 					    kOSKextLogErrorLevel |
8353 					    kOSKextLogIPCFlag,
8354 					    "Invalid arguments to kext info request.");
8355 					goto finish;
8356 				}
8357 			}
8358 		}
8359 
8360 		if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
8361 			responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
8362 		} else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
8363 			responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
8364 		}
8365 		if (!responseObject) {
8366 			result = kOSKextReturnInternalError;
8367 		} else {
8368 			OSKextLog(/* kext */ NULL,
8369 			    kOSKextLogDebugLevel |
8370 			    kOSKextLogIPCFlag,
8371 			    "Returning loaded kext info.");
8372 			result = kOSReturnSuccess;
8373 		}
8374 	} else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
8375 		/* Hand the current sKernelRequests array to the caller
8376 		 * (who must release it), and make a new one.
8377 		 */
8378 		responseObject = sKernelRequests;
8379 		sKernelRequests = OSArray::withCapacity(0);
8380 		sPostedKextLoadIdentifiers->flushCollection();
8381 		OSKextLog(/* kext */ NULL,
8382 		    kOSKextLogDebugLevel |
8383 		    kOSKextLogIPCFlag,
8384 		    "Returning kernel requests.");
8385 		result = kOSReturnSuccess;
8386 	} else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
8387 		/* Return the set of all requested bundle identifiers */
8388 		responseObject = sAllKextLoadIdentifiers;
8389 		responseObject->retain();
8390 		OSKextLog(/* kext */ NULL,
8391 		    kOSKextLogDebugLevel |
8392 		    kOSKextLogIPCFlag,
8393 		    "Returning load requests.");
8394 		result = kOSReturnSuccess;
8395 	} else {
8396 		OSKextLog(/* kext */ NULL,
8397 		    kOSKextLogDebugLevel |
8398 		    kOSKextLogIPCFlag,
8399 		    "Received '%s' invalid request from user space.",
8400 		    predicate->getCStringNoCopy());
8401 		goto finish;
8402 	}
8403 
8404 	/**********
8405 	 * Now we have handle the request, or not. Gather up the response & logging
8406 	 * info to ship to user space.
8407 	 *********/
8408 
8409 	/* Note: Nothing in OSKext is supposed to retain requestDict,
8410 	 * but you never know....
8411 	 */
8412 	if (requestDict->getRetainCount() > 1) {
8413 		OSKextLog(/* kext */ NULL,
8414 		    kOSKextLogWarningLevel |
8415 		    kOSKextLogIPCFlag,
8416 		    "Request from user space still retained by a kext; "
8417 		    "probable memory leak.");
8418 	}
8419 
8420 	if (responseOut && responseObject) {
8421 		serializer = OSSerialize::withCapacity(0);
8422 		if (!serializer) {
8423 			result = kOSKextReturnNoMemory;
8424 			goto finish;
8425 		}
8426 
8427 		if (!responseObject->serialize(serializer)) {
8428 			OSKextLog(/* kext */ NULL,
8429 			    kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
8430 			    "Failed to serialize response to request from user space.");
8431 			result = kOSKextReturnSerialization;
8432 			goto finish;
8433 		}
8434 
8435 		response = (char *)serializer->text();
8436 		responseLength = serializer->getLength();
8437 	}
8438 
8439 	if (responseOut && response) {
8440 		char * buffer;
8441 
8442 		/* This kmem_alloc sets the return value of the function.
8443 		 */
8444 		kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
8445 		    round_page(responseLength), VM_KERN_MEMORY_OSKEXT);
8446 		if (kmem_result != KERN_SUCCESS) {
8447 			OSKextLog(/* kext */ NULL,
8448 			    kOSKextLogErrorLevel |
8449 			    kOSKextLogIPCFlag,
8450 			    "Failed to copy response to request from user space.");
8451 			result = kmem_result;
8452 			goto finish;
8453 		} else {
8454 			/* 11981737 - clear uninitialized data in last page */
8455 			bzero((void *)(buffer + responseLength),
8456 			    (round_page(responseLength) - responseLength));
8457 			memcpy(buffer, response, responseLength);
8458 			*responseOut = buffer;
8459 			*responseLengthOut = responseLength;
8460 		}
8461 	}
8462 
8463 finish:
8464 
8465 	/* Gather up the collected log messages for user space. Any messages
8466 	 * messages past this call will not make it up as log messages but
8467 	 * will be in the system log. Note that we ignore the return of the
8468 	 * serialize; it has no bearing on the operation at hand even if we
8469 	 * fail to get the log messages.
8470 	 */
8471 	logInfoArray = OSKext::clearUserSpaceLogFilter();
8472 
8473 	if (logInfoArray && logInfoOut && logInfoLengthOut) {
8474 		(void)OSKext::serializeLogInfo(logInfoArray,
8475 		    logInfoOut, logInfoLengthOut);
8476 	}
8477 
8478 	IORecursiveLockUnlock(sKextLock);
8479 
8480 	OSSafeReleaseNULL(parsedXML);
8481 	OSSafeReleaseNULL(errorString);
8482 	OSSafeReleaseNULL(responseObject);
8483 	OSSafeReleaseNULL(serializer);
8484 	OSSafeReleaseNULL(logInfoArray);
8485 
8486 	return result;
8487 }
8488 
8489 
8490 // #include <InstrProfiling.h>
8491 extern "C" {
8492 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin,
8493     const char *DataEnd,
8494     const char *CountersBegin,
8495     const char *CountersEnd,
8496     const char *NamesBegin,
8497     const char *NamesEnd);
8498 int __llvm_profile_write_buffer_internal(char *Buffer,
8499     const char *DataBegin,
8500     const char *DataEnd,
8501     const char *CountersBegin,
8502     const char *CountersEnd,
8503     const char *NamesBegin,
8504     const char *NamesEnd);
8505 }
8506 
8507 
8508 static
8509 void
8510 OSKextPgoMetadataPut(char *pBuffer,
8511     size_t *position,
8512     size_t bufferSize,
8513     uint32_t *num_pairs,
8514     const char *key,
8515     const char *value)
8516 {
8517 	size_t strlen_key = strlen(key);
8518 	size_t strlen_value = strlen(value);
8519 	size_t len = strlen(key) + 1 + strlen(value) + 1;
8520 	char *pos = pBuffer + *position;
8521 	*position += len;
8522 	if (pBuffer && bufferSize && *position <= bufferSize) {
8523 		memcpy(pos, key, strlen_key); pos += strlen_key;
8524 		*(pos++) = '=';
8525 		memcpy(pos, value, strlen_value); pos += strlen_value;
8526 		*(pos++) = 0;
8527 		if (num_pairs) {
8528 			(*num_pairs)++;
8529 		}
8530 	}
8531 }
8532 
8533 
8534 static
8535 void
8536 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
8537 {
8538 	*position += strlen(key) + 1 + value_max + 1;
8539 }
8540 
8541 
8542 static
8543 void
8544 OSKextPgoMetadataPutAll(OSKext *kext,
8545     uuid_t instance_uuid,
8546     char *pBuffer,
8547     size_t *position,
8548     size_t bufferSize,
8549     uint32_t *num_pairs)
8550 {
8551 	_static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
8552 	//log_10 2^16 ≈ 4.82
8553 	const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
8554 	const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
8555 
8556 	if (!pBuffer) {
8557 		OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
8558 		OSKextPgoMetadataPutMax(position, "UUID", 36);
8559 		OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
8560 	} else {
8561 		uuid_string_t instance_uuid_string;
8562 		uuid_unparse(instance_uuid, instance_uuid_string);
8563 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8564 		    "INSTANCE", instance_uuid_string);
8565 
8566 		OSData *uuid_data;
8567 		uuid_t uuid;
8568 		uuid_string_t uuid_string;
8569 		uuid_data = kext->copyUUID();
8570 		if (uuid_data) {
8571 			memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
8572 			OSSafeReleaseNULL(uuid_data);
8573 			uuid_unparse(uuid, uuid_string);
8574 			OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8575 			    "UUID", uuid_string);
8576 		}
8577 
8578 		clock_sec_t secs;
8579 		clock_usec_t usecs;
8580 		clock_get_calendar_microtime(&secs, &usecs);
8581 		assert(usecs < 1000000);
8582 		char timestamp[max_timestamp_string_size + 1];
8583 		_static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
8584 		snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
8585 		OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8586 		    "TIMESTAMP", timestamp);
8587 	}
8588 
8589 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8590 	    "NAME", kext->getIdentifierCString());
8591 
8592 	char versionCString[kOSKextVersionMaxLength];
8593 	OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
8594 	OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8595 	    "VERSION", versionCString);
8596 }
8597 
8598 static
8599 size_t
8600 OSKextPgoMetadataSize(OSKext *kext)
8601 {
8602 	size_t position = 0;
8603 	uuid_t fakeuuid = {};
8604 	OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
8605 	return position;
8606 }
8607 
8608 int
8609 OSKextGrabPgoDataLocked(OSKext *kext,
8610     bool metadata,
8611     uuid_t instance_uuid,
8612     uint64_t *pSize,
8613     char *pBuffer,
8614     uint64_t bufferSize)
8615 {
8616 	int err = 0;
8617 
8618 	kernel_section_t *sect_prf_data = NULL;
8619 	kernel_section_t *sect_prf_name = NULL;
8620 	kernel_section_t *sect_prf_cnts = NULL;
8621 	uint64_t size;
8622 	size_t metadata_size = 0;
8623 
8624 	sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
8625 	sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
8626 	if (!sect_prf_name) {
8627 		// kextcache sometimes truncates the section name to 15 chars
8628 		// <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache
8629 		sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
8630 	}
8631 	sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
8632 
8633 	if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
8634 		err = ENOTSUP;
8635 		goto out;
8636 	}
8637 
8638 	size = __llvm_profile_get_size_for_buffer_internal(
8639 		(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
8640 		(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
8641 		(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
8642 
8643 	if (metadata) {
8644 		metadata_size = OSKextPgoMetadataSize(kext);
8645 		size += metadata_size;
8646 		size += sizeof(pgo_metadata_footer);
8647 	}
8648 
8649 
8650 	if (pSize) {
8651 		*pSize = size;
8652 	}
8653 
8654 	if (pBuffer && bufferSize) {
8655 		if (bufferSize < size) {
8656 			err = ERANGE;
8657 			goto out;
8658 		}
8659 
8660 		err = __llvm_profile_write_buffer_internal(
8661 			pBuffer,
8662 			(const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
8663 			(const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
8664 			(const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
8665 
8666 		if (err) {
8667 			err = EIO;
8668 			goto out;
8669 		}
8670 
8671 		if (metadata) {
8672 			char *end_of_buffer = pBuffer + size;
8673 			struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
8674 			char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
8675 
8676 			size_t metadata_position = 0;
8677 			uint32_t num_pairs = 0;
8678 			OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
8679 			while (metadata_position < metadata_size) {
8680 				metadata_buffer[metadata_position++] = 0;
8681 			}
8682 
8683 			struct pgo_metadata_footer footer;
8684 			footer.magic = htonl(0x6d657461);
8685 			footer.number_of_pairs = htonl( num_pairs );
8686 			footer.offset_to_pairs = htonl( sizeof(struct pgo_metadata_footer) + metadata_size );
8687 			memcpy(footerp, &footer, sizeof(footer));
8688 		}
8689 	}
8690 
8691 out:
8692 	return err;
8693 }
8694 
8695 
8696 int
8697 OSKextGrabPgoData(uuid_t uuid,
8698     uint64_t *pSize,
8699     char *pBuffer,
8700     uint64_t bufferSize,
8701     int wait_for_unload,
8702     int metadata)
8703 {
8704 	int err = 0;
8705 	OSKext *kext = NULL;
8706 
8707 
8708 	IORecursiveLockLock(sKextLock);
8709 
8710 	kext = OSKext::lookupKextWithUUID(uuid);
8711 	if (!kext) {
8712 		err = ENOENT;
8713 		goto out;
8714 	}
8715 
8716 	if (wait_for_unload) {
8717 		OSKextGrabPgoStruct s;
8718 
8719 		s.metadata = metadata;
8720 		s.pSize = pSize;
8721 		s.pBuffer = pBuffer;
8722 		s.bufferSize = bufferSize;
8723 		s.err = EINTR;
8724 
8725 		struct list_head *prev = &kext->pendingPgoHead;
8726 		struct list_head *next = kext->pendingPgoHead.next;
8727 
8728 		s.list_head.prev = prev;
8729 		s.list_head.next = next;
8730 
8731 		prev->next = &s.list_head;
8732 		next->prev = &s.list_head;
8733 
8734 		kext->release();
8735 		kext = NULL;
8736 
8737 		IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
8738 
8739 		prev = s.list_head.prev;
8740 		next = s.list_head.next;
8741 
8742 		prev->next = next;
8743 		next->prev = prev;
8744 
8745 		err = s.err;
8746 	} else {
8747 		err = OSKextGrabPgoDataLocked(kext, metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
8748 	}
8749 
8750 out:
8751 	if (kext) {
8752 		kext->release();
8753 	}
8754 
8755 	IORecursiveLockUnlock(sKextLock);
8756 
8757 	return err;
8758 }
8759 
8760 void
8761 OSKextResetPgoCountersLock()
8762 {
8763 	IORecursiveLockLock(sKextLock);
8764 }
8765 
8766 void
8767 OSKextResetPgoCountersUnlock()
8768 {
8769 	IORecursiveLockUnlock(sKextLock);
8770 }
8771 
8772 
8773 extern unsigned int not_in_kdp;
8774 
8775 void
8776 OSKextResetPgoCounters()
8777 {
8778 	assert(!not_in_kdp);
8779 	uint32_t count = sLoadedKexts->getCount();
8780 	for (uint32_t i = 0; i < count; i++) {
8781 		OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
8782 		kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
8783 		if (!sect_prf_cnts) {
8784 			continue;
8785 		}
8786 		memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
8787 	}
8788 }
8789 
8790 OSDictionary *
8791 OSKext::copyLoadedKextInfoByUUID(
8792 	OSArray * kextIdentifiers,
8793 	OSArray * infoKeys)
8794 {
8795 	OSDictionary * result = NULL;
8796 	OSDictionary * kextInfo = NULL; // must release
8797 	uint32_t       max_count, i, j;
8798 	uint32_t       idCount = 0;
8799 	uint32_t       idIndex = 0;
8800 	IORecursiveLockLock(sKextLock);
8801 	OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
8802 	uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
8803 
8804 #if CONFIG_MACF
8805 	/* Is the calling process allowed to query kext info? */
8806 	if (current_task() != kernel_task) {
8807 		int                 macCheckResult      = 0;
8808 		kauth_cred_t        cred                = NULL;
8809 
8810 		cred = kauth_cred_get_with_ref();
8811 		macCheckResult = mac_kext_check_query(cred);
8812 		kauth_cred_unref(&cred);
8813 
8814 		if (macCheckResult != 0) {
8815 			OSKextLog(/* kext */ NULL,
8816 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
8817 			    "Failed to query kext info (MAC policy error 0x%x).",
8818 			    macCheckResult);
8819 			goto finish;
8820 		}
8821 	}
8822 #endif
8823 
8824 	/* Empty list of UUIDs is equivalent to no list (get all).
8825 	 */
8826 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
8827 		kextIdentifiers = NULL;
8828 	} else if (kextIdentifiers) {
8829 		idCount = kextIdentifiers->getCount();
8830 	}
8831 
8832 	/* Same for keys.
8833 	 */
8834 	if (infoKeys && !infoKeys->getCount()) {
8835 		infoKeys = NULL;
8836 	}
8837 
8838 	max_count = count[0] + count[1];
8839 	result = OSDictionary::withCapacity(max_count);
8840 	if (!result) {
8841 		goto finish;
8842 	}
8843 
8844 	for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
8845 		for (i = 0; i < count[j]; i++) {
8846 			OSKext       *thisKext     = NULL;// do not release
8847 			Boolean       includeThis  = true;
8848 			uuid_t        thisKextUUID;
8849 			uuid_t        thisKextTextUUID;
8850 			OSData       *uuid_data;
8851 			uuid_string_t uuid_key;
8852 
8853 			thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
8854 			if (!thisKext) {
8855 				continue;
8856 			}
8857 
8858 			uuid_data = thisKext->copyUUID();
8859 			if (!uuid_data) {
8860 				continue;
8861 			}
8862 
8863 			memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
8864 			OSSafeReleaseNULL(uuid_data);
8865 
8866 			uuid_unparse(thisKextUUID, uuid_key);
8867 
8868 			uuid_data = thisKext->copyTextUUID();
8869 			if (!uuid_data) {
8870 				continue;
8871 			}
8872 			memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
8873 			OSSafeReleaseNULL(uuid_data);
8874 
8875 			/* Skip current kext if we have a list of UUIDs and
8876 			 * it isn't in the list.
8877 			 */
8878 			if (kextIdentifiers) {
8879 				includeThis = false;
8880 
8881 				for (idIndex = 0; idIndex < idCount; idIndex++) {
8882 					const OSString* wantedUUID = OSDynamicCast(OSString,
8883 					    kextIdentifiers->getObject(idIndex));
8884 
8885 					uuid_t uuid;
8886 					uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
8887 
8888 					if ((0 == uuid_compare(uuid, thisKextUUID))
8889 					    || (0 == uuid_compare(uuid, thisKextTextUUID))) {
8890 						includeThis = true;
8891 						/* Only need to find the first kext if multiple match,
8892 						 * ie. asking for the kernel uuid does not need to find
8893 						 * interface kexts or builtin static kexts.
8894 						 */
8895 						kextIdentifiers->removeObject(idIndex);
8896 						uuid_unparse(uuid, uuid_key);
8897 						break;
8898 					}
8899 				}
8900 			}
8901 
8902 			if (!includeThis) {
8903 				continue;
8904 			}
8905 
8906 			kextInfo = thisKext->copyInfo(infoKeys);
8907 			if (kextInfo) {
8908 				result->setObject(uuid_key, kextInfo);
8909 				kextInfo->release();
8910 			}
8911 
8912 			if (kextIdentifiers && !kextIdentifiers->getCount()) {
8913 				goto finish;
8914 			}
8915 		}
8916 	}
8917 
8918 finish:
8919 	IORecursiveLockUnlock(sKextLock);
8920 
8921 	return result;
8922 }
8923 
8924 /*********************************************************************
8925 *********************************************************************/
8926 /* static */
8927 OSDictionary *
8928 OSKext::copyLoadedKextInfo(
8929 	OSArray * kextIdentifiers,
8930 	OSArray * infoKeys)
8931 {
8932 	OSDictionary * result = NULL;
8933 	uint32_t       idCount = 0;
8934 	bool           onlyLoaded;
8935 
8936 	IORecursiveLockLock(sKextLock);
8937 
8938 #if CONFIG_MACF
8939 	/* Is the calling process allowed to query kext info? */
8940 	if (current_task() != kernel_task) {
8941 		int                 macCheckResult      = 0;
8942 		kauth_cred_t        cred                = NULL;
8943 
8944 		cred = kauth_cred_get_with_ref();
8945 		macCheckResult = mac_kext_check_query(cred);
8946 		kauth_cred_unref(&cred);
8947 
8948 		if (macCheckResult != 0) {
8949 			OSKextLog(/* kext */ NULL,
8950 			    kOSKextLogErrorLevel | kOSKextLogLoadFlag,
8951 			    "Failed to query kext info (MAC policy error 0x%x).",
8952 			    macCheckResult);
8953 			goto finish;
8954 		}
8955 	}
8956 #endif
8957 
8958 	/* Empty list of bundle ids is equivalent to no list (get all).
8959 	 */
8960 	if (kextIdentifiers && !kextIdentifiers->getCount()) {
8961 		kextIdentifiers = NULL;
8962 	} else if (kextIdentifiers) {
8963 		idCount = kextIdentifiers->getCount();
8964 	}
8965 
8966 	/* Same for keys.
8967 	 */
8968 	if (infoKeys && !infoKeys->getCount()) {
8969 		infoKeys = NULL;
8970 	}
8971 
8972 	onlyLoaded =  (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
8973 
8974 	result = OSDictionary::withCapacity(128);
8975 	if (!result) {
8976 		goto finish;
8977 	}
8978 
8979 #if 0
8980 	OSKextLog(/* kext */ NULL,
8981 	    kOSKextLogErrorLevel |
8982 	    kOSKextLogGeneralFlag,
8983 	    "kaslr: vm_kernel_slide 0x%lx \n",
8984 	    vm_kernel_slide);
8985 	OSKextLog(/* kext */ NULL,
8986 	    kOSKextLogErrorLevel |
8987 	    kOSKextLogGeneralFlag,
8988 	    "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
8989 	    vm_kernel_stext, vm_kernel_etext);
8990 	OSKextLog(/* kext */ NULL,
8991 	    kOSKextLogErrorLevel |
8992 	    kOSKextLogGeneralFlag,
8993 	    "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
8994 	    vm_kernel_base, vm_kernel_top);
8995 	OSKextLog(/* kext */ NULL,
8996 	    kOSKextLogErrorLevel |
8997 	    kOSKextLogGeneralFlag,
8998 	    "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
8999 	    vm_kext_base, vm_kext_top);
9000 	OSKextLog(/* kext */ NULL,
9001 	    kOSKextLogErrorLevel |
9002 	    kOSKextLogGeneralFlag,
9003 	    "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
9004 	    vm_prelink_stext, vm_prelink_etext);
9005 	OSKextLog(/* kext */ NULL,
9006 	    kOSKextLogErrorLevel |
9007 	    kOSKextLogGeneralFlag,
9008 	    "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
9009 	    vm_prelink_sinfo, vm_prelink_einfo);
9010 	OSKextLog(/* kext */ NULL,
9011 	    kOSKextLogErrorLevel |
9012 	    kOSKextLogGeneralFlag,
9013 	    "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
9014 	    vm_slinkedit, vm_elinkedit);
9015 #endif
9016 
9017 	sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
9018 	{
9019 		OSKext       * thisKext     = NULL;// do not release
9020 		Boolean        includeThis  = true;
9021 		OSDictionary * kextInfo     = NULL;// must release
9022 
9023 		thisKext = OSDynamicCast(OSKext, obj);
9024 		if (!thisKext) {
9025 		        return false;;
9026 		}
9027 
9028 		/* Skip current kext if not yet started and caller didn't request all.
9029 		 */
9030 		if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
9031 		        return false;;
9032 		}
9033 
9034 		/* Skip current kext if we have a list of bundle IDs and
9035 		 * it isn't in the list.
9036 		 */
9037 		if (kextIdentifiers) {
9038 		        includeThis = false;
9039 
9040 		        for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
9041 		                const OSString * thisRequestID = OSDynamicCast(OSString,
9042 		                kextIdentifiers->getObject(idIndex));
9043 		                if (thisKextID->isEqualTo(thisRequestID)) {
9044 		                        includeThis = true;
9045 		                        break;
9046 				}
9047 			}
9048 		}
9049 
9050 		if (!includeThis) {
9051 		        return false;
9052 		}
9053 
9054 		kextInfo = thisKext->copyInfo(infoKeys);
9055 		if (kextInfo) {
9056 		        result->setObject(thisKext->getIdentifier(), kextInfo);
9057 		        kextInfo->release();
9058 		}
9059 		return false;
9060 	});
9061 
9062 finish:
9063 	IORecursiveLockUnlock(sKextLock);
9064 
9065 	return result;
9066 }
9067 
9068 /*********************************************************************
9069 * Any info that needs to do allocations must goto finish on alloc
9070 * failure. Info that is just a lookup should just not set the object
9071 * if the info does not exist.
9072 *********************************************************************/
9073 #define _OSKextLoadInfoDictCapacity   (12)
9074 
9075 OSDictionary *
9076 OSKext::copyInfo(OSArray * infoKeys)
9077 {
9078 	OSDictionary         * result                      = NULL;
9079 	bool                   success                     = false;
9080 	OSData               * headerData                  = NULL;// must release
9081 	OSData               * logData                     = NULL;// must release
9082 	OSNumber             * cpuTypeNumber               = NULL;// must release
9083 	OSNumber             * cpuSubtypeNumber            = NULL;// must release
9084 	OSString             * versionString               = NULL;// do not release
9085 	uint32_t               executablePathCStringSize   = 0;
9086 	char                 * executablePathCString       = NULL;// must release
9087 	OSString             * executablePathString        = NULL;// must release
9088 	OSData               * uuid                        = NULL;// must release
9089 	OSNumber             * scratchNumber               = NULL;// must release
9090 	OSArray              * dependencyLoadTags          = NULL;// must release
9091 	OSCollectionIterator * metaClassIterator           = NULL;// must release
9092 	OSArray              * metaClassInfo               = NULL;// must release
9093 	OSDictionary         * metaClassDict               = NULL;// must release
9094 	OSMetaClass          * thisMetaClass               = NULL;// do not release
9095 	OSString             * metaClassName               = NULL;// must release
9096 	OSString             * superclassName              = NULL;// must release
9097 	uint32_t               count, i;
9098 
9099 	result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
9100 	if (!result) {
9101 		goto finish;
9102 	}
9103 
9104 
9105 	/* Empty keys means no keys, but NULL is quicker to check.
9106 	 */
9107 	if (infoKeys && !infoKeys->getCount()) {
9108 		infoKeys = NULL;
9109 	}
9110 
9111 	/* Headers, CPU type, and CPU subtype.
9112 	 */
9113 	if (!infoKeys ||
9114 	    _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
9115 	    _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
9116 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
9117 	    _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
9118 		if (linkedExecutable && !isInterface()) {
9119 			kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
9120 			    linkedExecutable->getBytesNoCopy();
9121 
9122 #if !SECURE_KERNEL
9123 			// do not return macho header info on shipping iOS - 19095897
9124 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
9125 				kernel_mach_header_t *  temp_kext_mach_hdr;
9126 				struct load_command *   lcp;
9127 
9128 				headerData = OSData::withBytes(kext_mach_hdr,
9129 				    (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
9130 				if (!headerData) {
9131 					goto finish;
9132 				}
9133 
9134 				// unslide any vmaddrs we return to userspace - 10726716
9135 				temp_kext_mach_hdr = (kernel_mach_header_t *)
9136 				    headerData->getBytesNoCopy();
9137 				if (temp_kext_mach_hdr == NULL) {
9138 					goto finish;
9139 				}
9140 
9141 				lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
9142 				for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) {
9143 					if (lcp->cmd == LC_SEGMENT_KERNEL) {
9144 						kernel_segment_command_t *  segp;
9145 						kernel_section_t *          secp;
9146 
9147 						segp = (kernel_segment_command_t *) lcp;
9148 						// 10543468 - if we jettisoned __LINKEDIT clear size info
9149 						if (flags.jettisonLinkeditSeg) {
9150 							if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
9151 								segp->vmsize = 0;
9152 								segp->fileoff = 0;
9153 								segp->filesize = 0;
9154 							}
9155 						}
9156 
9157 #if 0
9158 						OSKextLog(/* kext */ NULL,
9159 						    kOSKextLogErrorLevel |
9160 						    kOSKextLogGeneralFlag,
9161 						    "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
9162 						    __FUNCTION__, segp->segname, segp->vmaddr,
9163 						    VM_KERNEL_UNSLIDE(segp->vmaddr),
9164 						    segp->vmsize, segp->nsects);
9165 						if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
9166 						    (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
9167 						    (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
9168 						    (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
9169 						    (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
9170 							OSKextLog(/* kext */ NULL,
9171 							    kOSKextLogErrorLevel |
9172 							    kOSKextLogGeneralFlag,
9173 							    "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
9174 							    __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
9175 						}
9176 #endif
9177 						segp->vmaddr = ml_static_unslide(segp->vmaddr);
9178 
9179 						for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
9180 							secp->addr = ml_static_unslide(secp->addr);
9181 						}
9182 					}
9183 					lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
9184 				}
9185 				result->setObject(kOSBundleMachOHeadersKey, headerData);
9186 			}
9187 #endif // SECURE_KERNEL
9188 
9189 			if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
9190 				osLogDataHeaderRef *header;
9191 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
9192 
9193 				void *os_log_data          = NULL;
9194 				void *cstring_data         = NULL;
9195 				unsigned long os_log_size  = 0;
9196 				unsigned long cstring_size = 0;
9197 				uint32_t os_log_offset     = 0;
9198 				uint32_t cstring_offset    = 0;
9199 				bool res;
9200 
9201 				os_log_data       = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
9202 				os_log_offset     = getsectoffsetfromheader(kext_mach_hdr, "__TEXT", "__os_log");
9203 				cstring_data      = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
9204 				cstring_offset    = getsectoffsetfromheader(kext_mach_hdr, "__TEXT", "__cstring");
9205 
9206 				header             = (osLogDataHeaderRef *) headerBytes;
9207 				header->version    = OS_LOG_HDR_VERSION;
9208 				header->sect_count = NUM_OS_LOG_SECTIONS;
9209 				header->sections[OS_LOG_SECT_IDX].sect_offset  = os_log_offset;
9210 				header->sections[OS_LOG_SECT_IDX].sect_size    = (uint32_t) os_log_size;
9211 				header->sections[CSTRING_SECT_IDX].sect_offset = cstring_offset;
9212 				header->sections[CSTRING_SECT_IDX].sect_size   = (uint32_t) cstring_size;
9213 
9214 
9215 				logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef)));
9216 				if (!logData) {
9217 					goto finish;
9218 				}
9219 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
9220 				if (!res) {
9221 					goto finish;
9222 				}
9223 				if (os_log_data) {
9224 					res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
9225 					if (!res) {
9226 						goto finish;
9227 					}
9228 				}
9229 				if (cstring_data) {
9230 					res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
9231 					if (!res) {
9232 						goto finish;
9233 					}
9234 				}
9235 				result->setObject(kOSBundleLogStringsKey, logData);
9236 			}
9237 
9238 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
9239 				cpuTypeNumber = OSNumber::withNumber(
9240 					(uint64_t) kext_mach_hdr->cputype,
9241 					8 * sizeof(kext_mach_hdr->cputype));
9242 				if (!cpuTypeNumber) {
9243 					goto finish;
9244 				}
9245 				result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber);
9246 			}
9247 
9248 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
9249 				cpuSubtypeNumber = OSNumber::withNumber(
9250 					(uint64_t) kext_mach_hdr->cpusubtype,
9251 					8 * sizeof(kext_mach_hdr->cpusubtype));
9252 				if (!cpuSubtypeNumber) {
9253 					goto finish;
9254 				}
9255 				result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber);
9256 			}
9257 		} else {
9258 			if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
9259 				osLogDataHeaderRef *header;
9260 				char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
9261 				bool res;
9262 
9263 				header             = (osLogDataHeaderRef *) headerBytes;
9264 				header->version    = OS_LOG_HDR_VERSION;
9265 				header->sect_count = NUM_OS_LOG_SECTIONS;
9266 				header->sections[OS_LOG_SECT_IDX].sect_offset  = 0;
9267 				header->sections[OS_LOG_SECT_IDX].sect_size    = (uint32_t) 0;
9268 				header->sections[CSTRING_SECT_IDX].sect_offset = 0;
9269 				header->sections[CSTRING_SECT_IDX].sect_size   = (uint32_t) 0;
9270 
9271 				logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef)));
9272 				if (!logData) {
9273 					goto finish;
9274 				}
9275 				res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
9276 				if (!res) {
9277 					goto finish;
9278 				}
9279 				result->setObject(kOSBundleLogStringsKey, logData);
9280 			}
9281 		}
9282 	}
9283 
9284 	/* CFBundleIdentifier. We set this regardless because it's just stupid not to.
9285 	 */
9286 	result->setObject(kCFBundleIdentifierKey, bundleID);
9287 
9288 	/* CFBundleVersion.
9289 	 */
9290 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
9291 		versionString = OSDynamicCast(OSString,
9292 		    getPropertyForHostArch(kCFBundleVersionKey));
9293 		if (versionString) {
9294 			result->setObject(kCFBundleVersionKey, versionString);
9295 		}
9296 	}
9297 
9298 	/* OSBundleCompatibleVersion.
9299 	 */
9300 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
9301 		versionString = OSDynamicCast(OSString,
9302 		    getPropertyForHostArch(kOSBundleCompatibleVersionKey));
9303 		if (versionString) {
9304 			result->setObject(kOSBundleCompatibleVersionKey, versionString);
9305 		}
9306 	}
9307 
9308 	/* Path.
9309 	 */
9310 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
9311 		if (path) {
9312 			result->setObject(kOSBundlePathKey, path);
9313 		}
9314 	}
9315 
9316 
9317 	/* OSBundleExecutablePath.
9318 	 */
9319 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
9320 		if (path && executableRelPath) {
9321 			uint32_t pathLength = path->getLength(); // gets incremented below
9322 
9323 			// +1 for slash, +1 for \0
9324 			executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
9325 
9326 			executablePathCString = (char *)kalloc_tag((executablePathCStringSize) *
9327 			    sizeof(char), VM_KERN_MEMORY_OSKEXT); // +1 for \0
9328 			if (!executablePathCString) {
9329 				goto finish;
9330 			}
9331 			strlcpy(executablePathCString, path->getCStringNoCopy(),
9332 			    executablePathCStringSize);
9333 			executablePathCString[pathLength++] = '/';
9334 			executablePathCString[pathLength++] = '\0';
9335 			strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
9336 			    executablePathCStringSize);
9337 
9338 			executablePathString = OSString::withCString(executablePathCString);
9339 
9340 			if (!executablePathString) {
9341 				goto finish;
9342 			}
9343 
9344 			result->setObject(kOSBundleExecutablePathKey, executablePathString);
9345 		} else if (flags.builtin) {
9346 			result->setObject(kOSBundleExecutablePathKey, bundleID);
9347 		} else if (isDriverKit()) {
9348 			if (path) {
9349 				// +1 for slash, +1 for \0
9350 				uint32_t pathLength = path->getLength();
9351 				executablePathCStringSize = pathLength + 2;
9352 
9353 				executablePathCString = (char *)kalloc_tag((executablePathCStringSize) *
9354 				    sizeof(char), VM_KERN_MEMORY_OSKEXT);
9355 				if (!executablePathCString) {
9356 					goto finish;
9357 				}
9358 				strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize);
9359 				executablePathCString[pathLength++] = '/';
9360 				executablePathCString[pathLength++] = '\0';
9361 
9362 				executablePathString = OSString::withCString(executablePathCString);
9363 
9364 				if (!executablePathString) {
9365 					goto finish;
9366 				}
9367 
9368 				result->setObject(kOSBundleExecutablePathKey, executablePathString);
9369 			}
9370 		}
9371 	}
9372 
9373 	/* UUID, if the kext has one.
9374 	 */
9375 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
9376 		uuid = copyUUID();
9377 		if (uuid) {
9378 			result->setObject(kOSBundleUUIDKey, uuid);
9379 			uuid->release();
9380 		}
9381 	}
9382 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
9383 		uuid = copyTextUUID();
9384 		if (uuid) {
9385 			result->setObject(kOSBundleTextUUIDKey, uuid); uuid->release();
9386 		}
9387 	}
9388 
9389 	/*****
9390 	 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
9391 	 */
9392 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
9393 		result->setObject(kOSKernelResourceKey,
9394 		    isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
9395 	}
9396 
9397 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
9398 		result->setObject(kOSBundleIsInterfaceKey,
9399 		    isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
9400 	}
9401 
9402 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
9403 		result->setObject(kOSBundlePrelinkedKey,
9404 		    isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
9405 	}
9406 
9407 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
9408 		result->setObject(kOSBundleStartedKey,
9409 		    isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
9410 	}
9411 
9412 	/* LoadTag (Index).
9413 	 */
9414 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
9415 		scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
9416 		    /* numBits */ 8 * sizeof(loadTag));
9417 		if (!scratchNumber) {
9418 			goto finish;
9419 		}
9420 		result->setObject(kOSBundleLoadTagKey, scratchNumber);
9421 		OSSafeReleaseNULL(scratchNumber);
9422 	}
9423 
9424 	/* LoadAddress, LoadSize.
9425 	 */
9426 	if (!infoKeys ||
9427 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
9428 	    _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
9429 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
9430 	    _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
9431 	    _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
9432 		bool is_dext = isDriverKit();
9433 		if (isInterface() || flags.builtin || linkedExecutable || is_dext) {
9434 			/* These go to userspace via serialization, so we don't want any doubts
9435 			 * about their size.
9436 			 */
9437 			uint64_t    loadAddress     = 0;
9438 			uint32_t    loadSize        = 0;
9439 			uint32_t    wiredSize       = 0;
9440 			uint64_t    execLoadAddress = 0;
9441 			uint32_t    execLoadSize    = 0;
9442 
9443 			/* Interfaces always report 0 load address & size.
9444 			 * Just the way they roll.
9445 			 *
9446 			 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
9447 			 * xxx - shouldn't have one!
9448 			 */
9449 
9450 			if (flags.builtin || linkedExecutable) {
9451 				kernel_mach_header_t     *mh  = NULL;
9452 				kernel_segment_command_t *seg = NULL;
9453 
9454 				if (flags.builtin) {
9455 					loadAddress = kmod_info->address;
9456 					loadSize    = kmod_info->size;
9457 				} else {
9458 					loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
9459 					loadSize = linkedExecutable->getLength();
9460 				}
9461 				mh = (kernel_mach_header_t *)loadAddress;
9462 				loadAddress = ml_static_unslide(loadAddress);
9463 
9464 				/* Walk through the kext, looking for the first executable
9465 				 * segment in case we were asked for its size/address.
9466 				 */
9467 				for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
9468 					if (seg->initprot & VM_PROT_EXECUTE) {
9469 						execLoadAddress = ml_static_unslide(seg->vmaddr);
9470 						execLoadSize = seg->vmsize;
9471 						break;
9472 					}
9473 				}
9474 
9475 				/* If we have a kmod_info struct, calculated the wired size
9476 				 * from that. Otherwise it's the full load size.
9477 				 */
9478 				if (kmod_info) {
9479 					wiredSize = loadSize - kmod_info->hdr_size;
9480 				} else {
9481 					wiredSize = loadSize;
9482 				}
9483 			} else if (is_dext) {
9484 				/*
9485 				 * DriverKit userspace executables do not have a kernel linkedExecutable,
9486 				 * so we "fake" their address range with the LoadTag.
9487 				 */
9488 				if (loadTag) {
9489 					loadAddress = execLoadAddress = loadTag;
9490 					loadSize = execLoadSize = 1;
9491 				}
9492 			}
9493 
9494 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
9495 				scratchNumber = OSNumber::withNumber(
9496 					(unsigned long long)(loadAddress),
9497 					/* numBits */ 8 * sizeof(loadAddress));
9498 				if (!scratchNumber) {
9499 					goto finish;
9500 				}
9501 				result->setObject(kOSBundleLoadAddressKey, scratchNumber);
9502 				OSSafeReleaseNULL(scratchNumber);
9503 			}
9504 #if CONFIG_EMBEDDED
9505 			if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
9506 			    && loadAddress && loadSize) {
9507 				scratchNumber = OSNumber::withNumber(
9508 					(unsigned long long)ml_static_unslide((uintptr_t)segLOWESTTEXT),
9509 					/* numBits */ 8 * sizeof(loadAddress));
9510 				if (!scratchNumber) {
9511 					goto finish;
9512 				}
9513 				result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber);
9514 				OSSafeReleaseNULL(scratchNumber);
9515 			}
9516 			if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
9517 			    && (this == sKernelKext) && gBuiltinKmodsCount) {
9518 				result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
9519 			}
9520 #endif /* CONFIG_EMBEDDED */
9521 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
9522 				scratchNumber = OSNumber::withNumber(
9523 					(unsigned long long)(execLoadAddress),
9524 					/* numBits */ 8 * sizeof(execLoadAddress));
9525 				if (!scratchNumber) {
9526 					goto finish;
9527 				}
9528 				result->setObject(kOSBundleExecLoadAddressKey, scratchNumber);
9529 				OSSafeReleaseNULL(scratchNumber);
9530 			}
9531 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
9532 				scratchNumber = OSNumber::withNumber(
9533 					(unsigned long long)(loadSize),
9534 					/* numBits */ 8 * sizeof(loadSize));
9535 				if (!scratchNumber) {
9536 					goto finish;
9537 				}
9538 				result->setObject(kOSBundleLoadSizeKey, scratchNumber);
9539 				OSSafeReleaseNULL(scratchNumber);
9540 			}
9541 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
9542 				scratchNumber = OSNumber::withNumber(
9543 					(unsigned long long)(execLoadSize),
9544 					/* numBits */ 8 * sizeof(execLoadSize));
9545 				if (!scratchNumber) {
9546 					goto finish;
9547 				}
9548 				result->setObject(kOSBundleExecLoadSizeKey, scratchNumber);
9549 				OSSafeReleaseNULL(scratchNumber);
9550 			}
9551 			if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
9552 				scratchNumber = OSNumber::withNumber(
9553 					(unsigned long long)(wiredSize),
9554 					/* numBits */ 8 * sizeof(wiredSize));
9555 				if (!scratchNumber) {
9556 					goto finish;
9557 				}
9558 				result->setObject(kOSBundleWiredSizeKey, scratchNumber);
9559 				OSSafeReleaseNULL(scratchNumber);
9560 			}
9561 		}
9562 	}
9563 
9564 	/* OSBundleDependencies. In descending order for
9565 	 * easy compatibility with kextstat(8).
9566 	 */
9567 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
9568 		if ((count = getNumDependencies())) {
9569 			dependencyLoadTags = OSArray::withCapacity(count);
9570 			result->setObject(kOSBundleDependenciesKey, dependencyLoadTags);
9571 
9572 			i = count - 1;
9573 			do {
9574 				OSKext * dependency = OSDynamicCast(OSKext,
9575 				    dependencies->getObject(i));
9576 
9577 				OSSafeReleaseNULL(scratchNumber);
9578 
9579 				if (!dependency) {
9580 					continue;
9581 				}
9582 				scratchNumber = OSNumber::withNumber(
9583 					(unsigned long long)dependency->getLoadTag(),
9584 					/* numBits*/ 8 * sizeof(loadTag));
9585 				if (!scratchNumber) {
9586 					goto finish;
9587 				}
9588 				dependencyLoadTags->setObject(scratchNumber);
9589 			} while (i--);
9590 		}
9591 	}
9592 
9593 	OSSafeReleaseNULL(scratchNumber);
9594 
9595 	/* OSBundleMetaClasses.
9596 	 */
9597 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
9598 		if (metaClasses && metaClasses->getCount()) {
9599 			metaClassIterator = OSCollectionIterator::withCollection(metaClasses);
9600 			metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
9601 			if (!metaClassIterator || !metaClassInfo) {
9602 				goto finish;
9603 			}
9604 			result->setObject(kOSBundleClassesKey, metaClassInfo);
9605 
9606 			while ((thisMetaClass = OSDynamicCast(OSMetaClass,
9607 			    metaClassIterator->getNextObject()))) {
9608 				OSSafeReleaseNULL(metaClassDict);
9609 				OSSafeReleaseNULL(scratchNumber);
9610 				OSSafeReleaseNULL(metaClassName);
9611 				OSSafeReleaseNULL(superclassName);
9612 
9613 				metaClassDict = OSDictionary::withCapacity(3);
9614 				if (!metaClassDict) {
9615 					goto finish;
9616 				}
9617 
9618 				metaClassName = OSString::withCString(thisMetaClass->getClassName());
9619 				if (thisMetaClass->getSuperClass()) {
9620 					superclassName = OSString::withCString(
9621 						thisMetaClass->getSuperClass()->getClassName());
9622 				}
9623 				scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
9624 				    8 * sizeof(unsigned int));
9625 
9626 				/* Bail if any of the essentials is missing. The root class lacks a superclass,
9627 				 * of course.
9628 				 */
9629 				if (!metaClassDict || !metaClassName || !scratchNumber) {
9630 					goto finish;
9631 				}
9632 
9633 				metaClassInfo->setObject(metaClassDict);
9634 				metaClassDict->setObject(kOSMetaClassNameKey, metaClassName);
9635 				if (superclassName) {
9636 					metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName);
9637 				}
9638 				metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber);
9639 			}
9640 		}
9641 	}
9642 
9643 	/* OSBundleRetainCount.
9644 	 */
9645 	if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
9646 		OSSafeReleaseNULL(scratchNumber);
9647 		{
9648 			int kextRetainCount = getRetainCount() - 1;
9649 			if (isLoaded()) {
9650 				kextRetainCount--;
9651 			}
9652 			scratchNumber = OSNumber::withNumber(
9653 				(int)kextRetainCount,
9654 				/* numBits*/ 8 * sizeof(int));
9655 			if (scratchNumber) {
9656 				result->setObject(kOSBundleRetainCountKey, scratchNumber);
9657 			}
9658 		}
9659 	}
9660 
9661 	success = true;
9662 
9663 finish:
9664 	OSSafeReleaseNULL(headerData);
9665 	OSSafeReleaseNULL(logData);
9666 	OSSafeReleaseNULL(cpuTypeNumber);
9667 	OSSafeReleaseNULL(cpuSubtypeNumber);
9668 	OSSafeReleaseNULL(executablePathString);
9669 	if (executablePathCString) {
9670 		kfree(executablePathCString, executablePathCStringSize);
9671 	}
9672 	OSSafeReleaseNULL(scratchNumber);
9673 	OSSafeReleaseNULL(dependencyLoadTags);
9674 	OSSafeReleaseNULL(metaClassIterator);
9675 	OSSafeReleaseNULL(metaClassInfo);
9676 	OSSafeReleaseNULL(metaClassDict);
9677 	OSSafeReleaseNULL(metaClassName);
9678 	OSSafeReleaseNULL(superclassName);
9679 	if (!success) {
9680 		OSSafeReleaseNULL(result);
9681 	}
9682 	return result;
9683 }
9684 
9685 /*********************************************************************
9686 *********************************************************************/
9687 /* static */
9688 bool
9689 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
9690 {
9691 	bool ok;
9692 	OSKext * kext;
9693 
9694 	IORecursiveLockLock(sKextLock);
9695 	kext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID));
9696 	if (kext) {
9697 		kext->retain();
9698 	}
9699 	IORecursiveLockUnlock(sKextLock);
9700 
9701 	if (!kext || !kext->path || !kext->userExecutableRelPath) {
9702 		OSSafeReleaseNULL(kext);
9703 		return false;
9704 	}
9705 	snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
9706 	    kext->path->getCStringNoCopy(),
9707 	    kext->userExecutableRelPath->getCStringNoCopy());
9708 	ok = true;
9709 	kext->release();
9710 
9711 	return ok;
9712 }
9713 
9714 /*********************************************************************
9715 *********************************************************************/
9716 /* static */
9717 OSReturn
9718 OSKext::requestResource(
9719 	const char                    * kextIdentifierCString,
9720 	const char                    * resourceNameCString,
9721 	OSKextRequestResourceCallback   callback,
9722 	void                          * context,
9723 	OSKextRequestTag              * requestTagOut)
9724 {
9725 	OSReturn           result          = kOSReturnError;
9726 	OSKext           * callbackKext    = NULL;// must release (looked up)
9727 
9728 	OSKextRequestTag   requestTag      = -1;
9729 	OSNumber         * requestTagNum   = NULL;// must release
9730 
9731 	OSDictionary     * requestDict     = NULL;// must release
9732 	OSString         * kextIdentifier  = NULL;// must release
9733 	OSString         * resourceName    = NULL;// must release
9734 
9735 	OSDictionary     * callbackRecord  = NULL;// must release
9736 	OSData           * callbackWrapper = NULL;// must release
9737 
9738 	OSData           * contextWrapper  = NULL;// must release
9739 
9740 	IORecursiveLockLock(sKextLock);
9741 
9742 	if (requestTagOut) {
9743 		*requestTagOut = kOSKextRequestTagInvalid;
9744 	}
9745 
9746 	/* If requests to user space are disabled, don't go any further */
9747 	if (!sKernelRequestsEnabled) {
9748 		OSKextLog(/* kext */ NULL,
9749 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9750 		    "Can't request resource %s for %s - requests to user space are disabled.",
9751 		    resourceNameCString,
9752 		    kextIdentifierCString);
9753 		result = kOSKextReturnDisabled;
9754 		goto finish;
9755 	}
9756 
9757 	if (!kextIdentifierCString || !resourceNameCString || !callback) {
9758 		result = kOSKextReturnInvalidArgument;
9759 		goto finish;
9760 	}
9761 
9762 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
9763 	if (!callbackKext) {
9764 		OSKextLog(/* kext */ NULL,
9765 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9766 		    "Resource request has bad callback address.");
9767 		result = kOSKextReturnInvalidArgument;
9768 		goto finish;
9769 	}
9770 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
9771 		OSKextLog(/* kext */ NULL,
9772 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9773 		    "Resource request callback is in a kext that is not started.");
9774 		result = kOSKextReturnInvalidArgument;
9775 		goto finish;
9776 	}
9777 
9778 	/* Do not allow any new requests to be made on a kext that is unloading.
9779 	 */
9780 	if (callbackKext->flags.stopping) {
9781 		result = kOSKextReturnStopping;
9782 		goto finish;
9783 	}
9784 
9785 	/* If we're wrapped the next available request tag around to the negative
9786 	 * numbers, we can't service any more requests.
9787 	 */
9788 	if (sNextRequestTag == kOSKextRequestTagInvalid) {
9789 		OSKextLog(/* kext */ NULL,
9790 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9791 		    "No more request tags available; restart required.");
9792 		result = kOSKextReturnNoResources;
9793 		goto finish;
9794 	}
9795 	requestTag = sNextRequestTag++;
9796 
9797 	result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
9798 	    &requestDict);
9799 	if (result != kOSReturnSuccess) {
9800 		goto finish;
9801 	}
9802 
9803 	kextIdentifier = OSString::withCString(kextIdentifierCString);
9804 	resourceName   = OSString::withCString(resourceNameCString);
9805 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
9806 	    8 * sizeof(requestTag));
9807 	if (!kextIdentifier ||
9808 	    !resourceName ||
9809 	    !requestTagNum ||
9810 	    !_OSKextSetRequestArgument(requestDict,
9811 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
9812 	    !_OSKextSetRequestArgument(requestDict,
9813 	    kKextRequestArgumentNameKey, resourceName) ||
9814 	    !_OSKextSetRequestArgument(requestDict,
9815 	    kKextRequestArgumentRequestTagKey, requestTagNum)) {
9816 		result = kOSKextReturnNoMemory;
9817 		goto finish;
9818 	}
9819 
9820 	callbackRecord = OSDynamicCast(OSDictionary, requestDict->copyCollection());
9821 	if (!callbackRecord) {
9822 		result = kOSKextReturnNoMemory;
9823 		goto finish;
9824 	}
9825 	// we validate callback address at call time
9826 	callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *));
9827 	if (context) {
9828 		contextWrapper = OSData::withBytes((void *)&context, sizeof(void *));
9829 	}
9830 	if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord,
9831 	    kKextRequestArgumentCallbackKey, callbackWrapper)) {
9832 		result = kOSKextReturnNoMemory;
9833 		goto finish;
9834 	}
9835 
9836 	if (context) {
9837 		if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord,
9838 		    kKextRequestArgumentContextKey, contextWrapper)) {
9839 			result = kOSKextReturnNoMemory;
9840 			goto finish;
9841 		}
9842 	}
9843 
9844 	/* Only post the requests after all the other potential failure points
9845 	 * have been passed.
9846 	 */
9847 	if (!sKernelRequests->setObject(requestDict) ||
9848 	    !sRequestCallbackRecords->setObject(callbackRecord)) {
9849 		result = kOSKextReturnNoMemory;
9850 		goto finish;
9851 	}
9852 
9853 	OSKext::pingKextd();
9854 
9855 	result = kOSReturnSuccess;
9856 	if (requestTagOut) {
9857 		*requestTagOut = requestTag;
9858 	}
9859 
9860 finish:
9861 
9862 	/* If we didn't succeed, yank the request & callback
9863 	 * from their holding arrays.
9864 	 */
9865 	if (result != kOSReturnSuccess) {
9866 		unsigned int index;
9867 
9868 		index = sKernelRequests->getNextIndexOfObject(requestDict, 0);
9869 		if (index != (unsigned int)-1) {
9870 			sKernelRequests->removeObject(index);
9871 		}
9872 		index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord, 0);
9873 		if (index != (unsigned int)-1) {
9874 			sRequestCallbackRecords->removeObject(index);
9875 		}
9876 	}
9877 
9878 	OSKext::considerUnloads(/* rescheduleOnly? */ true);
9879 
9880 	IORecursiveLockUnlock(sKextLock);
9881 
9882 	if (callbackKext) {
9883 		callbackKext->release();
9884 	}
9885 	if (requestTagNum) {
9886 		requestTagNum->release();
9887 	}
9888 
9889 	if (requestDict) {
9890 		requestDict->release();
9891 	}
9892 	if (kextIdentifier) {
9893 		kextIdentifier->release();
9894 	}
9895 	if (resourceName) {
9896 		resourceName->release();
9897 	}
9898 
9899 	if (callbackRecord) {
9900 		callbackRecord->release();
9901 	}
9902 	if (callbackWrapper) {
9903 		callbackWrapper->release();
9904 	}
9905 	if (contextWrapper) {
9906 		contextWrapper->release();
9907 	}
9908 
9909 	return result;
9910 }
9911 
9912 OSReturn
9913 OSKext::requestDaemonLaunch(
9914 	OSString *kextIdentifier,
9915 	OSString *serverName,
9916 	OSNumber *serverTag)
9917 {
9918 	OSReturn       result        = kOSReturnError;
9919 	OSDictionary * requestDict   = NULL; // must release
9920 
9921 	if (!kextIdentifier || !serverName || !serverTag) {
9922 		result = kOSKextReturnInvalidArgument;
9923 		goto finish;
9924 	}
9925 
9926 	IORecursiveLockLock(sKextLock);
9927 
9928 	OSKextLog(/* kext */ NULL,
9929 	    kOSKextLogDebugLevel |
9930 	    kOSKextLogGeneralFlag,
9931 	    "Requesting daemon launch for %s with serverName %s and tag %llu",
9932 	    kextIdentifier->getCStringNoCopy(),
9933 	    serverName->getCStringNoCopy(),
9934 	    serverTag->unsigned64BitValue()
9935 	    );
9936 
9937 	result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, &requestDict);
9938 	if (result != kOSReturnSuccess) {
9939 		goto finish;
9940 	}
9941 
9942 	if (!_OSKextSetRequestArgument(requestDict,
9943 	    kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
9944 	    !_OSKextSetRequestArgument(requestDict,
9945 	    kKextRequestArgumentDriverExtensionServerName, serverName) ||
9946 	    !_OSKextSetRequestArgument(requestDict,
9947 	    kKextRequestArgumentDriverExtensionServerTag, serverTag)) {
9948 		result = kOSKextReturnNoMemory;
9949 		goto finish;
9950 	}
9951 
9952 	/* Only post the requests after all the other potential failure points
9953 	 * have been passed.
9954 	 */
9955 	if (!sKernelRequests->setObject(requestDict)) {
9956 		result = kOSKextReturnNoMemory;
9957 		goto finish;
9958 	}
9959 	OSKext::pingKextd();
9960 
9961 	result = kOSReturnSuccess;
9962 finish:
9963 	IORecursiveLockUnlock(sKextLock);
9964 	if (requestDict) {
9965 		requestDict->release();
9966 	}
9967 	return result;
9968 }
9969 
9970 /*********************************************************************
9971 * Assumes sKextLock is held.
9972 *********************************************************************/
9973 /* static */
9974 OSReturn
9975 OSKext::dequeueCallbackForRequestTag(
9976 	OSKextRequestTag    requestTag,
9977 	OSDictionary     ** callbackRecordOut)
9978 {
9979 	OSReturn   result = kOSReturnError;
9980 	OSNumber * requestTagNum  = NULL;// must release
9981 
9982 	requestTagNum  = OSNumber::withNumber((long long unsigned int)requestTag,
9983 	    8 * sizeof(requestTag));
9984 	if (!requestTagNum) {
9985 		goto finish;
9986 	}
9987 
9988 	result = OSKext::dequeueCallbackForRequestTag(requestTagNum,
9989 	    callbackRecordOut);
9990 
9991 finish:
9992 	OSSafeReleaseNULL(requestTagNum);
9993 
9994 	return result;
9995 }
9996 
9997 /*********************************************************************
9998 * Assumes sKextLock is held.
9999 *********************************************************************/
10000 /* static */
10001 OSReturn
10002 OSKext::dequeueCallbackForRequestTag(
10003 	OSNumber     *    requestTagNum,
10004 	OSDictionary ** callbackRecordOut)
10005 {
10006 	OSReturn        result          = kOSKextReturnInvalidArgument;
10007 	OSDictionary  * callbackRecord  = NULL;// retain if matched!
10008 	OSNumber      * callbackTagNum  = NULL;// do not release
10009 	unsigned int    count, i;
10010 
10011 	result = kOSReturnError;
10012 	count = sRequestCallbackRecords->getCount();
10013 	for (i = 0; i < count; i++) {
10014 		callbackRecord = OSDynamicCast(OSDictionary,
10015 		    sRequestCallbackRecords->getObject(i));
10016 		if (!callbackRecord) {
10017 			goto finish;
10018 		}
10019 
10020 		/* If we don't find a tag, we basically have a leak here. Maybe
10021 		 * we should just remove it.
10022 		 */
10023 		callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
10024 			    callbackRecord, kKextRequestArgumentRequestTagKey));
10025 		if (!callbackTagNum) {
10026 			goto finish;
10027 		}
10028 
10029 		/* We could be even more paranoid and check that all the incoming
10030 		 * args match what's in the callback record.
10031 		 */
10032 		if (callbackTagNum->isEqualTo(requestTagNum)) {
10033 			if (callbackRecordOut) {
10034 				*callbackRecordOut = callbackRecord;
10035 				callbackRecord->retain();
10036 			}
10037 			sRequestCallbackRecords->removeObject(i);
10038 			result = kOSReturnSuccess;
10039 			goto finish;
10040 		}
10041 	}
10042 	result = kOSKextReturnNotFound;
10043 
10044 finish:
10045 	return result;
10046 }
10047 
10048 
10049 /*********************************************************************
10050 * Busy timeout triage
10051 *********************************************************************/
10052 /* static */
10053 bool
10054 OSKext::isWaitingKextd(void)
10055 {
10056 	return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
10057 }
10058 
10059 /*********************************************************************
10060 * Assumes sKextLock is held.
10061 *********************************************************************/
10062 /* static */
10063 OSReturn
10064 OSKext::dispatchResource(OSDictionary * requestDict)
10065 {
10066 	OSReturn                        result          = kOSReturnError;
10067 	OSDictionary                  * callbackRecord  = NULL;// must release
10068 	OSNumber                      * requestTag      = NULL;// do not release
10069 	OSNumber                      * requestResult   = NULL;// do not release
10070 	OSData                        * dataObj         = NULL;// do not release
10071 	uint32_t                        dataLength      = 0;
10072 	const void                    * dataPtr         = NULL;// do not free
10073 	OSData                        * callbackWrapper = NULL;// do not release
10074 	OSKextRequestResourceCallback   callback        = NULL;
10075 	OSData                        * contextWrapper  = NULL;// do not release
10076 	void                          * context         = NULL;// do not free
10077 	OSKext                        * callbackKext    = NULL;// must release (looked up)
10078 
10079 	/* Get the args from the request. Right now we need the tag
10080 	 * to look up the callback record, and the result for invoking the callback.
10081 	 */
10082 	requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
10083 	    kKextRequestArgumentRequestTagKey));
10084 	requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
10085 	    kKextRequestArgumentResultKey));
10086 	if (!requestTag || !requestResult) {
10087 		result = kOSKextReturnInvalidArgument;
10088 		goto finish;
10089 	}
10090 
10091 	/* Look for a callback record matching this request's tag.
10092 	 */
10093 	result = dequeueCallbackForRequestTag(requestTag, &callbackRecord);
10094 	if (result != kOSReturnSuccess) {
10095 		goto finish;
10096 	}
10097 
10098 	/*****
10099 	 * Get the context pointer of the callback record (if there is one).
10100 	 */
10101 	contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord,
10102 	    kKextRequestArgumentContextKey));
10103 	context = _OSKextExtractPointer(contextWrapper);
10104 	if (contextWrapper && !context) {
10105 		goto finish;
10106 	}
10107 
10108 	callbackWrapper = OSDynamicCast(OSData,
10109 	    _OSKextGetRequestArgument(callbackRecord,
10110 	    kKextRequestArgumentCallbackKey));
10111 	callback = (OSKextRequestResourceCallback)
10112 	    _OSKextExtractPointer(callbackWrapper);
10113 	if (!callback) {
10114 		goto finish;
10115 	}
10116 
10117 	/* Check for a data obj. We might not have one and that's ok, that means
10118 	 * we didn't find the requested resource, and we still have to tell the
10119 	 * caller that via the callback.
10120 	 */
10121 	dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
10122 	    kKextRequestArgumentValueKey));
10123 	if (dataObj) {
10124 		dataPtr = dataObj->getBytesNoCopy();
10125 		dataLength = dataObj->getLength();
10126 	}
10127 
10128 	callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
10129 	if (!callbackKext) {
10130 		OSKextLog(/* kext */ NULL,
10131 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
10132 		    "Can't invoke callback for resource request; ");
10133 		goto finish;
10134 	}
10135 	if (!callbackKext->flags.starting && !callbackKext->flags.started) {
10136 		OSKextLog(/* kext */ NULL,
10137 		    kOSKextLogErrorLevel | kOSKextLogIPCFlag,
10138 		    "Can't invoke kext resource callback; ");
10139 		goto finish;
10140 	}
10141 
10142 	(void)callback(requestTag->unsigned32BitValue(),
10143 	    (OSReturn)requestResult->unsigned32BitValue(),
10144 	    dataPtr, dataLength, context);
10145 
10146 	result = kOSReturnSuccess;
10147 
10148 finish:
10149 	if (callbackKext) {
10150 		callbackKext->release();
10151 	}
10152 	if (callbackRecord) {
10153 		callbackRecord->release();
10154 	}
10155 
10156 	return result;
10157 }
10158 
10159 /*********************************************************************
10160 *********************************************************************/
10161 /* static */
10162 void
10163 OSKext::invokeRequestCallback(
10164 	OSDictionary * callbackRecord,
10165 	OSReturn       callbackResult)
10166 {
10167 	OSString * predicate  = _OSKextGetRequestPredicate(callbackRecord);
10168 	OSNumber * resultNum  = NULL;// must release
10169 
10170 	if (!predicate) {
10171 		goto finish;
10172 	}
10173 
10174 	resultNum  = OSNumber::withNumber((long long unsigned int)callbackResult,
10175 	    8 * sizeof(callbackResult));
10176 	if (!resultNum) {
10177 		goto finish;
10178 	}
10179 
10180 	/* Insert the result into the callback record and dispatch it as if it
10181 	 * were the reply coming down from user space.
10182 	 */
10183 	_OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
10184 	    resultNum);
10185 
10186 	if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
10187 		/* This removes the pending callback record.
10188 		 */
10189 		OSKext::dispatchResource(callbackRecord);
10190 	}
10191 
10192 finish:
10193 	if (resultNum) {
10194 		resultNum->release();
10195 	}
10196 	return;
10197 }
10198 
10199 /*********************************************************************
10200 * Assumes sKextLock is held.
10201 *********************************************************************/
10202 /* static */
10203 OSReturn
10204 OSKext::cancelRequest(
10205 	OSKextRequestTag    requestTag,
10206 	void             ** contextOut)
10207 {
10208 	OSReturn       result         = kOSKextReturnNoMemory;
10209 	OSDictionary * callbackRecord = NULL; // must release
10210 	OSData       * contextWrapper = NULL;// do not release
10211 
10212 	IORecursiveLockLock(sKextLock);
10213 	result = OSKext::dequeueCallbackForRequestTag(requestTag,
10214 	    &callbackRecord);
10215 	IORecursiveLockUnlock(sKextLock);
10216 
10217 	if (result == kOSReturnSuccess && contextOut) {
10218 		contextWrapper = OSDynamicCast(OSData,
10219 		    _OSKextGetRequestArgument(callbackRecord,
10220 		    kKextRequestArgumentContextKey));
10221 		*contextOut = _OSKextExtractPointer(contextWrapper);
10222 	}
10223 
10224 	if (callbackRecord) {
10225 		callbackRecord->release();
10226 	}
10227 
10228 	return result;
10229 }
10230 
10231 /*********************************************************************
10232 * Assumes sKextLock is held.
10233 *********************************************************************/
10234 void
10235 OSKext::invokeOrCancelRequestCallbacks(
10236 	OSReturn callbackResult,
10237 	bool     invokeFlag)
10238 {
10239 	unsigned int count, i;
10240 
10241 	count = sRequestCallbackRecords->getCount();
10242 	if (!count) {
10243 		goto finish;
10244 	}
10245 
10246 	i = count - 1;
10247 	do {
10248 		OSDictionary * request = OSDynamicCast(OSDictionary,
10249 		    sRequestCallbackRecords->getObject(i));
10250 
10251 		if (!request) {
10252 			continue;
10253 		}
10254 		OSData * callbackWrapper = OSDynamicCast(OSData,
10255 		    _OSKextGetRequestArgument(request,
10256 		    kKextRequestArgumentCallbackKey));
10257 
10258 		if (!callbackWrapper) {
10259 			sRequestCallbackRecords->removeObject(i);
10260 			continue;
10261 		}
10262 
10263 		vm_address_t callbackAddress = (vm_address_t)
10264 		    _OSKextExtractPointer(callbackWrapper);
10265 
10266 		if ((kmod_info->address <= callbackAddress) &&
10267 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
10268 			if (invokeFlag) {
10269 				/* This removes the callback record.
10270 				 */
10271 				invokeRequestCallback(request, callbackResult);
10272 			} else {
10273 				sRequestCallbackRecords->removeObject(i);
10274 			}
10275 		}
10276 	} while (i--);
10277 
10278 finish:
10279 	return;
10280 }
10281 
10282 /*********************************************************************
10283 * Assumes sKextLock is held.
10284 *********************************************************************/
10285 uint32_t
10286 OSKext::countRequestCallbacks(void)
10287 {
10288 	uint32_t     result = 0;
10289 	unsigned int count, i;
10290 
10291 	count = sRequestCallbackRecords->getCount();
10292 	if (!count) {
10293 		goto finish;
10294 	}
10295 
10296 	i = count - 1;
10297 	do {
10298 		OSDictionary * request = OSDynamicCast(OSDictionary,
10299 		    sRequestCallbackRecords->getObject(i));
10300 
10301 		if (!request) {
10302 			continue;
10303 		}
10304 		OSData * callbackWrapper = OSDynamicCast(OSData,
10305 		    _OSKextGetRequestArgument(request,
10306 		    kKextRequestArgumentCallbackKey));
10307 
10308 		if (!callbackWrapper) {
10309 			continue;
10310 		}
10311 
10312 		vm_address_t callbackAddress = (vm_address_t)
10313 		    _OSKextExtractPointer(callbackWrapper);
10314 
10315 		if ((kmod_info->address <= callbackAddress) &&
10316 		    (callbackAddress < (kmod_info->address + kmod_info->size))) {
10317 			result++;
10318 		}
10319 	} while (i--);
10320 
10321 finish:
10322 	return result;
10323 }
10324 
10325 /*********************************************************************
10326 *********************************************************************/
10327 static OSReturn
10328 _OSKextCreateRequest(
10329 	const char    * predicate,
10330 	OSDictionary ** requestP)
10331 {
10332 	OSReturn result = kOSKextReturnNoMemory;
10333 	OSDictionary * request = NULL; // must release on error
10334 
10335 	request = OSDictionary::withCapacity(2);
10336 	if (!request) {
10337 		goto finish;
10338 	}
10339 	result = _OSDictionarySetCStringValue(request,
10340 	    kKextRequestPredicateKey, predicate);
10341 	if (result != kOSReturnSuccess) {
10342 		goto finish;
10343 	}
10344 	result = kOSReturnSuccess;
10345 
10346 finish:
10347 	if (result != kOSReturnSuccess) {
10348 		if (request) {
10349 			request->release();
10350 		}
10351 	} else {
10352 		*requestP = request;
10353 	}
10354 
10355 	return result;
10356 }
10357 
10358 /*********************************************************************
10359 *********************************************************************/
10360 static OSString *
10361 _OSKextGetRequestPredicate(OSDictionary * requestDict)
10362 {
10363 	return OSDynamicCast(OSString,
10364 	           requestDict->getObject(kKextRequestPredicateKey));
10365 }
10366 
10367 /*********************************************************************
10368 *********************************************************************/
10369 static OSObject *
10370 _OSKextGetRequestArgument(
10371 	OSDictionary * requestDict,
10372 	const char   * argName)
10373 {
10374 	OSDictionary * args = OSDynamicCast(OSDictionary,
10375 	    requestDict->getObject(kKextRequestArgumentsKey));
10376 	if (args) {
10377 		return args->getObject(argName);
10378 	}
10379 	return NULL;
10380 }
10381 
10382 /*********************************************************************
10383 *********************************************************************/
10384 static bool
10385 _OSKextSetRequestArgument(
10386 	OSDictionary * requestDict,
10387 	const char   * argName,
10388 	OSObject     * value)
10389 {
10390 	OSDictionary * args = OSDynamicCast(OSDictionary,
10391 	    requestDict->getObject(kKextRequestArgumentsKey));
10392 	if (!args) {
10393 		args = OSDictionary::withCapacity(2);
10394 		if (!args) {
10395 			goto finish;
10396 		}
10397 		requestDict->setObject(kKextRequestArgumentsKey, args);
10398 		args->release();
10399 	}
10400 	if (args) {
10401 		return args->setObject(argName, value);
10402 	}
10403 finish:
10404 	return false;
10405 }
10406 
10407 /*********************************************************************
10408 *********************************************************************/
10409 static void *
10410 _OSKextExtractPointer(OSData * wrapper)
10411 {
10412 	void       * result = NULL;
10413 	const void * resultPtr = NULL;
10414 
10415 	if (!wrapper) {
10416 		goto finish;
10417 	}
10418 	resultPtr = wrapper->getBytesNoCopy();
10419 	result = *(void **)resultPtr;
10420 finish:
10421 	return result;
10422 }
10423 
10424 /*********************************************************************
10425 *********************************************************************/
10426 static OSReturn
10427 _OSDictionarySetCStringValue(
10428 	OSDictionary * dict,
10429 	const char   * cKey,
10430 	const char   * cValue)
10431 {
10432 	OSReturn result = kOSKextReturnNoMemory;
10433 	const OSSymbol * key = NULL; // must release
10434 	OSString * value = NULL; // must release
10435 
10436 	key = OSSymbol::withCString(cKey);
10437 	value = OSString::withCString(cValue);
10438 	if (!key || !value) {
10439 		goto finish;
10440 	}
10441 	if (dict->setObject(key, value)) {
10442 		result = kOSReturnSuccess;
10443 	}
10444 
10445 finish:
10446 	if (key) {
10447 		key->release();
10448 	}
10449 	if (value) {
10450 		value->release();
10451 	}
10452 
10453 	return result;
10454 }
10455 
10456 /*********************************************************************
10457 *********************************************************************/
10458 static bool
10459 _OSArrayContainsCString(
10460 	OSArray    * array,
10461 	const char * cString)
10462 {
10463 	bool             result = false;
10464 	const OSSymbol * symbol = NULL;
10465 	uint32_t         count, i;
10466 
10467 	if (!array || !cString) {
10468 		goto finish;
10469 	}
10470 
10471 	symbol = OSSymbol::withCStringNoCopy(cString);
10472 	if (!symbol) {
10473 		goto finish;
10474 	}
10475 
10476 	count = array->getCount();
10477 	for (i = 0; i < count; i++) {
10478 		OSObject * thisObject = array->getObject(i);
10479 		if (symbol->isEqualTo(thisObject)) {
10480 			result = true;
10481 			goto finish;
10482 		}
10483 	}
10484 
10485 finish:
10486 	if (symbol) {
10487 		symbol->release();
10488 	}
10489 	return result;
10490 }
10491 
10492 /*********************************************************************
10493 * We really only care about boot / system start up related kexts.
10494 * We return true if we're less than REBUILD_MAX_TIME since start up,
10495 * otherwise return false.
10496 *********************************************************************/
10497 bool
10498 _OSKextInPrelinkRebuildWindow(void)
10499 {
10500 	static bool     outside_the_window = false;
10501 	AbsoluteTime    my_abstime;
10502 	UInt64          my_ns;
10503 	SInt32          my_secs;
10504 
10505 	if (outside_the_window) {
10506 		return false;
10507 	}
10508 	clock_get_uptime(&my_abstime);
10509 	absolutetime_to_nanoseconds(my_abstime, &my_ns);
10510 	my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
10511 	if (my_secs > REBUILD_MAX_TIME) {
10512 		outside_the_window = true;
10513 		return false;
10514 	}
10515 	return true;
10516 }
10517 
10518 /*********************************************************************
10519 *********************************************************************/
10520 bool
10521 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
10522 {
10523 	int unLoadedCount, i;
10524 	bool result = false;
10525 
10526 	IORecursiveLockLock(sKextLock);
10527 
10528 	if (sUnloadedPrelinkedKexts == NULL) {
10529 		goto finish;
10530 	}
10531 	unLoadedCount = sUnloadedPrelinkedKexts->getCount();
10532 	if (unLoadedCount == 0) {
10533 		goto finish;
10534 	}
10535 
10536 	for (i = 0; i < unLoadedCount; i++) {
10537 		const OSSymbol *    myBundleID;// do not release
10538 
10539 		myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
10540 		if (!myBundleID) {
10541 			continue;
10542 		}
10543 		if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
10544 			result = true;
10545 			break;
10546 		}
10547 	}
10548 finish:
10549 	IORecursiveLockUnlock(sKextLock);
10550 	return result;
10551 }
10552 
10553 #if PRAGMA_MARK
10554 #pragma mark Personalities (IOKit Drivers)
10555 #endif
10556 /*********************************************************************
10557 *********************************************************************/
10558 /* static */
10559 OSArray *
10560 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
10561 {
10562 	OSArray              * result                = NULL;// returned
10563 	OSCollectionIterator * kextIterator          = NULL;// must release
10564 	OSArray              * personalities         = NULL;// must release
10565 	OSCollectionIterator * personalitiesIterator = NULL; // must release
10566 
10567 	OSString             * kextID                = NULL;// do not release
10568 	OSKext               * theKext               = NULL;// do not release
10569 
10570 	IORecursiveLockLock(sKextLock);
10571 
10572 	/* Let's conservatively guess that any given kext has around 3
10573 	 * personalities for now.
10574 	 */
10575 	result = OSArray::withCapacity(sKextsByID->getCount() * 3);
10576 	if (!result) {
10577 		goto finish;
10578 	}
10579 
10580 	kextIterator = OSCollectionIterator::withCollection(sKextsByID);
10581 	if (!kextIterator) {
10582 		goto finish;
10583 	}
10584 
10585 	while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
10586 		if (personalitiesIterator) {
10587 			personalitiesIterator->release();
10588 			personalitiesIterator = NULL;
10589 		}
10590 		if (personalities) {
10591 			personalities->release();
10592 			personalities = NULL;
10593 		}
10594 
10595 		theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
10596 		if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
10597 			personalities = theKext->copyPersonalitiesArray();
10598 			if (!personalities) {
10599 				continue;
10600 			}
10601 			result->merge(personalities);
10602 		} else {
10603 			// xxx - check for better place to put this log msg
10604 			OSKextLog(theKext,
10605 			    kOSKextLogWarningLevel |
10606 			    kOSKextLogLoadFlag,
10607 			    "Kext %s is not loadable during safe boot; "
10608 			    "omitting its personalities.",
10609 			    theKext->getIdentifierCString());
10610 		}
10611 	}
10612 
10613 finish:
10614 	IORecursiveLockUnlock(sKextLock);
10615 
10616 	if (kextIterator) {
10617 		kextIterator->release();
10618 	}
10619 	if (personalitiesIterator) {
10620 		personalitiesIterator->release();
10621 	}
10622 	if (personalities) {
10623 		personalities->release();
10624 	}
10625 
10626 	return result;
10627 }
10628 
10629 /*********************************************************************
10630 *********************************************************************/
10631 /* static */
10632 void
10633 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
10634 {
10635 	int numPersonalities = 0;
10636 
10637 	OSKextLog(/* kext */ NULL,
10638 	    kOSKextLogStepLevel |
10639 	    kOSKextLogLoadFlag,
10640 	    "Sending all eligible registered kexts' personalities "
10641 	    "to the IOCatalogue %s.",
10642 	    startMatching ? "and starting matching" : "but not starting matching");
10643 
10644 	OSArray * personalities = OSKext::copyAllKextPersonalities(
10645 		/* filterSafeBootFlag */ true);
10646 
10647 	if (personalities) {
10648 		gIOCatalogue->addDrivers(personalities, startMatching);
10649 		numPersonalities = personalities->getCount();
10650 		personalities->release();
10651 	}
10652 
10653 	OSKextLog(/* kext */ NULL,
10654 	    kOSKextLogStepLevel |
10655 	    kOSKextLogLoadFlag,
10656 	    "%d kext personalit%s sent to the IOCatalogue; %s.",
10657 	    numPersonalities, numPersonalities > 0 ? "ies" : "y",
10658 	    startMatching ? "matching started" : "matching not started");
10659 	return;
10660 }
10661 
10662 /*********************************************************************
10663 * Do not make a deep copy, just convert the IOKitPersonalities dict
10664 * to an array for sending to the IOCatalogue.
10665 *********************************************************************/
10666 OSArray *
10667 OSKext::copyPersonalitiesArray(void)
10668 {
10669 	OSArray              * result                      = NULL;
10670 	OSDictionary         * personalities               = NULL;// do not release
10671 	OSCollectionIterator * personalitiesIterator       = NULL;// must release
10672 
10673 	OSString             * personalityName             = NULL;// do not release
10674 	OSString             * personalityBundleIdentifier = NULL;// do not release
10675 
10676 	personalities = OSDynamicCast(OSDictionary,
10677 	    getPropertyForHostArch(kIOKitPersonalitiesKey));
10678 	if (!personalities) {
10679 		goto finish;
10680 	}
10681 
10682 	result = OSArray::withCapacity(personalities->getCount());
10683 	if (!result) {
10684 		goto finish;
10685 	}
10686 
10687 	personalitiesIterator =
10688 	    OSCollectionIterator::withCollection(personalities);
10689 	if (!personalitiesIterator) {
10690 		goto finish;
10691 	}
10692 	while ((personalityName = OSDynamicCast(OSString,
10693 	    personalitiesIterator->getNextObject()))) {
10694 		OSDictionary * personality = OSDynamicCast(OSDictionary,
10695 		    personalities->getObject(personalityName));
10696 
10697 		/******
10698 		 * If the personality doesn't have a CFBundleIdentifier, or if it
10699 		 * differs from the kext's, insert the kext's ID so we can find it.
10700 		 * The publisher ID is used to remove personalities from bundles
10701 		 * correctly.
10702 		 */
10703 		personalityBundleIdentifier = OSDynamicCast(OSString,
10704 		    personality->getObject(kCFBundleIdentifierKey));
10705 
10706 		if (!personalityBundleIdentifier) {
10707 			personality->setObject(kCFBundleIdentifierKey, bundleID);
10708 		} else if (!personalityBundleIdentifier->isEqualTo(bundleID)) {
10709 			personality->setObject(kIOPersonalityPublisherKey, bundleID);
10710 		}
10711 
10712 		result->setObject(personality);
10713 	}
10714 
10715 finish:
10716 	if (personalitiesIterator) {
10717 		personalitiesIterator->release();
10718 	}
10719 
10720 	return result;
10721 }
10722 
10723 /*********************************************************************
10724 *   Might want to change this to a bool return?
10725 *********************************************************************/
10726 OSReturn
10727 OSKext::sendPersonalitiesToCatalog(
10728 	bool      startMatching,
10729 	OSArray * personalityNames)
10730 {
10731 	OSReturn       result              = kOSReturnSuccess;
10732 	OSArray      * personalitiesToSend = NULL;// must release
10733 	OSDictionary * kextPersonalities   = NULL;// do not release
10734 	int            count, i;
10735 
10736 	if (!sLoadEnabled) {
10737 		OSKextLog(this,
10738 		    kOSKextLogErrorLevel |
10739 		    kOSKextLogLoadFlag,
10740 		    "Kext loading is disabled (attempt to start matching for kext %s).",
10741 		    getIdentifierCString());
10742 		result = kOSKextReturnDisabled;
10743 		goto finish;
10744 	}
10745 
10746 	if (sSafeBoot && !isLoadableInSafeBoot()) {
10747 		OSKextLog(this,
10748 		    kOSKextLogErrorLevel |
10749 		    kOSKextLogLoadFlag,
10750 		    "Kext %s is not loadable during safe boot; "
10751 		    "not sending personalities to the IOCatalogue.",
10752 		    getIdentifierCString());
10753 		result = kOSKextReturnNotLoadable;
10754 		goto finish;
10755 	}
10756 
10757 	if (!personalityNames || !personalityNames->getCount()) {
10758 		personalitiesToSend = copyPersonalitiesArray();
10759 	} else {
10760 		kextPersonalities = OSDynamicCast(OSDictionary,
10761 		    getPropertyForHostArch(kIOKitPersonalitiesKey));
10762 		if (!kextPersonalities || !kextPersonalities->getCount()) {
10763 			// not an error
10764 			goto finish;
10765 		}
10766 		personalitiesToSend = OSArray::withCapacity(0);
10767 		if (!personalitiesToSend) {
10768 			result = kOSKextReturnNoMemory;
10769 			goto finish;
10770 		}
10771 		count = personalityNames->getCount();
10772 		for (i = 0; i < count; i++) {
10773 			OSString * name = OSDynamicCast(OSString,
10774 			    personalityNames->getObject(i));
10775 			if (!name) {
10776 				continue;
10777 			}
10778 			OSDictionary * personality = OSDynamicCast(OSDictionary,
10779 			    kextPersonalities->getObject(name));
10780 			if (personality) {
10781 				personalitiesToSend->setObject(personality);
10782 			}
10783 		}
10784 	}
10785 	if (personalitiesToSend) {
10786 		unsigned numPersonalities = personalitiesToSend->getCount();
10787 		OSKextLog(this,
10788 		    kOSKextLogStepLevel |
10789 		    kOSKextLogLoadFlag,
10790 		    "Kext %s sending %d personalit%s to the IOCatalogue%s.",
10791 		    getIdentifierCString(),
10792 		    numPersonalities,
10793 		    numPersonalities > 1 ? "ies" : "y",
10794 		    startMatching ? " and starting matching" : " but not starting matching");
10795 		gIOCatalogue->addDrivers(personalitiesToSend, startMatching);
10796 	}
10797 finish:
10798 	if (personalitiesToSend) {
10799 		personalitiesToSend->release();
10800 	}
10801 	return result;
10802 }
10803 
10804 /*********************************************************************
10805 * xxx - We should allow removing the kext's declared personalities,
10806 * xxx - even with other bundle identifiers.
10807 *********************************************************************/
10808 void
10809 OSKext::removePersonalitiesFromCatalog(void)
10810 {
10811 	OSDictionary * personality = NULL; // do not release
10812 
10813 	personality = OSDictionary::withCapacity(1);
10814 	if (!personality) {
10815 		goto finish;
10816 	}
10817 	personality->setObject(kCFBundleIdentifierKey, getIdentifier());
10818 
10819 	OSKextLog(this,
10820 	    kOSKextLogStepLevel |
10821 	    kOSKextLogLoadFlag,
10822 	    "Kext %s removing all personalities naming it from the IOCatalogue.",
10823 	    getIdentifierCString());
10824 
10825 	/* Have the IOCatalog remove all personalities matching this kext's
10826 	 * bundle ID and trigger matching anew.
10827 	 */
10828 	gIOCatalogue->removeDrivers(personality, /* startMatching */ true);
10829 
10830 finish:
10831 	if (personality) {
10832 		personality->release();
10833 	}
10834 
10835 	return;
10836 }
10837 
10838 
10839 #if PRAGMA_MARK
10840 #pragma mark Logging
10841 #endif
10842 /*********************************************************************
10843 * Do not call any function that takes sKextLock here!
10844 *********************************************************************/
10845 /* static */
10846 OSKextLogSpec
10847 OSKext::setUserSpaceLogFilter(
10848 	OSKextLogSpec   newUserLogFilter,
10849 	bool            captureFlag)
10850 {
10851 	OSKextLogSpec result;
10852 	bool          allocError = false;
10853 
10854 	/* Do not call any function that takes sKextLoggingLock during
10855 	 * this critical block. That means do logging after.
10856 	 */
10857 	IOLockLock(sKextLoggingLock);
10858 
10859 	result = sUserSpaceKextLogFilter;
10860 	sUserSpaceKextLogFilter = newUserLogFilter;
10861 
10862 	if (newUserLogFilter && captureFlag &&
10863 	    !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
10864 		// xxx - do some measurements for a good initial capacity?
10865 		sUserSpaceLogSpecArray = OSArray::withCapacity(0);
10866 		sUserSpaceLogMessageArray = OSArray::withCapacity(0);
10867 
10868 		if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
10869 			OSSafeReleaseNULL(sUserSpaceLogSpecArray);
10870 			OSSafeReleaseNULL(sUserSpaceLogMessageArray);
10871 			allocError = true;
10872 		}
10873 	}
10874 
10875 	IOLockUnlock(sKextLoggingLock);
10876 
10877 	/* If the config flag itself is changing, log the state change
10878 	 * going both ways, before setting up the user-space log arrays,
10879 	 * so that this is only logged in the kernel.
10880 	 */
10881 	if (result != newUserLogFilter) {
10882 		OSKextLog(/* kext */ NULL,
10883 		    kOSKextLogDebugLevel |
10884 		    kOSKextLogGeneralFlag,
10885 		    "User-space log flags changed from 0x%x to 0x%x.",
10886 		    result, newUserLogFilter);
10887 	}
10888 	if (allocError) {
10889 		OSKextLog(/* kext */ NULL,
10890 		    kOSKextLogErrorLevel |
10891 		    kOSKextLogGeneralFlag,
10892 		    "Failed to allocate user-space log message arrays.");
10893 	}
10894 
10895 	return result;
10896 }
10897 
10898 /*********************************************************************
10899 * Do not call any function that takes sKextLock here!
10900 *********************************************************************/
10901 /* static */
10902 OSArray *
10903 OSKext::clearUserSpaceLogFilter(void)
10904 {
10905 	OSArray       * result       = NULL;
10906 	OSKextLogSpec   oldLogFilter;
10907 	OSKextLogSpec   newLogFilter = kOSKextLogSilentFilter;
10908 
10909 	/* Do not call any function that takes sKextLoggingLock during
10910 	 * this critical block. That means do logging after.
10911 	 */
10912 	IOLockLock(sKextLoggingLock);
10913 
10914 	result = OSArray::withCapacity(2);
10915 	if (result) {
10916 		result->setObject(sUserSpaceLogSpecArray);
10917 		result->setObject(sUserSpaceLogMessageArray);
10918 	}
10919 	OSSafeReleaseNULL(sUserSpaceLogSpecArray);
10920 	OSSafeReleaseNULL(sUserSpaceLogMessageArray);
10921 
10922 	oldLogFilter = sUserSpaceKextLogFilter;
10923 	sUserSpaceKextLogFilter = newLogFilter;
10924 
10925 	IOLockUnlock(sKextLoggingLock);
10926 
10927 	/* If the config flag itself is changing, log the state change
10928 	 * going both ways, after tearing down the user-space log
10929 	 * arrays, so this is only logged within the kernel.
10930 	 */
10931 	if (oldLogFilter != newLogFilter) {
10932 		OSKextLog(/* kext */ NULL,
10933 		    kOSKextLogDebugLevel |
10934 		    kOSKextLogGeneralFlag,
10935 		    "User-space log flags changed from 0x%x to 0x%x.",
10936 		    oldLogFilter, newLogFilter);
10937 	}
10938 
10939 	return result;
10940 }
10941 
10942 
10943 /*********************************************************************
10944 * Do not call any function that takes sKextLock here!
10945 *********************************************************************/
10946 /* static */
10947 OSKextLogSpec
10948 OSKext::getUserSpaceLogFilter(void)
10949 {
10950 	OSKextLogSpec result;
10951 
10952 	IOLockLock(sKextLoggingLock);
10953 	result = sUserSpaceKextLogFilter;
10954 	IOLockUnlock(sKextLoggingLock);
10955 
10956 	return result;
10957 }
10958 
10959 /*********************************************************************
10960 * This function is called by OSMetaClass during kernel C++ setup.
10961 * Be careful what you access here; assume only OSKext::initialize()
10962 * has been called.
10963 *
10964 * Do not call any function that takes sKextLock here!
10965 *********************************************************************/
10966 #define VTRESET   "\033[0m"
10967 
10968 #define VTBOLD    "\033[1m"
10969 #define VTUNDER   "\033[4m"
10970 
10971 #define VTRED     "\033[31m"
10972 #define VTGREEN   "\033[32m"
10973 #define VTYELLOW  "\033[33m"
10974 #define VTBLUE    "\033[34m"
10975 #define VTMAGENTA "\033[35m"
10976 #define VTCYAN    "\033[36m"
10977 
10978 inline const char *
10979 colorForFlags(OSKextLogSpec flags)
10980 {
10981 	OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
10982 
10983 	switch (logLevel) {
10984 	case kOSKextLogErrorLevel:
10985 		return VTRED VTBOLD;
10986 	case kOSKextLogWarningLevel:
10987 		return VTRED;
10988 	case kOSKextLogBasicLevel:
10989 		return VTYELLOW VTUNDER;
10990 	case kOSKextLogProgressLevel:
10991 		return VTYELLOW;
10992 	case kOSKextLogStepLevel:
10993 		return VTGREEN;
10994 	case kOSKextLogDetailLevel:
10995 		return VTCYAN;
10996 	case kOSKextLogDebugLevel:
10997 		return VTMAGENTA;
10998 	default:
10999 		return ""; // white
11000 	}
11001 }
11002 
11003 inline bool
11004 logSpecMatch(
11005 	OSKextLogSpec msgLogSpec,
11006 	OSKextLogSpec logFilter)
11007 {
11008 	OSKextLogSpec filterKextGlobal  = logFilter & kOSKextLogKextOrGlobalMask;
11009 	OSKextLogSpec filterLevel       = logFilter & kOSKextLogLevelMask;
11010 	OSKextLogSpec filterFlags       = logFilter & kOSKextLogFlagsMask;
11011 
11012 	OSKextLogSpec msgKextGlobal    = msgLogSpec & kOSKextLogKextOrGlobalMask;
11013 	OSKextLogSpec msgLevel         = msgLogSpec & kOSKextLogLevelMask;
11014 	OSKextLogSpec msgFlags         = msgLogSpec & kOSKextLogFlagsMask;
11015 
11016 	/* Explicit messages always get logged.
11017 	 */
11018 	if (msgLevel == kOSKextLogExplicitLevel) {
11019 		return true;
11020 	}
11021 
11022 	/* Warnings and errors are logged regardless of the flags.
11023 	 */
11024 	if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
11025 		return true;
11026 	}
11027 
11028 	/* A verbose message that isn't for a logging-enabled kext and isn't global
11029 	 * does *not* get logged.
11030 	 */
11031 	if (!msgKextGlobal && !filterKextGlobal) {
11032 		return false;
11033 	}
11034 
11035 	/* Warnings and errors are logged regardless of the flags.
11036 	 * All other messages must fit the flags and
11037 	 * have a level at or below the filter.
11038 	 *
11039 	 */
11040 	if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
11041 		return true;
11042 	}
11043 	return false;
11044 }
11045 
11046 extern "C" {
11047 void
11048 OSKextLog(
11049 	OSKext         * aKext,
11050 	OSKextLogSpec    msgLogSpec,
11051 	const char     * format, ...)
11052 {
11053 	va_list argList;
11054 
11055 	va_start(argList, format);
11056 	OSKextVLog(aKext, msgLogSpec, format, argList);
11057 	va_end(argList);
11058 }
11059 
11060 void
11061 OSKextVLog(
11062 	OSKext         * aKext,
11063 	OSKextLogSpec    msgLogSpec,
11064 	const char     * format,
11065 	va_list          srcArgList)
11066 {
11067 	extern int       disableConsoleOutput;
11068 
11069 	bool             logForKernel       = false;
11070 	bool             logForUser         = false;
11071 	va_list          argList;
11072 	char             stackBuffer[120];
11073 	uint32_t         length            = 0;
11074 	char           * allocBuffer       = NULL;     // must kfree
11075 	OSNumber       * logSpecNum        = NULL;     // must release
11076 	OSString       * logString         = NULL;     // must release
11077 	char           * buffer            = stackBuffer;// do not free
11078 
11079 	IOLockLock(sKextLoggingLock);
11080 
11081 	/* Set the kext/global bit in the message spec if we have no
11082 	 * kext or if the kext requests logging.
11083 	 */
11084 	if (!aKext || aKext->flags.loggingEnabled) {
11085 		msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
11086 	}
11087 
11088 	logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
11089 	if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
11090 		logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
11091 	}
11092 
11093 	if (!(logForKernel || logForUser)) {
11094 		goto finish;
11095 	}
11096 
11097 	/* No goto from here until past va_end()!
11098 	 */
11099 	va_copy(argList, srcArgList);
11100 	length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
11101 	va_end(argList);
11102 
11103 	if (length + 1 >= sizeof(stackBuffer)) {
11104 		allocBuffer = (char *)kalloc_tag((length + 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT);
11105 		if (!allocBuffer) {
11106 			goto finish;
11107 		}
11108 
11109 		/* No goto from here until past va_end()!
11110 		 */
11111 		va_copy(argList, srcArgList);
11112 		vsnprintf(allocBuffer, length + 1, format, argList);
11113 		va_end(argList);
11114 
11115 		buffer = allocBuffer;
11116 	}
11117 
11118 	/* If user space wants the log message, queue it up.
11119 	 */
11120 	if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
11121 		logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
11122 		logString = OSString::withCString(buffer);
11123 		if (logSpecNum && logString) {
11124 			sUserSpaceLogSpecArray->setObject(logSpecNum);
11125 			sUserSpaceLogMessageArray->setObject(logString);
11126 		}
11127 	}
11128 
11129 	/* Always log messages from the kernel according to the kernel's
11130 	 * log flags.
11131 	 */
11132 	if (logForKernel) {
11133 		/* If we are in console mode and have a custom log filter,
11134 		 * colorize the log message.
11135 		 */
11136 		if (!disableConsoleOutput && sBootArgLogFilterFound) {
11137 			const char * color = ""; // do not free
11138 			color = colorForFlags(msgLogSpec);
11139 			printf("%s%s%s\n", colorForFlags(msgLogSpec),
11140 			    buffer, color[0] ? VTRESET : "");
11141 		} else {
11142 			printf("%s\n", buffer);
11143 		}
11144 	}
11145 
11146 finish:
11147 	IOLockUnlock(sKextLoggingLock);
11148 
11149 	if (allocBuffer) {
11150 		kfree(allocBuffer, (length + 1) * sizeof(char));
11151 	}
11152 	OSSafeReleaseNULL(logString);
11153 	OSSafeReleaseNULL(logSpecNum);
11154 	return;
11155 }
11156 
11157 #if KASLR_IOREG_DEBUG
11158 
11159 #define IOLOG_INDENT( the_indention ) \
11160 { \
11161     int     i; \
11162     for ( i = 0; i < (the_indention); i++ ) { \
11163 	IOLog(" "); \
11164     } \
11165 }
11166 
11167 extern vm_offset_t       vm_kernel_stext;
11168 extern vm_offset_t       vm_kernel_etext;
11169 extern mach_vm_offset_t kext_alloc_base;
11170 extern mach_vm_offset_t kext_alloc_max;
11171 
11172 bool ScanForAddrInObject(OSObject * theObject,
11173     int indent );
11174 
11175 bool
11176 ScanForAddrInObject(OSObject * theObject,
11177     int indent)
11178 {
11179 	const OSMetaClass *     myTypeID;
11180 	OSCollectionIterator *  myIter;
11181 	OSSymbol *              myKey;
11182 	OSObject *              myValue;
11183 	bool                    myResult = false;
11184 
11185 	if (theObject == NULL) {
11186 		IOLog("%s: theObject is NULL \n",
11187 		    __FUNCTION__);
11188 		return myResult;
11189 	}
11190 
11191 	myTypeID = OSTypeIDInst(theObject);
11192 
11193 	if (myTypeID == OSTypeID(OSDictionary)) {
11194 		OSDictionary *      myDictionary;
11195 
11196 		myDictionary = OSDynamicCast(OSDictionary, theObject);
11197 		myIter = OSCollectionIterator::withCollection( myDictionary );
11198 		if (myIter == NULL) {
11199 			return myResult;
11200 		}
11201 		myIter->reset();
11202 
11203 		while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
11204 			bool    myTempResult;
11205 
11206 			myValue = myDictionary->getObject(myKey);
11207 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
11208 			if (myTempResult) {
11209 				// if we ever get a true result return true
11210 				myResult = true;
11211 				IOLOG_INDENT(indent);
11212 				IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
11213 			}
11214 		}
11215 		myIter->release();
11216 	} else if (myTypeID == OSTypeID(OSArray)) {
11217 		OSArray *   myArray;
11218 
11219 		myArray = OSDynamicCast(OSArray, theObject);
11220 		myIter = OSCollectionIterator::withCollection(myArray);
11221 		if (myIter == NULL) {
11222 			return myResult;
11223 		}
11224 		myIter->reset();
11225 
11226 		while ((myValue = myIter->getNextObject())) {
11227 			bool        myTempResult;
11228 			myTempResult = ScanForAddrInObject(myValue, (indent + 4));
11229 			if (myTempResult) {
11230 				// if we ever get a true result return true
11231 				myResult = true;
11232 				IOLOG_INDENT(indent);
11233 				IOLog("OSArray: \n");
11234 			}
11235 		}
11236 		myIter->release();
11237 	} else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
11238 		// should we look for addresses in strings?
11239 	} else if (myTypeID == OSTypeID(OSData)) {
11240 		void * *        myPtrPtr;
11241 		unsigned int    myLen;
11242 		OSData *        myDataObj;
11243 
11244 		myDataObj =    OSDynamicCast(OSData, theObject);
11245 		myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
11246 		myLen = myDataObj->getLength();
11247 
11248 		if (myPtrPtr && myLen && myLen > 7) {
11249 			int     i;
11250 			int     myPtrCount = (myLen / sizeof(void *));
11251 
11252 			for (i = 0; i < myPtrCount; i++) {
11253 				UInt64 numberValue = (UInt64) * (myPtrPtr);
11254 
11255 				if (kext_alloc_max != 0 &&
11256 				    numberValue >= kext_alloc_base &&
11257 				    numberValue < kext_alloc_max) {
11258 					OSKext * myKext    = NULL;// must release (looked up)
11259 					                          // IOLog("found OSData %p in kext map %p to %p  \n",
11260 					                          //       *(myPtrPtr),
11261 					                          //       (void *) kext_alloc_base,
11262 					                          //       (void *) kext_alloc_max);
11263 
11264 					myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
11265 					if (myKext) {
11266 						IOLog("found addr %p from an OSData obj within kext \"%s\"  \n",
11267 						    *(myPtrPtr),
11268 						    myKext->getIdentifierCString());
11269 						myKext->release();
11270 					}
11271 					myResult = true;
11272 				}
11273 				if (vm_kernel_etext != 0 &&
11274 				    numberValue >= vm_kernel_stext &&
11275 				    numberValue < vm_kernel_etext) {
11276 					IOLog("found addr %p from an OSData obj within kernel text segment %p to %p  \n",
11277 					    *(myPtrPtr),
11278 					    (void *) vm_kernel_stext,
11279 					    (void *) vm_kernel_etext);
11280 					myResult = true;
11281 				}
11282 				myPtrPtr++;
11283 			}
11284 		}
11285 	} else if (myTypeID == OSTypeID(OSBoolean)) {
11286 		// do nothing here...
11287 	} else if (myTypeID == OSTypeID(OSNumber)) {
11288 		OSNumber * number = OSDynamicCast(OSNumber, theObject);
11289 
11290 		UInt64 numberValue = number->unsigned64BitValue();
11291 
11292 		if (kext_alloc_max != 0 &&
11293 		    numberValue >= kext_alloc_base &&
11294 		    numberValue < kext_alloc_max) {
11295 			OSKext * myKext    = NULL;// must release (looked up)
11296 			IOLog("found OSNumber in kext map %p to %p  \n",
11297 			    (void *) kext_alloc_base,
11298 			    (void *) kext_alloc_max);
11299 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
11300 
11301 			myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
11302 			if (myKext) {
11303 				IOLog("found in kext \"%s\"  \n",
11304 				    myKext->getIdentifierCString());
11305 				myKext->release();
11306 			}
11307 
11308 			myResult = true;
11309 		}
11310 		if (vm_kernel_etext != 0 &&
11311 		    numberValue >= vm_kernel_stext &&
11312 		    numberValue < vm_kernel_etext) {
11313 			IOLog("found OSNumber in kernel text segment %p to %p  \n",
11314 			    (void *) vm_kernel_stext,
11315 			    (void *) vm_kernel_etext);
11316 			IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
11317 			myResult = true;
11318 		}
11319 	}
11320 #if 0
11321 	else {
11322 		const OSMetaClass* myMetaClass = NULL;
11323 
11324 		myMetaClass = theObject->getMetaClass();
11325 		if (myMetaClass) {
11326 			IOLog("class %s \n", myMetaClass->getClassName());
11327 		} else {
11328 			IOLog("Unknown object \n" );
11329 		}
11330 	}
11331 #endif
11332 
11333 	return myResult;
11334 }
11335 #endif // KASLR_KEXT_DEBUG
11336 }; /* extern "C" */
11337 
11338 #if PRAGMA_MARK
11339 #pragma mark Backtrace Dump & kmod_get_info() support
11340 #endif
11341 /*********************************************************************
11342 * This function must be safe to call in panic context.
11343 *********************************************************************/
11344 /* static */
11345 void
11346 OSKext::printKextsInBacktrace(
11347 	vm_offset_t  * addr __unused,
11348 	unsigned int   cnt __unused,
11349 	int         (* printf_func)(const char *fmt, ...) __unused,
11350 	uint32_t       flags __unused)
11351 {
11352 	addr64_t    summary_page = 0;
11353 	addr64_t    last_summary_page = 0;
11354 	bool        found_kmod = false;
11355 	u_int       i = 0;
11356 
11357 	if (kPrintKextsLock & flags) {
11358 		if (!sKextSummariesLock) {
11359 			return;
11360 		}
11361 		IOLockLock(sKextSummariesLock);
11362 	}
11363 
11364 	if (!gLoadedKextSummaries) {
11365 		(*printf_func)("         can't perform kext scan: no kext summary");
11366 		goto finish;
11367 	}
11368 
11369 	summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
11370 	last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
11371 	for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
11372 		if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
11373 			(*printf_func)("         can't perform kext scan: "
11374 			    "missing kext summary page %p", summary_page);
11375 			goto finish;
11376 		}
11377 	}
11378 
11379 	for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
11380 		OSKextLoadedKextSummary * summary;
11381 
11382 		summary = gLoadedKextSummaries->summaries + i;
11383 		if (!summary->address) {
11384 			continue;
11385 		}
11386 
11387 		if (!summaryIsInBacktrace(summary, addr, cnt)) {
11388 			continue;
11389 		}
11390 
11391 		if (!found_kmod) {
11392 			if (!(kPrintKextsTerse & flags)) {
11393 				(*printf_func)("      Kernel Extensions in backtrace:\n");
11394 			}
11395 			found_kmod = true;
11396 		}
11397 
11398 		printSummary(summary, printf_func, flags);
11399 	}
11400 
11401 finish:
11402 	if (kPrintKextsLock & flags) {
11403 		IOLockUnlock(sKextSummariesLock);
11404 	}
11405 
11406 	return;
11407 }
11408 
11409 /*********************************************************************
11410 * This function must be safe to call in panic context.
11411 *********************************************************************/
11412 /* static */
11413 boolean_t
11414 OSKext::summaryIsInBacktrace(
11415 	OSKextLoadedKextSummary   * summary,
11416 	vm_offset_t               * addr,
11417 	unsigned int                cnt)
11418 {
11419 	u_int i = 0;
11420 
11421 	for (i = 0; i < cnt; i++) {
11422 		vm_offset_t kscan_addr = addr[i];
11423 		if ((kscan_addr >= summary->address) &&
11424 		    (kscan_addr < (summary->address + summary->size))) {
11425 			return TRUE;
11426 		}
11427 	}
11428 
11429 	return FALSE;
11430 }
11431 
11432 /*
11433  * Get the kext summary object for the kext where 'addr' lies. Must be called with
11434  * sKextSummariesLock held.
11435  */
11436 OSKextLoadedKextSummary *
11437 OSKext::summaryForAddress(const uintptr_t addr)
11438 {
11439 	for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
11440 		OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
11441 		if (!summary->address) {
11442 			continue;
11443 		}
11444 
11445 #if VM_MAPPED_KEXTS
11446 		/* On our platforms that use VM_MAPPED_KEXTS, we currently do not
11447 		 * support split kexts, but we also may unmap the kexts, which can
11448 		 * race with the above codepath (see OSKext::unload).  As such,
11449 		 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
11450 		 */
11451 		if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
11452 			return summary;
11453 		}
11454 #else
11455 		kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
11456 		kernel_segment_command_t *seg;
11457 
11458 		for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
11459 			if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
11460 				return summary;
11461 			}
11462 		}
11463 #endif
11464 	}
11465 
11466 	/* addr did not map to any kext */
11467 	return NULL;
11468 }
11469 
11470 /* static */
11471 void *
11472 OSKext::kextForAddress(const void *address)
11473 {
11474 	void                * image = NULL;
11475 	OSKextActiveAccount * active;
11476 	OSKext              * kext = NULL;
11477 	uint32_t              baseIdx;
11478 	uint32_t              lim;
11479 	uintptr_t             addr = (uintptr_t) address;
11480 
11481 	if (!addr) {
11482 		return NULL;
11483 	}
11484 
11485 	if (sKextAccountsCount) {
11486 		IOSimpleLockLock(sKextAccountsLock);
11487 		// bsearch sKextAccounts list
11488 		for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
11489 			active = &sKextAccounts[baseIdx + (lim >> 1)];
11490 			if ((addr >= active->address) && (addr < active->address_end)) {
11491 				kext = active->account->kext;
11492 				if (kext && kext->kmod_info) {
11493 					image = (void *) kext->kmod_info->address;
11494 				}
11495 				break;
11496 			} else if (addr > active->address) {
11497 				// move right
11498 				baseIdx += (lim >> 1) + 1;
11499 				lim--;
11500 			}
11501 			// else move left
11502 		}
11503 		IOSimpleLockUnlock(sKextAccountsLock);
11504 	}
11505 	if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) {
11506 		image = (void *) &_mh_execute_header;
11507 	}
11508 
11509 	return image;
11510 }
11511 
11512 /*********************************************************************
11513 * scan list of loaded kext summaries looking for a load address match and if
11514 * found return the UUID C string.  If not found then set empty string.
11515 *********************************************************************/
11516 static void findSummaryUUID(
11517 	uint32_t        tag_ID,
11518 	uuid_string_t   uuid);
11519 
11520 static void
11521 findSummaryUUID(
11522 	uint32_t        tag_ID,
11523 	uuid_string_t   uuid)
11524 {
11525 	u_int     i;
11526 
11527 	uuid[0] = 0x00; // default to no UUID
11528 
11529 	for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
11530 		OSKextLoadedKextSummary * summary;
11531 
11532 		summary = gLoadedKextSummaries->summaries + i;
11533 
11534 		if (summary->loadTag == tag_ID) {
11535 			(void) uuid_unparse(summary->uuid, uuid);
11536 			break;
11537 		}
11538 	}
11539 	return;
11540 }
11541 
11542 /*********************************************************************
11543 * This function must be safe to call in panic context.
11544 *********************************************************************/
11545 void
11546 OSKext::printSummary(
11547 	OSKextLoadedKextSummary * summary,
11548 	int                    (* printf_func)(const char *fmt, ...),
11549 	uint32_t                  flags)
11550 {
11551 	kmod_reference_t * kmod_ref = NULL;
11552 	uuid_string_t uuid;
11553 	char version[kOSKextVersionMaxLength];
11554 	uint64_t tmpAddr;
11555 
11556 	if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
11557 		strlcpy(version, "unknown version", sizeof(version));
11558 	}
11559 	(void) uuid_unparse(summary->uuid, uuid);
11560 
11561 	if (kPrintKextsUnslide & flags) {
11562 		tmpAddr = ml_static_unslide(summary->address);
11563 	} else {
11564 		tmpAddr = summary->address;
11565 	}
11566 	(*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
11567 	    (kPrintKextsTerse & flags) ? "" : "         ",
11568 	    summary->name, version, uuid,
11569 	    tmpAddr, tmpAddr + summary->size - 1);
11570 
11571 	if (kPrintKextsTerse & flags) {
11572 		return;
11573 	}
11574 
11575 	/* print dependency info */
11576 	for (kmod_ref = (kmod_reference_t *) summary->reference_list;
11577 	    kmod_ref;
11578 	    kmod_ref = kmod_ref->next) {
11579 		kmod_info_t * rinfo;
11580 
11581 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
11582 			(*printf_func)("            kmod dependency scan stopped "
11583 			    "due to missing dependency page: %p\n",
11584 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
11585 			break;
11586 		}
11587 		rinfo = kmod_ref->info;
11588 
11589 		if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
11590 			(*printf_func)("            kmod dependency scan stopped "
11591 			    "due to missing kmod page: %p\n",
11592 			    (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
11593 			break;
11594 		}
11595 
11596 		if (!rinfo->address) {
11597 			continue; // skip fake entries for built-ins
11598 		}
11599 
11600 		/* locate UUID in gLoadedKextSummaries */
11601 		findSummaryUUID(rinfo->id, uuid);
11602 
11603 		if (kPrintKextsUnslide & flags) {
11604 			tmpAddr = ml_static_unslide(rinfo->address);
11605 		} else {
11606 			tmpAddr = rinfo->address;
11607 		}
11608 		(*printf_func)("            dependency: %s(%s)[%s]@%p\n",
11609 		    rinfo->name, rinfo->version, uuid, tmpAddr);
11610 	}
11611 	return;
11612 }
11613 
11614 
11615 /*******************************************************************************
11616 * substitute() looks at an input string (a pointer within a larger buffer)
11617 * for a match to a substring, and on match it writes the marker & substitution
11618 * character to an output string, updating the scan (from) and
11619 * output (to) indexes as appropriate.
11620 *******************************************************************************/
11621 static int substitute(
11622 	const char * scan_string,
11623 	char       * string_out,
11624 	uint32_t   * to_index,
11625 	uint32_t   * from_index,
11626 	const char * substring,
11627 	char         marker,
11628 	char         substitution);
11629 
11630 /* string_out must be at least KMOD_MAX_NAME bytes.
11631  */
11632 static int
11633 substitute(
11634 	const char * scan_string,
11635 	char       * string_out,
11636 	uint32_t   * to_index,
11637 	uint32_t   * from_index,
11638 	const char * substring,
11639 	char         marker,
11640 	char         substitution)
11641 {
11642 	uint32_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
11643 
11644 	/* On a substring match, append the marker (if there is one) and then
11645 	 * the substitution character, updating the output (to) index accordingly.
11646 	 * Then update the input (from) length by the length of the substring
11647 	 * that got replaced.
11648 	 */
11649 	if (!strncmp(scan_string, substring, substring_length)) {
11650 		if (marker) {
11651 			string_out[(*to_index)++] = marker;
11652 		}
11653 		string_out[(*to_index)++] = substitution;
11654 		(*from_index) += substring_length;
11655 		return 1;
11656 	}
11657 	return 0;
11658 }
11659 
11660 /*******************************************************************************
11661 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
11662 * KMOD_MAX_NAME characters and performs various substitutions of common
11663 * prefixes & substrings as defined by tables in kext_panic_report.h.
11664 *******************************************************************************/
11665 static void compactIdentifier(
11666 	const char * identifier,
11667 	char       * identifier_out,
11668 	char      ** identifier_out_end);
11669 
11670 static void
11671 compactIdentifier(
11672 	const char * identifier,
11673 	char       * identifier_out,
11674 	char      ** identifier_out_end)
11675 {
11676 	uint32_t       from_index, to_index;
11677 	uint32_t       scan_from_index = 0;
11678 	uint32_t       scan_to_index   = 0;
11679 	subs_entry_t * subs_entry    = NULL;
11680 	int            did_sub       = 0;
11681 
11682 	from_index = to_index = 0;
11683 	identifier_out[0] = '\0';
11684 
11685 	/* Replace certain identifier prefixes with shorter @+character sequences.
11686 	 * Check the return value of substitute() so we only replace the prefix.
11687 	 */
11688 	for (subs_entry = &kext_identifier_prefix_subs[0];
11689 	    subs_entry->substring && !did_sub;
11690 	    subs_entry++) {
11691 		did_sub = substitute(identifier, identifier_out,
11692 		    &scan_to_index, &scan_from_index,
11693 		    subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
11694 	}
11695 	did_sub = 0;
11696 
11697 	/* Now scan through the identifier looking for the common substrings
11698 	 * and replacing them with shorter !+character sequences via substitute().
11699 	 */
11700 	for (/* see above */;
11701 	    scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
11702 	    /* see loop */) {
11703 		const char   * scan_string = &identifier[scan_from_index];
11704 
11705 		did_sub = 0;
11706 
11707 		if (scan_from_index) {
11708 			for (subs_entry = &kext_identifier_substring_subs[0];
11709 			    subs_entry->substring && !did_sub;
11710 			    subs_entry++) {
11711 				did_sub = substitute(scan_string, identifier_out,
11712 				    &scan_to_index, &scan_from_index,
11713 				    subs_entry->substring, '!', subs_entry->substitute);
11714 			}
11715 		}
11716 
11717 		/* If we didn't substitute, copy the input character to the output.
11718 		 */
11719 		if (!did_sub) {
11720 			identifier_out[scan_to_index++] = identifier[scan_from_index++];
11721 		}
11722 	}
11723 
11724 	identifier_out[scan_to_index] = '\0';
11725 	if (identifier_out_end) {
11726 		*identifier_out_end = &identifier_out[scan_to_index];
11727 	}
11728 
11729 	return;
11730 }
11731 
11732 /*******************************************************************************
11733 * assemble_identifier_and_version() adds to a string buffer a compacted
11734 * bundle identifier followed by a version string.
11735 *******************************************************************************/
11736 
11737 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
11738  */
11739 static int assemble_identifier_and_version(
11740 	kmod_info_t * kmod_info,
11741 	char        * identPlusVers,
11742 	int           bufSize);
11743 
11744 static int
11745 assemble_identifier_and_version(
11746 	kmod_info_t * kmod_info,
11747 	char        * identPlusVers,
11748 	int           bufSize)
11749 {
11750 	int result = 0;
11751 
11752 	compactIdentifier(kmod_info->name, identPlusVers, NULL);
11753 	result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
11754 	identPlusVers[result++] = '\t'; // increment for real char
11755 	identPlusVers[result] = '\0'; // don't increment for nul char
11756 	result = strlcat(identPlusVers, kmod_info->version, bufSize);
11757 	if (result >= bufSize) {
11758 		identPlusVers[bufSize - 1] = '\0';
11759 		result = bufSize - 1;
11760 	}
11761 
11762 	return result;
11763 }
11764 
11765 /*******************************************************************************
11766 * Assumes sKextLock is held.
11767 *******************************************************************************/
11768 /* static */
11769 int
11770 OSKext::saveLoadedKextPanicListTyped(
11771 	const char * prefix,
11772 	int          invertFlag,
11773 	int          libsFlag,
11774 	char       * paniclist,
11775 	uint32_t     list_size)
11776 {
11777 	int             result = -1;
11778 	unsigned int    count, i;
11779 
11780 	count = sLoadedKexts->getCount();
11781 	if (!count) {
11782 		goto finish;
11783 	}
11784 
11785 	i = count - 1;
11786 	do {
11787 		OSObject    * rawKext = sLoadedKexts->getObject(i);
11788 		OSKext      * theKext = OSDynamicCast(OSKext, rawKext);
11789 		int           match;
11790 		uint32_t      identPlusVersLength;
11791 		uint32_t      tempLen;
11792 		char          identPlusVers[2 * KMOD_MAX_NAME];
11793 
11794 		if (!rawKext) {
11795 			printf("OSKext::saveLoadedKextPanicListTyped - "
11796 			    "NULL kext in loaded kext list; continuing\n");
11797 			continue;
11798 		}
11799 
11800 		if (!theKext) {
11801 			printf("OSKext::saveLoadedKextPanicListTyped - "
11802 			    "Kext type cast failed in loaded kext list; continuing\n");
11803 			continue;
11804 		}
11805 
11806 		/* Skip all built-in kexts.
11807 		 */
11808 		if (theKext->isKernelComponent()) {
11809 			continue;
11810 		}
11811 
11812 		kmod_info_t * kmod_info = theKext->kmod_info;
11813 
11814 		/* Filter for kmod name (bundle identifier).
11815 		 */
11816 		match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
11817 		if ((match && invertFlag) || (!match && !invertFlag)) {
11818 			continue;
11819 		}
11820 
11821 		/* Filter for libraries (kexts that have a compatible version).
11822 		 */
11823 		if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
11824 		    (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
11825 			continue;
11826 		}
11827 
11828 		if (!kmod_info ||
11829 		    !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
11830 			printf("kext scan stopped due to missing kmod_info page: %p\n",
11831 			    kmod_info);
11832 			goto finish;
11833 		}
11834 
11835 		identPlusVersLength = assemble_identifier_and_version(kmod_info,
11836 		    identPlusVers,
11837 		    sizeof(identPlusVers));
11838 		if (!identPlusVersLength) {
11839 			printf("error saving loaded kext info\n");
11840 			goto finish;
11841 		}
11842 
11843 		/* make sure everything fits and we null terminate.
11844 		 */
11845 		tempLen = strlcat(paniclist, identPlusVers, list_size);
11846 		if (tempLen >= list_size) {
11847 			// panic list is full, keep it and null terminate
11848 			paniclist[list_size - 1] = 0x00;
11849 			result = 0;
11850 			goto finish;
11851 		}
11852 		tempLen = strlcat(paniclist, "\n", list_size);
11853 		if (tempLen >= list_size) {
11854 			// panic list is full, keep it and null terminate
11855 			paniclist[list_size - 1] = 0x00;
11856 			result = 0;
11857 			goto finish;
11858 		}
11859 	} while (i--);
11860 
11861 	result = 0;
11862 finish:
11863 
11864 	return result;
11865 }
11866 
11867 /*********************************************************************
11868 *********************************************************************/
11869 /* static */
11870 void
11871 OSKext::saveLoadedKextPanicList(void)
11872 {
11873 	char     * newlist        = NULL;
11874 	uint32_t   newlist_size   = 0;
11875 
11876 	newlist_size = KEXT_PANICLIST_SIZE;
11877 	newlist = (char *)kalloc_tag(newlist_size, VM_KERN_MEMORY_OSKEXT);
11878 
11879 	if (!newlist) {
11880 		OSKextLog(/* kext */ NULL,
11881 		    kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
11882 		    "Couldn't allocate kext panic log buffer.");
11883 		goto finish;
11884 	}
11885 
11886 	newlist[0] = '\0';
11887 
11888 	// non-"com.apple." kexts
11889 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
11890 	    /* libs? */ -1, newlist, newlist_size) != 0) {
11891 		goto finish;
11892 	}
11893 	// "com.apple." nonlibrary kexts
11894 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11895 	    /* libs? */ 0, newlist, newlist_size) != 0) {
11896 		goto finish;
11897 	}
11898 	// "com.apple." library kexts
11899 	if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11900 	    /* libs? */ 1, newlist, newlist_size) != 0) {
11901 		goto finish;
11902 	}
11903 
11904 	if (loaded_kext_paniclist) {
11905 		kfree(loaded_kext_paniclist, loaded_kext_paniclist_size);
11906 	}
11907 	loaded_kext_paniclist = newlist;
11908 	newlist = NULL;
11909 	loaded_kext_paniclist_size = newlist_size;
11910 
11911 finish:
11912 	if (newlist) {
11913 		kfree(newlist, newlist_size);
11914 	}
11915 	return;
11916 }
11917 
11918 /*********************************************************************
11919 * Assumes sKextLock is held.
11920 *********************************************************************/
11921 void
11922 OSKext::savePanicString(bool isLoading)
11923 {
11924 	u_long len;
11925 
11926 	if (!kmod_info) {
11927 		return; // do not goto finish here b/c of lock
11928 	}
11929 
11930 	len = assemble_identifier_and_version( kmod_info,
11931 	    (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
11932 	    (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
11933 	if (!len) {
11934 		printf("error saving unloaded kext info\n");
11935 		goto finish;
11936 	}
11937 
11938 	if (isLoading) {
11939 		last_loaded_strlen = len;
11940 		last_loaded_address = (void *)kmod_info->address;
11941 		last_loaded_size = kmod_info->size;
11942 		clock_get_uptime(&last_loaded_timestamp);
11943 	} else {
11944 		last_unloaded_strlen = len;
11945 		last_unloaded_address = (void *)kmod_info->address;
11946 		last_unloaded_size = kmod_info->size;
11947 		clock_get_uptime(&last_unloaded_timestamp);
11948 	}
11949 
11950 finish:
11951 	return;
11952 }
11953 
11954 /*********************************************************************
11955 *********************************************************************/
11956 /* static */
11957 void
11958 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
11959 {
11960 	if (last_loaded_strlen) {
11961 		printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
11962 		    AbsoluteTime_to_scalar(&last_loaded_timestamp),
11963 		    last_loaded_strlen, last_loaded_str_buf,
11964 		    last_loaded_address, last_loaded_size);
11965 	}
11966 
11967 	if (last_unloaded_strlen) {
11968 		printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
11969 		    AbsoluteTime_to_scalar(&last_unloaded_timestamp),
11970 		    last_unloaded_strlen, last_unloaded_str_buf,
11971 		    last_unloaded_address, last_unloaded_size);
11972 	}
11973 
11974 	printf_func("loaded kexts:\n");
11975 	if (loaded_kext_paniclist &&
11976 	    pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
11977 	    loaded_kext_paniclist[0]) {
11978 		printf_func("%.*s",
11979 		    strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
11980 		    loaded_kext_paniclist);
11981 	} else {
11982 		printf_func("(none)\n");
11983 	}
11984 	return;
11985 }
11986 
11987 /*********************************************************************
11988 * Assumes sKextLock is held.
11989 *********************************************************************/
11990 /* static */
11991 void
11992 OSKext::updateLoadedKextSummaries(void)
11993 {
11994 	kern_return_t result = KERN_FAILURE;
11995 	OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
11996 	OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
11997 	OSKext *aKext;
11998 	vm_map_offset_t start, end;
11999 	size_t summarySize = 0;
12000 	size_t size;
12001 	u_int count;
12002 	u_int maxKexts;
12003 	u_int i, j;
12004 	OSKextActiveAccount * accountingList;
12005 	OSKextActiveAccount * prevAccountingList;
12006 	uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
12007 
12008 	prevAccountingList = NULL;
12009 	prevAccountingListCount = 0;
12010 
12011 #if DEVELOPMENT || DEBUG
12012 	if (IORecursiveLockHaveLock(sKextLock) == false) {
12013 		panic("sKextLock must be held");
12014 	}
12015 #endif
12016 
12017 	IOLockLock(sKextSummariesLock);
12018 
12019 	count = sLoadedKexts->getCount();
12020 	for (i = 0, maxKexts = 0; i < count; ++i) {
12021 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
12022 		maxKexts += (aKext && aKext->isExecutable());
12023 	}
12024 
12025 	if (!maxKexts) {
12026 		goto finish;
12027 	}
12028 	if (maxKexts < kOSKextTypicalLoadCount) {
12029 		maxKexts = kOSKextTypicalLoadCount;
12030 	}
12031 
12032 	/* Calculate the size needed for the new summary headers.
12033 	 */
12034 
12035 	size = sizeof(*gLoadedKextSummaries);
12036 	size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
12037 	size = round_page(size);
12038 
12039 	if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
12040 		if (gLoadedKextSummaries) {
12041 			kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
12042 			gLoadedKextSummaries = NULL;
12043 			gLoadedKextSummariesTimestamp = mach_absolute_time();
12044 			sLoadedKextSummariesAllocSize = 0;
12045 		}
12046 		result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, VM_KERN_MEMORY_OSKEXT);
12047 		if (result != KERN_SUCCESS) {
12048 			goto finish;
12049 		}
12050 		summaryHeader = summaryHeaderAlloc;
12051 		summarySize = size;
12052 	} else {
12053 		summaryHeader = gLoadedKextSummaries;
12054 		summarySize = sLoadedKextSummariesAllocSize;
12055 
12056 		start = (vm_map_offset_t) summaryHeader;
12057 		end = start + summarySize;
12058 		result = vm_map_protect(kernel_map,
12059 		    start,
12060 		    end,
12061 		    VM_PROT_DEFAULT,
12062 		    FALSE);
12063 		if (result != KERN_SUCCESS) {
12064 			goto finish;
12065 		}
12066 	}
12067 
12068 	/* Populate the summary header.
12069 	 */
12070 
12071 	bzero(summaryHeader, summarySize);
12072 	summaryHeader->version = kOSKextLoadedKextSummaryVersion;
12073 	summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
12074 
12075 	/* Populate each kext summary.
12076 	 */
12077 
12078 	count = sLoadedKexts->getCount();
12079 	accountingListAlloc = 0;
12080 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
12081 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
12082 		if (!aKext || !aKext->isExecutable()) {
12083 			continue;
12084 		}
12085 
12086 		aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
12087 		summaryHeader->numSummaries++;
12088 		accountingListAlloc++;
12089 	}
12090 
12091 	accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
12092 	accountingListCount = 0;
12093 	for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
12094 		aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
12095 		if (!aKext || !aKext->isExecutable()) {
12096 			continue;
12097 		}
12098 
12099 		OSKextActiveAccount activeAccount;
12100 		aKext->updateActiveAccount(&activeAccount);
12101 		// order by address
12102 		for (idx = 0; idx < accountingListCount; idx++) {
12103 			if (activeAccount.address < accountingList[idx].address) {
12104 				break;
12105 			}
12106 		}
12107 		bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
12108 		accountingList[idx] = activeAccount;
12109 		accountingListCount++;
12110 	}
12111 	assert(accountingListCount == accountingListAlloc);
12112 	/* Write protect the buffer and move it into place.
12113 	 */
12114 
12115 	start = (vm_map_offset_t) summaryHeader;
12116 	end = start + summarySize;
12117 
12118 	result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
12119 	if (result != KERN_SUCCESS) {
12120 		goto finish;
12121 	}
12122 
12123 	gLoadedKextSummaries = summaryHeader;
12124 	gLoadedKextSummariesTimestamp = mach_absolute_time();
12125 	sLoadedKextSummariesAllocSize = summarySize;
12126 	summaryHeaderAlloc = NULL;
12127 
12128 	/* Call the magic breakpoint function through a static function pointer so
12129 	 * the compiler can't optimize the function away.
12130 	 */
12131 	if (sLoadedKextSummariesUpdated) {
12132 		(*sLoadedKextSummariesUpdated)();
12133 	}
12134 
12135 	IOSimpleLockLock(sKextAccountsLock);
12136 	prevAccountingList      = sKextAccounts;
12137 	prevAccountingListCount = sKextAccountsCount;
12138 	sKextAccounts           = accountingList;
12139 	sKextAccountsCount      = accountingListCount;
12140 	IOSimpleLockUnlock(sKextAccountsLock);
12141 
12142 finish:
12143 	IOLockUnlock(sKextSummariesLock);
12144 
12145 	/* If we had to allocate a new buffer but failed to generate the summaries,
12146 	 * free that now.
12147 	 */
12148 	if (summaryHeaderAlloc) {
12149 		kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
12150 	}
12151 	if (prevAccountingList) {
12152 		IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
12153 	}
12154 
12155 	return;
12156 }
12157 
12158 /*********************************************************************
12159 *********************************************************************/
12160 void
12161 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
12162 {
12163 	OSData *uuid;
12164 
12165 	strlcpy(summary->name, getIdentifierCString(),
12166 	    sizeof(summary->name));
12167 
12168 	uuid = copyUUID();
12169 	if (uuid) {
12170 		memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
12171 		OSSafeReleaseNULL(uuid);
12172 	}
12173 
12174 	if (flags.builtin) {
12175 //      this value will stop lldb from parsing the mach-o header
12176 //      summary->address = UINT64_MAX;
12177 //      summary->size = 0;
12178 		summary->address = kmod_info->address;
12179 		summary->size = kmod_info->size;
12180 	} else {
12181 		summary->address = kmod_info->address;
12182 		summary->size = kmod_info->size;
12183 	}
12184 	summary->version = getVersion();
12185 	summary->loadTag = kmod_info->id;
12186 	summary->flags = 0;
12187 	summary->reference_list = (uint64_t) kmod_info->reference_list;
12188 
12189 	return;
12190 }
12191 
12192 /*********************************************************************
12193 *********************************************************************/
12194 
12195 void
12196 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
12197 {
12198 	kernel_mach_header_t     *hdr = NULL;
12199 	kernel_segment_command_t *seg = NULL;
12200 
12201 	bzero(accountp, sizeof(*accountp));
12202 
12203 	hdr = (kernel_mach_header_t *)kmod_info->address;
12204 	if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO)) {
12205 		/* If this kext supports split segments, use the first
12206 		 * executable segment as the range for instructions
12207 		 * (and thus for backtracing.
12208 		 */
12209 		for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
12210 			if (seg->initprot & VM_PROT_EXECUTE) {
12211 				break;
12212 			}
12213 		}
12214 	}
12215 	if (seg) {
12216 		accountp->address = seg->vmaddr;
12217 		if (accountp->address) {
12218 			accountp->address_end = seg->vmaddr + seg->vmsize;
12219 		}
12220 	} else {
12221 		/* For non-split kexts and for kexts without executable
12222 		 * segments, just use the kmod_info range (as the kext
12223 		 * is either all in one range or should not show up in
12224 		 * instruction backtraces).
12225 		 */
12226 		accountp->address = kmod_info->address;
12227 		if (accountp->address) {
12228 			accountp->address_end = kmod_info->address + kmod_info->size;
12229 		}
12230 	}
12231 
12232 	accountp->account = this->account;
12233 }
12234 
12235 bool
12236 OSKext::isDriverKit(void)
12237 {
12238 	OSString *bundleType;
12239 
12240 	if (infoDict) {
12241 		bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey));
12242 		if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) {
12243 			return TRUE;
12244 		}
12245 	}
12246 	return FALSE;
12247 }
12248 
12249 extern "C" const vm_allocation_site_t *
12250 OSKextGetAllocationSiteForCaller(uintptr_t address)
12251 {
12252 	OSKextActiveAccount *  active;
12253 	vm_allocation_site_t * site;
12254 	vm_allocation_site_t * releasesite;
12255 
12256 	uint32_t baseIdx;
12257 	uint32_t lim;
12258 
12259 	IOSimpleLockLock(sKextAccountsLock);
12260 	site = releasesite = NULL;
12261 
12262 	// bsearch sKextAccounts list
12263 	for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
12264 		active = &sKextAccounts[baseIdx + (lim >> 1)];
12265 		if ((address >= active->address) && (address < active->address_end)) {
12266 			site = &active->account->site;
12267 			if (!site->tag) {
12268 				vm_tag_alloc_locked(site, &releasesite);
12269 			}
12270 			break;
12271 		} else if (address > active->address) {
12272 			// move right
12273 			baseIdx += (lim >> 1) + 1;
12274 			lim--;
12275 		}
12276 		// else move left
12277 	}
12278 	IOSimpleLockUnlock(sKextAccountsLock);
12279 	if (releasesite) {
12280 		kern_allocation_name_release(releasesite);
12281 	}
12282 
12283 	return site;
12284 }
12285 
12286 extern "C" uint32_t
12287 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
12288 {
12289 	OSKextAccount * account = (typeof(account))site;
12290 	const char    * kname;
12291 
12292 	if (name) {
12293 		if (account->kext) {
12294 			kname = account->kext->getIdentifierCString();
12295 		} else {
12296 			kname = "<>";
12297 		}
12298 		strlcpy(name, kname, namelen);
12299 	}
12300 
12301 	return account->loadTag;
12302 }
12303 
12304 extern "C" void
12305 OSKextFreeSite(vm_allocation_site_t * site)
12306 {
12307 	OSKextAccount * freeAccount = (typeof(freeAccount))site;
12308 	IODelete(freeAccount, OSKextAccount, 1);
12309 }
12310 
12311 /*********************************************************************
12312 *********************************************************************/
12313 
12314 #if CONFIG_IMAGEBOOT
12315 int
12316 OSKextGetUUIDForName(const char *name, uuid_t uuid)
12317 {
12318 	OSKext *kext = OSKext::lookupKextWithIdentifier(name);
12319 	if (!kext) {
12320 		return 1;
12321 	}
12322 
12323 	OSData *uuid_data = kext->copyUUID();
12324 	if (uuid_data) {
12325 		memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
12326 		OSSafeReleaseNULL(uuid_data);
12327 		return 0;
12328 	}
12329 
12330 	return 1;
12331 }
12332 #endif
12333