2 * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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>
56 #include <sys/kauth.h>
57 #include <security/mac_framework.h>
61 #include <libkern/OSKextLibPrivate.h>
62 #include <libkern/c++/OSKext.h>
63 #include <libkern/c++/OSLib.h>
65 #include <IOKit/IOLib.h>
66 #include <IOKit/IOCatalogue.h>
67 #include <IOKit/IORegistryEntry.h>
68 #include <IOKit/IOService.h>
70 #include <IOKit/IOStatisticsPrivate.h>
71 #include <IOKit/IOBSD.h>
73 #include <san/kasan.h>
76 #pragma mark External & Internal Function Protos
78 /*********************************************************************
79 *********************************************************************/
81 extern int IODTGetLoaderInfo(const char * key
, void ** infoAddr
, int * infoSize
);
82 extern void IODTFreeLoaderInfo(const char * key
, void * infoAddr
, int infoSize
);
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);
88 extern unsigned long gVirtBase
;
89 extern unsigned long gPhysBase
;
91 extern vm_offset_t segLOWESTTEXT
;
92 #endif /* CONFIG_EMBEDDED */
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
,
105 static void * _OSKextExtractPointer(OSData
* wrapper
);
106 static OSReturn
_OSDictionarySetCStringValue(
110 static bool _OSKextInPrelinkRebuildWindow(void);
111 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol
* theBundleID
);
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
);
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().
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
131 #error Unsupported architecture
135 #pragma mark Constants & Macros
137 /*********************************************************************
139 *********************************************************************/
141 /* Use this number to create containers.
143 #define kOSKextTypicalLoadCount (150)
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.
148 #define kOSKextMinRetainCount (1)
149 #define kOSKextMinLoadedRetainCount (2)
152 * Strings and substrings used in dependency resolution.
154 #define APPLE_KEXT_PREFIX "com.apple."
155 #define KERNEL_LIB "com.apple.kernel"
157 #define PRIVATE_KPI "com.apple.kpi.private"
159 /* Version for compatbility pseudokexts (com.apple.kernel.*),
160 * compatible back to v6.0.
162 #define KERNEL6_LIB "com.apple.kernel.6.0"
163 #define KERNEL6_VERSION "7.9.9"
165 #define KERNEL_LIB_PREFIX "com.apple.kernel."
166 #define KPI_LIB_PREFIX "com.apple.kpi."
168 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0)
170 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
171 #define MINIMUM_WAKEUP_SECONDS (30)
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 *********************************************************************/
178 /* A usable, uncompressed file is stored under this key.
180 #define _kOSKextExecutableKey "_OSKextExecutable"
182 /* An indirect reference to the executable file from an mkext
183 * is stored under this key.
185 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference"
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.
191 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
193 #define OS_LOG_HDR_VERSION 1
194 #define NUM_OS_LOG_SECTIONS 2
196 #define OS_LOG_SECT_IDX 0
197 #define CSTRING_SECT_IDX 1
200 #pragma mark Typedefs
202 /*********************************************************************
204 *********************************************************************/
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
{
217 uint32_t sect_offset
;
220 } osLogDataHeaderRef
;
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.
227 * It contains the mkextVersion in case we ever wind up supporting
228 * multiple mkext formats. Mkext format 1 is officially retired as of
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
237 #pragma mark Global and static Module Variables
239 /*********************************************************************
240 * Global & static variables, used to keep track of kexts.
241 *********************************************************************/
243 static bool sPrelinkBoot
= false;
244 static bool sSafeBoot
= false;
245 static bool sKeepSymbols
= false;
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.
253 * sKextLock and sKextInnerLock are recursive due to multiple functions
254 * that are called both externally and internally. The other locks are
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:
263 * 3. sKextSummariesLock
264 * 4. sKextLoggingLock
266 static IORecursiveLock
* sKextLock
= NULL
;
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
;
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
;
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;
287 static bool sUserLoadsActive
= false;
288 static bool sKextdActive
= false;
289 static bool sDeferredLoadSucceeded
= false;
290 static bool sConsiderUnloadsExecuted
= false;
293 static bool sKernelRequestsEnabled
= false;
295 static bool sKernelRequestsEnabled
= true;
297 static bool sLoadEnabled
= true;
298 static bool sUnloadEnabled
= true;
300 /*********************************************************************
301 * Stuff for the OSKext representing the kernel itself.
303 static OSKext
* sKernelKext
= NULL
;
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.
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.
317 kmod_info_t g_kernel_kmod_info
= {
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
,
326 .size
= 0, // filled in in OSKext::initialize()
332 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
334 kmod_info_t invalid_kmod_info
= {
336 .info_version
= KMOD_INFO_VERSION
,
340 .reference_count
= -1,
341 .reference_list
= NULL
,
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
;
356 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
359 static char * loaded_kext_paniclist
= NULL
;
360 static uint32_t loaded_kext_paniclist_size
= 0;
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;
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;
374 // Statically linked kmods described by several mach-o sections:
376 // kPrelinkInfoSegment:kBuiltinInfoSection
377 // Array of pointers to kmod_info_t structs.
379 // kPrelinkInfoSegment:kBuiltinInfoSection
380 // Array of pointers to an embedded mach-o header.
382 // __DATA:kBuiltinInitSection, kBuiltinTermSection
383 // Structors for all kmods. Has to be filtered by proc address.
386 static uint32_t gBuiltinKmodsCount
;
387 static kernel_section_t
* gBuiltinKmodsSectionInfo
;
388 static kernel_section_t
* gBuiltinKmodsSectionStart
;
390 static const OSSymbol
* gIOSurfaceIdentifier
;
391 vm_tag_t gIOSurfaceTag
;
393 /*********************************************************************
394 * sKextInnerLock protects against cross-calls with IOService and
395 * IOCatalogue, and owns the variables declared immediately below.
397 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
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.
405 static IORecursiveLock
* sKextInnerLock
= NULL
;
407 static bool sAutounloadEnabled
= true;
408 static bool sConsiderUnloadsCalled
= false;
409 static bool sConsiderUnloadsPending
= false;
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
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.
422 * gLoadedKextSummaries is accessed by other modules, but only during
423 * a panic so the lock isn't needed then.
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.
430 static IOLock
* sKextSummariesLock
= NULL
;
431 extern "C" lck_spin_t vm_allocation_sites_lock
;
432 static IOSimpleLock
* sKextAccountsLock
= &vm_allocation_sites_lock
;
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;
439 static OSKextActiveAccount
* sKextAccounts
;
440 static uint32_t sKextAccountsCount
;
443 /*********************************************************************
444 * sKextLoggingLock protects the logging variables declared immediately below.
446 static IOLock
* sKextLoggingLock
= NULL
;
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");
455 static OSKextLogSpec sUserSpaceKextLogFilter
= kOSKextLogSilentFilter
;
456 static OSArray
* sUserSpaceLogSpecArray
= NULL
;
457 static OSArray
* sUserSpaceLogMessageArray
= NULL
;
460 * End scope for sKextInnerLock-protected variables.
461 *********************************************************************/
464 /*********************************************************************
465 * helper function used for collecting PGO data upon unload of a kext
468 static int OSKextGrabPgoDataLocked(OSKext
*kext
,
470 uuid_t instance_uuid
,
473 uint64_t bufferSize
);
475 /**********************************************************************/
480 #pragma mark OSData callbacks (need to move to OSData)
482 /*********************************************************************
483 * C functions used for callbacks.
484 *********************************************************************/
487 osdata_kmem_free(void * ptr
, unsigned int length
)
489 kmem_free(kernel_map
, (vm_address_t
)ptr
, length
);
494 osdata_phys_free(void * ptr
, unsigned int length
)
496 ml_static_mfree((vm_offset_t
)ptr
, length
);
501 osdata_vm_deallocate(void * ptr
, unsigned int length
)
503 (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
);
508 osdata_kext_free(void * ptr
, unsigned int length
)
510 (void)kext_free((vm_offset_t
)ptr
, length
);
515 #pragma mark KXLD Allocation Callback
517 /*********************************************************************
518 * KXLD Allocation Callback
519 *********************************************************************/
523 KXLDAllocateFlags
* flags
,
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
533 mach_result
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
);
534 if (mach_result
!= KERN_SUCCESS
) {
536 kOSKextLogErrorLevel
|
537 kOSKextLogGeneralFlag
,
538 "Can't allocate kernel memory to link %s.",
539 theKext
->getIdentifierCString());
543 /* Create an OSData wrapper for the allocated buffer.
545 linkBuffer
= OSData::withBytesNoCopy((void *)result
, roundSize
);
548 kOSKextLogErrorLevel
|
549 kOSKextLogGeneralFlag
,
550 "Can't allocate linked executable wrapper for %s.",
551 theKext
->getIdentifierCString());
554 linkBuffer
->setDeallocFunction(osdata_kext_free
);
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
);
562 theKext
->setLinkedExecutable(linkBuffer
);
564 *flags
= kKxldAllocateWritable
;
568 if (!success
&& result
) {
569 kext_free(result
, roundSize
);
573 OSSafeReleaseNULL(linkBuffer
);
575 return (kxld_addr_t
)result
;
578 /*********************************************************************
579 *********************************************************************/
582 KXLDLogSubsystem subsystem
,
588 OSKext
*theKext
= (OSKext
*) user_data
;
589 OSKextLogSpec logSpec
= 0;
592 case kKxldLogLinking
:
593 logSpec
|= kOSKextLogLinkFlag
;
595 case kKxldLogPatching
:
596 logSpec
|= kOSKextLogPatchFlag
;
601 case kKxldLogExplicit
:
602 logSpec
|= kOSKextLogExplicitLevel
;
605 logSpec
|= kOSKextLogErrorLevel
;
608 logSpec
|= kOSKextLogWarningLevel
;
611 logSpec
|= kOSKextLogProgressLevel
;
614 logSpec
|= kOSKextLogDetailLevel
;
617 logSpec
|= kOSKextLogDebugLevel
;
621 OSKextVLog(theKext
, logSpec
, format
, argList
);
625 #pragma mark IOStatistics defines
630 #define notifyKextLoadObservers(kext, kmod_info) \
632 IOStatistics::onKextLoad(kext, kmod_info); \
635 #define notifyKextUnloadObservers(kext) \
637 IOStatistics::onKextUnload(kext); \
640 #define notifyAddClassObservers(kext, addedClass, flags) \
642 IOStatistics::onClassAdded(kext, addedClass); \
645 #define notifyRemoveClassObservers(kext, removedClass, flags) \
647 IOStatistics::onClassRemoved(kext, removedClass); \
652 #define notifyKextLoadObservers(kext, kmod_info)
653 #define notifyKextUnloadObservers(kext)
654 #define notifyAddClassObservers(kext, addedClass, flags)
655 #define notifyRemoveClassObservers(kext, removedClass, flags)
657 #endif /* IOKITSTATS */
660 #pragma mark Module Config (Startup & Shutdown)
662 /*********************************************************************
663 * Module Config (Class Definition & Class Methods)
664 *********************************************************************/
665 #define super OSObject
666 OSDefineMetaClassAndStructors(OSKext
, OSObject
)
668 /*********************************************************************
669 *********************************************************************/
672 OSKext::initialize(void)
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
686 /* This must be the first thing allocated. Everything else grabs this lock.
688 sKextLock
= IORecursiveLockAlloc();
689 sKextInnerLock
= IORecursiveLockAlloc();
690 sKextSummariesLock
= IOLockAlloc();
691 sKextLoggingLock
= IOLockAlloc();
693 assert(sKextInnerLock
);
694 assert(sKextSummariesLock
);
695 assert(sKextLoggingLock
);
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
);
709 /* Read the log flag boot-args and set the log flags.
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
|
718 "Kernel kext log filter 0x%x per kextlog boot arg.",
719 (unsigned)sKernelLogFilter
);
722 sSafeBoot
= PE_parse_boot_argn("-x", bootArgBuffer
,
723 sizeof(bootArgBuffer
)) ? true : false;
726 OSKextLog(/* kext */ NULL
,
727 kOSKextLogWarningLevel
|
728 kOSKextLogGeneralFlag
,
729 "SAFE BOOT DETECTED - "
730 "only valid OSBundleRequired kexts will be loaded.");
733 PE_parse_boot_argn("keepsyms", &sKeepSymbols
, sizeof(sKeepSymbols
));
735 if (dtrace_keep_kernel_symbols()) {
738 #endif /* CONFIG_DTRACE */
739 #if KASAN_DYNAMIC_BLACKLIST
740 /* needed for function lookup */
744 /* Set up an OSKext instance to represent the kernel itself.
746 sKernelKext
= new OSKext
;
749 kernelStart
= (u_char
*)&_mh_execute_header
;
750 kernelLength
= getlastaddr() - (vm_offset_t
)kernelStart
;
751 kernelExecutable
= OSData::withBytesNoCopy(
752 kernelStart
, kernelLength
);
753 assert(kernelExecutable
);
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(),
760 (unsigned long)vm_kernel_slide
,
761 (unsigned long)vm_kernel_slide
);
764 sKernelKext
->loadTag
= sNextLoadTag
++; // the kernel is load tag 0
765 sKernelKext
->bundleID
= OSSymbol::withCString(kOSKextKernelIdentifier
);
767 sKernelKext
->version
= OSKextParseVersionString(osrelease
);
768 sKernelKext
->compatibleVersion
= sKernelKext
->version
;
769 sKernelKext
->linkedExecutable
= kernelExecutable
;
770 sKernelKext
->interfaceUUID
= sKernelKext
->copyUUID();
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;
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
;
786 /* Cons up an info dict, so we don't have to have special-case
789 sKernelKext
->infoDict
= OSDictionary::withCapacity(5);
790 assert(sKernelKext
->infoDict
);
791 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
,
792 sKernelKext
->bundleID
);
794 setResult
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
,
798 scratchString
= OSString::withCStringNoCopy(osrelease
);
799 assert(scratchString
);
800 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
,
803 OSSafeReleaseNULL(scratchString
);
805 scratchString
= OSString::withCStringNoCopy("mach_kernel");
806 assert(scratchString
);
807 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
,
810 OSSafeReleaseNULL(scratchString
);
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.
816 setResult
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
);
818 setResult
= sLoadedKexts
->setObject(sKernelKext
);
820 sKernelKext
->release();
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
);
831 registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
);
832 registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
);
834 OSSafeReleaseNULL(kernelCPUType
);
835 OSSafeReleaseNULL(kernelCPUSubtype
);
837 gBuiltinKmodsSectionInfo
= getsectbyname(kPrelinkInfoSegment
, kBuiltinInfoSection
);
838 if (gBuiltinKmodsSectionInfo
) {
841 assert(gBuiltinKmodsSectionInfo
->addr
);
842 assert(gBuiltinKmodsSectionInfo
->size
);
843 gBuiltinKmodsCount
= (gBuiltinKmodsSectionInfo
->size
/ sizeof(kmod_info_t
*));
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));
853 vm_kernel_builtinkmod_text
= ((uintptr_t *)gBuiltinKmodsSectionStart
->addr
)[0];
854 vm_kernel_builtinkmod_text_end
= ((uintptr_t *)gBuiltinKmodsSectionStart
->addr
)[count
- 1];
856 gIOSurfaceIdentifier
= OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface");
858 timestamp
= __OSAbsoluteTimePtr(&last_loaded_timestamp
);
860 timestamp
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
);
862 timestamp
= __OSAbsoluteTimePtr(&sLastWakeTime
);
865 OSKextLog(/* kext */ NULL
,
866 kOSKextLogProgressLevel
|
867 kOSKextLogGeneralFlag
,
868 "Kext system initialized.");
870 notifyKextLoadObservers(sKernelKext
, sKernelKext
->kmod_info
);
875 /*********************************************************************
876 * This is expected to be called exactly once, from exactly one thread
877 * context, during kernel bootstrap.
878 *********************************************************************/
881 OSKext::removeKextBootstrap(void)
883 OSReturn result
= kOSReturnError
;
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;
893 kernel_segment_command_t
* seg_to_remove
= NULL
;
895 #if __arm__ || __arm64__
896 const char * dt_segment_name
= NULL
;
897 void * segment_paddress
= NULL
;
898 int segment_size
= 0;
901 OSKextLog(/* kext */ NULL
,
902 kOSKextLogProgressLevel
|
903 kOSKextLogGeneralFlag
,
904 "Jettisoning kext bootstrap segments.");
907 * Dispose of unnecessary stuff that the booter didn't need to load.
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
));
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
));
923 * KLD bootstrap segment.
925 // xxx - should rename KLD segment
926 seg_to_remove
= getsegbyname("__KLD");
928 OSRuntimeUnloadCPPForSegment(seg_to_remove
);
931 #if __arm__ || __arm64__
932 /* Free the memory that was set up by bootx.
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.
940 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
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.
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
953 read_frandom((void *) seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
954 ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
960 seg_to_remove
= NULL
;
963 * Prelinked kernel's symtab (if there is one).
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
);
971 seg_to_remove
= (kernel_segment_command_t
*)getsegbyname("__LINKEDIT");
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.
979 #if (__arm__ || __arm64__)
980 #error CONFIG_KXLD not expected for this arch
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;
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
;
994 /* Allocate space for the LINKEDIT copy.
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.");
1005 seg_copy_offset
= (vm_map_offset_t
) seg_copy
;
1009 memcpy(seg_copy
, seg_data
, seg_length
);
1011 /* Dump the booter memory.
1013 ml_static_mfree(seg_offset
, seg_length
);
1015 /* Set up the VM region.
1017 mem_result
= vm_map_enter_mem_object(
1020 seg_length
, /* mask */ 0,
1021 VM_FLAGS_FIXED
| VM_FLAGS_OVERWRITE
,
1022 VM_MAP_KERNEL_FLAGS_NONE
,
1023 VM_KERN_MEMORY_NONE
,
1025 (vm_object_offset_t
) 0,
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
);
1040 /* And copy it back.
1042 memcpy(seg_data
, seg_copy
, seg_length
);
1046 kmem_free(kernel_map
, seg_copy_offset
, seg_length
);
1048 #else /* we are not CONFIG_KXLD */
1049 #if !(__arm__ || __arm64__)
1050 #error CONFIG_KXLD is expected for this arch
1054 * Dump the LINKEDIT segment, unless keepsyms is set.
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
);
1064 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
1068 OSKextLog(/* kext */ NULL
,
1069 kOSKextLogBasicLevel
|
1070 kOSKextLogGeneralFlag
,
1071 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1073 #endif /* CONFIG_KXLD */
1075 seg_to_remove
= NULL
;
1077 result
= kOSReturnSuccess
;
1082 /*********************************************************************
1083 *********************************************************************/
1085 OSKext::flushNonloadedKexts(
1086 Boolean flushPrelinkedKexts
)
1088 OSSet
* keepKexts
= NULL
;// must release
1090 IORecursiveLockLock(sKextLock
);
1092 OSKextLog(/* kext */ NULL
,
1093 kOSKextLogProgressLevel
|
1094 kOSKextLogKextBookkeepingFlag
,
1095 "Flushing nonloaded kexts and other unused data.");
1097 OSKext::considerDestroyingLinkContext();
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.
1102 keepKexts
= OSSet::withCapacity(16);
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.
1111 sKextsByID
->iterateObjects(^bool (const OSSymbol
* thisID __unused
, OSObject
* obj
) {
1112 OSKext
* thisKext
= OSDynamicCast(OSKext
, obj
);
1116 if (!flushPrelinkedKexts
&& thisKext
->isPrelinked()) {
1117 keepKexts
->setObject(thisKext
);
1119 if (!thisKext
->declaresExecutable()) {
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.
1126 keepKexts
->setObject(thisKext
);
1129 thisKext
->flushDependencies(/* forceIfLoaded */ false);
1133 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1135 sKextsByID
->flushCollection();
1137 /* Now put the loaded kexts back into the ID dictionary.
1139 sLoadedKexts
->iterateObjects(^bool (OSObject
* obj
) {
1140 OSKext
* thisKext
= OSDynamicCast(OSKext
, obj
);
1144 sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
);
1148 /* Finally, put back the kept kexts if we saved any.
1150 keepKexts
->iterateObjects(^bool (OSObject
* obj
) {
1151 OSKext
* thisKext
= OSDynamicCast(OSKext
, obj
);
1155 sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
);
1160 IORecursiveLockUnlock(sKextLock
);
1162 OSSafeReleaseNULL(keepKexts
);
1167 /*********************************************************************
1168 *********************************************************************/
1171 OSKext::setKextdActive(Boolean active
)
1173 IORecursiveLockLock(sKextLock
);
1174 sKextdActive
= active
;
1175 if (sKernelRequests
->getCount()) {
1176 OSKext::pingKextd();
1178 IORecursiveLockUnlock(sKextLock
);
1183 /*********************************************************************
1184 * OSKextLib.cpp might need access to this someday but for now it's
1186 *********************************************************************/
1188 extern void ipc_port_release_send(ipc_port_t
);
1193 OSKext::pingKextd(void)
1195 OSReturn result
= kOSReturnError
;
1197 mach_port_t kextd_port
= IPC_PORT_NULL
;
1199 if (!sKextdActive
) {
1200 result
= kOSKextReturnDisabled
; // basically unavailable
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
|
1209 "Can't get kextd port.");
1213 result
= kextd_ping(kextd_port
);
1214 if (result
!= KERN_SUCCESS
) {
1215 OSKextLog(/* kext */ NULL
,
1216 kOSKextLogErrorLevel
|
1218 "kextd ping failed (0x%x).", (int)result
);
1223 if (IPC_PORT_VALID(kextd_port
)) {
1224 ipc_port_release_send(kextd_port
);
1231 /*********************************************************************
1232 *********************************************************************/
1235 OSKext::setDeferredLoadSucceeded(Boolean succeeded
)
1237 IORecursiveLockLock(sKextLock
);
1238 sDeferredLoadSucceeded
= succeeded
;
1239 IORecursiveLockUnlock(sKextLock
);
1244 /*********************************************************************
1245 * Called from IOSystemShutdownNotification.
1246 *********************************************************************/
1249 OSKext::willShutdown(void)
1252 OSReturn checkResult
= kOSReturnError
;
1254 OSDictionary
* exitRequest
= NULL
; // must release
1256 IORecursiveLockLock(sKextLock
);
1258 OSKext::setLoadEnabled(false);
1259 OSKext::setUnloadEnabled(false);
1260 OSKext::setAutounloadsEnabled(false);
1261 OSKext::setKernelRequestsEnabled(false);
1264 OSKextLog(/* kext */ NULL
,
1265 kOSKextLogProgressLevel
|
1266 kOSKextLogGeneralFlag
,
1267 "System shutdown; requesting immediate kextd exit.");
1269 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
,
1271 if (checkResult
!= kOSReturnSuccess
) {
1274 if (!sKernelRequests
->setObject(exitRequest
)) {
1278 OSKext::pingKextd();
1283 IORecursiveLockUnlock(sKextLock
);
1285 OSSafeReleaseNULL(exitRequest
);
1289 /*********************************************************************
1290 *********************************************************************/
1293 OSKext::getLoadEnabled(void)
1297 IORecursiveLockLock(sKextLock
);
1298 result
= sLoadEnabled
;
1299 IORecursiveLockUnlock(sKextLock
);
1303 /*********************************************************************
1304 *********************************************************************/
1307 OSKext::setLoadEnabled(bool flag
)
1311 IORecursiveLockLock(sKextLock
);
1312 result
= sLoadEnabled
;
1313 sLoadEnabled
= (flag
? true : false);
1315 if (sLoadEnabled
!= result
) {
1316 OSKextLog(/* kext */ NULL
,
1317 kOSKextLogBasicLevel
|
1319 "Kext loading now %sabled.", sLoadEnabled
? "en" : "dis");
1322 IORecursiveLockUnlock(sKextLock
);
1327 /*********************************************************************
1328 *********************************************************************/
1331 OSKext::getUnloadEnabled(void)
1335 IORecursiveLockLock(sKextLock
);
1336 result
= sUnloadEnabled
;
1337 IORecursiveLockUnlock(sKextLock
);
1341 /*********************************************************************
1342 *********************************************************************/
1345 OSKext::setUnloadEnabled(bool flag
)
1349 IORecursiveLockLock(sKextLock
);
1350 result
= sUnloadEnabled
;
1351 sUnloadEnabled
= (flag
? true : false);
1352 IORecursiveLockUnlock(sKextLock
);
1354 if (sUnloadEnabled
!= result
) {
1355 OSKextLog(/* kext */ NULL
,
1356 kOSKextLogBasicLevel
|
1357 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1358 "Kext unloading now %sabled.", sUnloadEnabled
? "en" : "dis");
1364 /*********************************************************************
1365 * Do not call any function that takes sKextLock here!
1366 *********************************************************************/
1369 OSKext::getAutounloadEnabled(void)
1373 IORecursiveLockLock(sKextInnerLock
);
1374 result
= sAutounloadEnabled
? true : false;
1375 IORecursiveLockUnlock(sKextInnerLock
);
1379 /*********************************************************************
1380 * Do not call any function that takes sKextLock here!
1381 *********************************************************************/
1384 OSKext::setAutounloadsEnabled(bool flag
)
1388 IORecursiveLockLock(sKextInnerLock
);
1390 result
= sAutounloadEnabled
;
1391 sAutounloadEnabled
= (flag
? true : false);
1392 if (!sAutounloadEnabled
&& sUnloadCallout
) {
1393 thread_call_cancel(sUnloadCallout
);
1396 if (sAutounloadEnabled
!= result
) {
1397 OSKextLog(/* kext */ NULL
,
1398 kOSKextLogBasicLevel
|
1399 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1400 "Kext autounloading now %sabled.",
1401 sAutounloadEnabled
? "en" : "dis");
1404 IORecursiveLockUnlock(sKextInnerLock
);
1409 /*********************************************************************
1410 *********************************************************************/
1411 /* instance method operating on OSKext field */
1413 OSKext::setAutounloadEnabled(bool flag
)
1415 bool result
= flags
.autounloadEnabled
? true : false;
1416 flags
.autounloadEnabled
= flag
? 1 : 0;
1418 if (result
!= (flag
? true : false)) {
1420 kOSKextLogProgressLevel
|
1421 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
1422 "Autounloading for kext %s now %sabled.",
1423 getIdentifierCString(),
1424 flags
.autounloadEnabled
? "en" : "dis");
1429 /*********************************************************************
1430 *********************************************************************/
1433 OSKext::setKernelRequestsEnabled(bool flag
)
1437 IORecursiveLockLock(sKextLock
);
1438 result
= sKernelRequestsEnabled
;
1439 sKernelRequestsEnabled
= flag
? true : false;
1441 if (sKernelRequestsEnabled
!= result
) {
1442 OSKextLog(/* kext */ NULL
,
1443 kOSKextLogBasicLevel
|
1444 kOSKextLogGeneralFlag
,
1445 "Kernel requests now %sabled.",
1446 sKernelRequestsEnabled
? "en" : "dis");
1448 IORecursiveLockUnlock(sKextLock
);
1452 /*********************************************************************
1453 *********************************************************************/
1456 OSKext::getKernelRequestsEnabled(void)
1460 IORecursiveLockLock(sKextLock
);
1461 result
= sKernelRequestsEnabled
;
1462 IORecursiveLockUnlock(sKextLock
);
1467 #pragma mark Kext Life Cycle
1469 /*********************************************************************
1470 *********************************************************************/
1472 OSKext::withPrelinkedInfoDict(
1473 OSDictionary
* anInfoDict
,
1474 bool doCoalesedSlides
)
1476 OSKext
* newKext
= new OSKext
;
1478 if (newKext
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
, doCoalesedSlides
)) {
1486 /*********************************************************************
1487 *********************************************************************/
1489 OSKext::initWithPrelinkedInfoDict(
1490 OSDictionary
* anInfoDict
,
1491 bool doCoalesedSlides
)
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
1502 if (!super::init()) {
1506 /* Get the path. Don't look for an arch-specific path property.
1508 kextPath
= OSDynamicCast(OSString
,
1509 anInfoDict
->getObject(kPrelinkBundlePathKey
));
1511 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
1514 #if KASLR_KEXT_DEBUG
1515 IOLog("kaslr: doCoalesedSlides %d kext %s \n", doCoalesedSlides
, getIdentifierCString());
1518 /* Also get the executable's bundle-relative path if present.
1519 * Don't look for an arch-specific path property.
1521 executableRelPath
= OSDynamicCast(OSString
,
1522 anInfoDict
->getObject(kPrelinkExecutableRelativePathKey
));
1523 if (executableRelPath
) {
1524 executableRelPath
->retain();
1527 userExecutableRelPath
= OSDynamicCast(OSString
,
1528 anInfoDict
->getObject("CFBundleUEXTExecutable"));
1529 if (userExecutableRelPath
) {
1530 userExecutableRelPath
->retain();
1533 /* Don't need the paths to be in the info dictionary any more.
1535 anInfoDict
->removeObject(kPrelinkBundlePathKey
);
1536 anInfoDict
->removeObject(kPrelinkExecutableRelativePathKey
);
1538 /* Create an OSData wrapper around the linked executable.
1540 addressNum
= OSDynamicCast(OSNumber
,
1541 anInfoDict
->getObject(kPrelinkExecutableLoadKey
));
1543 lengthNum
= OSDynamicCast(OSNumber
,
1544 anInfoDict
->getObject(kPrelinkExecutableSizeKey
));
1547 kOSKextLogErrorLevel
|
1548 kOSKextLogArchiveFlag
,
1549 "Kext %s can't find prelinked kext executable size.",
1550 getIdentifierCString());
1554 data
= (void *) ml_static_slide((intptr_t) (addressNum
->unsigned64BitValue()));
1555 length
= (uint32_t) (lengthNum
->unsigned32BitValue());
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
,
1564 anInfoDict
->removeObject(kPrelinkExecutableLoadKey
);
1565 anInfoDict
->removeObject(kPrelinkExecutableSizeKey
);
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.
1570 addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
));
1572 srcData
= (void *) ml_static_slide((intptr_t) (addressNum
->unsigned64BitValue()));
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
);
1580 if (data
!= srcData
) {
1582 kern_return_t alloc_result
;
1584 alloc_result
= kext_alloc((vm_offset_t
*)&data
, length
, /* fixed */ TRUE
);
1585 if (alloc_result
!= KERN_SUCCESS
) {
1587 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1588 "Failed to allocate space for prelinked kext %s.",
1589 getIdentifierCString());
1592 memcpy(data
, srcData
, length
);
1595 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1596 "Error: prelinked kext %s - source and load addresses "
1597 "differ on ILP32 architecture.",
1598 getIdentifierCString());
1600 #endif /* __LP64__ */
1603 anInfoDict
->removeObject(kPrelinkExecutableSourceKey
);
1606 prelinkedExecutable
= OSData::withBytesNoCopy(data
, length
);
1607 if (!prelinkedExecutable
) {
1609 kOSKextLogErrorLevel
|
1610 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
1611 "Kext %s failed to create executable wrapper.",
1612 getIdentifierCString());
1617 prelinkedExecutable
->setDeallocFunction(osdata_kext_free
);
1619 prelinkedExecutable
->setDeallocFunction(osdata_phys_free
);
1621 setLinkedExecutable(prelinkedExecutable
);
1622 addressNum
= OSDynamicCast(OSNumber
,
1623 anInfoDict
->getObject(kPrelinkKmodInfoKey
));
1626 kOSKextLogErrorLevel
|
1627 kOSKextLogArchiveFlag
,
1628 "Kext %s can't find prelinked kext kmod_info address.",
1629 getIdentifierCString());
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
);
1646 anInfoDict
->removeObject(kPrelinkKmodInfoKey
);
1649 if ((addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject("ModuleIndex")))) {
1650 uintptr_t builtinTextStart
;
1651 uintptr_t builtinTextEnd
;
1653 flags
.builtin
= true;
1654 builtinKmodIdx
= addressNum
->unsigned32BitValue();
1655 assert(builtinKmodIdx
< gBuiltinKmodsCount
);
1657 builtinTextStart
= ((uintptr_t *)gBuiltinKmodsSectionStart
->addr
)[builtinKmodIdx
];
1658 builtinTextEnd
= ((uintptr_t *)gBuiltinKmodsSectionStart
->addr
)[builtinKmodIdx
+ 1];
1660 kmod_info
= ((kmod_info_t
**)gBuiltinKmodsSectionInfo
->addr
)[builtinKmodIdx
];
1661 kmod_info
->address
= builtinTextStart
;
1662 kmod_info
->size
= builtinTextEnd
- builtinTextStart
;
1665 /* If the plist has a UUID for an interface, save that off.
1667 if (isInterface()) {
1668 interfaceUUID
= OSDynamicCast(OSData
,
1669 anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
));
1670 if (interfaceUUID
) {
1671 interfaceUUID
->retain();
1672 anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
);
1676 result
= slidePrelinkedExecutable(doCoalesedSlides
);
1677 if (result
!= kOSReturnSuccess
) {
1681 if (doCoalesedSlides
== false) {
1682 /* set VM protections now, wire later at kext load */
1683 result
= setVMAttributes(true, false);
1684 if (result
!= KERN_SUCCESS
) {
1689 flags
.prelinked
= true;
1691 /* If we created a kext from prelink info,
1692 * we must be booting from a prelinked kernel.
1694 sPrelinkBoot
= true;
1696 result
= registerIdentifier();
1699 OSSafeReleaseNULL(prelinkedExecutable
);
1704 /*********************************************************************
1705 *********************************************************************/
1708 OSKext::setAllVMAttributes(void)
1710 OSCollectionIterator
* kextIterator
= NULL
;// must release
1711 const OSSymbol
* thisID
= NULL
;// do not release
1713 IORecursiveLockLock(sKextLock
);
1715 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1716 if (!kextIterator
) {
1720 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
1721 OSKext
* thisKext
;// do not release
1723 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1724 if (!thisKext
|| thisKext
->isInterface() || !thisKext
->declaresExecutable()) {
1728 /* set VM protections now, wire later at kext load */
1729 thisKext
->setVMAttributes(true, false);
1733 IORecursiveLockUnlock(sKextLock
);
1734 OSSafeReleaseNULL(kextIterator
);
1739 /*********************************************************************
1740 *********************************************************************/
1742 OSKext::withBooterData(
1743 OSString
* deviceTreeName
,
1744 OSData
* booterData
)
1746 OSKext
* newKext
= new OSKext
;
1748 if (newKext
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) {
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
;
1768 OSKext::initWithBooterData(
1769 OSString
* deviceTreeName
,
1770 OSData
* booterData
)
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
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
1784 if (!super::init()) {
1788 kextFileInfo
= (_BooterKextFileInfo
*)booterData
->getBytesNoCopy();
1789 if (!kextFileInfo
) {
1791 kOSKextLogErrorLevel
|
1792 kOSKextLogGeneralFlag
,
1793 "No booter-provided data for kext device tree entry %s.",
1794 deviceTreeName
->getCStringNoCopy());
1798 /* The info plist must exist or we can't read the kext.
1800 if (!kextFileInfo
->infoDictPhysAddr
|| !kextFileInfo
->infoDictLength
) {
1802 kOSKextLogErrorLevel
|
1803 kOSKextLogGeneralFlag
,
1804 "No kext info dictionary for booter device tree entry %s.",
1805 deviceTreeName
->getCStringNoCopy());
1809 infoDictAddr
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
1810 if (!infoDictAddr
) {
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());
1821 parsedXML
= OSUnserializeXML(infoDictAddr
, &errorString
);
1823 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
1826 const char * errorCString
= "(unknown error)";
1828 if (errorString
&& errorString
->getCStringNoCopy()) {
1829 errorCString
= errorString
->getCStringNoCopy();
1830 } else if (parsedXML
) {
1831 errorCString
= "not a dictionary";
1834 kOSKextLogErrorLevel
|
1835 kOSKextLogGeneralFlag
,
1836 "Error unserializing info dictionary for device tree entry %s: %s.",
1837 deviceTreeName
->getCStringNoCopy(), errorCString
);
1841 /* A bundle path is not mandatory.
1843 if (kextFileInfo
->bundlePathPhysAddr
&& kextFileInfo
->bundlePathLength
) {
1844 bundlePathAddr
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
);
1845 if (!bundlePathAddr
) {
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());
1855 bundlePathAddr
[kextFileInfo
->bundlePathLength
- 1] = '\0'; // just in case!
1857 kextPath
= OSString::withCString(bundlePathAddr
);
1860 kOSKextLogErrorLevel
|
1861 kOSKextLogGeneralFlag
,
1862 "Failed to create wrapper for device tree entry %s kext path %s.",
1863 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
);
1868 if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) {
1872 /* An executable is not mandatory.
1874 if (kextFileInfo
->executablePhysAddr
&& kextFileInfo
->executableLength
) {
1875 executableAddr
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
);
1876 if (!executableAddr
) {
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());
1887 executable
= OSData::withBytesNoCopy(executableAddr
,
1888 kextFileInfo
->executableLength
);
1891 kOSKextLogErrorLevel
|
1892 kOSKextLogGeneralFlag
,
1893 "Failed to create executable wrapper for device tree entry %s.",
1894 deviceTreeName
->getCStringNoCopy());
1898 /* A kext with an executable needs to retain the whole booterData
1899 * object to keep the executable in memory.
1901 if (!setExecutable(executable
, booterData
)) {
1903 kOSKextLogErrorLevel
|
1904 kOSKextLogGeneralFlag
,
1905 "Failed to set kext executable for device tree entry %s.",
1906 deviceTreeName
->getCStringNoCopy());
1911 result
= registerIdentifier();
1914 OSSafeReleaseNULL(parsedXML
);
1915 OSSafeReleaseNULL(kextPath
);
1916 OSSafeReleaseNULL(errorString
);
1917 OSSafeReleaseNULL(executable
);
1922 /*********************************************************************
1923 *********************************************************************/
1925 OSKext::registerIdentifier(void)
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
1938 IORecursiveLockLock(sKextLock
);
1940 /* Get the new kext's version for checks & log messages.
1942 newVersion
= getVersion();
1943 OSKextVersionGetString(newVersion
, newVersionCString
,
1944 kOSKextVersionMaxLength
);
1946 /* If we don't have an existing kext with this identifier,
1947 * just record the new kext and we're done!
1949 existingKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
));
1950 if (!existingKext
) {
1951 sKextsByID
->setObject(bundleID
, this);
1956 /* Get the existing kext's version for checks & log messages.
1958 existingVersion
= existingKext
->getVersion();
1959 OSKextVersionGetString(existingVersion
,
1960 existingVersionCString
, kOSKextVersionMaxLength
);
1962 existingIsLoaded
= existingKext
->isLoaded();
1963 existingIsPrelinked
= existingKext
->isPrelinked();
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.
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.
1974 if (existingIsLoaded
|| existingIsPrelinked
) {
1975 bool sameVersion
= (newVersion
== existingVersion
);
1976 bool sameExecutable
= true; // assume true unless we have UUIDs
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.
1982 newUUID
= copyUUID();
1983 existingUUID
= existingKext
->copyUUID();
1985 /* I'm entirely too paranoid about checking equivalence of executables,
1986 * but I remember nasty problems with it in the past.
1988 * - If we have UUIDs for both kexts, compare them.
1989 * - If only one kext has a UUID, they're definitely different.
1991 if (newUUID
&& existingUUID
) {
1992 sameExecutable
= newUUID
->isEqualTo(existingUUID
);
1993 } else if (newUUID
|| existingUUID
) {
1994 sameExecutable
= false;
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.
2005 OSKextVersionGetString(version
, newVersionCString
,
2006 sizeof(newVersionCString
));
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(),
2014 (existingIsLoaded
? "loaded" : "prelinked"));
2017 if (sameVersion
&& sameExecutable
) {
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"));
2027 /* This condition is significant so log it under warnings.
2030 kOSKextLogWarningLevel
|
2031 kOSKextLogKextBookkeepingFlag
,
2032 "Refusing new kext %s, v%s: already have %s v%s.",
2033 getIdentifierCString(),
2035 (existingIsLoaded
? "loaded" : "prelinked"),
2036 existingVersionCString
);
2038 /* This condition is significant so log it under warnings.
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"));
2049 } /* if (existingIsLoaded || existingIsPrelinked) */
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).
2057 if (sUserLoadsActive
) {
2058 sKextsByID
->setObject(bundleID
, this);
2062 kOSKextLogStepLevel
|
2063 kOSKextLogKextBookkeepingFlag
,
2064 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2065 getIdentifierCString(),
2066 existingVersionCString
,
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.
2076 if (newVersion
> existingVersion
) {
2077 sKextsByID
->setObject(bundleID
, this);
2081 kOSKextLogStepLevel
|
2082 kOSKextLogKextBookkeepingFlag
,
2083 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2084 existingVersionCString
,
2085 getIdentifierCString(),
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
,
2098 /* result has been set appropriately by now. */
2102 IORecursiveLockUnlock(sKextLock
);
2106 kOSKextLogStepLevel
|
2107 kOSKextLogKextBookkeepingFlag
,
2108 "Kext %s, v%s registered and available for loading.",
2109 getIdentifierCString(), newVersionCString
);
2112 OSSafeReleaseNULL(newUUID
);
2113 OSSafeReleaseNULL(existingUUID
);
2118 /*********************************************************************
2119 * Does the bare minimum validation to look up a kext.
2120 * All other validation is done on the spot as needed.
2121 **********************************************************************/
2123 OSKext::setInfoDictionaryAndPath(
2124 OSDictionary
* aDictionary
,
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
2137 panic("Attempt to set info dictionary on a kext "
2138 "that already has one (%s).",
2139 getIdentifierCString());
2142 if (!aDictionary
|| !OSDynamicCast(OSDictionary
, aDictionary
)) {
2146 infoDict
= aDictionary
;
2149 /* Check right away if the info dictionary has any log flags.
2151 scratchBool
= OSDynamicCast(OSBoolean
,
2152 getPropertyForHostArch(kOSBundleEnableKextLoggingKey
));
2153 if (scratchBool
== kOSBooleanTrue
) {
2154 flags
.loggingEnabled
= 1;
2157 /* The very next thing to get is the bundle identifier. Unlike
2158 * in user space, a kext with no bundle identifier gets axed
2161 bundleIDString
= OSDynamicCast(OSString
,
2162 getPropertyForHostArch(kCFBundleIdentifierKey
));
2163 if (!bundleIDString
) {
2165 kOSKextLogErrorLevel
|
2166 kOSKextLogValidationFlag
,
2167 "CFBundleIdentifier missing/invalid type in kext %s.",
2168 aPath
? aPath
->getCStringNoCopy() : "(unknown)");
2171 bundleID
= OSSymbol::withString(bundleIDString
);
2174 kOSKextLogErrorLevel
|
2175 kOSKextLogValidationFlag
,
2176 "Can't copy bundle identifier as symbol for kext %s.",
2177 bundleIDString
->getCStringNoCopy());
2181 /* Save the path if we got one (it should always be available but it's
2182 * just something nice to have for bookkeeping).
2190 * Minimal validation to initialize. We'll do other validation on the spot.
2192 if (bundleID
->getLength() >= KMOD_MAX_NAME
) {
2194 kOSKextLogErrorLevel
|
2195 kOSKextLogValidationFlag
,
2196 "Kext %s error - CFBundleIdentifier over max length %d.",
2197 getIdentifierCString(), KMOD_MAX_NAME
- 1);
2201 version
= compatibleVersion
= -1;
2203 versionString
= OSDynamicCast(OSString
,
2204 getPropertyForHostArch(kCFBundleVersionKey
));
2205 if (!versionString
) {
2207 kOSKextLogErrorLevel
|
2208 kOSKextLogValidationFlag
,
2209 "Kext %s error - CFBundleVersion missing/invalid type.",
2210 getIdentifierCString());
2213 versionCString
= versionString
->getCStringNoCopy();
2214 version
= OSKextParseVersionString(versionCString
);
2217 kOSKextLogErrorLevel
|
2218 kOSKextLogValidationFlag
,
2219 "Kext %s error - CFBundleVersion bad value '%s'.",
2220 getIdentifierCString(), versionCString
);
2224 compatibleVersion
= -1; // set to illegal value for kexts that don't have
2226 compatibleVersionString
= OSDynamicCast(OSString
,
2227 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
2228 if (compatibleVersionString
) {
2229 compatibleVersionCString
= compatibleVersionString
->getCStringNoCopy();
2230 compatibleVersion
= OSKextParseVersionString(compatibleVersionCString
);
2231 if (compatibleVersion
< 0) {
2233 kOSKextLogErrorLevel
|
2234 kOSKextLogValidationFlag
,
2235 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2236 getIdentifierCString(), compatibleVersionCString
);
2240 if (compatibleVersion
> version
) {
2242 kOSKextLogErrorLevel
|
2243 kOSKextLogValidationFlag
,
2244 "Kext %s error - %s %s > %s %s (must be <=).",
2245 getIdentifierCString(),
2246 kOSBundleCompatibleVersionKey
, compatibleVersionCString
,
2247 kCFBundleVersionKey
, versionCString
);
2252 /* Check to see if this kext is in exclude list */
2253 if (isInExcludeList()) {
2255 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
2256 "Kext %s is in exclude list, not loadable",
2257 getIdentifierCString());
2261 /* Set flags for later use if the infoDict gets flushed. We only
2262 * check for true values, not false ones(!)
2264 scratchBool
= OSDynamicCast(OSBoolean
,
2265 getPropertyForHostArch(kOSBundleIsInterfaceKey
));
2266 if (scratchBool
== kOSBooleanTrue
) {
2267 flags
.interface
= 1;
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...
2277 /* A kernel component has one implicit dependency on the kernel.
2279 flags
.hasAllDependencies
= 1;
2282 /* Make sure common string values in personalities are uniqued to OSSymbols.
2284 scratchDict
= OSDynamicCast(OSDictionary
,
2285 getPropertyForHostArch(kIOKitPersonalitiesKey
));
2287 uniquePersonalityProperties(scratchDict
);
2297 /*********************************************************************
2298 * Not used for prelinked kernel boot as there is no unrelocated
2300 *********************************************************************/
2302 OSKext::setExecutable(
2303 OSData
* anExecutable
,
2304 OSData
* externalData
,
2305 bool externalDataIsMkext
)
2307 bool result
= false;
2308 const char * executableKey
= NULL
; // do not free
2310 if (!anExecutable
) {
2311 infoDict
->removeObject(_kOSKextExecutableKey
);
2312 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
2313 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
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());
2326 if (externalDataIsMkext
) {
2327 executableKey
= _kOSKextMkextExecutableReferenceKey
;
2329 executableKey
= _kOSKextExecutableKey
;
2333 infoDict
->setObject(executableKey
, anExecutable
);
2335 infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
);
2345 /*********************************************************************
2346 *********************************************************************/
2348 uniqueStringPlistProperty(OSDictionary
* dict
, const char * key
)
2350 OSString
* stringValue
= NULL
;// do not release
2351 const OSSymbol
* symbolValue
= NULL
; // must release
2353 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2358 symbolValue
= OSSymbol::withString(stringValue
);
2363 dict
->setObject(key
, symbolValue
);
2367 symbolValue
->release();
2373 /*********************************************************************
2374 *********************************************************************/
2376 uniqueStringPlistProperty(OSDictionary
* dict
, const OSString
* key
)
2378 OSString
* stringValue
= NULL
;// do not release
2379 const OSSymbol
* symbolValue
= NULL
; // must release
2381 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2386 symbolValue
= OSSymbol::withString(stringValue
);
2391 dict
->setObject(key
, symbolValue
);
2395 symbolValue
->release();
2401 /*********************************************************************
2402 * Replace common personality property values with uniqued instances
2403 * to save on wired memory.
2404 *********************************************************************/
2407 OSKext::uniquePersonalityProperties(OSDictionary
* personalityDict
)
2409 /* Properties every personality has.
2411 uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKey
);
2412 uniqueStringPlistProperty(personalityDict
, kIOProviderClassKey
);
2413 uniqueStringPlistProperty(personalityDict
, gIOClassKey
);
2414 if (personalityDict
->getObject(kCFBundleIdentifierKernelKey
)) {
2415 uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKernelKey
);
2417 personalityDict
->setObject(kCFBundleIdentifierKernelKey
, personalityDict
->getObject(kCFBundleIdentifierKey
));
2420 /* Other commonly used properties.
2422 uniqueStringPlistProperty(personalityDict
, gIOMatchCategoryKey
);
2423 uniqueStringPlistProperty(personalityDict
, gIOResourceMatchKey
);
2424 uniqueStringPlistProperty(personalityDict
, gIOUserClientClassKey
);
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");
2443 /*********************************************************************
2444 *********************************************************************/
2449 panic("Attempt to free loaded kext %s.", getIdentifierCString());
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
);
2463 if (isInterface() && kmod_info
) {
2464 kfree(kmod_info
, sizeof(kmod_info_t
));
2472 #pragma mark Mkext files
2474 /*********************************************************************
2475 *********************************************************************/
2477 OSKext::readMkextArchive(OSData
* mkextData
,
2478 uint32_t * checksumPtr
)
2480 OSReturn result
= kOSKextReturnBadData
;
2481 uint32_t mkextLength
= 0;
2482 mkext_header
* mkextHeader
= NULL
;// do not free
2483 uint32_t mkextVersion
= 0;
2485 /* Note default return of kOSKextReturnBadData above.
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.");
2496 mkextHeader
= (mkext_header
*)mkextData
->getBytesNoCopy();
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.");
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.");
2515 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2517 if (mkextVersion
== MKEXT_VERS_2
) {
2518 result
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
);
2520 OSKextLog(/* kext */ NULL
,
2521 kOSKextLogErrorLevel
|
2522 kOSKextLogArchiveFlag
,
2523 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
);
2524 result
= kOSKextReturnUnsupported
;
2531 /*********************************************************************
2532 * Assumes magic, signature, version, length have been checked.
2533 * xxx - need to add further bounds checking for each file entry
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 *********************************************************************/
2542 OSKext::readMkext2Archive(
2544 OSDictionary
** mkextPlistOut
,
2545 uint32_t * checksumPtr
)
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
;
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
2566 mkextLength
= mkextData
->getLength();
2567 mkextHeader
= (mkext2_header
*)mkextData
->getBytesNoCopy();
2568 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2569 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
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
);
2576 if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) {
2577 OSKextLog(/* kext */ NULL
,
2578 kOSKextLogErrorLevel
|
2579 kOSKextLogArchiveFlag
,
2580 "Mkext archive has bad checksum.");
2581 result
= kOSKextReturnBadData
;
2586 *checksumPtr
= checksum
;
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
;
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
;
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
;
2621 mkextPlistFullSize
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
);
2622 if (mkextPlistCompressedSize
) {
2623 mkextPlistUncompressedData
= sKernelKext
->extractMkext2FileData(
2624 (UInt8
*)mkextHeader
+ mkextPlistOffset
,
2626 mkextPlistCompressedSize
, mkextPlistFullSize
);
2627 if (!mkextPlistUncompressedData
) {
2630 mkextPlistDataBuffer
= (const char *)
2631 mkextPlistUncompressedData
->getBytesNoCopy();
2633 mkextPlistDataBuffer
= (const char *)mkextHeader
+ mkextPlistOffset
;
2636 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2638 parsedXML
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
);
2640 mkextPlist
= OSDynamicCast(OSDictionary
, parsedXML
);
2643 const char * errorCString
= "(unknown error)";
2645 if (errorString
&& errorString
->getCStringNoCopy()) {
2646 errorCString
= errorString
->getCStringNoCopy();
2647 } else if (parsedXML
) {
2648 errorCString
= "not a dictionary";
2650 OSKextLog(/* kext */ NULL
,
2651 kOSKextLogErrorLevel
|
2652 kOSKextLogArchiveFlag
,
2653 "Error unserializing mkext plist: %s.", errorCString
);
2657 /* If the caller needs the plist, hand it back and retain it.
2658 * (This function releases it at the end.)
2660 if (mkextPlistOut
) {
2661 *mkextPlistOut
= mkextPlist
;
2662 (*mkextPlistOut
)->retain();
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.");
2675 count
= mkextInfoDictArray
->getCount();
2676 for (i
= 0; i
< count
; i
++) {
2677 OSDictionary
* infoDict
;
2680 infoDict
= OSDynamicCast(OSDictionary
,
2681 mkextInfoDictArray
->getObject(i
));
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.
2688 OSKext
* newKext
= OSKext::withMkext2Info(infoDict
, mkextData
);
2689 OSSafeReleaseNULL(newKext
);
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).
2696 result
= kOSReturnSuccess
;
2700 OSSafeReleaseNULL(parsedXML
);
2701 OSSafeReleaseNULL(mkextPlistUncompressedData
);
2702 OSSafeReleaseNULL(errorString
);
2707 /*********************************************************************
2708 *********************************************************************/
2711 OSKext::withMkext2Info(
2712 OSDictionary
* anInfoDict
,
2715 OSKext
* newKext
= new OSKext
;
2717 if (newKext
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) {
2725 /*********************************************************************
2726 *********************************************************************/
2728 OSKext::initWithMkext2Info(
2729 OSDictionary
* anInfoDict
,
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
2738 if (anInfoDict
== NULL
|| !super::init()) {
2742 /* Get the path. Don't look for an arch-specific path property.
2744 kextPath
= OSDynamicCast(OSString
,
2745 anInfoDict
->getObject(kMKEXTBundlePathKey
));
2747 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
2751 /* If we have a path to the executable, save it.
2753 executableRelPath
= OSDynamicCast(OSString
,
2754 anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
));
2755 if (executableRelPath
) {
2756 executableRelPath
->retain();
2759 /* Don't need the paths to be in the info dictionary any more.
2761 anInfoDict
->removeObject(kMKEXTBundlePathKey
);
2762 anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
);
2764 executableOffsetNum
= OSDynamicCast(OSNumber
,
2765 infoDict
->getObject(kMKEXTExecutableKey
));
2766 if (executableOffsetNum
) {
2767 executable
= createMkext2FileEntry(mkextData
,
2768 executableOffsetNum
, "executable");
2769 infoDict
->removeObject(kMKEXTExecutableKey
);
2773 if (!setExecutable(executable
, mkextData
, true)) {
2778 result
= registerIdentifier();
2782 OSSafeReleaseNULL(executable
);
2783 OSSafeReleaseNULL(iterator
);
2787 /*********************************************************************
2788 *********************************************************************/
2790 OSKext::createMkext2FileEntry(
2792 OSNumber
* offsetNum
,
2795 OSData
* result
= NULL
;
2796 MkextEntryRef entryRef
;
2797 uint8_t * mkextBuffer
= (uint8_t *)mkextData
->getBytesNoCopy();
2798 uint32_t entryOffset
= offsetNum
->unsigned32BitValue();
2800 result
= OSData::withCapacity(sizeof(entryRef
));
2805 entryRef
.mkext
= (mkext_basic_header
*)mkextBuffer
;
2806 entryRef
.fileinfo
= mkextBuffer
+ entryOffset
;
2807 if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) {
2808 OSSafeReleaseNULL(result
);
2815 kOSKextLogErrorLevel
|
2816 kOSKextLogArchiveFlag
,
2817 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2818 name
, getIdentifierCString());
2823 /*********************************************************************
2824 *********************************************************************/
2826 static void * z_alloc(void *, u_int items
, u_int size
);
2827 static void z_free(void *, void *ptr
);
2829 typedef struct z_mem
{
2830 uint32_t alloc_size
;
2835 * Space allocation and freeing routines for use by zlib routines.
2838 z_alloc(void * notused __unused
, u_int num_items
, u_int size
)
2840 void * result
= NULL
;
2841 z_mem
* zmem
= NULL
;
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
);
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
));
2856 uint32_t allocSize
= (uint32_t)allocSize64
;
2858 zmem
= (z_mem
*)kalloc_tag(allocSize
, VM_KERN_MEMORY_OSKEXT
);
2862 zmem
->alloc_size
= allocSize
;
2863 result
= (void *)&(zmem
->data
);
2869 z_free(void * notused __unused
, void * ptr
)
2871 uint32_t * skipper
= (uint32_t *)ptr
- 1;
2872 z_mem
* zmem
= (z_mem
*)skipper
;
2873 kfree(zmem
, zmem
->alloc_size
);
2879 OSKext::extractMkext2FileData(
2882 uint32_t compressedSize
,
2885 OSData
* result
= NULL
;
2887 OSData
* uncompressedData
= NULL
;// release on error
2889 uint8_t * uncompressedDataBuffer
= NULL
;// do not free
2890 unsigned long uncompressedSize
;
2892 bool zstream_inited
= false;
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.
2898 if (!compressedSize
) {
2899 uncompressedData
= OSData::withBytes(data
, fullSize
);
2900 // xxx - no check for failure?
2901 result
= uncompressedData
;
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.
2912 kOSKextLogErrorLevel
|
2913 kOSKextLogArchiveFlag
,
2914 "Allocation failure extracting %s from mkext.", name
);
2917 kOSKextLogErrorLevel
|
2918 kOSKextLogArchiveFlag
,
2919 "Allocation failure extracting %s from mkext for kext %s.",
2920 name
, getIdentifierCString());
2925 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
);
2926 if (!uncompressedData
) {
2929 kOSKextLogErrorLevel
|
2930 kOSKextLogArchiveFlag
,
2931 "Allocation failure extracting %s from mkext.", name
);
2934 kOSKextLogErrorLevel
|
2935 kOSKextLogArchiveFlag
,
2936 "Allocation failure extracting %s from mkext for kext %s.",
2937 name
, getIdentifierCString());
2941 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
2945 kOSKextLogDetailLevel
|
2946 kOSKextLogArchiveFlag
,
2947 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2948 name
, compressedSize
, fullSize
);
2951 kOSKextLogDetailLevel
|
2952 kOSKextLogArchiveFlag
,
2953 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2954 getIdentifierCString(), name
, compressedSize
, fullSize
);
2957 bzero(&zstream
, sizeof(zstream
));
2958 zstream
.next_in
= (UInt8
*)data
;
2959 zstream
.avail_in
= compressedSize
;
2961 zstream
.next_out
= uncompressedDataBuffer
;
2962 zstream
.avail_out
= fullSize
;
2964 zstream
.zalloc
= z_alloc
;
2965 zstream
.zfree
= z_free
;
2967 zlib_result
= inflateInit(&zstream
);
2968 if (Z_OK
!= zlib_result
) {
2971 kOSKextLogErrorLevel
|
2972 kOSKextLogArchiveFlag
,
2973 "Mkext error; zlib inflateInit failed (%d) for %s.",
2977 kOSKextLogErrorLevel
|
2978 kOSKextLogArchiveFlag
,
2979 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2980 getIdentifierCString(), zlib_result
, name
);
2984 zstream_inited
= true;
2987 zlib_result
= inflate(&zstream
, Z_FINISH
);
2989 if (zlib_result
== Z_STREAM_END
|| zlib_result
== Z_OK
) {
2990 uncompressedSize
= zstream
.total_out
;
2994 kOSKextLogErrorLevel
|
2995 kOSKextLogArchiveFlag
,
2996 "Mkext error; zlib inflate failed (%d) for %s.",
3000 kOSKextLogErrorLevel
|
3001 kOSKextLogArchiveFlag
,
3002 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3003 getIdentifierCString(), zlib_result
, name
);
3007 kOSKextLogErrorLevel
|
3008 kOSKextLogArchiveFlag
,
3009 "zlib error: %s.", zstream
.msg
);
3014 if (uncompressedSize
!= fullSize
) {
3017 kOSKextLogErrorLevel
|
3018 kOSKextLogArchiveFlag
,
3019 "Mkext error; zlib inflate discrepancy for %s, "
3020 "uncompressed size != original size.", name
);
3023 kOSKextLogErrorLevel
|
3024 kOSKextLogArchiveFlag
,
3025 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3026 "uncompressed size != original size.",
3027 getIdentifierCString(), name
);
3032 result
= uncompressedData
;
3035 /* Don't bother checking return, nothing we can do on fail.
3037 if (zstream_inited
) {
3038 inflateEnd(&zstream
);
3042 OSSafeReleaseNULL(uncompressedData
);
3048 /*********************************************************************
3049 *********************************************************************/
3052 OSKext::loadFromMkext(
3053 OSKextLogSpec clientLogFilter
,
3055 uint32_t mkextBufferLength
,
3057 uint32_t * logInfoLengthOut
)
3059 OSReturn result
= kOSReturnError
;
3060 OSReturn tempResult
= kOSReturnError
;
3062 OSData
* mkextData
= NULL
;// must release
3063 OSDictionary
* mkextPlist
= NULL
;// must release
3065 OSArray
* logInfoArray
= NULL
;// must release
3066 OSSerialize
* serializer
= NULL
;// must release
3068 OSString
* predicate
= NULL
;// do not release
3069 OSDictionary
* requestArgs
= NULL
;// do not release
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
3077 /* Default values for these two options: regular autounload behavior,
3078 * load all kexts, send no personalities.
3080 Boolean delayAutounload
= false;
3081 OSKextExcludeLevel startKextExcludeLevel
= kOSKextExcludeNone
;
3082 OSKextExcludeLevel startMatchingExcludeLevel
= kOSKextExcludeAll
;
3084 IORecursiveLockLock(sKextLock
);
3088 *logInfoLengthOut
= 0;
3091 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
3093 OSKextLog(/* kext */ NULL
,
3094 kOSKextLogDebugLevel
|
3096 "Received kext load request from user space.");
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.
3102 if (!sUserLoadsActive
) {
3103 OSKextLog(/* kext */ NULL
,
3104 kOSKextLogProgressLevel
|
3105 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
3106 "Switching to late startup (user-space) kext loading policy.");
3108 sUserLoadsActive
= true;
3111 if (!sLoadEnabled
) {
3112 OSKextLog(/* kext */ NULL
,
3113 kOSKextLogErrorLevel
|
3115 "Kext loading is disabled.");
3116 result
= kOSKextReturnDisabled
;
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()
3125 mkextData
= OSData::withBytesNoCopy(mkextBuffer
,
3128 OSKextLog(/* kext */ NULL
,
3129 kOSKextLogErrorLevel
|
3130 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3131 "Failed to create wrapper for kext load request.");
3132 result
= kOSKextReturnNoMemory
;
3136 result
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
);
3137 if (result
!= kOSReturnSuccess
) {
3138 OSKextLog(/* kext */ NULL
,
3139 kOSKextLogErrorLevel
|
3141 "Failed to read kext load request.");
3145 predicate
= _OSKextGetRequestPredicate(mkextPlist
);
3146 if (!predicate
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) {
3147 OSKextLog(/* kext */ NULL
,
3148 kOSKextLogErrorLevel
|
3150 "Received kext load request with no predicate; skipping.");
3151 result
= kOSKextReturnInvalidArgument
;
3155 requestArgs
= OSDynamicCast(OSDictionary
,
3156 mkextPlist
->getObject(kKextRequestArgumentsKey
));
3157 if (!requestArgs
|| !requestArgs
->getCount()) {
3158 OSKextLog(/* kext */ NULL
,
3159 kOSKextLogErrorLevel
|
3161 "Received kext load request with no arguments.");
3162 result
= kOSKextReturnInvalidArgument
;
3166 kextIdentifier
= OSDynamicCast(OSString
,
3167 requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
));
3169 if (!kextIdentifier
) {
3170 OSKextLog(/* kext */ NULL
,
3171 kOSKextLogErrorLevel
|
3173 "Received kext load request with no kext identifier.");
3174 result
= kOSKextReturnInvalidArgument
;
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
));
3187 if (delayAutounloadBool
) {
3188 delayAutounload
= delayAutounloadBool
->getValue();
3190 if (startKextExcludeNum
) {
3191 startKextExcludeLevel
= startKextExcludeNum
->unsigned8BitValue();
3193 if (startMatchingExcludeNum
) {
3194 startMatchingExcludeLevel
= startMatchingExcludeNum
->unsigned8BitValue();
3197 OSKextLog(/* kext */ NULL
,
3198 kOSKextLogProgressLevel
|
3200 "Received request from user space to load kext %s.",
3201 kextIdentifier
->getCStringNoCopy());
3203 /* Load the kext, with no deferral, since this is a load from outside
3205 * xxx - Would like a better way to handle the default values for the
3206 * xxx - start/match opt args.
3208 result
= OSKext::loadKextWithIdentifier(
3211 /* allowDefer */ false,
3213 startKextExcludeLevel
,
3214 startMatchingExcludeLevel
,
3216 if (result
!= kOSReturnSuccess
) {
3219 /* If the load came down from kextd, it will shortly inform IOCatalogue
3220 * for matching via a separate IOKit calldown.
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.
3229 logInfoArray
= OSKext::clearUserSpaceLogFilter();
3231 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
3232 tempResult
= OSKext::serializeLogInfo(logInfoArray
,
3233 logInfoOut
, logInfoLengthOut
);
3234 if (tempResult
!= kOSReturnSuccess
) {
3235 result
= tempResult
;
3239 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
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....
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.");
3253 IORecursiveLockUnlock(sKextLock
);
3255 OSSafeReleaseNULL(mkextData
);
3256 OSSafeReleaseNULL(mkextPlist
);
3257 OSSafeReleaseNULL(serializer
);
3258 OSSafeReleaseNULL(logInfoArray
);
3263 /*********************************************************************
3264 *********************************************************************/
3267 OSKext::serializeLogInfo(
3268 OSArray
* logInfoArray
,
3270 uint32_t * logInfoLengthOut
)
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;
3279 if (!logInfoArray
|| !logInfoOut
|| !logInfoLengthOut
) {
3280 OSKextLog(/* kext */ NULL
,
3281 kOSKextLogErrorLevel
|
3283 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3284 /* Bad programmer. */
3285 result
= kOSKextReturnInvalidArgument
;
3289 serializer
= OSSerialize::withCapacity(0);
3291 OSKextLog(/* kext */ NULL
,
3292 kOSKextLogErrorLevel
|
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. */
3299 if (!logInfoArray
->serialize(serializer
)) {
3300 OSKextLog(/* kext */ NULL
,
3301 kOSKextLogErrorLevel
|
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. */
3307 logInfo
= serializer
->text();
3308 logInfoLength
= serializer
->getLength();
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
|
3315 "Failed to copy log info for request from user space.");
3316 /* Incidental error; we're going to (try to) allow the request
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
;
3328 result
= kOSReturnSuccess
;
3330 OSSafeReleaseNULL(serializer
);
3335 #pragma mark Instance Management Methods
3337 /*********************************************************************
3338 *********************************************************************/
3340 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
)
3342 OSKext
* foundKext
= NULL
;
3344 IORecursiveLockLock(sKextLock
);
3345 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3347 foundKext
->retain();
3349 IORecursiveLockUnlock(sKextLock
);
3354 /*********************************************************************
3355 *********************************************************************/
3357 OSKext::lookupKextWithIdentifier(OSString
* kextIdentifier
)
3359 return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy());
3362 /*********************************************************************
3363 *********************************************************************/
3365 OSKext::lookupKextWithLoadTag(uint32_t aTag
)
3367 OSKext
* foundKext
= NULL
; // returned
3369 OSArray
*list
[2] = {sLoadedKexts
, sLoadedDriverKitKexts
};
3370 uint32_t count
[2] = {sLoadedKexts
->getCount(), sLoadedDriverKitKexts
->getCount()};
3372 IORecursiveLockLock(sKextLock
);
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();
3386 IORecursiveLockUnlock(sKextLock
);
3391 /*********************************************************************
3392 *********************************************************************/
3394 OSKext::lookupKextWithAddress(vm_address_t address
)
3396 OSKext
* foundKext
= NULL
; // returned
3399 IORecursiveLockLock(sKextLock
);
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();
3417 count
= sLoadedDriverKitKexts
->getCount();
3418 for (i
= 0; i
< count
; i
++) {
3419 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedDriverKitKexts
->getObject(i
));
3421 * DriverKitKexts do not have a linkedExecutable,
3422 * so we "fake" their address with the LoadTag
3424 if (thisKext
->getLoadTag() == address
) {
3425 foundKext
= thisKext
;
3426 foundKext
->retain();
3431 IORecursiveLockUnlock(sKextLock
);
3437 OSKext::copyKextUUIDForAddress(OSNumber
*address
)
3439 OSData
* uuid
= NULL
;
3440 OSKextActiveAccount
* active
;
3441 OSKext
* kext
= NULL
;
3450 uintptr_t addr
= ml_static_slide((uintptr_t)address
->unsigned64BitValue());
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
;
3458 cred
= kauth_cred_get_with_ref();
3459 macCheckResult
= mac_kext_check_query(cred
);
3460 kauth_cred_unref(&cred
);
3462 if (macCheckResult
!= 0) {
3463 OSKextLog(/* kext */ NULL
,
3464 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
3465 "Failed to query kext UUID (MAC policy error 0x%x).",
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
;
3482 } else if (addr
> active
->address
) {
3484 baseIdx
+= (lim
>> 1) + 1;
3489 IOSimpleLockUnlock(sKextAccountsLock
);
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.
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.
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
;
3508 thisKext
= OSDynamicCast(OSKext
, sLoadedDriverKitKexts
->getObject(i
));
3512 if (thisKext
->getLoadTag() == addr
) {
3518 IORecursiveLockUnlock(sKextLock
);
3522 uuid
= kext
->copyTextUUID();
3524 } else if (((vm_offset_t
)addr
>= vm_kernel_stext
) && ((vm_offset_t
)addr
< vm_kernel_etext
)) {
3525 uuid
= sKernelKext
->copyTextUUID();
3531 /*********************************************************************
3532 *********************************************************************/
3534 OSKext::lookupKextWithUUID(uuid_t wanted
)
3536 OSKext
* foundKext
= NULL
; // returned
3538 OSArray
*list
[2] = {sLoadedKexts
, sLoadedDriverKitKexts
};
3539 uint32_t count
[2] = {sLoadedKexts
->getCount(), sLoadedDriverKitKexts
->getCount()};
3542 IORecursiveLockLock(sKextLock
);
3544 for (j
= 0; j
< (sizeof(list
) / sizeof(list
[0])); j
++) {
3545 for (i
= 0; i
< count
[j
]; i
++) {
3546 OSKext
* thisKext
= NULL
;
3548 thisKext
= OSDynamicCast(OSKext
, list
[j
]->getObject(i
));
3553 OSData
*uuid_data
= thisKext
->copyUUID();
3559 memcpy(&uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
3560 uuid_data
->release();
3562 if (0 == uuid_compare(wanted
, uuid
)) {
3563 foundKext
= thisKext
;
3564 foundKext
->retain();
3570 IORecursiveLockUnlock(sKextLock
);
3578 /*********************************************************************
3579 *********************************************************************/
3582 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
)
3584 bool result
= false;
3585 OSKext
* foundKext
= NULL
; // returned
3587 IORecursiveLockLock(sKextLock
);
3589 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3590 if (foundKext
&& foundKext
->isLoaded()) {
3594 IORecursiveLockUnlock(sKextLock
);
3599 /*********************************************************************
3600 * xxx - should spawn a separate thread so a kext can safely have
3601 * xxx - itself unloaded.
3602 *********************************************************************/
3610 bool terminateServicesAndRemovePersonalitiesFlag
)
3614 kOSKextLogErrorLevel
|
3615 kOSKextLogKextBookkeepingFlag
,
3616 "removeKext() called for %s, not supported on embedded",
3617 aKext
->getIdentifier() ? aKext
->getIdentifierCString() : "unknown kext");
3619 return kOSReturnSuccess
;
3620 #else /* CONFIG_EMBEDDED */
3622 OSReturn result
= kOSKextReturnInUse
;
3623 OSKext
* checkKext
= NULL
; // do not release
3625 int macCheckResult
= 0;
3626 kauth_cred_t cred
= NULL
;
3629 IORecursiveLockLock(sKextLock
);
3631 /* If the kext has no identifier, it failed to init
3632 * so isn't in sKextsByID and it isn't loaded.
3634 if (!aKext
->getIdentifier()) {
3635 result
= kOSReturnSuccess
;
3639 checkKext
= OSDynamicCast(OSKext
,
3640 sKextsByID
->getObject(aKext
->getIdentifier()));
3641 if (checkKext
!= aKext
) {
3642 result
= kOSKextReturnNotFound
;
3646 if (aKext
->isLoaded()) {
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
);
3654 if (macCheckResult
!= 0) {
3655 result
= kOSReturnError
;
3657 kOSKextLogErrorLevel
|
3658 kOSKextLogKextBookkeepingFlag
,
3659 "Failed to remove kext %s (MAC policy error 0x%x).",
3660 aKext
->getIdentifierCString(), macCheckResult
);
3665 /* make sure there are no resource requests in flight - 17187548 */
3666 if (aKext
->countRequestCallbacks()) {
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.
3675 if (terminateServicesAndRemovePersonalitiesFlag
) {
3676 result
= gIOCatalogue
->terminateDriversForModule(
3677 aKext
->getIdentifierCString(), /* unload */ false);
3678 if (result
!= kOSReturnSuccess
) {
3680 kOSKextLogErrorLevel
|
3681 kOSKextLogKextBookkeepingFlag
,
3682 "Can't remove kext %s; services failed to terminate - 0x%x.",
3683 aKext
->getIdentifierCString(), result
);
3688 result
= aKext
->unload();
3689 if (result
!= kOSReturnSuccess
) {
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
3700 if (terminateServicesAndRemovePersonalitiesFlag
) {
3701 aKext
->removePersonalitiesFromCatalog();
3705 kOSKextLogProgressLevel
|
3706 kOSKextLogKextBookkeepingFlag
,
3707 "Removing kext %s.",
3708 aKext
->getIdentifierCString());
3710 sKextsByID
->removeObject(aKext
->getIdentifier());
3711 result
= kOSReturnSuccess
;
3714 IORecursiveLockUnlock(sKextLock
);
3716 #endif /* CONFIG_EMBEDDED */
3719 /*********************************************************************
3720 *********************************************************************/
3723 OSKext::removeKextWithIdentifier(
3724 const char * kextIdentifier
,
3725 bool terminateServicesAndRemovePersonalitiesFlag
)
3727 OSReturn result
= kOSReturnError
;
3729 IORecursiveLockLock(sKextLock
);
3731 OSKext
* aKext
= OSDynamicCast(OSKext
,
3732 sKextsByID
->getObject(kextIdentifier
));
3734 result
= kOSKextReturnNotFound
;
3735 OSKextLog(/* kext */ NULL
,
3736 kOSKextLogErrorLevel
|
3737 kOSKextLogKextBookkeepingFlag
,
3738 "Can't remove kext %s - not found.",
3743 result
= OSKext::removeKext(aKext
,
3744 terminateServicesAndRemovePersonalitiesFlag
);
3747 IORecursiveLockUnlock(sKextLock
);
3752 /*********************************************************************
3753 *********************************************************************/
3756 OSKext::removeKextWithLoadTag(
3757 OSKextLoadTag loadTag
,
3758 bool terminateServicesAndRemovePersonalitiesFlag
)
3760 OSReturn result
= kOSReturnError
;
3761 OSKext
* foundKext
= NULL
;
3763 OSArray
*list
[2] = {sLoadedKexts
, sLoadedDriverKitKexts
};
3764 uint32_t count
[2] = {sLoadedKexts
->getCount(), sLoadedDriverKitKexts
->getCount()};
3767 IORecursiveLockLock(sKextLock
);
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
;
3780 result
= kOSKextReturnNotFound
;
3781 OSKextLog(/* kext */ NULL
,
3782 kOSKextLogErrorLevel
|
3783 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
3784 "Can't remove kext with load tag %d - not found.",
3789 result
= OSKext::removeKext(foundKext
,
3790 terminateServicesAndRemovePersonalitiesFlag
);
3793 IORecursiveLockUnlock(sKextLock
);
3798 /*********************************************************************
3799 *********************************************************************/
3801 OSKext::copyKexts(void)
3803 OSDictionary
* result
;
3805 IORecursiveLockLock(sKextLock
);
3806 result
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection());
3807 IORecursiveLockUnlock(sKextLock
);
3812 /*********************************************************************
3813 *********************************************************************/
3814 #define BOOTER_KEXT_PREFIX "Driver-"
3816 typedef struct _DeviceTreeBuffer
{
3819 } _DeviceTreeBuffer
;
3821 /*********************************************************************
3822 * Create a dictionary of excluded kexts from the given booter data.
3823 *********************************************************************/
3826 OSKext::createExcludeListFromBooterData(
3827 OSDictionary
* theDictionary
,
3828 OSCollectionIterator
* theIterator
)
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
3838 theIterator
->reset();
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
3847 OSSafeReleaseNULL(parsedXML
);
3850 OSDynamicCast(OSData
, theDictionary
->getObject(deviceTreeName
));
3851 if (!deviceTreeEntry
) {
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) {
3860 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3861 "\"%s\" not a kext",
3862 devTreeNameCString
);
3866 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
3867 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
3868 if (!deviceTreeBuffer
) {
3872 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
3873 if (!booterDataPtr
) {
3877 kextFileInfo
= (_BooterKextFileInfo
*) booterDataPtr
;
3878 if (!kextFileInfo
->infoDictPhysAddr
||
3879 !kextFileInfo
->infoDictLength
) {
3883 infoDictAddr
= (char *)
3884 ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
3885 if (!infoDictAddr
) {
3889 parsedXML
= OSUnserializeXML(infoDictAddr
);
3894 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
3900 OSDynamicCast(OSString
,
3901 theInfoDict
->getObject(kCFBundleIdentifierKey
));
3903 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
3904 boolean_t updated
= updateExcludeList(theInfoDict
);
3907 panic("Missing OSKextExcludeList dictionary\n");
3911 } // while ( (deviceTreeName = ...) )
3913 OSSafeReleaseNULL(parsedXML
);
3917 /*********************************************************************
3918 * Create a dictionary of excluded kexts from the given prelink
3919 * info (kernelcache).
3920 *********************************************************************/
3923 OSKext::createExcludeListFromPrelinkInfo( OSArray
* theInfoArray
)
3925 OSDictionary
* myInfoDict
= NULL
;// do not release
3926 OSString
* myBundleID
; // do not release
3929 /* Find com.apple.driver.KextExcludeList. */
3930 for (i
= 0; i
< theInfoArray
->getCount(); i
++) {
3931 myInfoDict
= OSDynamicCast(OSDictionary
, theInfoArray
->getObject(i
));
3936 OSDynamicCast(OSString
,
3937 myInfoDict
->getObject(kCFBundleIdentifierKey
));
3939 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
3940 boolean_t updated
= updateExcludeList(myInfoDict
);
3943 panic("Missing OSKextExcludeList dictionary\n");
3947 } // for (i = 0; i < theInfoArray->getCount()...
3954 OSKext::updateExcludeList(OSDictionary
*infoDict
)
3956 OSDictionary
*myTempDict
= NULL
; // do not free
3957 OSString
*myTempString
= NULL
;// do not free
3958 OSKextVersion newVersion
= 0;
3959 boolean_t updated
= false;
3965 myTempDict
= OSDynamicCast(OSDictionary
, infoDict
->getObject("OSKextExcludeList"));
3970 myTempString
= OSDynamicCast(OSString
, infoDict
->getObject(kCFBundleVersionKey
));
3971 if (!myTempString
) {
3975 newVersion
= OSKextParseVersionString(myTempString
->getCStringNoCopy());
3976 if (newVersion
== 0) {
3980 IORecursiveLockLock(sKextLock
);
3982 if (newVersion
> sExcludeListVersion
) {
3983 OSSafeReleaseNULL(sExcludeListByID
);
3984 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3985 sExcludeListVersion
= newVersion
;
3989 IORecursiveLockUnlock(sKextLock
);
3994 #pragma mark Accessors
3996 /*********************************************************************
3997 *********************************************************************/
3999 OSKext::getIdentifier(void)
4004 /*********************************************************************
4005 * A kext must have a bundle identifier to even survive initialization;
4006 * this is guaranteed to exist past then.
4007 *********************************************************************/
4009 OSKext::getIdentifierCString(void)
4011 return bundleID
->getCStringNoCopy();
4014 /*********************************************************************
4015 *********************************************************************/
4017 OSKext::getVersion(void)
4022 /*********************************************************************
4023 *********************************************************************/
4025 OSKext::getCompatibleVersion(void)
4027 return compatibleVersion
;
4030 /*********************************************************************
4031 *********************************************************************/
4033 OSKext::isLibrary(void)
4035 return getCompatibleVersion() > 0;
4038 /*********************************************************************
4039 *********************************************************************/
4041 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
)
4043 if ((compatibleVersion
> -1 && version
> -1) &&
4044 (compatibleVersion
<= version
&& aVersion
<= version
)) {
4050 /*********************************************************************
4051 *********************************************************************/
4053 OSKext::declaresExecutable(void)
4055 if (isDriverKit()) {
4058 return getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
;
4061 /*********************************************************************
4062 *********************************************************************/
4064 OSKext::getExecutable(void)
4066 OSData
* result
= NULL
;
4067 OSData
* extractedExecutable
= NULL
; // must release
4068 OSData
* mkextExecutableRef
= NULL
;// do not release
4070 if (flags
.builtin
) {
4071 return sKernelKext
->linkedExecutable
;
4074 result
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
));
4079 mkextExecutableRef
= OSDynamicCast(OSData
,
4080 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
));
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
);
4095 OSKextLog(this, kOSKextLogErrorLevel
|
4096 kOSKextLogArchiveFlag
,
4097 "Kext %s - unknown mkext version 0x%x for executable.",
4098 getIdentifierCString(), mkextVersion
);
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.)
4105 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
4106 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
4108 if (extractedExecutable
&& extractedExecutable
->getLength()) {
4109 if (!setExecutable(extractedExecutable
)) {
4112 result
= extractedExecutable
;
4120 OSSafeReleaseNULL(extractedExecutable
);
4125 /*********************************************************************
4126 *********************************************************************/
4128 OSKext::isInterface(void)
4130 return flags
.interface
;
4133 /*********************************************************************
4134 *********************************************************************/
4136 OSKext::isKernel(void)
4138 return this == sKernelKext
;
4141 /*********************************************************************
4142 *********************************************************************/
4144 OSKext::isKernelComponent(void)
4146 return flags
.kernelComponent
? true : false;
4149 /*********************************************************************
4150 *********************************************************************/
4152 OSKext::isExecutable(void)
4154 return !isKernel() && !isInterface() && declaresExecutable();
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.
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 *********************************************************************/
4170 OSKext::isLoadableInSafeBoot(void)
4172 bool result
= false;
4173 OSString
* required
= NULL
; // do not release
4180 required
= OSDynamicCast(OSString
,
4181 getPropertyForHostArch(kOSBundleRequiredKey
));
4185 if (required
->isEqualTo(kOSBundleRequiredRoot
) ||
4186 required
->isEqualTo(kOSBundleRequiredLocalRoot
) ||
4187 required
->isEqualTo(kOSBundleRequiredNetworkRoot
) ||
4188 required
->isEqualTo(kOSBundleRequiredSafeBoot
) ||
4189 required
->isEqualTo(kOSBundleRequiredConsole
)) {
4197 /*********************************************************************
4198 *********************************************************************/
4200 OSKext::isPrelinked(void)
4202 return flags
.prelinked
? true : false;
4205 /*********************************************************************
4206 *********************************************************************/
4208 OSKext::isLoaded(void)
4210 return flags
.loaded
? true : false;
4213 /*********************************************************************
4214 *********************************************************************/
4216 OSKext::isStarted(void)
4218 return flags
.started
? true : false;
4221 /*********************************************************************
4222 *********************************************************************/
4224 OSKext::isCPPInitialized(void)
4226 return flags
.CPPInitialized
;
4229 /*********************************************************************
4230 *********************************************************************/
4232 OSKext::setCPPInitialized(bool initialized
)
4234 flags
.CPPInitialized
= initialized
;
4237 /*********************************************************************
4238 *********************************************************************/
4240 OSKext::getLoadTag(void)
4245 /*********************************************************************
4246 *********************************************************************/
4248 OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
)
4250 if (linkedExecutable
) {
4251 *loadSize
= linkedExecutable
->getLength();
4253 /* If we have a kmod_info struct, calculated the wired size
4254 * from that. Otherwise it's the full load size.
4257 *wiredSize
= *loadSize
- kmod_info
->hdr_size
;
4259 *wiredSize
= *loadSize
;
4267 /*********************************************************************
4268 *********************************************************************/
4270 OSKext::copyUUID(void)
4272 OSData
* result
= NULL
;
4273 OSData
* theExecutable
= NULL
;// do not release
4274 const kernel_mach_header_t
* header
;
4276 /* An interface kext doesn't have a linked executable with an LC_UUID,
4277 * we create one when it's linked.
4279 if (interfaceUUID
) {
4280 result
= interfaceUUID
;
4285 if (flags
.builtin
|| isInterface()) {
4286 return sKernelKext
->copyUUID();
4289 if (isDriverKit() && infoDict
) {
4290 if (driverKitUUID
) {
4291 driverKitUUID
->retain();
4292 return driverKitUUID
;
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.
4301 theExecutable
= linkedExecutable
;
4302 if (!theExecutable
) {
4303 theExecutable
= getExecutable();
4306 if (!theExecutable
) {
4310 header
= (const kernel_mach_header_t
*)theExecutable
->getBytesNoCopy();
4311 result
= copyMachoUUID(header
);
4317 /*********************************************************************
4318 *********************************************************************/
4320 OSKext::copyTextUUID(void)
4322 if (flags
.builtin
) {
4323 return copyMachoUUID((const kernel_mach_header_t
*)kmod_info
->address
);
4328 /*********************************************************************
4329 *********************************************************************/
4331 OSKext::copyMachoUUID(const kernel_mach_header_t
* header
)
4333 OSData
* result
= NULL
;
4334 const struct load_command
* load_cmd
= NULL
;
4335 const struct uuid_command
* uuid_cmd
= NULL
;
4338 load_cmd
= (const struct load_command
*)&header
[1];
4340 if (header
->magic
!= MH_MAGIC_KERNEL
) {
4342 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4343 "%s: bad header %p",
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
));
4355 load_cmd
= (struct load_command
*)((caddr_t
)load_cmd
+ load_cmd
->cmdsize
);
4363 OSKext::setDriverKitUUID(OSData
*uuid
)
4365 if (!OSCompareAndSwapPtr(nullptr, uuid
, &driverKitUUID
)) {
4366 OSSafeReleaseNULL(uuid
);
4370 /*********************************************************************
4371 *********************************************************************/
4372 #if defined (__arm__)
4373 #include <arm/arch.h>
4376 #if defined (__x86_64__)
4377 #define ARCHNAME "x86_64"
4378 #elif defined (__arm64__)
4379 #define ARCHNAME "arm64"
4380 #elif defined (__arm__)
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"
4394 #elif defined (__arm64__)
4395 #define ARCHNAME "arm64"
4397 #error architecture not supported
4400 #define ARCH_SEPARATOR_CHAR '_'
4403 makeHostArchKey(const char * key
, uint32_t * keySizeOut
)
4405 char * result
= NULL
;
4406 uint32_t keyLength
= strlen(key
);
4409 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4411 keySize
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
);
4412 result
= (char *)kalloc_tag(keySize
, VM_KERN_MEMORY_OSKEXT
);
4416 strlcpy(result
, key
, keySize
);
4417 result
[keyLength
++] = ARCH_SEPARATOR_CHAR
;
4418 result
[keyLength
] = '\0';
4419 strlcat(result
, ARCHNAME
, keySize
);
4420 *keySizeOut
= keySize
;
4426 /*********************************************************************
4427 *********************************************************************/
4429 OSKext::getPropertyForHostArch(const char * key
)
4431 OSObject
* result
= NULL
;// do not release
4432 uint32_t hostArchKeySize
= 0;
4433 char * hostArchKey
= NULL
;// must kfree
4435 if (!key
|| !infoDict
) {
4439 /* Some properties are not allowed to be arch-variant:
4440 * - Any CFBundle... property.
4441 * - OSBundleIsInterface.
4442 * - OSKernelResource.
4444 if (STRING_HAS_PREFIX(key
, "OS") ||
4445 STRING_HAS_PREFIX(key
, "IO")) {
4446 hostArchKey
= makeHostArchKey(key
, &hostArchKeySize
);
4448 OSKextLog(/* kext (this isn't about a kext) */ NULL
,
4449 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4450 "Allocation failure.");
4453 result
= infoDict
->getObject(hostArchKey
);
4457 result
= infoDict
->getObject(key
);
4462 kfree(hostArchKey
, hostArchKeySize
);
4468 #pragma mark Load/Start/Stop/Unload
4471 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
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:
4481 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4482 * not load the kext.
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)
4488 * NOTE - we cannot use the characters "<=" or "<" because we have code
4489 * that serializes plists and treats '<' as a special character.
4490 *********************************************************************/
4492 OSKext::isInExcludeList(void)
4494 OSString
* versionString
= NULL
;// do not release
4495 char * versionCString
= NULL
;// do not free
4497 boolean_t wantLessThan
= false;
4498 boolean_t wantLessThanEqualTo
= false;
4499 boolean_t isInExcludeList
= true;
4502 IORecursiveLockLock(sKextLock
);
4504 if (!sExcludeListByID
) {
4505 isInExcludeList
= false;
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
4510 versionString
= OSDynamicCast(OSString
, sExcludeListByID
->getObject(bundleID
));
4511 if (versionString
== NULL
|| versionString
->getLength() > (sizeof(myBuffer
) - 1)) {
4512 isInExcludeList
= false;
4516 IORecursiveLockUnlock(sKextLock
);
4518 if (!isInExcludeList
) {
4522 /* parse version strings */
4523 versionCString
= (char *) versionString
->getCStringNoCopy();
4525 /* look for "LT" or "LE" form of version string, must be in first two
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;
4536 for (i
= 0; *versionCString
!= 0x00; versionCString
++) {
4537 /* skip whitespace */
4538 if (isWhiteSpace(*versionCString
)) {
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
;
4548 OSKextVersion excludeVers
;
4549 excludeVers
= OSKextParseVersionString(myBuffer
);
4551 if (wantLessThanEqualTo
) {
4552 if (version
<= excludeVers
) {
4555 } else if (wantLessThan
) {
4556 if (version
< excludeVers
) {
4559 } else if (version
== excludeVers
) {
4563 /* reset for the next (if any) version string */
4565 wantLessThan
= false;
4566 wantLessThanEqualTo
= false;
4568 /* save valid version character */
4569 myBuffer
[i
++] = *versionCString
;
4571 /* make sure bogus version string doesn't overrun local buffer */
4572 if (i
>= sizeof(myBuffer
)) {
4581 /*********************************************************************
4582 *********************************************************************/
4585 OSKext::loadKextWithIdentifier(
4586 const char * kextIdentifierCString
,
4587 Boolean allowDeferFlag
,
4588 Boolean delayAutounloadFlag
,
4589 OSKextExcludeLevel startOpt
,
4590 OSKextExcludeLevel startMatchingOpt
,
4591 OSArray
* personalityNames
)
4593 OSReturn result
= kOSReturnError
;
4594 OSString
* kextIdentifier
= NULL
; // must release
4596 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
4597 if (!kextIdentifier
) {
4598 result
= kOSKextReturnNoMemory
;
4601 result
= OSKext::loadKextWithIdentifier(kextIdentifier
,
4603 allowDeferFlag
, delayAutounloadFlag
,
4604 startOpt
, startMatchingOpt
, personalityNames
);
4607 OSSafeReleaseNULL(kextIdentifier
);
4611 /*********************************************************************
4612 *********************************************************************/
4614 OSKext::loadKextWithIdentifier(
4615 OSString
* kextIdentifier
,
4616 OSObject
** kextRef
,
4617 Boolean allowDeferFlag
,
4618 Boolean delayAutounloadFlag
,
4619 OSKextExcludeLevel startOpt
,
4620 OSKextExcludeLevel startMatchingOpt
,
4621 OSArray
* personalityNames
)
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
4633 IORecursiveLockLock(sKextLock
);
4635 if (!kextIdentifier
) {
4636 result
= kOSKextReturnInvalidArgument
;
4640 OSKext::recordIdentifierRequest(kextIdentifier
);
4642 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
4644 if (!allowDeferFlag
) {
4645 OSKextLog(/* kext */ NULL
,
4646 kOSKextLogErrorLevel
|
4648 "Can't load kext %s - not found.",
4649 kextIdentifier
->getCStringNoCopy());
4653 if (!sKernelRequestsEnabled
) {
4655 kOSKextLogErrorLevel
|
4657 "Can't load kext %s - requests to user space are disabled.",
4658 kextIdentifier
->getCStringNoCopy());
4659 result
= kOSKextReturnDisabled
;
4663 /* Create a new request unless one is already sitting
4664 * in sKernelRequests for this bundle identifier
4666 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4667 if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4668 result
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
,
4670 if (result
!= kOSReturnSuccess
) {
4673 if (!_OSKextSetRequestArgument(loadRequest
,
4674 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
4675 result
= kOSKextReturnNoMemory
;
4678 if (!sKernelRequests
->setObject(loadRequest
)) {
4679 result
= kOSKextReturnNoMemory
;
4683 if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4684 result
= kOSKextReturnNoMemory
;
4689 kOSKextLogDebugLevel
|
4691 "Kext %s not found; queued load request to user space.",
4692 kextIdentifier
->getCStringNoCopy());
4695 pingResult
= OSKext::pingKextd();
4696 if (pingResult
== kOSKextReturnDisabled
) {
4697 OSKextLog(/* kext */ NULL
,
4698 ((sPrelinkBoot
) ? kOSKextLogDebugLevel
: kOSKextLogErrorLevel
) |
4700 "Kext %s might not load - kextd is currently unavailable.",
4701 kextIdentifier
->getCStringNoCopy());
4704 result
= kOSKextReturnDeferred
;
4708 result
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
);
4710 if (result
!= kOSReturnSuccess
) {
4712 kOSKextLogErrorLevel
|
4714 "Failed to load kext %s (error 0x%x).",
4715 kextIdentifier
->getCStringNoCopy(), (int)result
);
4717 OSKext::removeKext(theKext
,
4718 /* terminateService/removePersonalities */ true);
4722 if (delayAutounloadFlag
) {
4724 kOSKextLogProgressLevel
|
4725 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4726 "Setting delayed autounload for %s.",
4727 kextIdentifier
->getCStringNoCopy());
4728 theKext
->flags
.delayAutounload
= 1;
4732 OSSafeReleaseNULL(loadRequest
);
4733 OSSafeReleaseNULL(kextIdentifierSymbol
);
4735 if ((kOSReturnSuccess
== result
) && kextRef
) {
4737 theKext
->matchingRefCount
++;
4741 IORecursiveLockUnlock(sKextLock
);
4745 /*********************************************************************
4746 *********************************************************************/
4749 OSKext::dropMatchingReferences(
4752 IORecursiveLockLock(sKextLock
);
4753 kexts
->iterateObjects(^bool (OSObject
* obj
) {
4754 OSKext
* thisKext
= OSDynamicCast(OSKext
, obj
);
4758 thisKext
->matchingRefCount
--;
4761 IORecursiveLockUnlock(sKextLock
);
4764 /*********************************************************************
4765 *********************************************************************/
4768 OSKext::recordIdentifierRequest(
4769 OSString
* kextIdentifier
)
4771 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4774 if (!sAllKextLoadIdentifiers
|| !kextIdentifier
) {
4778 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4779 if (!kextIdentifierSymbol
) {
4780 // xxx - this is really a basic alloc failure
4785 IORecursiveLockLock(sKextLock
);
4786 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4787 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
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());
4799 IORecursiveLockUnlock(sKextLock
);
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());
4810 OSSafeReleaseNULL(kextIdentifierSymbol
);
4814 /*********************************************************************
4815 *********************************************************************/
4818 OSKextExcludeLevel startOpt
,
4819 OSKextExcludeLevel startMatchingOpt
,
4820 OSArray
* personalityNames
)
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
;
4830 if (isInExcludeList()) {
4832 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
|
4834 "Kext %s is in exclude list, not loadable",
4835 getIdentifierCString());
4837 result
= kOSKextReturnNotLoadable
;
4842 alreadyLoaded
= true;
4843 result
= kOSReturnSuccess
;
4846 kOSKextLogDebugLevel
|
4847 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4848 "Kext %s is already loaded.",
4849 getIdentifierCString());
4854 if (current_task() != kernel_task
) {
4855 int macCheckResult
= 0;
4856 kauth_cred_t cred
= NULL
;
4858 cred
= kauth_cred_get_with_ref();
4859 macCheckResult
= mac_kext_check_load(cred
, getIdentifierCString());
4860 kauth_cred_unref(&cred
);
4862 if (macCheckResult
!= 0) {
4863 result
= kOSReturnError
;
4865 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4866 "Failed to load kext %s (MAC policy error 0x%x).",
4867 getIdentifierCString(), macCheckResult
);
4873 if (!sLoadEnabled
) {
4875 kOSKextLogErrorLevel
|
4877 "Kext loading is disabled (attempt to load kext %s).",
4878 getIdentifierCString());
4879 result
= kOSKextReturnDisabled
;
4883 /* If we've pushed the next available load tag to the invalid value,
4884 * we can't load any more kexts.
4886 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4888 kOSKextLogErrorLevel
|
4890 "Can't load kext %s - no more load tags to assign.",
4891 getIdentifierCString());
4892 result
= kOSKextReturnNoResources
;
4896 /* This is a bit of a hack, because we shouldn't be handling
4897 * personalities within the load function.
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
4904 if (strcmp(getIdentifierCString(), "com.apple.driver.KextExcludeList") == 0) {
4905 boolean_t updated
= updateExcludeList(infoDict
);
4908 kOSKextLogDebugLevel
| kOSKextLogLoadFlag
,
4909 "KextExcludeList was updated to version: %lld", sExcludeListVersion
);
4913 if (isDriverKit()) {
4915 sLoadedDriverKitKexts
->setObject(this);
4916 loadTag
= sNextLoadTag
++;
4919 result
= kOSReturnSuccess
;
4923 /* Are we in safe boot?
4925 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4927 kOSKextLogErrorLevel
|
4929 "Can't load kext %s - not loadable during safe boot.",
4930 getIdentifierCString());
4931 result
= kOSKextReturnBootLevel
;
4936 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4938 getIdentifierCString());
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);
4946 kOSKextLogErrorLevel
|
4947 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4948 "Can't load kext %s - failed to create link context.",
4949 getIdentifierCString());
4950 result
= kOSKextReturnNoMemory
;
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.
4959 if (!resolveDependencies()) {
4960 // xxx - check resolveDependencies() for log msg
4962 kOSKextLogErrorLevel
|
4963 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4964 "Can't load kext %s - failed to resolve library dependencies.",
4965 getIdentifierCString());
4966 result
= kOSKextReturnDependencies
;
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.
4974 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4975 dependenciesStartOpt
= kOSKextExcludeNone
;
4978 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4979 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4982 /* Load the dependencies, recursively.
4984 count
= getNumDependencies();
4985 for (i
= 0; i
< count
; i
++) {
4986 OSKext
* dependency
= OSDynamicCast(OSKext
,
4987 dependencies
->getObject(i
));
4988 if (dependency
== NULL
) {
4990 kOSKextLogErrorLevel
|
4991 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4992 "Internal error loading kext %s; dependency disappeared.",
4993 getIdentifierCString());
4994 result
= kOSKextReturnInternalError
;
4998 /* Dependencies must be started accorting to the opt,
4999 * but not given the personality names of the main kext.
5001 result
= dependency
->load(dependenciesStartOpt
,
5002 dependenciesStartMatchingOpt
,
5003 /* personalityNames */ NULL
);
5004 if (result
!= KERN_SUCCESS
) {
5006 kOSKextLogErrorLevel
|
5007 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
5008 "Dependency %s of kext %s failed to load.",
5009 dependency
->getIdentifierCString(),
5010 getIdentifierCString());
5012 OSKext::removeKext(dependency
,
5013 /* terminateService/removePersonalities */ true);
5014 result
= kOSKextReturnDependencyLoadError
;
5020 result
= loadExecutable();
5021 if (result
!= KERN_SUCCESS
) {
5025 pendingPgoHead
.next
= &pendingPgoHead
;
5026 pendingPgoHead
.prev
= &pendingPgoHead
;
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);
5033 result
= KERN_MEMORY_ERROR
;
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
;
5046 flags
.loaded
= true;
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).
5052 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
5053 sLoadedKexts
->setObject(this);
5055 /* Keep the kernel itself out of the kmod list.
5057 if (lastLoadedKext
->isKernel()) {
5058 lastLoadedKext
= NULL
;
5061 if (lastLoadedKext
) {
5062 kmod_info
->next
= lastLoadedKext
->kmod_info
;
5065 notifyKextLoadObservers(this, kmod_info
);
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.
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.)
5078 /* Save the list of loaded kexts in case we panic.
5080 OSKext::saveLoadedKextPanicList();
5082 if (isExecutable()) {
5083 OSKext::updateLoadedKextSummaries();
5084 savePanicString(/* isLoading */ true);
5087 registerWithDTrace();
5089 jettisonLinkeditSegment();
5090 #endif /* CONFIG_DTRACE */
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
5097 jettisonDATASegmentPadding();
5102 if (isExecutable() && !flags
.started
) {
5103 if (startOpt
== kOSKextExcludeNone
) {
5105 if (result
!= kOSReturnSuccess
) {
5107 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5108 "Kext %s start failed (result 0x%x).",
5109 getIdentifierCString(), result
);
5110 result
= kOSKextReturnStartStopError
;
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.
5120 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
5121 result
= sendPersonalitiesToCatalog(true, personalityNames
);
5126 if (result
!= kOSReturnSuccess
) {
5128 kOSKextLogErrorLevel
|
5130 "Kext %s failed to load (0x%x).",
5131 getIdentifierCString(), (int)result
);
5132 } else if (!alreadyLoaded
) {
5134 kOSKextLogProgressLevel
|
5137 getIdentifierCString());
5139 queueKextNotification(kKextRequestPredicateLoadNotification
,
5140 OSDynamicCast(OSString
, bundleID
));
5145 /*********************************************************************
5147 *********************************************************************/
5149 strdup(const char * string
)
5151 char * result
= NULL
;
5158 size
= 1 + strlen(string
);
5159 result
= (char *)kalloc_tag(size
, VM_KERN_MEMORY_OSKEXT
);
5164 memcpy(result
, string
, size
);
5170 /*********************************************************************
5172 *********************************************************************/
5175 OSKext::lookupSection(const char *segname
, const char *secname
)
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
;
5182 if (!linkedExecutable
) {
5186 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
5188 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
5189 if (0 != strncmp(seg
->segname
, segname
, sizeof(seg
->segname
))) {
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
;
5202 return found_section
;
5205 /*********************************************************************
5207 *********************************************************************/
5210 OSKext::slidePrelinkedExecutable(bool doCoalesedSlides
)
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
;
5228 vm_offset_t new_kextsize
;
5230 if (linkedExecutable
== NULL
|| flags
.builtin
) {
5231 result
= kOSReturnSuccess
;
5235 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
5236 segmentSplitInfo
= (struct linkedit_data_command
*) getcommandfromheader(mh
, LC_SEGMENT_SPLIT_INFO
);
5238 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
5243 seg
->vmaddr
= ml_static_slide(seg
->vmaddr
);
5245 #if KASLR_KEXT_DEBUG
5246 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
5248 (unsigned long)ml_static_unslide(seg
->vmaddr
),
5249 (unsigned long)seg
->vmaddr
);
5252 if (!haveRelocBase
) {
5253 relocBase
= (char *) seg
->vmaddr
;
5254 haveRelocBase
= true;
5256 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
5257 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
5258 haveLinkeditBase
= true;
5261 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
5262 sec
->addr
= ml_static_slide(sec
->addr
);
5264 #if KASLR_KEXT_DEBUG
5265 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
5267 (unsigned long)ml_static_unslide(sec
->addr
),
5268 (unsigned long)sec
->addr
);
5273 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
5275 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
5277 if (symtab
!= NULL
&& doCoalesedSlides
== false) {
5278 /* Some pseudo-kexts have symbol tables without segments.
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
) {
5286 sym
[i
].n_value
= ml_static_slide(sym
[i
].n_value
);
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
);
5300 if (dysymtab
!= NULL
&& doCoalesedSlides
== false) {
5301 if (dysymtab
->nextrel
> 0) {
5303 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5305 "Sliding kext %s: External relocations found.",
5306 getIdentifierCString());
5310 if (dysymtab
->nlocrel
> 0) {
5311 if (!haveLinkeditBase
) {
5313 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5315 "Sliding kext %s: No linkedit segment.",
5316 getIdentifierCString());
5320 if (!haveRelocBase
) {
5322 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5325 "Sliding kext %s: No writable segments.",
5327 "Sliding kext %s: No segments.",
5329 getIdentifierCString());
5333 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
5334 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
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)
5342 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5344 "Sliding kext %s: Unexpected relocation found.",
5345 getIdentifierCString());
5348 if (reloc
[i
].r_pcrel
!= 0) {
5351 uintptr_t *relocAddr
= (uintptr_t*)(relocBase
+ reloc
[i
].r_address
);
5352 *relocAddr
= ml_static_slide(*relocAddr
);
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
)));
5364 /* We should free these relocations, not just delete the reference to them.
5365 * <rdar://problem/10535549> Free relocations from PIE kexts.
5367 * For now, we do not free LINKEDIT for kexts with split segments.
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
;
5377 /* fix up symbol offsets if they are after the dsymtab local relocs */
5379 if (dysymtab
->locreloff
< symtab
->symoff
) {
5380 symtab
->symoff
-= reloc_size
;
5382 if (dysymtab
->locreloff
< symtab
->stroff
) {
5383 symtab
->stroff
-= reloc_size
;
5386 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
5387 dysymtab
->extreloff
-= reloc_size
;
5390 /* move data behind reloc info down to new offset */
5391 if (endofrelocInfo
< endofkext
) {
5392 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
5395 /* Create a new OSData for the smaller kext object and reflect
5396 * new linkedit segment size.
5398 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
5399 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
5401 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
5403 /* Fix up kmod info and linkedExecutable.
5405 kmod_info
->size
= new_kextsize
;
5407 new_osdata
->setDeallocFunction(osdata_kext_free
);
5409 new_osdata
->setDeallocFunction(osdata_phys_free
);
5411 linkedExecutable
->setDeallocFunction(NULL
);
5412 linkedExecutable
->release();
5413 linkedExecutable
= new_osdata
;
5416 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
5418 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
5422 dysymtab
->nlocrel
= 0;
5423 dysymtab
->locreloff
= 0;
5427 result
= kOSReturnSuccess
;
5432 /*********************************************************************
5433 * called only by load()
5434 *********************************************************************/
5436 OSKext::loadExecutable()
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
5453 /* We need the version string for a variety of bits below.
5455 versString
= OSDynamicCast(OSString
,
5456 getPropertyForHostArch(kCFBundleVersionKey
));
5460 versCString
= versString
->getCStringNoCopy();
5462 if (isKernelComponent()) {
5463 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
5464 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
5466 kOSKextLogErrorLevel
|
5468 "Kernel component %s has incorrect version %s; "
5470 getIdentifierCString(),
5471 versCString
, KERNEL6_VERSION
);
5472 result
= kOSKextReturnInternalError
;
5474 } else if (strcmp(versCString
, osrelease
)) {
5476 kOSKextLogErrorLevel
|
5478 "Kernel component %s has incorrect version %s; "
5480 getIdentifierCString(),
5481 versCString
, osrelease
);
5482 result
= kOSKextReturnInternalError
;
5488 if (isPrelinked()) {
5492 /* <rdar://problem/21444003> all callers must be entitled */
5493 if (FALSE
== IOTaskHasEntitlement(current_task(), kOSKextManagementEntitlement
)) {
5495 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5496 "Not entitled to link kext '%s'",
5497 getIdentifierCString());
5498 result
= kOSKextReturnNotPrivileged
;
5502 theExecutable
= getExecutable();
5503 if (!theExecutable
) {
5504 if (declaresExecutable()) {
5506 kOSKextLogErrorLevel
|
5508 "Can't load kext %s - executable is missing.",
5509 getIdentifierCString());
5510 result
= kOSKextReturnValidation
;
5516 if (isInterface()) {
5517 OSData
*executableCopy
= OSData::withData(theExecutable
);
5518 setLinkedExecutable(executableCopy
);
5519 executableCopy
->release();
5523 numDirectDependencies
= getNumDependencies();
5525 if (flags
.hasBleedthrough
) {
5526 linkDependencies
= dependencies
;
5527 linkDependencies
->retain();
5529 linkDependencies
= OSArray::withArray(dependencies
);
5530 if (!linkDependencies
) {
5532 kOSKextLogErrorLevel
|
5533 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5534 "Can't allocate link dependencies to load kext %s.",
5535 getIdentifierCString());
5539 for (i
= 0; i
< numDirectDependencies
; ++i
) {
5540 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
5541 dependencies
->getObject(i
));
5542 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
5546 num_kxlddeps
= linkDependencies
->getCount();
5547 if (!num_kxlddeps
) {
5549 kOSKextLogErrorLevel
|
5550 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
5551 "Can't load kext %s - it has no library dependencies.",
5552 getIdentifierCString());
5556 kxlddeps
= (KXLDDependency
*)kalloc_tag(num_kxlddeps
* sizeof(*kxlddeps
), VM_KERN_MEMORY_OSKEXT
);
5559 kOSKextLogErrorLevel
|
5560 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5561 "Can't allocate link context to load kext %s.",
5562 getIdentifierCString());
5565 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
5567 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5568 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
5570 if (dependency
->isInterface()) {
5571 OSKext
*interfaceTargetKext
= NULL
;
5572 OSData
* interfaceTarget
= NULL
;
5574 if (dependency
->isKernelComponent()) {
5575 interfaceTargetKext
= sKernelKext
;
5576 interfaceTarget
= sKernelKext
->linkedExecutable
;
5578 interfaceTargetKext
= OSDynamicCast(OSKext
,
5579 dependency
->dependencies
->getObject(0));
5581 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
5584 if (!interfaceTarget
) {
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.
5593 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
5594 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
5595 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
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());
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());
5606 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
5609 kxldHeaderPtr
= &kxld_header
;
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"
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
);
5627 /* After this call, the linkedExecutable instance variable
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
);
5636 if (kxldResult
!= KERN_SUCCESS
) {
5637 // xxx - add kxldResult here?
5639 kOSKextLogErrorLevel
|
5641 "Can't load kext %s - link failed.",
5642 getIdentifierCString());
5643 result
= kOSKextReturnLinkError
;
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
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);
5657 if (isInterface()) {
5658 /* Whip up a fake kmod_info entry for the interface kext.
5660 kmod_info
= (kmod_info_t
*)kalloc_tag(sizeof(kmod_info_t
), VM_KERN_MEMORY_OSKEXT
);
5662 result
= KERN_MEMORY_ERROR
;
5666 /* A pseudokext has almost nothing in its kmod_info struct.
5668 bzero(kmod_info
, sizeof(kmod_info_t
));
5670 kmod_info
->info_version
= KMOD_INFO_VERSION
;
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.
5676 interfaceUUID
= copyUUID();
5679 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5680 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5682 /* Stamp the bundle ID and version from the OSKext over anything
5683 * resident inside the kmod_info.
5685 string
= getIdentifierCString();
5686 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5688 string
= versCString
;
5689 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5691 /* Add the dependencies' kmod_info structs as kmod_references.
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
;
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
++;
5709 if (refIndex
+ 1 < num_kmod_refs
) {
5710 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5715 if (!isInterface() && linkedExecutable
) {
5717 kOSKextLogProgressLevel
|
5719 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5721 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5722 (unsigned long)ml_static_unslide(kmod_info
->address
),
5723 (unsigned)kmod_info
->id
);
5726 /* if prelinked, VM protections are already set */
5727 result
= setVMAttributes(!isPrelinked(), true);
5728 if (result
!= KERN_SUCCESS
) {
5733 if (linkedExecutable
) {
5734 kasan_load_kext((vm_offset_t
)linkedExecutable
->getBytesNoCopy(),
5735 linkedExecutable
->getLength(), getIdentifierCString());
5738 if (lookupSection(KASAN_GLOBAL_SEGNAME
, KASAN_GLOBAL_SECTNAME
)) {
5740 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5741 "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
5742 getIdentifierCString()
5744 result
= KERN_FAILURE
;
5749 result
= kOSReturnSuccess
;
5752 OSSafeReleaseNULL(linkDependencies
);
5754 /* Clear up locally allocated dependency info.
5756 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5759 if (kxlddeps
[i
].kext_name
) {
5760 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5761 kfree(kxlddeps
[i
].kext_name
, size
);
5763 if (kxlddeps
[i
].interface_name
) {
5764 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5765 kfree(kxlddeps
[i
].interface_name
, size
);
5769 kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5772 /* We no longer need the unrelocated executable (which the linker
5773 * has altered anyhow).
5775 setExecutable(NULL
);
5777 if (result
!= kOSReturnSuccess
) {
5779 kOSKextLogErrorLevel
|
5781 "Failed to load executable for kext %s.",
5782 getIdentifierCString());
5784 if (kmod_info
&& kmod_info
->reference_list
) {
5785 kfree(kmod_info
->reference_list
,
5786 num_kmod_refs
* sizeof(kmod_reference_t
));
5788 if (isInterface()) {
5789 kfree(kmod_info
, sizeof(kmod_info_t
));
5792 if (linkedExecutable
) {
5793 linkedExecutable
->release();
5794 linkedExecutable
= NULL
;
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 *********************************************************************/
5808 OSKext::jettisonLinkeditSegment(void)
5810 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5811 kernel_segment_command_t
* linkedit
= NULL
;
5813 vm_size_t linkeditsize
, kextsize
;
5814 OSData
* data
= NULL
;
5817 /* We can free symbol tables for all embedded kexts because we don't
5818 * support runtime kext linking.
5820 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5822 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
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.
5831 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5836 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5837 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
)) {
5841 /* Create a new OSData for the smaller kext object.
5843 linkeditsize
= round_page(linkedit
->vmsize
);
5844 kextsize
= kmod_info
->size
- linkeditsize
;
5845 start
= linkedit
->vmaddr
;
5847 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5852 /* Fix the kmod info and linkedExecutable.
5854 kmod_info
->size
= kextsize
;
5857 data
->setDeallocFunction(osdata_kext_free
);
5859 data
->setDeallocFunction(osdata_phys_free
);
5861 linkedExecutable
->setDeallocFunction(NULL
);
5862 linkedExecutable
->release();
5863 linkedExecutable
= data
;
5864 flags
.jettisonLinkeditSeg
= 1;
5866 /* Free the linkedit segment.
5869 kext_free(start
, linkeditsize
);
5871 ml_static_mfree(start
, linkeditsize
);
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
5882 *********************************************************************/
5884 OSKext::jettisonDATASegmentPadding(void)
5886 kernel_mach_header_t
* mh
;
5887 kernel_segment_command_t
* dataSeg
;
5888 kernel_section_t
* sec
, * lastSec
;
5889 vm_offset_t dataSegEnd
, lastSecEnd
;
5892 if (flags
.builtin
) {
5895 mh
= (kernel_mach_header_t
*)kmod_info
->address
;
5897 dataSeg
= getsegbynamefromheader(mh
, SEG_DATA
);
5898 if (dataSeg
== NULL
) {
5903 sec
= firstsect(dataSeg
);
5904 while (sec
!= NULL
) {
5906 sec
= nextsect(dataSeg
, sec
);
5909 if (lastSec
== NULL
) {
5913 if ((dataSeg
->vmaddr
!= round_page(dataSeg
->vmaddr
)) ||
5914 (dataSeg
->vmsize
!= round_page(dataSeg
->vmsize
))) {
5918 dataSegEnd
= dataSeg
->vmaddr
+ dataSeg
->vmsize
;
5919 lastSecEnd
= round_page(lastSec
->addr
+ lastSec
->size
);
5921 if (dataSegEnd
<= lastSecEnd
) {
5925 padSize
= dataSegEnd
- lastSecEnd
;
5927 if (padSize
>= PAGE_SIZE
) {
5929 kext_free(lastSecEnd
, padSize
);
5931 ml_static_mfree(lastSecEnd
, padSize
);
5936 /*********************************************************************
5937 *********************************************************************/
5939 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5941 if (linkedExecutable
) {
5942 panic("Attempt to set linked executable on kext "
5943 "that already has one (%s).\n",
5944 getIdentifierCString());
5946 linkedExecutable
= anExecutable
;
5947 linkedExecutable
->retain();
5952 /*********************************************************************
5953 * Go through all loaded kexts and tell them to register with dtrace.
5954 * The instance method only registers if necessary.
5955 *********************************************************************/
5958 OSKext::registerKextsWithDTrace(void)
5960 uint32_t count
= sLoadedKexts
->getCount();
5963 IORecursiveLockLock(sKextLock
);
5965 for (i
= 0; i
< count
; i
++) {
5966 OSKext
* thisKext
= NULL
;// do not release
5968 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5969 if (!thisKext
|| !thisKext
->isExecutable()) {
5973 thisKext
->registerWithDTrace();
5976 IORecursiveLockUnlock(sKextLock
);
5982 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5983 extern int (*dtrace_modunload
)(struct kmod_info
*);
5986 /*********************************************************************
5987 *********************************************************************/
5989 OSKext::registerWithDTrace(void)
5991 /* Register kext with dtrace. A dtrace_modload failure should not
5992 * prevent a kext from loading, so we ignore the return code.
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
;
6000 if (flags
.builtin
) {
6001 modflag
|= KMOD_DTRACE_STATIC_KEXT
;
6004 (void)(*dtrace_modload
)(kmod_info
, modflag
);
6005 flags
.dtraceInitialized
= true;
6006 jettisonLinkeditSegment();
6010 /*********************************************************************
6011 *********************************************************************/
6013 OSKext::unregisterWithDTrace(void)
6015 /* Unregister kext with dtrace. A dtrace_modunload failure should not
6016 * prevent a kext from loading, so we ignore the return code.
6018 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
6019 (void)(*dtrace_modunload
)(kmod_info
);
6020 flags
.dtraceInitialized
= false;
6024 #endif /* CONFIG_DTRACE */
6027 /*********************************************************************
6028 * called only by loadExecutable()
6029 *********************************************************************/
6030 #if !VM_MAPPED_KEXTS
6031 #if defined(__arm__) || defined(__arm64__)
6032 static inline kern_return_t
6035 vm_map_offset_t start
,
6036 vm_map_offset_t end
,
6041 assert(map
== kernel_map
); // we can handle KEXTs arising from the PRELINK segment and no others
6042 assert(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
6048 return ml_static_protect(start
, end
- start
, new_prot
);
6052 static inline kern_return_t
6055 vm_map_offset_t start
,
6056 vm_map_offset_t end
,
6057 vm_prot_t access_type
,
6058 boolean_t user_wire
)
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
6064 #error Unrecognized architecture
6067 static inline kern_return_t
6070 vm_map_offset_t start
,
6071 vm_map_offset_t end
,
6075 if (start
== end
) { // 10538581
6076 return KERN_SUCCESS
;
6078 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
6081 static inline kern_return_t
6084 vm_map_offset_t start
,
6085 vm_map_offset_t end
,
6086 vm_prot_t access_type
,
6087 boolean_t user_wire
)
6089 return vm_map_wire_kernel(map
, start
, end
, access_type
, VM_KERN_MEMORY_KEXT
, user_wire
);
6094 OSKext::setVMAttributes(bool protect
, bool wire
)
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
;
6102 if (isInterface() || !declaresExecutable() || flags
.builtin
) {
6103 result
= kOSReturnSuccess
;
6107 /* Get the kext's vm map */
6108 kext_map
= kext_get_vm_map(kmod_info
);
6110 result
= KERN_MEMORY_ERROR
;
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.
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
6123 result
= KERN_SUCCESS
;
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
)
6132 if (result
!= KERN_SUCCESS
) {
6136 /* Set the VM protections and wire down each of the segments */
6137 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
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);
6145 start
= round_page(seg
->vmaddr
);
6146 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
6149 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
6150 if (result
!= KERN_SUCCESS
) {
6152 kOSKextLogErrorLevel
|
6154 "Kext %s failed to set maximum VM protections "
6155 "for segment %s - 0x%x.",
6156 getIdentifierCString(), seg
->segname
, (int)result
);
6160 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
6161 if (result
!= KERN_SUCCESS
) {
6163 kOSKextLogErrorLevel
|
6165 "Kext %s failed to set initial VM protections "
6166 "for segment %s - 0x%x.",
6167 getIdentifierCString(), seg
->segname
, (int)result
);
6172 if (segmentShouldBeWired(seg
) && wire
) {
6173 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
6174 if (result
!= KERN_SUCCESS
) {
6179 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6186 /*********************************************************************
6187 *********************************************************************/
6189 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
6191 return sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
));
6194 /*********************************************************************
6195 *********************************************************************/
6197 OSKext::validateKextMapping(bool startFlag
)
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;
6207 mach_msg_type_number_t count
;
6208 vm_region_submap_short_info_data_64_t info
;
6210 if (flags
.builtin
) {
6211 return kOSReturnSuccess
;
6214 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
6215 bzero(&info
, sizeof(info
));
6217 // xxx - do we need a distinct OSReturn value for these or is "bad data"
6218 // xxx - sufficient?
6220 /* Verify that the kmod_info and start/stop pointers are non-NULL.
6224 kOSKextLogErrorLevel
|
6226 "Kext %s - NULL kmod_info pointer.",
6227 getIdentifierCString());
6228 result
= kOSKextReturnBadData
;
6233 address
= (mach_vm_address_t
)kmod_info
->start
;
6235 address
= (mach_vm_address_t
)kmod_info
->stop
;
6240 kOSKextLogErrorLevel
|
6242 "Kext %s - NULL module %s pointer.",
6243 getIdentifierCString(), whichOp
);
6244 result
= kOSKextReturnBadData
;
6248 kext_map
= kext_get_vm_map(kmod_info
);
6249 depth
= (kernel_map
== kext_map
) ? 1 : 2;
6251 /* Verify that the start/stop function lies within the kext's address range.
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.
6257 for (seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6259 seg
= nextsegfromheader((kernel_mach_header_t
*)kmod_info
->address
, seg
)) {
6260 if ((address
>= seg
->vmaddr
) && address
< (seg
->vmaddr
+ seg
->vmsize
)) {
6267 kOSKextLogErrorLevel
|
6269 "Kext %s module %s pointer is outside of kext range "
6270 "(%s %p - kext starts at %p).",
6271 getIdentifierCString(),
6274 (void *)ml_static_unslide(address
),
6275 (void *)ml_static_unslide(kmod_info
->address
));
6276 result
= kOSKextReturnBadData
;
6282 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
6283 kmod_info
->address
+ kmod_info
->size
<= address
) {
6285 kOSKextLogErrorLevel
|
6287 "Kext %s module %s pointer is outside of kext range "
6288 "(%s %p - kext at %p-%p).",
6289 getIdentifierCString(),
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
;
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.
6305 /* Verify that the start/stop function is executable.
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
) {
6311 kOSKextLogErrorLevel
|
6313 "Kext %s - bad %s pointer %p.",
6314 getIdentifierCString(),
6315 whichOp
, (void *)ml_static_unslide(address
));
6316 result
= kOSKextReturnBadData
;
6321 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
6323 kOSKextLogErrorLevel
|
6325 "Kext %s - memory region containing module %s function "
6326 "is not executable.",
6327 getIdentifierCString(), whichOp
);
6328 result
= kOSKextReturnBadData
;
6333 /* Verify that the kext's segments are backed by physical memory.
6335 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6337 if (!verifySegmentMapping(seg
)) {
6338 result
= kOSKextReturnBadData
;
6342 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6346 result
= kOSReturnSuccess
;
6351 /*********************************************************************
6352 *********************************************************************/
6354 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
6356 mach_vm_address_t address
= 0;
6358 if (!segmentShouldBeWired(seg
)) {
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
)) {
6367 kOSKextLogErrorLevel
|
6369 "Kext %s - page %p is not backed by physical memory.",
6370 getIdentifierCString(),
6379 /*********************************************************************
6380 *********************************************************************/
6382 OSKextLogKextInfo(OSKext
*aKext
, uint64_t address
, uint64_t size
, firehose_tracepoint_code_t code
)
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
);
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
);
6394 uuid_data
= aKext
->copyTextUUID();
6396 memcpy(uuid_info
->ftui_uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_info
->ftui_uuid
));
6397 OSSafeReleaseNULL(uuid_data
);
6400 uuid_info
->ftui_size
= size
;
6401 if (aKext
->isDriverKit()) {
6402 uuid_info
->ftui_address
= address
;
6404 uuid_info
->ftui_address
= ml_static_unslide(address
);
6406 firehose_trace_metadata(firehose_stream_metadata
, trace_id
, stamp
, uuid_info
, uuid_info_len
);
6411 OSKext::OSKextLogDriverKitInfoLoad(OSKext
*kext
)
6413 OSKextLogKextInfo(kext
, kext
->getLoadTag(), 1, firehose_tracepoint_code_load
);
6416 /*********************************************************************
6417 *********************************************************************/
6419 OSKext::start(bool startDependenciesFlag
)
6421 OSReturn result
= kOSReturnError
;
6422 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
6423 unsigned int i
, count
;
6424 void * kmodStartData
= NULL
;
6426 if (isStarted() || isInterface() || isKernelComponent()) {
6427 result
= kOSReturnSuccess
;
6433 kOSKextLogErrorLevel
|
6435 "Attempt to start nonloaded kext %s.",
6436 getIdentifierCString());
6437 result
= kOSKextReturnInvalidArgument
;
6441 if (!sLoadEnabled
) {
6443 kOSKextLogErrorLevel
|
6445 "Kext loading is disabled (attempt to start kext %s).",
6446 getIdentifierCString());
6447 result
= kOSKextReturnDisabled
;
6451 result
= validateKextMapping(/* start? */ true);
6452 if (result
!= kOSReturnSuccess
) {
6456 startfunc
= kmod_info
->start
;
6458 count
= getNumDependencies();
6459 for (i
= 0; i
< count
; i
++) {
6460 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
6461 if (dependency
== NULL
) {
6463 kOSKextLogErrorLevel
|
6465 "Kext %s start - internal error, dependency disappeared.",
6466 getIdentifierCString());
6469 if (!dependency
->isStarted()) {
6470 if (startDependenciesFlag
) {
6471 OSReturn dependencyResult
=
6472 dependency
->start(startDependenciesFlag
);
6473 if (dependencyResult
!= KERN_SUCCESS
) {
6475 kOSKextLogErrorLevel
|
6477 "Kext %s start - dependency %s failed to start (error 0x%x).",
6478 getIdentifierCString(),
6479 dependency
->getIdentifierCString(),
6485 kOSKextLogErrorLevel
|
6487 "Not starting %s - dependency %s not started yet.",
6488 getIdentifierCString(),
6489 dependency
->getIdentifierCString());
6490 result
= kOSKextReturnStartStopError
; // xxx - make new return?
6497 kOSKextLogDetailLevel
|
6499 "Kext %s calling module start function.",
6500 getIdentifierCString());
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
);
6513 /* On success overlap the setting of started/starting. On failure just
6516 if (result
== KERN_SUCCESS
) {
6519 // xxx - log start error from kernel?
6521 kOSKextLogProgressLevel
|
6523 "Kext %s is now started.",
6524 getIdentifierCString());
6526 invokeOrCancelRequestCallbacks(
6527 /* result not actually used */ kOSKextReturnStartStopError
,
6528 /* invokeFlag */ false);
6530 kOSKextLogProgressLevel
|
6532 "Kext %s did not start (return code 0x%x).",
6533 getIdentifierCString(), result
);
6540 /*********************************************************************
6541 *********************************************************************/
6544 OSKext::canUnloadKextWithIdentifier(
6545 OSString
* kextIdentifier
,
6546 bool checkClassesFlag
)
6548 bool result
= false;
6549 OSKext
* aKext
= NULL
;// do not release
6551 IORecursiveLockLock(sKextLock
);
6553 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
6556 goto finish
; // can't unload what's not loaded
6559 if (aKext
->isLoaded()) {
6560 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
6563 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
6571 IORecursiveLockUnlock(sKextLock
);
6575 /*********************************************************************
6576 *********************************************************************/
6580 OSReturn result
= kOSReturnError
;
6581 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
6583 if (!isStarted() || isInterface()) {
6584 result
= kOSReturnSuccess
;
6590 kOSKextLogErrorLevel
|
6592 "Attempt to stop nonloaded kext %s.",
6593 getIdentifierCString());
6594 result
= kOSKextReturnInvalidArgument
;
6598 /* Refuse to stop if we have clients or instances. It is up to
6599 * the caller to make sure those aren't true.
6601 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6603 kOSKextLogErrorLevel
|
6605 "Kext %s - C++ instances; can't stop.",
6606 getIdentifierCString());
6607 result
= kOSKextReturnInUse
;
6611 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6613 kOSKextLogErrorLevel
|
6615 "Kext %s - has references (linkage or tracking object); "
6617 getIdentifierCString());
6618 result
= kOSKextReturnInUse
;
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.
6626 result
= validateKextMapping(/* start? */ false);
6627 if (result
!= kOSReturnSuccess
) {
6631 stopfunc
= kmod_info
->stop
;
6634 kOSKextLogDetailLevel
|
6636 "Kext %s calling module stop function.",
6637 getIdentifierCString());
6641 result
= stopfunc(kmod_info
, /* userData */ NULL
);
6642 if (result
== KERN_SUCCESS
) {
6643 result
= OSRuntimeFinalizeCPP(this);
6648 if (result
== KERN_SUCCESS
) {
6652 kOSKextLogDetailLevel
|
6654 "Kext %s is now stopped and ready to unload.",
6655 getIdentifierCString());
6658 kOSKextLogErrorLevel
|
6660 "Kext %s did not stop (return code 0x%x).",
6661 getIdentifierCString(), result
);
6662 result
= kOSKextReturnStartStopError
;
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
);
6672 /*********************************************************************
6673 *********************************************************************/
6675 OSKext::unload(void)
6677 OSReturn result
= kOSReturnError
;
6679 uint32_t num_kmod_refs
= 0;
6680 OSKextAccount
* freeAccount
;
6682 if (!sUnloadEnabled
) {
6684 kOSKextLogErrorLevel
|
6686 "Kext unloading is disabled (%s).",
6687 this->getIdentifierCString());
6689 result
= kOSKextReturnDisabled
;
6693 /* Refuse to unload if we have clients or instances. It is up to
6694 * the caller to make sure those aren't true.
6696 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6697 // xxx - Don't log under errors? this is more of an info thing
6699 kOSKextLogErrorLevel
|
6700 kOSKextLogKextBookkeepingFlag
,
6701 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6702 getIdentifierCString());
6703 result
= kOSKextReturnInUse
;
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
);
6717 result
= kOSReturnSuccess
;
6721 if (isKernelComponent()) {
6722 result
= kOSKextReturnInvalidArgument
;
6726 if (metaClasses
&& !OSMetaClass::removeClasses(metaClasses
)) {
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
;
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
6743 flags
.unloading
= 1;
6745 /* Update the string describing the last kext to unload in case we panic.
6747 savePanicString(/* isLoading */ false);
6751 if (result
!= KERN_SUCCESS
) {
6753 kOSKextLogErrorLevel
|
6755 "Kext %s can't unload - module stop returned 0x%x.",
6756 getIdentifierCString(), (unsigned)result
);
6757 result
= kOSKextReturnStartStopError
;
6763 kOSKextLogProgressLevel
|
6765 "Kext %s unloading.",
6766 getIdentifierCString());
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
);
6781 IORecursiveLockWakeup(sKextLock
, s
, false);
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.
6792 metaClasses
->flushCollection();
6794 (void) OSRuntimeFinalizeCPP(this);
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).
6800 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
6801 if (index
!= (unsigned int)-1) {
6802 sLoadedKexts
->removeObject(index
);
6804 OSKext
* nextKext
= OSDynamicCast(OSKext
,
6805 sLoadedKexts
->getObject(index
));
6809 OSKext
* gapKext
= OSDynamicCast(OSKext
,
6810 sLoadedKexts
->getObject(index
- 1));
6812 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
6813 } else { /* index == 0 */
6814 nextKext
->kmod_info
->next
= NULL
;
6818 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
6819 if (lastKext
&& !lastKext
->isKernel()) {
6820 kmod
= lastKext
->kmod_info
;
6822 kmod
= NULL
; // clear the global kmod variable
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.
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
--;
6836 kfree(kmod_info
->reference_list
,
6837 num_kmod_refs
* sizeof(kmod_reference_t
));
6841 unregisterWithDTrace();
6842 #endif /* CONFIG_DTRACE */
6844 notifyKextUnloadObservers(this);
6847 IOSimpleLockLock(sKextAccountsLock
);
6848 account
->kext
= NULL
;
6849 if (account
->site
.tag
) {
6850 account
->site
.flags
|= VM_TAG_UNLOAD
;
6852 freeAccount
= account
;
6854 IOSimpleLockUnlock(sKextAccountsLock
);
6856 IODelete(freeAccount
, OSKextAccount
, 1);
6859 /* Unwire and free the linked executable.
6861 if (linkedExecutable
) {
6863 kasan_unload_kext((vm_offset_t
)linkedExecutable
->getBytesNoCopy(), linkedExecutable
->getLength());
6867 if (!isInterface()) {
6868 kernel_segment_command_t
*seg
= NULL
;
6869 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6873 kOSKextLogErrorLevel
|
6875 "Failed to free kext %s; couldn't find the kext map.",
6876 getIdentifierCString());
6877 result
= kOSKextReturnInternalError
;
6882 kOSKextLogProgressLevel
|
6884 "Kext %s unwiring and unmapping linked executable.",
6885 getIdentifierCString());
6887 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6889 if (segmentShouldBeWired(seg
)) {
6890 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6891 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6892 if (result
!= KERN_SUCCESS
) {
6894 kOSKextLogErrorLevel
|
6896 "Failed to unwire kext %s.",
6897 getIdentifierCString());
6898 result
= kOSKextReturnInternalError
;
6903 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6907 OSSafeReleaseNULL(linkedExecutable
);
6910 /* An interface kext has a fake kmod_info that was allocated,
6911 * so we have to free it.
6913 if (isInterface()) {
6914 kfree(kmod_info
, sizeof(kmod_info_t
));
6919 flags
.loaded
= false;
6920 flushDependencies();
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
6927 if (isPrelinked()) {
6928 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6929 IORecursiveLockLock(sKextLock
);
6930 if (sUnloadedPrelinkedKexts
) {
6931 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6933 IORecursiveLockUnlock(sKextLock
);
6938 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6939 "Kext %s unloaded.", getIdentifierCString());
6941 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6942 OSDynamicCast(OSString
, bundleID
));
6945 OSKext::saveLoadedKextPanicList();
6946 OSKext::updateLoadedKextSummaries();
6948 flags
.unloading
= 0;
6952 /*********************************************************************
6953 * Assumes sKextLock is held.
6954 *********************************************************************/
6957 OSKext::queueKextNotification(
6958 const char * notificationName
,
6959 OSString
* kextIdentifier
)
6961 OSReturn result
= kOSReturnError
;
6962 OSDictionary
* loadRequest
= NULL
;// must release
6964 if (!kextIdentifier
) {
6965 result
= kOSKextReturnInvalidArgument
;
6969 /* Create a new request unless one is already sitting
6970 * in sKernelRequests for this bundle identifier
6972 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6973 if (result
!= kOSReturnSuccess
) {
6976 if (!_OSKextSetRequestArgument(loadRequest
,
6977 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6978 result
= kOSKextReturnNoMemory
;
6981 if (!sKernelRequests
->setObject(loadRequest
)) {
6982 result
= kOSKextReturnNoMemory
;
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.
6991 OSKext::pingKextd();
6993 result
= kOSReturnSuccess
;
6996 OSSafeReleaseNULL(loadRequest
);
7001 /*********************************************************************
7002 *********************************************************************/
7004 _OSKextConsiderDestroyingLinkContext(
7005 __unused thread_call_param_t p0
,
7006 __unused thread_call_param_t p1
)
7008 /* Take multiple locks in the correct order.
7010 IORecursiveLockLock(sKextLock
);
7011 IORecursiveLockLock(sKextInnerLock
);
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.
7018 if (sConsiderUnloadsCalled
&& sKxldContext
) {
7019 kxld_destroy_context(sKxldContext
);
7020 sKxldContext
= NULL
;
7023 /* Free the thread_call that was allocated to execute this function.
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.");
7032 sDestroyLinkContextThread
= NULL
;
7035 IORecursiveLockUnlock(sKextInnerLock
);
7036 IORecursiveLockUnlock(sKextLock
);
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.
7047 * This function must be invoked with sKextInnerLock held.
7048 * Do not call any function that takes sKextLock here!
7049 *********************************************************************/
7052 OSKext::considerDestroyingLinkContext(void)
7054 IORecursiveLockLock(sKextInnerLock
);
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.
7059 if (sDestroyLinkContextThread
) {
7063 /* The function to be invoked in the thread will deallocate
7064 * this thread_call, so don't share it around.
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.");
7075 thread_call_enter(sDestroyLinkContextThread
);
7078 IORecursiveLockUnlock(sKextInnerLock
);
7083 #pragma mark Autounload
7085 /*********************************************************************
7086 * This is a static method because the kext will be deallocated if it
7088 *********************************************************************/
7091 OSKext::autounloadKext(OSKext
* aKext
)
7093 OSReturn result
= kOSKextReturnInUse
;
7095 /* Check for external references to this kext (usu. dependents),
7096 * instances of defined classes (or classes derived from them),
7097 * outstanding requests.
7099 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
7100 !aKext
->flags
.autounloadEnabled
||
7101 aKext
->isKernelComponent()) {
7105 /* Skip a delay-autounload kext, once.
7107 if (aKext
->flags
.delayAutounload
) {
7109 kOSKextLogProgressLevel
|
7110 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
7111 "Kext %s has delayed autounload set; skipping and clearing flag.",
7112 aKext
->getIdentifierCString());
7113 aKext
->flags
.delayAutounload
= 0;
7117 if (aKext
->hasOSMetaClassInstances() ||
7118 aKext
->countRequestCallbacks()) {
7122 result
= OSKext::removeKext(aKext
);
7128 /*********************************************************************
7129 *********************************************************************/
7131 _OSKextConsiderUnloads(
7132 __unused thread_call_param_t p0
,
7133 __unused thread_call_param_t p1
)
7135 bool didUnload
= false;
7136 unsigned int count
, i
;
7138 /* Take multiple locks in the correct order
7139 * (note also sKextSummaries lock further down).
7141 IORecursiveLockLock(sKextLock
);
7142 IORecursiveLockLock(sKextInnerLock
);
7144 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
7146 /* If the system is powering down, don't try to unload anything.
7152 OSKextLog(/* kext */ NULL
,
7153 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
7154 "Checking for unused kexts to autounload.");
7157 * Remove any request callbacks marked as stale,
7158 * and mark as stale any currently in flight.
7160 count
= sRequestCallbackRecords
->getCount();
7164 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
7165 sRequestCallbackRecords
->getObject(i
));
7166 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
7167 callbackRecord
->getObject(kKextRequestStaleKey
));
7169 if (stale
== kOSBooleanTrue
) {
7170 OSKext::invokeRequestCallback(callbackRecord
,
7171 kOSKextReturnTimeout
);
7173 callbackRecord
->setObject(kKextRequestStaleKey
,
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....
7191 count
= sLoadedKexts
->getCount();
7195 OSKext
* thisKext
= OSDynamicCast(OSKext
,
7196 sLoadedKexts
->getObject(i
));
7197 didUnload
|= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
7200 } while (didUnload
);
7203 sConsiderUnloadsPending
= false;
7204 sConsiderUnloadsExecuted
= true;
7206 (void) OSKext::considerRebuildOfPrelinkedKernel();
7208 IORecursiveLockUnlock(sKextInnerLock
);
7209 IORecursiveLockUnlock(sKextLock
);
7214 /*********************************************************************
7215 * Do not call any function that takes sKextLock here!
7216 *********************************************************************/
7218 OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
7222 IORecursiveLockLock(sKextInnerLock
);
7224 if (!sUnloadCallout
) {
7225 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, NULL
);
7228 /* we only reset delay value for unloading if we already have something
7229 * pending. rescheduleOnlyFlag should not start the count down.
7231 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
7235 thread_call_cancel(sUnloadCallout
);
7236 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
7237 clock_interval_to_deadline(sConsiderUnloadDelay
,
7238 1000 * 1000 * 1000, &when
);
7240 OSKextLog(/* kext */ NULL
,
7241 kOSKextLogProgressLevel
|
7243 "%scheduling %sscan for unused kexts in %lu seconds.",
7244 sConsiderUnloadsPending
? "Res" : "S",
7245 sConsiderUnloadsCalled
? "" : "initial ",
7246 (unsigned long)sConsiderUnloadDelay
);
7248 sConsiderUnloadsPending
= true;
7249 thread_call_enter_delayed(sUnloadCallout
, when
);
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.
7258 if (!sConsiderUnloadsCalled
) {
7259 sConsiderUnloadsCalled
= true;
7260 OSKext::considerDestroyingLinkContext();
7263 IORecursiveLockUnlock(sKextInnerLock
);
7267 /*********************************************************************
7268 * Do not call any function that takes sKextLock here!
7269 *********************************************************************/
7271 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
);
7273 OSKextSystemSleepOrWake(UInt32 messageType
)
7275 IORecursiveLockLock(sKextInnerLock
);
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.
7283 if (messageType
== kIOMessageSystemWillSleep
) {
7284 if (sUnloadCallout
) {
7285 thread_call_cancel(sUnloadCallout
);
7287 sSystemSleep
= true;
7288 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
7289 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
7290 sSystemSleep
= false;
7291 clock_get_uptime(&sLastWakeTime
);
7293 IORecursiveLockUnlock(sKextInnerLock
);
7295 return kIOReturnSuccess
;
7301 #pragma mark Prelinked Kernel
7303 /*********************************************************************
7304 * Do not access sConsiderUnloads... variables other than
7305 * sConsiderUnloadsExecuted in this function. They are guarded by a
7307 *********************************************************************/
7310 OSKext::considerRebuildOfPrelinkedKernel(void)
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
;
7322 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
7323 if (requestedPrelink
|| !sPrelinkBoot
) {
7327 /* no direct return from this point */
7328 IORecursiveLockLock(sKextLock
);
7330 /* We need to wait for kextd to get up and running with unloads already done
7331 * and any new startup kexts loaded.
7333 if (!sConsiderUnloadsExecuted
||
7334 !sDeferredLoadSucceeded
) {
7338 /* we really only care about boot / system start up related kexts so bail
7339 * if we're here after REBUILD_MAX_TIME.
7341 if (!_OSKextInPrelinkRebuildWindow()) {
7342 OSKextLog(/* kext */ NULL
,
7343 kOSKextLogArchiveFlag
,
7344 "%s prebuild rebuild has expired",
7346 requestedPrelink
= true;
7350 /* we do not want to trigger a rebuild if we get here too close to waking
7351 * up. (see radar 10233768)
7353 IORecursiveLockLock(sKextInnerLock
);
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
);
7362 IORecursiveLockUnlock(sKextInnerLock
);
7364 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
7365 /* too close to time of last wake from sleep */
7368 requestedPrelink
= true;
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)
7375 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
7376 if (!kextIterator
) {
7380 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
7381 OSKext
* thisKext
;// do not release
7383 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
7384 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
7388 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
7391 /* kext is loaded and was not in current kernel cache so let's rebuild
7394 OSKextLog(/* kext */ NULL
,
7395 kOSKextLogArchiveFlag
,
7396 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
7397 thisKext
->bundleID
->getCStringNoCopy());
7400 sUnloadedPrelinkedKexts
->flushCollection();
7406 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
7408 if (checkResult
!= kOSReturnSuccess
) {
7412 if (!sKernelRequests
->setObject(prelinkRequest
)) {
7416 OSKext::pingKextd();
7419 IORecursiveLockUnlock(sKextLock
);
7420 OSSafeReleaseNULL(prelinkRequest
);
7421 OSSafeReleaseNULL(kextIterator
);
7427 #pragma mark Dependencies
7429 /*********************************************************************
7430 *********************************************************************/
7432 OSKext::resolveDependencies(
7433 OSArray
* loopStack
)
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;
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).
7454 if (flags
.hasAllDependencies
) {
7459 /* Check for loops in the dependency graph.
7462 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
7464 kOSKextLogErrorLevel
|
7465 kOSKextLogDependenciesFlag
,
7466 "Kext %s has a dependency loop; can't resolve dependencies.",
7467 getIdentifierCString());
7472 kOSKextLogStepLevel
|
7473 kOSKextLogDependenciesFlag
,
7474 "Kext %s resolving dependencies.",
7475 getIdentifierCString());
7477 loopStack
= OSArray::withCapacity(6); // any small capacity will do
7480 kOSKextLogErrorLevel
|
7481 kOSKextLogDependenciesFlag
,
7482 "Kext %s can't create bookkeeping stack to resolve dependencies.",
7483 getIdentifierCString());
7486 localLoopStack
= loopStack
;
7488 if (!loopStack
->setObject(this)) {
7490 kOSKextLogErrorLevel
|
7491 kOSKextLogDependenciesFlag
,
7492 "Kext %s - internal error resolving dependencies.",
7493 getIdentifierCString());
7496 addedToLoopStack
= true;
7498 /* Purge any existing kexts in the dependency list and start over.
7500 flushDependencies();
7503 kOSKextLogErrorLevel
|
7504 kOSKextLogDependenciesFlag
,
7505 "Kext %s - internal error resolving dependencies.",
7506 getIdentifierCString());
7509 libraries
= OSDynamicCast(OSDictionary
,
7510 getPropertyForHostArch(kOSBundleLibrariesKey
));
7511 if (libraries
== NULL
|| libraries
->getCount() == 0) {
7513 kOSKextLogErrorLevel
|
7514 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7515 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7516 getIdentifierCString(), kOSBundleLibrariesKey
);
7520 /* Make a new array to hold the dependencies (flush freed the old one).
7522 dependencies
= OSArray::withCapacity(libraries
->getCount());
7523 if (!dependencies
) {
7525 kOSKextLogErrorLevel
|
7526 kOSKextLogDependenciesFlag
,
7527 "Kext %s - can't allocate dependencies array.",
7528 getIdentifierCString());
7532 // xxx - compat: We used to add an implicit dependency on kernel 6.0
7533 // xxx - compat: if none were declared.
7535 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
7536 if (!libraryIterator
) {
7538 kOSKextLogErrorLevel
|
7539 kOSKextLogDependenciesFlag
,
7540 "Kext %s - can't allocate dependencies iterator.",
7541 getIdentifierCString());
7545 while ((libraryID
= OSDynamicCast(OSString
,
7546 libraryIterator
->getNextObject()))) {
7547 const char * library_id
= libraryID
->getCStringNoCopy();
7549 OSString
* libraryVersion
= OSDynamicCast(OSString
,
7550 libraries
->getObject(libraryID
));
7551 if (libraryVersion
== NULL
) {
7553 kOSKextLogErrorLevel
|
7554 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7555 "Kext %s - illegal type in OSBundleLibraries.",
7556 getIdentifierCString());
7560 OSKextVersion libraryVers
=
7561 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
7562 if (libraryVers
== -1) {
7564 kOSKextLogErrorLevel
|
7565 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7566 "Kext %s - invalid library version %s.",
7567 getIdentifierCString(),
7568 libraryVersion
->getCStringNoCopy());
7572 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
7573 if (libraryKext
== NULL
) {
7575 kOSKextLogErrorLevel
|
7576 kOSKextLogDependenciesFlag
,
7577 "Kext %s - library kext %s not found.",
7578 getIdentifierCString(), library_id
);
7582 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
7584 kOSKextLogErrorLevel
|
7585 kOSKextLogDependenciesFlag
,
7586 "Kext %s - library kext %s not compatible "
7587 "with requested version %s.",
7588 getIdentifierCString(), library_id
,
7589 libraryVersion
->getCStringNoCopy());
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.
7597 if (this->isPrelinked() &&
7598 libraryKext
->declaresExecutable() &&
7599 !libraryKext
->isPrelinked()) {
7601 kOSKextLogErrorLevel
|
7602 kOSKextLogDependenciesFlag
,
7603 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7604 getIdentifierCString(), library_id
,
7605 libraryVersion
->getCStringNoCopy());
7609 if (!libraryKext
->resolveDependencies(loopStack
)) {
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.
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
);
7626 kOSKextLogDetailLevel
|
7627 kOSKextLogDependenciesFlag
,
7628 "Kext %s added dependency %s.",
7629 getIdentifierCString(),
7630 libraryKext
->getIdentifierCString());
7633 int numLibDependencies
= libraryKext
->getNumDependencies();
7634 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
7637 if (numLibDependencies
) {
7638 // xxx - this msg level should be 1 lower than the per-kext one
7640 kOSKextLogDetailLevel
|
7641 kOSKextLogDependenciesFlag
,
7642 "Kext %s pulling %d dependencies from codeless library %s.",
7643 getIdentifierCString(),
7645 libraryKext
->getIdentifierCString());
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
);
7653 kOSKextLogDetailLevel
|
7654 kOSKextLogDependenciesFlag
,
7655 "Kext %s added dependency %s from codeless library %s.",
7656 getIdentifierCString(),
7657 thisLibDependency
->getIdentifierCString(),
7658 libraryKext
->getIdentifierCString());
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;
7676 if (hasRawKernelDependency
) {
7678 kOSKextLogErrorLevel
|
7679 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7680 "Error - kext %s declares a dependency on %s, which is not permitted.",
7681 getIdentifierCString(), KERNEL_LIB
);
7685 if (hasKernelDependency
) {
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
);
7694 if (!hasKPIDependency
) {
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
);
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.*"?
7707 if (hasKernelDependency
&& hasKPIDependency
) {
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
);
7716 if (!hasKernelDependency
&& !hasKPIDependency
) {
7717 // xxx - do we want to use validation flag for these too?
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
));
7726 dependencies
->setObject(kernelKext
);
7729 kOSKextLogErrorLevel
|
7730 kOSKextLogDependenciesFlag
,
7731 "Error - Library %s not found for %s.",
7732 KERNEL6_LIB
, getIdentifierCString());
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.
7740 if (!hasKPIDependency
) {
7743 flags
.hasBleedthrough
= true;
7745 count
= getNumDependencies();
7747 /* We add to the dependencies array in this loop, but do not iterate
7748 * past its original count.
7750 for (i
= 0; i
< count
; i
++) {
7751 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
7752 dependencies
->getObject(i
));
7753 dependencyKext
->addBleedthroughDependencies(dependencies
);
7756 #endif /* __LP64__ */
7758 if (hasPrivateKPIDependency
) {
7759 bool hasApplePrefix
= false;
7760 bool infoCopyrightIsValid
= false;
7761 bool readableCopyrightIsValid
= false;
7763 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
7766 infoString
= OSDynamicCast(OSString
,
7767 getPropertyForHostArch("CFBundleGetInfoString"));
7769 infoCopyrightIsValid
=
7770 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
7773 readableString
= OSDynamicCast(OSString
,
7774 getPropertyForHostArch("NSHumanReadableCopyright"));
7775 if (readableString
) {
7776 readableCopyrightIsValid
=
7777 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
7780 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
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
);
7792 flags
.hasAllDependencies
= 1;
7796 if (addedToLoopStack
) {
7797 count
= loopStack
->getCount();
7798 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
7799 loopStack
->removeObject(count
- 1);
7802 kOSKextLogErrorLevel
|
7803 kOSKextLogDependenciesFlag
,
7804 "Kext %s - internal error resolving dependencies.",
7805 getIdentifierCString());
7809 if (result
&& localLoopStack
) {
7811 kOSKextLogStepLevel
|
7812 kOSKextLogDependenciesFlag
,
7813 "Kext %s successfully resolved dependencies.",
7814 getIdentifierCString());
7817 OSSafeReleaseNULL(localLoopStack
);
7818 OSSafeReleaseNULL(libraryIterator
);
7823 /*********************************************************************
7824 *********************************************************************/
7826 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
7828 bool result
= false;
7829 unsigned int dependencyIndex
, dependencyCount
;
7831 dependencyCount
= getNumDependencies();
7833 for (dependencyIndex
= 0;
7834 dependencyIndex
< dependencyCount
;
7835 dependencyIndex
++) {
7836 OSKext
* dependency
= OSDynamicCast(OSKext
,
7837 dependencies
->getObject(dependencyIndex
));
7840 kOSKextLogErrorLevel
|
7841 kOSKextLogDependenciesFlag
,
7842 "Kext %s - internal error propagating compatibility dependencies.",
7843 getIdentifierCString());
7846 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7847 anArray
->setObject(dependency
);
7849 dependency
->addBleedthroughDependencies(anArray
);
7858 /*********************************************************************
7859 *********************************************************************/
7861 OSKext::flushDependencies(bool forceFlag
)
7863 bool result
= false;
7865 /* Only clear the dependencies if the kext isn't loaded;
7866 * we need the info for loaded kexts to track references.
7868 if (!isLoaded() || forceFlag
) {
7870 // xxx - check level
7872 kOSKextLogProgressLevel
|
7873 kOSKextLogDependenciesFlag
,
7874 "Kext %s flushing dependencies.",
7875 getIdentifierCString());
7876 OSSafeReleaseNULL(dependencies
);
7878 if (!isKernelComponent()) {
7879 flags
.hasAllDependencies
= 0;
7887 /*********************************************************************
7888 *********************************************************************/
7890 OSKext::getNumDependencies(void)
7892 if (!dependencies
) {
7895 return dependencies
->getCount();
7898 /*********************************************************************
7899 *********************************************************************/
7901 OSKext::getDependencies(void)
7903 return dependencies
;
7907 #pragma mark OSMetaClass Support
7909 /*********************************************************************
7910 *********************************************************************/
7913 OSMetaClass
* aClass
,
7914 uint32_t numClasses
)
7916 OSReturn result
= kOSMetaClassNoInsKModSet
;
7919 metaClasses
= OSSet::withCapacity(numClasses
);
7925 if (metaClasses
->containsObject(aClass
)) {
7927 kOSKextLogWarningLevel
|
7929 "Notice - kext %s has already registered class %s.",
7930 getIdentifierCString(),
7931 aClass
->getClassName());
7932 result
= kOSReturnSuccess
;
7936 if (!metaClasses
->setObject(aClass
)) {
7940 kOSKextLogDetailLevel
|
7942 "Kext %s registered class %s.",
7943 getIdentifierCString(),
7944 aClass
->getClassName());
7947 if (!flags
.autounloadEnabled
) {
7948 const OSMetaClass
* metaScan
= NULL
;// do not release
7950 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7951 if (metaScan
== OSTypeID(IOService
)) {
7953 kOSKextLogProgressLevel
|
7955 "Kext %s has IOService subclass %s; enabling autounload.",
7956 getIdentifierCString(),
7957 aClass
->getClassName());
7959 flags
.autounloadEnabled
= 1;
7965 notifyAddClassObservers(this, aClass
, flags
);
7967 result
= kOSReturnSuccess
;
7970 if (result
!= kOSReturnSuccess
) {
7972 kOSKextLogErrorLevel
|
7974 "Kext %s failed to register class %s.",
7975 getIdentifierCString(),
7976 aClass
->getClassName());
7982 /*********************************************************************
7983 *********************************************************************/
7985 OSKext::removeClass(
7986 OSMetaClass
* aClass
)
7988 OSReturn result
= kOSMetaClassNoKModSet
;
7994 if (!metaClasses
->containsObject(aClass
)) {
7996 kOSKextLogWarningLevel
|
7998 "Notice - kext %s asked to unregister unknown class %s.",
7999 getIdentifierCString(),
8000 aClass
->getClassName());
8001 result
= kOSReturnSuccess
;
8006 kOSKextLogDetailLevel
|
8008 "Kext %s unregistering class %s.",
8009 getIdentifierCString(),
8010 aClass
->getClassName());
8012 metaClasses
->removeObject(aClass
);
8014 notifyRemoveClassObservers(this, aClass
, flags
);
8016 result
= kOSReturnSuccess
;
8019 if (result
!= kOSReturnSuccess
) {
8021 kOSKextLogErrorLevel
|
8023 "Failed to unregister kext %s class %s.",
8024 getIdentifierCString(),
8025 aClass
->getClassName());
8030 /*********************************************************************
8031 *********************************************************************/
8033 OSKext::getMetaClasses(void)
8038 /*********************************************************************
8039 *********************************************************************/
8041 OSKext::hasOSMetaClassInstances(void)
8043 bool result
= false;
8044 OSCollectionIterator
* classIterator
= NULL
; // must release
8045 OSMetaClass
* checkClass
= NULL
;// do not release
8051 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
8052 if (!classIterator
) {
8053 // xxx - log alloc failure?
8056 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
8057 if (checkClass
->getInstanceCount()) {
8065 OSSafeReleaseNULL(classIterator
);
8069 /*********************************************************************
8070 *********************************************************************/
8073 OSKext::reportOSMetaClassInstances(
8074 const char * kextIdentifier
,
8075 OSKextLogSpec msgLogSpec
)
8077 OSKext
* theKext
= NULL
; // must release
8079 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
8084 theKext
->reportOSMetaClassInstances(msgLogSpec
);
8086 OSSafeReleaseNULL(theKext
);
8090 /*********************************************************************
8091 *********************************************************************/
8093 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
8095 OSCollectionIterator
* classIterator
= NULL
; // must release
8096 OSMetaClass
* checkClass
= NULL
;// do not release
8102 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
8103 if (!classIterator
) {
8106 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
8107 if (checkClass
->getInstanceCount()) {
8110 " Kext %s class %s has %d instance%s.",
8111 getIdentifierCString(),
8112 checkClass
->getClassName(),
8113 checkClass
->getInstanceCount(),
8114 checkClass
->getInstanceCount() == 1 ? "" : "s");
8119 OSSafeReleaseNULL(classIterator
);
8124 #pragma mark User-Space Requests
8126 /*********************************************************************
8127 * XXX - this function is a big ugly mess
8128 *********************************************************************/
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
,
8139 uint32_t * logInfoLengthOut
)
8141 OSReturn result
= kOSReturnError
;
8142 kern_return_t kmem_result
= KERN_FAILURE
;
8144 char * response
= NULL
;// returned by reference
8145 uint32_t responseLength
= 0;
8147 OSObject
* parsedXML
= NULL
;// must release
8148 OSDictionary
* requestDict
= NULL
;// do not release
8149 OSString
* errorString
= NULL
;// must release
8151 OSObject
* responseObject
= NULL
;// must release
8153 OSSerialize
* serializer
= NULL
;// must release
8155 OSArray
* logInfoArray
= NULL
;// must release
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
8163 IORecursiveLockLock(sKextLock
);
8166 *responseOut
= NULL
;
8167 *responseLengthOut
= 0;
8171 *logInfoLengthOut
= 0;
8174 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
8176 /* XML must be nul-terminated.
8178 if (requestBuffer
[requestLength
- 1] != '\0') {
8179 OSKextLog(/* kext */ NULL
,
8180 kOSKextLogErrorLevel
|
8182 "Invalid request from user space (not nul-terminated).");
8183 result
= kOSKextReturnBadData
;
8186 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
8188 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
8191 const char * errorCString
= "(unknown error)";
8193 if (errorString
&& errorString
->getCStringNoCopy()) {
8194 errorCString
= errorString
->getCStringNoCopy();
8195 } else if (parsedXML
) {
8196 errorCString
= "not a dictionary";
8198 OSKextLog(/* kext */ NULL
,
8199 kOSKextLogErrorLevel
|
8201 "Error unserializing request from user space: %s.",
8203 result
= kOSKextReturnSerialization
;
8207 predicate
= _OSKextGetRequestPredicate(requestDict
);
8209 OSKextLog(/* kext */ NULL
,
8210 kOSKextLogErrorLevel
|
8212 "Recieved kext request from user space with no predicate.");
8213 result
= kOSKextReturnInvalidArgument
;
8217 OSKextLog(/* kext */ NULL
,
8218 kOSKextLogDebugLevel
|
8220 "Received '%s' request from user space.",
8221 predicate
->getCStringNoCopy());
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
|
8234 "Access Failure - must be root user.");
8239 /* Get common args in anticipation of use.
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
));
8248 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
8249 requestDict
, kKextRequestArgumentValueKey
));
8251 result
= kOSKextReturnInvalidArgument
;
8253 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
8254 if (!kextIdentifier
) {
8255 OSKextLog(/* kext */ NULL
,
8256 kOSKextLogErrorLevel
|
8258 "Invalid arguments to kext start request.");
8259 } else if (!theKext
) {
8260 OSKextLog(/* kext */ NULL
,
8261 kOSKextLogErrorLevel
|
8263 "Kext %s not found for start request.",
8264 kextIdentifier
->getCStringNoCopy());
8265 result
= kOSKextReturnNotFound
;
8267 result
= theKext
->start();
8269 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
8270 if (!kextIdentifier
) {
8271 OSKextLog(/* kext */ NULL
,
8272 kOSKextLogErrorLevel
|
8274 "Invalid arguments to kext stop request.");
8275 } else if (!theKext
) {
8276 OSKextLog(/* kext */ NULL
,
8277 kOSKextLogErrorLevel
|
8279 "Kext %s not found for stop request.",
8280 kextIdentifier
->getCStringNoCopy());
8281 result
= kOSKextReturnNotFound
;
8283 result
= theKext
->stop();
8285 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
8286 if (!kextIdentifier
) {
8287 OSKextLog(/* kext */ NULL
,
8288 kOSKextLogErrorLevel
|
8290 "Invalid arguments to kext unload request.");
8291 } else if (!theKext
) {
8292 OSKextLog(/* kext */ NULL
,
8293 kOSKextLogErrorLevel
|
8295 "Kext %s not found for unload request.",
8296 kextIdentifier
->getCStringNoCopy());
8297 result
= kOSKextReturnNotFound
;
8299 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
8300 _OSKextGetRequestArgument(requestDict
,
8301 kKextRequestArgumentTerminateIOServicesKey
));
8302 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
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
));
8312 responseObject
= OSKext::copyKextUUIDForAddress(lookupNum
);
8313 if (responseObject
) {
8314 result
= kOSReturnSuccess
;
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;
8325 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
8326 _OSKextGetRequestArgument(requestDict
,
8327 kKextRequestArgumentDelayAutounloadKey
));
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.
8332 if (delayAutounloadBool
== kOSBooleanTrue
) {
8333 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8336 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
8337 kKextRequestArgumentInfoKeysKey
);
8338 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
8339 if (infoKeysRaw
&& !infoKeys
) {
8340 OSKextLog(/* kext */ NULL
,
8341 kOSKextLogErrorLevel
|
8343 "Invalid arguments to kext info request.");
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
|
8354 "Invalid arguments to kext info request.");
8360 if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
8361 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
8362 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
8363 responseObject
= OSKext::copyLoadedKextInfoByUUID(kextIdentifiers
, infoKeys
);
8365 if (!responseObject
) {
8366 result
= kOSKextReturnInternalError
;
8368 OSKextLog(/* kext */ NULL
,
8369 kOSKextLogDebugLevel
|
8371 "Returning loaded kext info.");
8372 result
= kOSReturnSuccess
;
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.
8378 responseObject
= sKernelRequests
;
8379 sKernelRequests
= OSArray::withCapacity(0);
8380 sPostedKextLoadIdentifiers
->flushCollection();
8381 OSKextLog(/* kext */ NULL
,
8382 kOSKextLogDebugLevel
|
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
|
8393 "Returning load requests.");
8394 result
= kOSReturnSuccess
;
8396 OSKextLog(/* kext */ NULL
,
8397 kOSKextLogDebugLevel
|
8399 "Received '%s' invalid request from user space.",
8400 predicate
->getCStringNoCopy());
8405 * Now we have handle the request, or not. Gather up the response & logging
8406 * info to ship to user space.
8409 /* Note: Nothing in OSKext is supposed to retain requestDict,
8410 * but you never know....
8412 if (requestDict
->getRetainCount() > 1) {
8413 OSKextLog(/* kext */ NULL
,
8414 kOSKextLogWarningLevel
|
8416 "Request from user space still retained by a kext; "
8417 "probable memory leak.");
8420 if (responseOut
&& responseObject
) {
8421 serializer
= OSSerialize::withCapacity(0);
8423 result
= kOSKextReturnNoMemory
;
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
;
8435 response
= (char *)serializer
->text();
8436 responseLength
= serializer
->getLength();
8439 if (responseOut
&& response
) {
8442 /* This kmem_alloc sets the return value of the function.
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
|
8450 "Failed to copy response to request from user space.");
8451 result
= kmem_result
;
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
;
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.
8471 logInfoArray
= OSKext::clearUserSpaceLogFilter();
8473 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
8474 (void)OSKext::serializeLogInfo(logInfoArray
,
8475 logInfoOut
, logInfoLengthOut
);
8478 IORecursiveLockUnlock(sKextLock
);
8480 OSSafeReleaseNULL(parsedXML
);
8481 OSSafeReleaseNULL(errorString
);
8482 OSSafeReleaseNULL(responseObject
);
8483 OSSafeReleaseNULL(serializer
);
8484 OSSafeReleaseNULL(logInfoArray
);
8490 // #include <InstrProfiling.h>
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
);
8510 OSKextPgoMetadataPut(char *pBuffer
,
8513 uint32_t *num_pairs
,
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
;
8522 if (pBuffer
&& bufferSize
&& *position
<= bufferSize
) {
8523 memcpy(pos
, key
, strlen_key
); pos
+= strlen_key
;
8525 memcpy(pos
, value
, strlen_value
); pos
+= strlen_value
;
8536 OSKextPgoMetadataPutMax(size_t *position
, const char *key
, size_t value_max
)
8538 *position
+= strlen(key
) + 1 + value_max
+ 1;
8544 OSKextPgoMetadataPutAll(OSKext
*kext
,
8545 uuid_t instance_uuid
,
8549 uint32_t *num_pairs
)
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;
8557 OSKextPgoMetadataPutMax(position
, "INSTANCE", 36);
8558 OSKextPgoMetadataPutMax(position
, "UUID", 36);
8559 OSKextPgoMetadataPutMax(position
, "TIMESTAMP", max_timestamp_string_size
);
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
);
8568 uuid_string_t uuid_string
;
8569 uuid_data
= kext
->copyUUID();
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
);
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
);
8589 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8590 "NAME", kext
->getIdentifierCString());
8592 char versionCString
[kOSKextVersionMaxLength
];
8593 OSKextVersionGetString(kext
->getVersion(), versionCString
, kOSKextVersionMaxLength
);
8594 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8595 "VERSION", versionCString
);
8600 OSKextPgoMetadataSize(OSKext
*kext
)
8602 size_t position
= 0;
8603 uuid_t fakeuuid
= {};
8604 OSKextPgoMetadataPutAll(kext
, fakeuuid
, NULL
, &position
, 0, NULL
);
8609 OSKextGrabPgoDataLocked(OSKext
*kext
,
8611 uuid_t instance_uuid
,
8614 uint64_t bufferSize
)
8618 kernel_section_t
*sect_prf_data
= NULL
;
8619 kernel_section_t
*sect_prf_name
= NULL
;
8620 kernel_section_t
*sect_prf_cnts
= NULL
;
8622 size_t metadata_size
= 0;
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");
8631 sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8633 if (!sect_prf_data
|| !sect_prf_name
|| !sect_prf_cnts
) {
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
);
8644 metadata_size
= OSKextPgoMetadataSize(kext
);
8645 size
+= metadata_size
;
8646 size
+= sizeof(pgo_metadata_footer
);
8654 if (pBuffer
&& bufferSize
) {
8655 if (bufferSize
< size
) {
8660 err
= __llvm_profile_write_buffer_internal(
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
);
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
);
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;
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
));
8697 OSKextGrabPgoData(uuid_t uuid
,
8700 uint64_t bufferSize
,
8701 int wait_for_unload
,
8705 OSKext
*kext
= NULL
;
8708 IORecursiveLockLock(sKextLock
);
8710 kext
= OSKext::lookupKextWithUUID(uuid
);
8716 if (wait_for_unload
) {
8717 OSKextGrabPgoStruct s
;
8719 s
.metadata
= metadata
;
8721 s
.pBuffer
= pBuffer
;
8722 s
.bufferSize
= bufferSize
;
8725 struct list_head
*prev
= &kext
->pendingPgoHead
;
8726 struct list_head
*next
= kext
->pendingPgoHead
.next
;
8728 s
.list_head
.prev
= prev
;
8729 s
.list_head
.next
= next
;
8731 prev
->next
= &s
.list_head
;
8732 next
->prev
= &s
.list_head
;
8737 IORecursiveLockSleep(sKextLock
, &s
, THREAD_ABORTSAFE
);
8739 prev
= s
.list_head
.prev
;
8740 next
= s
.list_head
.next
;
8747 err
= OSKextGrabPgoDataLocked(kext
, metadata
, kext
->instance_uuid
, pSize
, pBuffer
, bufferSize
);
8755 IORecursiveLockUnlock(sKextLock
);
8761 OSKextResetPgoCountersLock()
8763 IORecursiveLockLock(sKextLock
);
8767 OSKextResetPgoCountersUnlock()
8769 IORecursiveLockUnlock(sKextLock
);
8773 extern unsigned int not_in_kdp
;
8776 OSKextResetPgoCounters()
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
) {
8786 memset((void*)sect_prf_cnts
->addr
, 0, sect_prf_cnts
->size
);
8791 OSKext::copyLoadedKextInfoByUUID(
8792 OSArray
* kextIdentifiers
,
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()};
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
;
8810 cred
= kauth_cred_get_with_ref();
8811 macCheckResult
= mac_kext_check_query(cred
);
8812 kauth_cred_unref(&cred
);
8814 if (macCheckResult
!= 0) {
8815 OSKextLog(/* kext */ NULL
,
8816 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8817 "Failed to query kext info (MAC policy error 0x%x).",
8824 /* Empty list of UUIDs is equivalent to no list (get all).
8826 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8827 kextIdentifiers
= NULL
;
8828 } else if (kextIdentifiers
) {
8829 idCount
= kextIdentifiers
->getCount();
8834 if (infoKeys
&& !infoKeys
->getCount()) {
8838 max_count
= count
[0] + count
[1];
8839 result
= OSDictionary::withCapacity(max_count
);
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
;
8851 uuid_string_t uuid_key
;
8853 thisKext
= OSDynamicCast(OSKext
, list
[j
]->getObject(i
));
8858 uuid_data
= thisKext
->copyUUID();
8863 memcpy(&thisKextUUID
, uuid_data
->getBytesNoCopy(), sizeof(thisKextUUID
));
8864 OSSafeReleaseNULL(uuid_data
);
8866 uuid_unparse(thisKextUUID
, uuid_key
);
8868 uuid_data
= thisKext
->copyTextUUID();
8872 memcpy(&thisKextTextUUID
, uuid_data
->getBytesNoCopy(), sizeof(thisKextTextUUID
));
8873 OSSafeReleaseNULL(uuid_data
);
8875 /* Skip current kext if we have a list of UUIDs and
8876 * it isn't in the list.
8878 if (kextIdentifiers
) {
8879 includeThis
= false;
8881 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8882 const OSString
* wantedUUID
= OSDynamicCast(OSString
,
8883 kextIdentifiers
->getObject(idIndex
));
8886 uuid_parse(wantedUUID
->getCStringNoCopy(), uuid
);
8888 if ((0 == uuid_compare(uuid
, thisKextUUID
))
8889 || (0 == uuid_compare(uuid
, thisKextTextUUID
))) {
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.
8895 kextIdentifiers
->removeObject(idIndex
);
8896 uuid_unparse(uuid
, uuid_key
);
8906 kextInfo
= thisKext
->copyInfo(infoKeys
);
8908 result
->setObject(uuid_key
, kextInfo
);
8909 kextInfo
->release();
8912 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8919 IORecursiveLockUnlock(sKextLock
);
8924 /*********************************************************************
8925 *********************************************************************/
8928 OSKext::copyLoadedKextInfo(
8929 OSArray
* kextIdentifiers
,
8932 OSDictionary
* result
= NULL
;
8933 uint32_t idCount
= 0;
8936 IORecursiveLockLock(sKextLock
);
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
;
8944 cred
= kauth_cred_get_with_ref();
8945 macCheckResult
= mac_kext_check_query(cred
);
8946 kauth_cred_unref(&cred
);
8948 if (macCheckResult
!= 0) {
8949 OSKextLog(/* kext */ NULL
,
8950 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8951 "Failed to query kext info (MAC policy error 0x%x).",
8958 /* Empty list of bundle ids is equivalent to no list (get all).
8960 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8961 kextIdentifiers
= NULL
;
8962 } else if (kextIdentifiers
) {
8963 idCount
= kextIdentifiers
->getCount();
8968 if (infoKeys
&& !infoKeys
->getCount()) {
8972 onlyLoaded
= (!infoKeys
|| !_OSArrayContainsCString(infoKeys
, kOSBundleAllPrelinkedKey
));
8974 result
= OSDictionary::withCapacity(128);
8980 OSKextLog(/* kext */ NULL
,
8981 kOSKextLogErrorLevel
|
8982 kOSKextLogGeneralFlag
,
8983 "kaslr: vm_kernel_slide 0x%lx \n",
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
);
9017 sKextsByID
->iterateObjects(^bool (const OSSymbol
* thisKextID
, OSObject
* obj
)
9019 OSKext
* thisKext
= NULL
;// do not release
9020 Boolean includeThis
= true;
9021 OSDictionary
* kextInfo
= NULL
;// must release
9023 thisKext
= OSDynamicCast(OSKext
, obj
);
9028 /* Skip current kext if not yet started and caller didn't request all.
9030 if (onlyLoaded
&& (-1U == sLoadedKexts
->getNextIndexOfObject(thisKext
, 0))) {
9034 /* Skip current kext if we have a list of bundle IDs and
9035 * it isn't in the list.
9037 if (kextIdentifiers
) {
9038 includeThis
= false;
9040 for (uint32_t idIndex
= 0; idIndex
< idCount
; idIndex
++) {
9041 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
9042 kextIdentifiers
->getObject(idIndex
));
9043 if (thisKextID
->isEqualTo(thisRequestID
)) {
9054 kextInfo
= thisKext
->copyInfo(infoKeys
);
9056 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
9057 kextInfo
->release();
9063 IORecursiveLockUnlock(sKextLock
);
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)
9076 OSKext::copyInfo(OSArray
* infoKeys
)
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
9099 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
9105 /* Empty keys means no keys, but NULL is quicker to check.
9107 if (infoKeys
&& !infoKeys
->getCount()) {
9111 /* Headers, CPU type, and CPU subtype.
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();
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
;
9128 headerData
= OSData::withBytes(kext_mach_hdr
,
9129 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
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
) {
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
;
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) {
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
);
9177 segp
->vmaddr
= ml_static_unslide(segp
->vmaddr
);
9179 for (secp
= firstsect(segp
); secp
!= NULL
; secp
= nextsect(segp
, secp
)) {
9180 secp
->addr
= ml_static_unslide(secp
->addr
);
9183 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
9185 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
9187 #endif // SECURE_KERNEL
9189 if (_OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
)) {
9190 osLogDataHeaderRef
*header
;
9191 char headerBytes
[offsetof(osLogDataHeaderRef
, sections
) + NUM_OS_LOG_SECTIONS
* sizeof(header
->sections
[0])];
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;
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");
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
;
9215 logData
= OSData::withBytes(header
, (u_int
) (sizeof(osLogDataHeaderRef
)));
9219 res
= logData
->appendBytes(&(header
->sections
[0]), (u_int
)(header
->sect_count
* sizeof(header
->sections
[0])));
9224 res
= logData
->appendBytes(os_log_data
, (u_int
)header
->sections
[OS_LOG_SECT_IDX
].sect_size
);
9230 res
= logData
->appendBytes(cstring_data
, (u_int
)header
->sections
[CSTRING_SECT_IDX
].sect_size
);
9235 result
->setObject(kOSBundleLogStringsKey
, logData
);
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
) {
9245 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
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
) {
9255 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
9258 if (isDriverKit() && _OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
)) {
9259 osLogDataHeaderRef
*header
;
9260 char headerBytes
[offsetof(osLogDataHeaderRef
, sections
) + NUM_OS_LOG_SECTIONS
* sizeof(header
->sections
[0])];
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;
9271 logData
= OSData::withBytes(header
, (u_int
) (sizeof(osLogDataHeaderRef
)));
9275 res
= logData
->appendBytes(&(header
->sections
[0]), (u_int
)(header
->sect_count
* sizeof(header
->sections
[0])));
9279 result
->setObject(kOSBundleLogStringsKey
, logData
);
9284 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
9286 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
9290 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
9291 versionString
= OSDynamicCast(OSString
,
9292 getPropertyForHostArch(kCFBundleVersionKey
));
9293 if (versionString
) {
9294 result
->setObject(kCFBundleVersionKey
, versionString
);
9298 /* OSBundleCompatibleVersion.
9300 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
9301 versionString
= OSDynamicCast(OSString
,
9302 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
9303 if (versionString
) {
9304 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
9310 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
9312 result
->setObject(kOSBundlePathKey
, path
);
9317 /* OSBundleExecutablePath.
9319 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
9320 if (path
&& executableRelPath
) {
9321 uint32_t pathLength
= path
->getLength(); // gets incremented below
9323 // +1 for slash, +1 for \0
9324 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
9326 executablePathCString
= (char *)kalloc_tag((executablePathCStringSize
) *
9327 sizeof(char), VM_KERN_MEMORY_OSKEXT
); // +1 for \0
9328 if (!executablePathCString
) {
9331 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
9332 executablePathCStringSize
);
9333 executablePathCString
[pathLength
++] = '/';
9334 executablePathCString
[pathLength
++] = '\0';
9335 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
9336 executablePathCStringSize
);
9338 executablePathString
= OSString::withCString(executablePathCString
);
9340 if (!executablePathString
) {
9344 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
9345 } else if (flags
.builtin
) {
9346 result
->setObject(kOSBundleExecutablePathKey
, bundleID
);
9347 } else if (isDriverKit()) {
9349 // +1 for slash, +1 for \0
9350 uint32_t pathLength
= path
->getLength();
9351 executablePathCStringSize
= pathLength
+ 2;
9353 executablePathCString
= (char *)kalloc_tag((executablePathCStringSize
) *
9354 sizeof(char), VM_KERN_MEMORY_OSKEXT
);
9355 if (!executablePathCString
) {
9358 strlcpy(executablePathCString
, path
->getCStringNoCopy(), executablePathCStringSize
);
9359 executablePathCString
[pathLength
++] = '/';
9360 executablePathCString
[pathLength
++] = '\0';
9362 executablePathString
= OSString::withCString(executablePathCString
);
9364 if (!executablePathString
) {
9368 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
9373 /* UUID, if the kext has one.
9375 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
9378 result
->setObject(kOSBundleUUIDKey
, uuid
);
9382 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleTextUUIDKey
)) {
9383 uuid
= copyTextUUID();
9385 result
->setObject(kOSBundleTextUUIDKey
, uuid
); uuid
->release();
9390 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
9392 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSKernelResourceKey
)) {
9393 result
->setObject(kOSKernelResourceKey
,
9394 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
9397 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
9398 result
->setObject(kOSBundleIsInterfaceKey
,
9399 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
9402 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
9403 result
->setObject(kOSBundlePrelinkedKey
,
9404 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
9407 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
9408 result
->setObject(kOSBundleStartedKey
,
9409 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
9414 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
9415 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
9416 /* numBits */ 8 * sizeof(loadTag
));
9417 if (!scratchNumber
) {
9420 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
9421 OSSafeReleaseNULL(scratchNumber
);
9424 /* LoadAddress, LoadSize.
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
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;
9443 /* Interfaces always report 0 load address & size.
9444 * Just the way they roll.
9446 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
9447 * xxx - shouldn't have one!
9450 if (flags
.builtin
|| linkedExecutable
) {
9451 kernel_mach_header_t
*mh
= NULL
;
9452 kernel_segment_command_t
*seg
= NULL
;
9454 if (flags
.builtin
) {
9455 loadAddress
= kmod_info
->address
;
9456 loadSize
= kmod_info
->size
;
9458 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
9459 loadSize
= linkedExecutable
->getLength();
9461 mh
= (kernel_mach_header_t
*)loadAddress
;
9462 loadAddress
= ml_static_unslide(loadAddress
);
9464 /* Walk through the kext, looking for the first executable
9465 * segment in case we were asked for its size/address.
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
;
9475 /* If we have a kmod_info struct, calculated the wired size
9476 * from that. Otherwise it's the full load size.
9479 wiredSize
= loadSize
- kmod_info
->hdr_size
;
9481 wiredSize
= loadSize
;
9483 } else if (is_dext
) {
9485 * DriverKit userspace executables do not have a kernel linkedExecutable,
9486 * so we "fake" their address range with the LoadTag.
9489 loadAddress
= execLoadAddress
= loadTag
;
9490 loadSize
= execLoadSize
= 1;
9494 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
9495 scratchNumber
= OSNumber::withNumber(
9496 (unsigned long long)(loadAddress
),
9497 /* numBits */ 8 * sizeof(loadAddress
));
9498 if (!scratchNumber
) {
9501 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
9502 OSSafeReleaseNULL(scratchNumber
);
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
) {
9513 result
->setObject(kOSBundleCacheLoadAddressKey
, scratchNumber
);
9514 OSSafeReleaseNULL(scratchNumber
);
9516 if ((!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleKextsInKernelTextKey
))
9517 && (this == sKernelKext
) && gBuiltinKmodsCount
) {
9518 result
->setObject(kOSBundleKextsInKernelTextKey
, kOSBooleanTrue
);
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
) {
9528 result
->setObject(kOSBundleExecLoadAddressKey
, scratchNumber
);
9529 OSSafeReleaseNULL(scratchNumber
);
9531 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
9532 scratchNumber
= OSNumber::withNumber(
9533 (unsigned long long)(loadSize
),
9534 /* numBits */ 8 * sizeof(loadSize
));
9535 if (!scratchNumber
) {
9538 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
9539 OSSafeReleaseNULL(scratchNumber
);
9541 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
)) {
9542 scratchNumber
= OSNumber::withNumber(
9543 (unsigned long long)(execLoadSize
),
9544 /* numBits */ 8 * sizeof(execLoadSize
));
9545 if (!scratchNumber
) {
9548 result
->setObject(kOSBundleExecLoadSizeKey
, scratchNumber
);
9549 OSSafeReleaseNULL(scratchNumber
);
9551 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
9552 scratchNumber
= OSNumber::withNumber(
9553 (unsigned long long)(wiredSize
),
9554 /* numBits */ 8 * sizeof(wiredSize
));
9555 if (!scratchNumber
) {
9558 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
9559 OSSafeReleaseNULL(scratchNumber
);
9564 /* OSBundleDependencies. In descending order for
9565 * easy compatibility with kextstat(8).
9567 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
9568 if ((count
= getNumDependencies())) {
9569 dependencyLoadTags
= OSArray::withCapacity(count
);
9570 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
9574 OSKext
* dependency
= OSDynamicCast(OSKext
,
9575 dependencies
->getObject(i
));
9577 OSSafeReleaseNULL(scratchNumber
);
9582 scratchNumber
= OSNumber::withNumber(
9583 (unsigned long long)dependency
->getLoadTag(),
9584 /* numBits*/ 8 * sizeof(loadTag
));
9585 if (!scratchNumber
) {
9588 dependencyLoadTags
->setObject(scratchNumber
);
9593 OSSafeReleaseNULL(scratchNumber
);
9595 /* OSBundleMetaClasses.
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
) {
9604 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
9606 while ((thisMetaClass
= OSDynamicCast(OSMetaClass
,
9607 metaClassIterator
->getNextObject()))) {
9608 OSSafeReleaseNULL(metaClassDict
);
9609 OSSafeReleaseNULL(scratchNumber
);
9610 OSSafeReleaseNULL(metaClassName
);
9611 OSSafeReleaseNULL(superclassName
);
9613 metaClassDict
= OSDictionary::withCapacity(3);
9614 if (!metaClassDict
) {
9618 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
9619 if (thisMetaClass
->getSuperClass()) {
9620 superclassName
= OSString::withCString(
9621 thisMetaClass
->getSuperClass()->getClassName());
9623 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
9624 8 * sizeof(unsigned int));
9626 /* Bail if any of the essentials is missing. The root class lacks a superclass,
9629 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
9633 metaClassInfo
->setObject(metaClassDict
);
9634 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
9635 if (superclassName
) {
9636 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
9638 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
9643 /* OSBundleRetainCount.
9645 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
9646 OSSafeReleaseNULL(scratchNumber
);
9648 int kextRetainCount
= getRetainCount() - 1;
9652 scratchNumber
= OSNumber::withNumber(
9653 (int)kextRetainCount
,
9654 /* numBits*/ 8 * sizeof(int));
9655 if (scratchNumber
) {
9656 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
9664 OSSafeReleaseNULL(headerData
);
9665 OSSafeReleaseNULL(logData
);
9666 OSSafeReleaseNULL(cpuTypeNumber
);
9667 OSSafeReleaseNULL(cpuSubtypeNumber
);
9668 OSSafeReleaseNULL(executablePathString
);
9669 if (executablePathCString
) {
9670 kfree(executablePathCString
, executablePathCStringSize
);
9672 OSSafeReleaseNULL(scratchNumber
);
9673 OSSafeReleaseNULL(dependencyLoadTags
);
9674 OSSafeReleaseNULL(metaClassIterator
);
9675 OSSafeReleaseNULL(metaClassInfo
);
9676 OSSafeReleaseNULL(metaClassDict
);
9677 OSSafeReleaseNULL(metaClassName
);
9678 OSSafeReleaseNULL(superclassName
);
9680 OSSafeReleaseNULL(result
);
9685 /*********************************************************************
9686 *********************************************************************/
9689 OSKext::copyUserExecutablePath(const OSSymbol
* bundleID
, char * pathResult
, size_t pathSize
)
9694 IORecursiveLockLock(sKextLock
);
9695 kext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
));
9699 IORecursiveLockUnlock(sKextLock
);
9701 if (!kext
|| !kext
->path
|| !kext
->userExecutableRelPath
) {
9702 OSSafeReleaseNULL(kext
);
9705 snprintf(pathResult
, pathSize
, "%s/Contents/MacOS/%s",
9706 kext
->path
->getCStringNoCopy(),
9707 kext
->userExecutableRelPath
->getCStringNoCopy());
9714 /*********************************************************************
9715 *********************************************************************/
9718 OSKext::requestResource(
9719 const char * kextIdentifierCString
,
9720 const char * resourceNameCString
,
9721 OSKextRequestResourceCallback callback
,
9723 OSKextRequestTag
* requestTagOut
)
9725 OSReturn result
= kOSReturnError
;
9726 OSKext
* callbackKext
= NULL
;// must release (looked up)
9728 OSKextRequestTag requestTag
= -1;
9729 OSNumber
* requestTagNum
= NULL
;// must release
9731 OSDictionary
* requestDict
= NULL
;// must release
9732 OSString
* kextIdentifier
= NULL
;// must release
9733 OSString
* resourceName
= NULL
;// must release
9735 OSDictionary
* callbackRecord
= NULL
;// must release
9736 OSData
* callbackWrapper
= NULL
;// must release
9738 OSData
* contextWrapper
= NULL
;// must release
9740 IORecursiveLockLock(sKextLock
);
9742 if (requestTagOut
) {
9743 *requestTagOut
= kOSKextRequestTagInvalid
;
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
;
9757 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
9758 result
= kOSKextReturnInvalidArgument
;
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
;
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
;
9778 /* Do not allow any new requests to be made on a kext that is unloading.
9780 if (callbackKext
->flags
.stopping
) {
9781 result
= kOSKextReturnStopping
;
9785 /* If we're wrapped the next available request tag around to the negative
9786 * numbers, we can't service any more requests.
9788 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
9789 OSKextLog(/* kext */ NULL
,
9790 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9791 "No more request tags available; restart required.");
9792 result
= kOSKextReturnNoResources
;
9795 requestTag
= sNextRequestTag
++;
9797 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
9799 if (result
!= kOSReturnSuccess
) {
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
||
9810 !_OSKextSetRequestArgument(requestDict
,
9811 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
9812 !_OSKextSetRequestArgument(requestDict
,
9813 kKextRequestArgumentNameKey
, resourceName
) ||
9814 !_OSKextSetRequestArgument(requestDict
,
9815 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
9816 result
= kOSKextReturnNoMemory
;
9820 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
9821 if (!callbackRecord
) {
9822 result
= kOSKextReturnNoMemory
;
9825 // we validate callback address at call time
9826 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
9828 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
9830 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9831 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
9832 result
= kOSKextReturnNoMemory
;
9837 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9838 kKextRequestArgumentContextKey
, contextWrapper
)) {
9839 result
= kOSKextReturnNoMemory
;
9844 /* Only post the requests after all the other potential failure points
9847 if (!sKernelRequests
->setObject(requestDict
) ||
9848 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
9849 result
= kOSKextReturnNoMemory
;
9853 OSKext::pingKextd();
9855 result
= kOSReturnSuccess
;
9856 if (requestTagOut
) {
9857 *requestTagOut
= requestTag
;
9862 /* If we didn't succeed, yank the request & callback
9863 * from their holding arrays.
9865 if (result
!= kOSReturnSuccess
) {
9868 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
9869 if (index
!= (unsigned int)-1) {
9870 sKernelRequests
->removeObject(index
);
9872 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
9873 if (index
!= (unsigned int)-1) {
9874 sRequestCallbackRecords
->removeObject(index
);
9878 OSKext::considerUnloads(/* rescheduleOnly? */ true);
9880 IORecursiveLockUnlock(sKextLock
);
9883 callbackKext
->release();
9885 if (requestTagNum
) {
9886 requestTagNum
->release();
9890 requestDict
->release();
9892 if (kextIdentifier
) {
9893 kextIdentifier
->release();
9896 resourceName
->release();
9899 if (callbackRecord
) {
9900 callbackRecord
->release();
9902 if (callbackWrapper
) {
9903 callbackWrapper
->release();
9905 if (contextWrapper
) {
9906 contextWrapper
->release();
9913 OSKext::requestDaemonLaunch(
9914 OSString
*kextIdentifier
,
9915 OSString
*serverName
,
9916 OSNumber
*serverTag
)
9918 OSReturn result
= kOSReturnError
;
9919 OSDictionary
* requestDict
= NULL
; // must release
9921 if (!kextIdentifier
|| !serverName
|| !serverTag
) {
9922 result
= kOSKextReturnInvalidArgument
;
9926 IORecursiveLockLock(sKextLock
);
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()
9937 result
= _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch
, &requestDict
);
9938 if (result
!= kOSReturnSuccess
) {
9942 if (!_OSKextSetRequestArgument(requestDict
,
9943 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
9944 !_OSKextSetRequestArgument(requestDict
,
9945 kKextRequestArgumentDriverExtensionServerName
, serverName
) ||
9946 !_OSKextSetRequestArgument(requestDict
,
9947 kKextRequestArgumentDriverExtensionServerTag
, serverTag
)) {
9948 result
= kOSKextReturnNoMemory
;
9952 /* Only post the requests after all the other potential failure points
9955 if (!sKernelRequests
->setObject(requestDict
)) {
9956 result
= kOSKextReturnNoMemory
;
9959 OSKext::pingKextd();
9961 result
= kOSReturnSuccess
;
9963 IORecursiveLockUnlock(sKextLock
);
9965 requestDict
->release();
9970 /*********************************************************************
9971 * Assumes sKextLock is held.
9972 *********************************************************************/
9975 OSKext::dequeueCallbackForRequestTag(
9976 OSKextRequestTag requestTag
,
9977 OSDictionary
** callbackRecordOut
)
9979 OSReturn result
= kOSReturnError
;
9980 OSNumber
* requestTagNum
= NULL
;// must release
9982 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9983 8 * sizeof(requestTag
));
9984 if (!requestTagNum
) {
9988 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
9992 OSSafeReleaseNULL(requestTagNum
);
9997 /*********************************************************************
9998 * Assumes sKextLock is held.
9999 *********************************************************************/
10002 OSKext::dequeueCallbackForRequestTag(
10003 OSNumber
* requestTagNum
,
10004 OSDictionary
** callbackRecordOut
)
10006 OSReturn result
= kOSKextReturnInvalidArgument
;
10007 OSDictionary
* callbackRecord
= NULL
;// retain if matched!
10008 OSNumber
* callbackTagNum
= NULL
;// do not release
10009 unsigned int count
, i
;
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
) {
10020 /* If we don't find a tag, we basically have a leak here. Maybe
10021 * we should just remove it.
10023 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
10024 callbackRecord
, kKextRequestArgumentRequestTagKey
));
10025 if (!callbackTagNum
) {
10029 /* We could be even more paranoid and check that all the incoming
10030 * args match what's in the callback record.
10032 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
10033 if (callbackRecordOut
) {
10034 *callbackRecordOut
= callbackRecord
;
10035 callbackRecord
->retain();
10037 sRequestCallbackRecords
->removeObject(i
);
10038 result
= kOSReturnSuccess
;
10042 result
= kOSKextReturnNotFound
;
10049 /*********************************************************************
10050 * Busy timeout triage
10051 *********************************************************************/
10054 OSKext::isWaitingKextd(void)
10056 return sRequestCallbackRecords
&& sRequestCallbackRecords
->getCount();
10059 /*********************************************************************
10060 * Assumes sKextLock is held.
10061 *********************************************************************/
10064 OSKext::dispatchResource(OSDictionary
* requestDict
)
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)
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.
10082 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
10083 kKextRequestArgumentRequestTagKey
));
10084 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
10085 kKextRequestArgumentResultKey
));
10086 if (!requestTag
|| !requestResult
) {
10087 result
= kOSKextReturnInvalidArgument
;
10091 /* Look for a callback record matching this request's tag.
10093 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
10094 if (result
!= kOSReturnSuccess
) {
10099 * Get the context pointer of the callback record (if there is one).
10101 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
10102 kKextRequestArgumentContextKey
));
10103 context
= _OSKextExtractPointer(contextWrapper
);
10104 if (contextWrapper
&& !context
) {
10108 callbackWrapper
= OSDynamicCast(OSData
,
10109 _OSKextGetRequestArgument(callbackRecord
,
10110 kKextRequestArgumentCallbackKey
));
10111 callback
= (OSKextRequestResourceCallback
)
10112 _OSKextExtractPointer(callbackWrapper
);
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.
10121 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
10122 kKextRequestArgumentValueKey
));
10124 dataPtr
= dataObj
->getBytesNoCopy();
10125 dataLength
= dataObj
->getLength();
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; ");
10135 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
10136 OSKextLog(/* kext */ NULL
,
10137 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
10138 "Can't invoke kext resource callback; ");
10142 (void)callback(requestTag
->unsigned32BitValue(),
10143 (OSReturn
)requestResult
->unsigned32BitValue(),
10144 dataPtr
, dataLength
, context
);
10146 result
= kOSReturnSuccess
;
10149 if (callbackKext
) {
10150 callbackKext
->release();
10152 if (callbackRecord
) {
10153 callbackRecord
->release();
10159 /*********************************************************************
10160 *********************************************************************/
10163 OSKext::invokeRequestCallback(
10164 OSDictionary
* callbackRecord
,
10165 OSReturn callbackResult
)
10167 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
10168 OSNumber
* resultNum
= NULL
;// must release
10174 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
10175 8 * sizeof(callbackResult
));
10180 /* Insert the result into the callback record and dispatch it as if it
10181 * were the reply coming down from user space.
10183 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
10186 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
10187 /* This removes the pending callback record.
10189 OSKext::dispatchResource(callbackRecord
);
10194 resultNum
->release();
10199 /*********************************************************************
10200 * Assumes sKextLock is held.
10201 *********************************************************************/
10204 OSKext::cancelRequest(
10205 OSKextRequestTag requestTag
,
10206 void ** contextOut
)
10208 OSReturn result
= kOSKextReturnNoMemory
;
10209 OSDictionary
* callbackRecord
= NULL
; // must release
10210 OSData
* contextWrapper
= NULL
;// do not release
10212 IORecursiveLockLock(sKextLock
);
10213 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
10215 IORecursiveLockUnlock(sKextLock
);
10217 if (result
== kOSReturnSuccess
&& contextOut
) {
10218 contextWrapper
= OSDynamicCast(OSData
,
10219 _OSKextGetRequestArgument(callbackRecord
,
10220 kKextRequestArgumentContextKey
));
10221 *contextOut
= _OSKextExtractPointer(contextWrapper
);
10224 if (callbackRecord
) {
10225 callbackRecord
->release();
10231 /*********************************************************************
10232 * Assumes sKextLock is held.
10233 *********************************************************************/
10235 OSKext::invokeOrCancelRequestCallbacks(
10236 OSReturn callbackResult
,
10239 unsigned int count
, i
;
10241 count
= sRequestCallbackRecords
->getCount();
10248 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
10249 sRequestCallbackRecords
->getObject(i
));
10254 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
10255 _OSKextGetRequestArgument(request
,
10256 kKextRequestArgumentCallbackKey
));
10258 if (!callbackWrapper
) {
10259 sRequestCallbackRecords
->removeObject(i
);
10263 vm_address_t callbackAddress
= (vm_address_t
)
10264 _OSKextExtractPointer(callbackWrapper
);
10266 if ((kmod_info
->address
<= callbackAddress
) &&
10267 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
10269 /* This removes the callback record.
10271 invokeRequestCallback(request
, callbackResult
);
10273 sRequestCallbackRecords
->removeObject(i
);
10282 /*********************************************************************
10283 * Assumes sKextLock is held.
10284 *********************************************************************/
10286 OSKext::countRequestCallbacks(void)
10288 uint32_t result
= 0;
10289 unsigned int count
, i
;
10291 count
= sRequestCallbackRecords
->getCount();
10298 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
10299 sRequestCallbackRecords
->getObject(i
));
10304 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
10305 _OSKextGetRequestArgument(request
,
10306 kKextRequestArgumentCallbackKey
));
10308 if (!callbackWrapper
) {
10312 vm_address_t callbackAddress
= (vm_address_t
)
10313 _OSKextExtractPointer(callbackWrapper
);
10315 if ((kmod_info
->address
<= callbackAddress
) &&
10316 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
10325 /*********************************************************************
10326 *********************************************************************/
10328 _OSKextCreateRequest(
10329 const char * predicate
,
10330 OSDictionary
** requestP
)
10332 OSReturn result
= kOSKextReturnNoMemory
;
10333 OSDictionary
* request
= NULL
; // must release on error
10335 request
= OSDictionary::withCapacity(2);
10339 result
= _OSDictionarySetCStringValue(request
,
10340 kKextRequestPredicateKey
, predicate
);
10341 if (result
!= kOSReturnSuccess
) {
10344 result
= kOSReturnSuccess
;
10347 if (result
!= kOSReturnSuccess
) {
10349 request
->release();
10352 *requestP
= request
;
10358 /*********************************************************************
10359 *********************************************************************/
10361 _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
10363 return OSDynamicCast(OSString
,
10364 requestDict
->getObject(kKextRequestPredicateKey
));
10367 /*********************************************************************
10368 *********************************************************************/
10370 _OSKextGetRequestArgument(
10371 OSDictionary
* requestDict
,
10372 const char * argName
)
10374 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
10375 requestDict
->getObject(kKextRequestArgumentsKey
));
10377 return args
->getObject(argName
);
10382 /*********************************************************************
10383 *********************************************************************/
10385 _OSKextSetRequestArgument(
10386 OSDictionary
* requestDict
,
10387 const char * argName
,
10390 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
10391 requestDict
->getObject(kKextRequestArgumentsKey
));
10393 args
= OSDictionary::withCapacity(2);
10397 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
10401 return args
->setObject(argName
, value
);
10407 /*********************************************************************
10408 *********************************************************************/
10410 _OSKextExtractPointer(OSData
* wrapper
)
10412 void * result
= NULL
;
10413 const void * resultPtr
= NULL
;
10418 resultPtr
= wrapper
->getBytesNoCopy();
10419 result
= *(void **)resultPtr
;
10424 /*********************************************************************
10425 *********************************************************************/
10427 _OSDictionarySetCStringValue(
10428 OSDictionary
* dict
,
10430 const char * cValue
)
10432 OSReturn result
= kOSKextReturnNoMemory
;
10433 const OSSymbol
* key
= NULL
; // must release
10434 OSString
* value
= NULL
; // must release
10436 key
= OSSymbol::withCString(cKey
);
10437 value
= OSString::withCString(cValue
);
10438 if (!key
|| !value
) {
10441 if (dict
->setObject(key
, value
)) {
10442 result
= kOSReturnSuccess
;
10456 /*********************************************************************
10457 *********************************************************************/
10459 _OSArrayContainsCString(
10461 const char * cString
)
10463 bool result
= false;
10464 const OSSymbol
* symbol
= NULL
;
10467 if (!array
|| !cString
) {
10471 symbol
= OSSymbol::withCStringNoCopy(cString
);
10476 count
= array
->getCount();
10477 for (i
= 0; i
< count
; i
++) {
10478 OSObject
* thisObject
= array
->getObject(i
);
10479 if (symbol
->isEqualTo(thisObject
)) {
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 *********************************************************************/
10498 _OSKextInPrelinkRebuildWindow(void)
10500 static bool outside_the_window
= false;
10501 AbsoluteTime my_abstime
;
10505 if (outside_the_window
) {
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;
10518 /*********************************************************************
10519 *********************************************************************/
10521 _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
10523 int unLoadedCount
, i
;
10524 bool result
= false;
10526 IORecursiveLockLock(sKextLock
);
10528 if (sUnloadedPrelinkedKexts
== NULL
) {
10531 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
10532 if (unLoadedCount
== 0) {
10536 for (i
= 0; i
< unLoadedCount
; i
++) {
10537 const OSSymbol
* myBundleID
;// do not release
10539 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
10543 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
10549 IORecursiveLockUnlock(sKextLock
);
10554 #pragma mark Personalities (IOKit Drivers)
10556 /*********************************************************************
10557 *********************************************************************/
10560 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
10562 OSArray
* result
= NULL
;// returned
10563 OSCollectionIterator
* kextIterator
= NULL
;// must release
10564 OSArray
* personalities
= NULL
;// must release
10565 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
10567 OSString
* kextID
= NULL
;// do not release
10568 OSKext
* theKext
= NULL
;// do not release
10570 IORecursiveLockLock(sKextLock
);
10572 /* Let's conservatively guess that any given kext has around 3
10573 * personalities for now.
10575 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
10580 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
10581 if (!kextIterator
) {
10585 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
10586 if (personalitiesIterator
) {
10587 personalitiesIterator
->release();
10588 personalitiesIterator
= NULL
;
10590 if (personalities
) {
10591 personalities
->release();
10592 personalities
= NULL
;
10595 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
10596 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
10597 personalities
= theKext
->copyPersonalitiesArray();
10598 if (!personalities
) {
10601 result
->merge(personalities
);
10603 // xxx - check for better place to put this log msg
10605 kOSKextLogWarningLevel
|
10606 kOSKextLogLoadFlag
,
10607 "Kext %s is not loadable during safe boot; "
10608 "omitting its personalities.",
10609 theKext
->getIdentifierCString());
10614 IORecursiveLockUnlock(sKextLock
);
10616 if (kextIterator
) {
10617 kextIterator
->release();
10619 if (personalitiesIterator
) {
10620 personalitiesIterator
->release();
10622 if (personalities
) {
10623 personalities
->release();
10629 /*********************************************************************
10630 *********************************************************************/
10633 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
10635 int numPersonalities
= 0;
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");
10644 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
10645 /* filterSafeBootFlag */ true);
10647 if (personalities
) {
10648 gIOCatalogue
->addDrivers(personalities
, startMatching
);
10649 numPersonalities
= personalities
->getCount();
10650 personalities
->release();
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");
10662 /*********************************************************************
10663 * Do not make a deep copy, just convert the IOKitPersonalities dict
10664 * to an array for sending to the IOCatalogue.
10665 *********************************************************************/
10667 OSKext::copyPersonalitiesArray(void)
10669 OSArray
* result
= NULL
;
10670 OSDictionary
* personalities
= NULL
;// do not release
10671 OSCollectionIterator
* personalitiesIterator
= NULL
;// must release
10673 OSString
* personalityName
= NULL
;// do not release
10674 OSString
* personalityBundleIdentifier
= NULL
;// do not release
10676 personalities
= OSDynamicCast(OSDictionary
,
10677 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10678 if (!personalities
) {
10682 result
= OSArray::withCapacity(personalities
->getCount());
10687 personalitiesIterator
=
10688 OSCollectionIterator::withCollection(personalities
);
10689 if (!personalitiesIterator
) {
10692 while ((personalityName
= OSDynamicCast(OSString
,
10693 personalitiesIterator
->getNextObject()))) {
10694 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10695 personalities
->getObject(personalityName
));
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
10703 personalityBundleIdentifier
= OSDynamicCast(OSString
,
10704 personality
->getObject(kCFBundleIdentifierKey
));
10706 if (!personalityBundleIdentifier
) {
10707 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
10708 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
10709 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
10712 result
->setObject(personality
);
10716 if (personalitiesIterator
) {
10717 personalitiesIterator
->release();
10723 /*********************************************************************
10724 * Might want to change this to a bool return?
10725 *********************************************************************/
10727 OSKext::sendPersonalitiesToCatalog(
10728 bool startMatching
,
10729 OSArray
* personalityNames
)
10731 OSReturn result
= kOSReturnSuccess
;
10732 OSArray
* personalitiesToSend
= NULL
;// must release
10733 OSDictionary
* kextPersonalities
= NULL
;// do not release
10736 if (!sLoadEnabled
) {
10738 kOSKextLogErrorLevel
|
10739 kOSKextLogLoadFlag
,
10740 "Kext loading is disabled (attempt to start matching for kext %s).",
10741 getIdentifierCString());
10742 result
= kOSKextReturnDisabled
;
10746 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
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
;
10757 if (!personalityNames
|| !personalityNames
->getCount()) {
10758 personalitiesToSend
= copyPersonalitiesArray();
10760 kextPersonalities
= OSDynamicCast(OSDictionary
,
10761 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10762 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
10766 personalitiesToSend
= OSArray::withCapacity(0);
10767 if (!personalitiesToSend
) {
10768 result
= kOSKextReturnNoMemory
;
10771 count
= personalityNames
->getCount();
10772 for (i
= 0; i
< count
; i
++) {
10773 OSString
* name
= OSDynamicCast(OSString
,
10774 personalityNames
->getObject(i
));
10778 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10779 kextPersonalities
->getObject(name
));
10781 personalitiesToSend
->setObject(personality
);
10785 if (personalitiesToSend
) {
10786 unsigned numPersonalities
= personalitiesToSend
->getCount();
10788 kOSKextLogStepLevel
|
10789 kOSKextLogLoadFlag
,
10790 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
10791 getIdentifierCString(),
10793 numPersonalities
> 1 ? "ies" : "y",
10794 startMatching
? " and starting matching" : " but not starting matching");
10795 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
10798 if (personalitiesToSend
) {
10799 personalitiesToSend
->release();
10804 /*********************************************************************
10805 * xxx - We should allow removing the kext's declared personalities,
10806 * xxx - even with other bundle identifiers.
10807 *********************************************************************/
10809 OSKext::removePersonalitiesFromCatalog(void)
10811 OSDictionary
* personality
= NULL
; // do not release
10813 personality
= OSDictionary::withCapacity(1);
10814 if (!personality
) {
10817 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
10820 kOSKextLogStepLevel
|
10821 kOSKextLogLoadFlag
,
10822 "Kext %s removing all personalities naming it from the IOCatalogue.",
10823 getIdentifierCString());
10825 /* Have the IOCatalog remove all personalities matching this kext's
10826 * bundle ID and trigger matching anew.
10828 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
10832 personality
->release();
10840 #pragma mark Logging
10842 /*********************************************************************
10843 * Do not call any function that takes sKextLock here!
10844 *********************************************************************/
10847 OSKext::setUserSpaceLogFilter(
10848 OSKextLogSpec newUserLogFilter
,
10851 OSKextLogSpec result
;
10852 bool allocError
= false;
10854 /* Do not call any function that takes sKextLoggingLock during
10855 * this critical block. That means do logging after.
10857 IOLockLock(sKextLoggingLock
);
10859 result
= sUserSpaceKextLogFilter
;
10860 sUserSpaceKextLogFilter
= newUserLogFilter
;
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);
10868 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
10869 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10870 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10875 IOLockUnlock(sKextLoggingLock
);
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.
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
);
10889 OSKextLog(/* kext */ NULL
,
10890 kOSKextLogErrorLevel
|
10891 kOSKextLogGeneralFlag
,
10892 "Failed to allocate user-space log message arrays.");
10898 /*********************************************************************
10899 * Do not call any function that takes sKextLock here!
10900 *********************************************************************/
10903 OSKext::clearUserSpaceLogFilter(void)
10905 OSArray
* result
= NULL
;
10906 OSKextLogSpec oldLogFilter
;
10907 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
10909 /* Do not call any function that takes sKextLoggingLock during
10910 * this critical block. That means do logging after.
10912 IOLockLock(sKextLoggingLock
);
10914 result
= OSArray::withCapacity(2);
10916 result
->setObject(sUserSpaceLogSpecArray
);
10917 result
->setObject(sUserSpaceLogMessageArray
);
10919 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10920 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10922 oldLogFilter
= sUserSpaceKextLogFilter
;
10923 sUserSpaceKextLogFilter
= newLogFilter
;
10925 IOLockUnlock(sKextLoggingLock
);
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.
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
);
10943 /*********************************************************************
10944 * Do not call any function that takes sKextLock here!
10945 *********************************************************************/
10948 OSKext::getUserSpaceLogFilter(void)
10950 OSKextLogSpec result
;
10952 IOLockLock(sKextLoggingLock
);
10953 result
= sUserSpaceKextLogFilter
;
10954 IOLockUnlock(sKextLoggingLock
);
10959 /*********************************************************************
10960 * This function is called by OSMetaClass during kernel C++ setup.
10961 * Be careful what you access here; assume only OSKext::initialize()
10964 * Do not call any function that takes sKextLock here!
10965 *********************************************************************/
10966 #define VTRESET "\033[0m"
10968 #define VTBOLD "\033[1m"
10969 #define VTUNDER "\033[4m"
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"
10978 inline const char *
10979 colorForFlags(OSKextLogSpec flags
)
10981 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
10983 switch (logLevel
) {
10984 case kOSKextLogErrorLevel
:
10985 return VTRED VTBOLD
;
10986 case kOSKextLogWarningLevel
:
10988 case kOSKextLogBasicLevel
:
10989 return VTYELLOW VTUNDER
;
10990 case kOSKextLogProgressLevel
:
10992 case kOSKextLogStepLevel
:
10994 case kOSKextLogDetailLevel
:
10996 case kOSKextLogDebugLevel
:
10999 return ""; // white
11005 OSKextLogSpec msgLogSpec
,
11006 OSKextLogSpec logFilter
)
11008 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
11009 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
11010 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
11012 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
11013 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
11014 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
11016 /* Explicit messages always get logged.
11018 if (msgLevel
== kOSKextLogExplicitLevel
) {
11022 /* Warnings and errors are logged regardless of the flags.
11024 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
11028 /* A verbose message that isn't for a logging-enabled kext and isn't global
11029 * does *not* get logged.
11031 if (!msgKextGlobal
&& !filterKextGlobal
) {
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.
11040 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
11050 OSKextLogSpec msgLogSpec
,
11051 const char * format
, ...)
11055 va_start(argList
, format
);
11056 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
11063 OSKextLogSpec msgLogSpec
,
11064 const char * format
,
11065 va_list srcArgList
)
11067 extern int disableConsoleOutput
;
11069 bool logForKernel
= false;
11070 bool logForUser
= false;
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
11079 IOLockLock(sKextLoggingLock
);
11081 /* Set the kext/global bit in the message spec if we have no
11082 * kext or if the kext requests logging.
11084 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
11085 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
11088 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
11089 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
11090 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
11093 if (!(logForKernel
|| logForUser
)) {
11097 /* No goto from here until past va_end()!
11099 va_copy(argList
, srcArgList
);
11100 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
11103 if (length
+ 1 >= sizeof(stackBuffer
)) {
11104 allocBuffer
= (char *)kalloc_tag((length
+ 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT
);
11105 if (!allocBuffer
) {
11109 /* No goto from here until past va_end()!
11111 va_copy(argList
, srcArgList
);
11112 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
11115 buffer
= allocBuffer
;
11118 /* If user space wants the log message, queue it up.
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
);
11129 /* Always log messages from the kernel according to the kernel's
11132 if (logForKernel
) {
11133 /* If we are in console mode and have a custom log filter,
11134 * colorize the log message.
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
: "");
11142 printf("%s\n", buffer
);
11147 IOLockUnlock(sKextLoggingLock
);
11150 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
11152 OSSafeReleaseNULL(logString
);
11153 OSSafeReleaseNULL(logSpecNum
);
11157 #if KASLR_IOREG_DEBUG
11159 #define IOLOG_INDENT( the_indention ) \
11162 for ( i = 0; i < (the_indention); i++ ) { \
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
;
11172 bool ScanForAddrInObject(OSObject
* theObject
,
11176 ScanForAddrInObject(OSObject
* theObject
,
11179 const OSMetaClass
* myTypeID
;
11180 OSCollectionIterator
* myIter
;
11182 OSObject
* myValue
;
11183 bool myResult
= false;
11185 if (theObject
== NULL
) {
11186 IOLog("%s: theObject is NULL \n",
11191 myTypeID
= OSTypeIDInst(theObject
);
11193 if (myTypeID
== OSTypeID(OSDictionary
)) {
11194 OSDictionary
* myDictionary
;
11196 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
11197 myIter
= OSCollectionIterator::withCollection( myDictionary
);
11198 if (myIter
== NULL
) {
11203 while ((myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject()))) {
11206 myValue
= myDictionary
->getObject(myKey
);
11207 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
11208 if (myTempResult
) {
11209 // if we ever get a true result return true
11211 IOLOG_INDENT(indent
);
11212 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
11216 } else if (myTypeID
== OSTypeID(OSArray
)) {
11219 myArray
= OSDynamicCast(OSArray
, theObject
);
11220 myIter
= OSCollectionIterator::withCollection(myArray
);
11221 if (myIter
== NULL
) {
11226 while ((myValue
= myIter
->getNextObject())) {
11228 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
11229 if (myTempResult
) {
11230 // if we ever get a true result return true
11232 IOLOG_INDENT(indent
);
11233 IOLog("OSArray: \n");
11237 } else if (myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
)) {
11238 // should we look for addresses in strings?
11239 } else if (myTypeID
== OSTypeID(OSData
)) {
11241 unsigned int myLen
;
11242 OSData
* myDataObj
;
11244 myDataObj
= OSDynamicCast(OSData
, theObject
);
11245 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
11246 myLen
= myDataObj
->getLength();
11248 if (myPtrPtr
&& myLen
&& myLen
> 7) {
11250 int myPtrCount
= (myLen
/ sizeof(void *));
11252 for (i
= 0; i
< myPtrCount
; i
++) {
11253 UInt64 numberValue
= (UInt64
) * (myPtrPtr
);
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",
11261 // (void *) kext_alloc_base,
11262 // (void *) kext_alloc_max);
11264 myKext
= OSKext::lookupKextWithAddress((vm_address_t
) *(myPtrPtr
));
11266 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
11268 myKext
->getIdentifierCString());
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",
11278 (void *) vm_kernel_stext
,
11279 (void *) vm_kernel_etext
);
11285 } else if (myTypeID
== OSTypeID(OSBoolean
)) {
11286 // do nothing here...
11287 } else if (myTypeID
== OSTypeID(OSNumber
)) {
11288 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
11290 UInt64 numberValue
= number
->unsigned64BitValue();
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
);
11301 myKext
= OSKext::lookupKextWithAddress((vm_address_t
) numberValue
);
11303 IOLog("found in kext \"%s\" \n",
11304 myKext
->getIdentifierCString());
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
);
11322 const OSMetaClass
* myMetaClass
= NULL
;
11324 myMetaClass
= theObject
->getMetaClass();
11326 IOLog("class %s \n", myMetaClass
->getClassName());
11328 IOLog("Unknown object \n" );
11335 #endif // KASLR_KEXT_DEBUG
11336 }; /* extern "C" */
11339 #pragma mark Backtrace Dump & kmod_get_info() support
11341 /*********************************************************************
11342 * This function must be safe to call in panic context.
11343 *********************************************************************/
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
)
11352 addr64_t summary_page
= 0;
11353 addr64_t last_summary_page
= 0;
11354 bool found_kmod
= false;
11357 if (kPrintKextsLock
& flags
) {
11358 if (!sKextSummariesLock
) {
11361 IOLockLock(sKextSummariesLock
);
11364 if (!gLoadedKextSummaries
) {
11365 (*printf_func
)(" can't perform kext scan: no kext summary");
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
);
11379 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
11380 OSKextLoadedKextSummary
* summary
;
11382 summary
= gLoadedKextSummaries
->summaries
+ i
;
11383 if (!summary
->address
) {
11387 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
11392 if (!(kPrintKextsTerse
& flags
)) {
11393 (*printf_func
)(" Kernel Extensions in backtrace:\n");
11398 printSummary(summary
, printf_func
, flags
);
11402 if (kPrintKextsLock
& flags
) {
11403 IOLockUnlock(sKextSummariesLock
);
11409 /*********************************************************************
11410 * This function must be safe to call in panic context.
11411 *********************************************************************/
11414 OSKext::summaryIsInBacktrace(
11415 OSKextLoadedKextSummary
* summary
,
11416 vm_offset_t
* addr
,
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
))) {
11433 * Get the kext summary object for the kext where 'addr' lies. Must be called with
11434 * sKextSummariesLock held.
11436 OSKextLoadedKextSummary
*
11437 OSKext::summaryForAddress(const uintptr_t addr
)
11439 for (unsigned i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
11440 OSKextLoadedKextSummary
*summary
= &gLoadedKextSummaries
->summaries
[i
];
11441 if (!summary
->address
) {
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.
11451 if ((addr
>= summary
->address
) && (addr
< (summary
->address
+ summary
->size
))) {
11455 kernel_mach_header_t
*mh
= (kernel_mach_header_t
*)summary
->address
;
11456 kernel_segment_command_t
*seg
;
11458 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
11459 if ((addr
>= seg
->vmaddr
) && (addr
< (seg
->vmaddr
+ seg
->vmsize
))) {
11466 /* addr did not map to any kext */
11472 OSKext::kextForAddress(const void *address
)
11474 void * image
= NULL
;
11475 OSKextActiveAccount
* active
;
11476 OSKext
* kext
= NULL
;
11479 uintptr_t addr
= (uintptr_t) address
;
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
;
11496 } else if (addr
> active
->address
) {
11498 baseIdx
+= (lim
>> 1) + 1;
11503 IOSimpleLockUnlock(sKextAccountsLock
);
11505 if (!image
&& (addr
>= vm_kernel_stext
) && (addr
< vm_kernel_etext
)) {
11506 image
= (void *) &_mh_execute_header
;
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(
11518 uuid_string_t uuid
);
11523 uuid_string_t uuid
)
11527 uuid
[0] = 0x00; // default to no UUID
11529 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
11530 OSKextLoadedKextSummary
* summary
;
11532 summary
= gLoadedKextSummaries
->summaries
+ i
;
11534 if (summary
->loadTag
== tag_ID
) {
11535 (void) uuid_unparse(summary
->uuid
, uuid
);
11542 /*********************************************************************
11543 * This function must be safe to call in panic context.
11544 *********************************************************************/
11546 OSKext::printSummary(
11547 OSKextLoadedKextSummary
* summary
,
11548 int (* printf_func
)(const char *fmt
, ...),
11551 kmod_reference_t
* kmod_ref
= NULL
;
11552 uuid_string_t uuid
;
11553 char version
[kOSKextVersionMaxLength
];
11556 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
11557 strlcpy(version
, "unknown version", sizeof(version
));
11559 (void) uuid_unparse(summary
->uuid
, uuid
);
11561 if (kPrintKextsUnslide
& flags
) {
11562 tmpAddr
= ml_static_unslide(summary
->address
);
11564 tmpAddr
= summary
->address
;
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);
11571 if (kPrintKextsTerse
& flags
) {
11575 /* print dependency info */
11576 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
11578 kmod_ref
= kmod_ref
->next
) {
11579 kmod_info_t
* rinfo
;
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
);
11587 rinfo
= kmod_ref
->info
;
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
);
11596 if (!rinfo
->address
) {
11597 continue; // skip fake entries for built-ins
11600 /* locate UUID in gLoadedKextSummaries */
11601 findSummaryUUID(rinfo
->id
, uuid
);
11603 if (kPrintKextsUnslide
& flags
) {
11604 tmpAddr
= ml_static_unslide(rinfo
->address
);
11606 tmpAddr
= rinfo
->address
;
11608 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
11609 rinfo
->name
, rinfo
->version
, uuid
, tmpAddr
);
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
,
11624 uint32_t * to_index
,
11625 uint32_t * from_index
,
11626 const char * substring
,
11628 char substitution
);
11630 /* string_out must be at least KMOD_MAX_NAME bytes.
11634 const char * scan_string
,
11636 uint32_t * to_index
,
11637 uint32_t * from_index
,
11638 const char * substring
,
11642 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
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.
11649 if (!strncmp(scan_string
, substring
, substring_length
)) {
11651 string_out
[(*to_index
)++] = marker
;
11653 string_out
[(*to_index
)++] = substitution
;
11654 (*from_index
) += substring_length
;
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
);
11672 const char * identifier
,
11673 char * identifier_out
,
11674 char ** identifier_out_end
)
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
;
11682 from_index
= to_index
= 0;
11683 identifier_out
[0] = '\0';
11685 /* Replace certain identifier prefixes with shorter @+character sequences.
11686 * Check the return value of substitute() so we only replace the prefix.
11688 for (subs_entry
= &kext_identifier_prefix_subs
[0];
11689 subs_entry
->substring
&& !did_sub
;
11691 did_sub
= substitute(identifier
, identifier_out
,
11692 &scan_to_index
, &scan_from_index
,
11693 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
11697 /* Now scan through the identifier looking for the common substrings
11698 * and replacing them with shorter !+character sequences via substitute().
11700 for (/* see above */;
11701 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
11703 const char * scan_string
= &identifier
[scan_from_index
];
11707 if (scan_from_index
) {
11708 for (subs_entry
= &kext_identifier_substring_subs
[0];
11709 subs_entry
->substring
&& !did_sub
;
11711 did_sub
= substitute(scan_string
, identifier_out
,
11712 &scan_to_index
, &scan_from_index
,
11713 subs_entry
->substring
, '!', subs_entry
->substitute
);
11717 /* If we didn't substitute, copy the input character to the output.
11720 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
11724 identifier_out
[scan_to_index
] = '\0';
11725 if (identifier_out_end
) {
11726 *identifier_out_end
= &identifier_out
[scan_to_index
];
11732 /*******************************************************************************
11733 * assemble_identifier_and_version() adds to a string buffer a compacted
11734 * bundle identifier followed by a version string.
11735 *******************************************************************************/
11737 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
11739 static int assemble_identifier_and_version(
11740 kmod_info_t
* kmod_info
,
11741 char * identPlusVers
,
11745 assemble_identifier_and_version(
11746 kmod_info_t
* kmod_info
,
11747 char * identPlusVers
,
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;
11765 /*******************************************************************************
11766 * Assumes sKextLock is held.
11767 *******************************************************************************/
11770 OSKext::saveLoadedKextPanicListTyped(
11771 const char * prefix
,
11775 uint32_t list_size
)
11778 unsigned int count
, i
;
11780 count
= sLoadedKexts
->getCount();
11787 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
11788 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
11790 uint32_t identPlusVersLength
;
11792 char identPlusVers
[2 * KMOD_MAX_NAME
];
11795 printf("OSKext::saveLoadedKextPanicListTyped - "
11796 "NULL kext in loaded kext list; continuing\n");
11801 printf("OSKext::saveLoadedKextPanicListTyped - "
11802 "Kext type cast failed in loaded kext list; continuing\n");
11806 /* Skip all built-in kexts.
11808 if (theKext
->isKernelComponent()) {
11812 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
11814 /* Filter for kmod name (bundle identifier).
11816 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
11817 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
11821 /* Filter for libraries (kexts that have a compatible version).
11823 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
11824 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
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",
11835 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
11837 sizeof(identPlusVers
));
11838 if (!identPlusVersLength
) {
11839 printf("error saving loaded kext info\n");
11843 /* make sure everything fits and we null terminate.
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;
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;
11867 /*********************************************************************
11868 *********************************************************************/
11871 OSKext::saveLoadedKextPanicList(void)
11873 char * newlist
= NULL
;
11874 uint32_t newlist_size
= 0;
11876 newlist_size
= KEXT_PANICLIST_SIZE
;
11877 newlist
= (char *)kalloc_tag(newlist_size
, VM_KERN_MEMORY_OSKEXT
);
11880 OSKextLog(/* kext */ NULL
,
11881 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
11882 "Couldn't allocate kext panic log buffer.");
11888 // non-"com.apple." kexts
11889 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
11890 /* libs? */ -1, newlist
, newlist_size
) != 0) {
11893 // "com.apple." nonlibrary kexts
11894 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11895 /* libs? */ 0, newlist
, newlist_size
) != 0) {
11898 // "com.apple." library kexts
11899 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11900 /* libs? */ 1, newlist
, newlist_size
) != 0) {
11904 if (loaded_kext_paniclist
) {
11905 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
11907 loaded_kext_paniclist
= newlist
;
11909 loaded_kext_paniclist_size
= newlist_size
;
11913 kfree(newlist
, newlist_size
);
11918 /*********************************************************************
11919 * Assumes sKextLock is held.
11920 *********************************************************************/
11922 OSKext::savePanicString(bool isLoading
)
11927 return; // do not goto finish here b/c of lock
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
));
11934 printf("error saving unloaded kext info\n");
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
);
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
);
11954 /*********************************************************************
11955 *********************************************************************/
11958 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
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
);
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
);
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
);
11982 printf_func("(none)\n");
11987 /*********************************************************************
11988 * Assumes sKextLock is held.
11989 *********************************************************************/
11992 OSKext::updateLoadedKextSummaries(void)
11994 kern_return_t result
= KERN_FAILURE
;
11995 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
11996 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
11998 vm_map_offset_t start
, end
;
11999 size_t summarySize
= 0;
12004 OSKextActiveAccount
* accountingList
;
12005 OSKextActiveAccount
* prevAccountingList
;
12006 uint32_t idx
, accountingListAlloc
, accountingListCount
, prevAccountingListCount
;
12008 prevAccountingList
= NULL
;
12009 prevAccountingListCount
= 0;
12011 #if DEVELOPMENT || DEBUG
12012 if (IORecursiveLockHaveLock(sKextLock
) == false) {
12013 panic("sKextLock must be held");
12017 IOLockLock(sKextSummariesLock
);
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());
12028 if (maxKexts
< kOSKextTypicalLoadCount
) {
12029 maxKexts
= kOSKextTypicalLoadCount
;
12032 /* Calculate the size needed for the new summary headers.
12035 size
= sizeof(*gLoadedKextSummaries
);
12036 size
+= maxKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
12037 size
= round_page(size
);
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;
12046 result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&summaryHeaderAlloc
, size
, VM_KERN_MEMORY_OSKEXT
);
12047 if (result
!= KERN_SUCCESS
) {
12050 summaryHeader
= summaryHeaderAlloc
;
12051 summarySize
= size
;
12053 summaryHeader
= gLoadedKextSummaries
;
12054 summarySize
= sLoadedKextSummariesAllocSize
;
12056 start
= (vm_map_offset_t
) summaryHeader
;
12057 end
= start
+ summarySize
;
12058 result
= vm_map_protect(kernel_map
,
12063 if (result
!= KERN_SUCCESS
) {
12068 /* Populate the summary header.
12071 bzero(summaryHeader
, summarySize
);
12072 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
12073 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
12075 /* Populate each kext summary.
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()) {
12086 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
12087 summaryHeader
->numSummaries
++;
12088 accountingListAlloc
++;
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()) {
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
) {
12107 bcopy(&accountingList
[idx
], &accountingList
[idx
+ 1], (accountingListCount
- idx
) * sizeof(accountingList
[0]));
12108 accountingList
[idx
] = activeAccount
;
12109 accountingListCount
++;
12111 assert(accountingListCount
== accountingListAlloc
);
12112 /* Write protect the buffer and move it into place.
12115 start
= (vm_map_offset_t
) summaryHeader
;
12116 end
= start
+ summarySize
;
12118 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_READ
, FALSE
);
12119 if (result
!= KERN_SUCCESS
) {
12123 gLoadedKextSummaries
= summaryHeader
;
12124 gLoadedKextSummariesTimestamp
= mach_absolute_time();
12125 sLoadedKextSummariesAllocSize
= summarySize
;
12126 summaryHeaderAlloc
= NULL
;
12128 /* Call the magic breakpoint function through a static function pointer so
12129 * the compiler can't optimize the function away.
12131 if (sLoadedKextSummariesUpdated
) {
12132 (*sLoadedKextSummariesUpdated
)();
12135 IOSimpleLockLock(sKextAccountsLock
);
12136 prevAccountingList
= sKextAccounts
;
12137 prevAccountingListCount
= sKextAccountsCount
;
12138 sKextAccounts
= accountingList
;
12139 sKextAccountsCount
= accountingListCount
;
12140 IOSimpleLockUnlock(sKextAccountsLock
);
12143 IOLockUnlock(sKextSummariesLock
);
12145 /* If we had to allocate a new buffer but failed to generate the summaries,
12148 if (summaryHeaderAlloc
) {
12149 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
12151 if (prevAccountingList
) {
12152 IODelete(prevAccountingList
, typeof(accountingList
[0]), prevAccountingListCount
);
12158 /*********************************************************************
12159 *********************************************************************/
12161 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
12165 strlcpy(summary
->name
, getIdentifierCString(),
12166 sizeof(summary
->name
));
12170 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
12171 OSSafeReleaseNULL(uuid
);
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
;
12181 summary
->address
= kmod_info
->address
;
12182 summary
->size
= kmod_info
->size
;
12184 summary
->version
= getVersion();
12185 summary
->loadTag
= kmod_info
->id
;
12186 summary
->flags
= 0;
12187 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
12192 /*********************************************************************
12193 *********************************************************************/
12196 OSKext::updateActiveAccount(OSKextActiveAccount
*accountp
)
12198 kernel_mach_header_t
*hdr
= NULL
;
12199 kernel_segment_command_t
*seg
= NULL
;
12201 bzero(accountp
, sizeof(*accountp
));
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.
12209 for (seg
= firstsegfromheader(hdr
); seg
!= NULL
; seg
= nextsegfromheader(hdr
, seg
)) {
12210 if (seg
->initprot
& VM_PROT_EXECUTE
) {
12216 accountp
->address
= seg
->vmaddr
;
12217 if (accountp
->address
) {
12218 accountp
->address_end
= seg
->vmaddr
+ seg
->vmsize
;
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).
12226 accountp
->address
= kmod_info
->address
;
12227 if (accountp
->address
) {
12228 accountp
->address_end
= kmod_info
->address
+ kmod_info
->size
;
12232 accountp
->account
= this->account
;
12236 OSKext::isDriverKit(void)
12238 OSString
*bundleType
;
12241 bundleType
= OSDynamicCast(OSString
, infoDict
->getObject(kCFBundlePackageTypeKey
));
12242 if (bundleType
&& bundleType
->isEqualTo(kOSKextBundlePackageTypeDriverKit
)) {
12249 extern "C" const vm_allocation_site_t
*
12250 OSKextGetAllocationSiteForCaller(uintptr_t address
)
12252 OSKextActiveAccount
* active
;
12253 vm_allocation_site_t
* site
;
12254 vm_allocation_site_t
* releasesite
;
12259 IOSimpleLockLock(sKextAccountsLock
);
12260 site
= releasesite
= NULL
;
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
;
12268 vm_tag_alloc_locked(site
, &releasesite
);
12271 } else if (address
> active
->address
) {
12273 baseIdx
+= (lim
>> 1) + 1;
12278 IOSimpleLockUnlock(sKextAccountsLock
);
12280 kern_allocation_name_release(releasesite
);
12286 extern "C" uint32_t
12287 OSKextGetKmodIDForSite(const vm_allocation_site_t
* site
, char * name
, vm_size_t namelen
)
12289 OSKextAccount
* account
= (typeof(account
))site
;
12290 const char * kname
;
12293 if (account
->kext
) {
12294 kname
= account
->kext
->getIdentifierCString();
12298 strlcpy(name
, kname
, namelen
);
12301 return account
->loadTag
;
12305 OSKextFreeSite(vm_allocation_site_t
* site
)
12307 OSKextAccount
* freeAccount
= (typeof(freeAccount
))site
;
12308 IODelete(freeAccount
, OSKextAccount
, 1);
12311 /*********************************************************************
12312 *********************************************************************/
12314 #if CONFIG_IMAGEBOOT
12316 OSKextGetUUIDForName(const char *name
, uuid_t uuid
)
12318 OSKext
*kext
= OSKext::lookupKextWithIdentifier(name
);
12323 OSData
*uuid_data
= kext
->copyUUID();
12325 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_t
));
12326 OSSafeReleaseNULL(uuid_data
);