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
);
117 /* Prelinked arm kexts do not have VM entries because the method we use to
118 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
119 * not work on ARM. To get around that, we must free prelinked kext
120 * executables with ml_static_mfree() instead of kext_free().
122 #if __i386__ || __x86_64__
123 #define VM_MAPPED_KEXTS 1
124 #define KASLR_KEXT_DEBUG 0
125 #define KASLR_IOREG_DEBUG 0
126 #elif __arm__ || __arm64__
127 #define VM_MAPPED_KEXTS 0
128 #define KASLR_KEXT_DEBUG 0
130 #error Unsupported architecture
134 #pragma mark Constants & Macros
136 /*********************************************************************
138 *********************************************************************/
140 /* Use this number to create containers.
142 #define kOSKextTypicalLoadCount (150)
144 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
145 * A loaded kext will no dependents or external retains will have 2 retains.
147 #define kOSKextMinRetainCount (1)
148 #define kOSKextMinLoadedRetainCount (2)
151 * Strings and substrings used in dependency resolution.
153 #define APPLE_KEXT_PREFIX "com.apple."
154 #define KERNEL_LIB "com.apple.kernel"
156 #define PRIVATE_KPI "com.apple.kpi.private"
158 /* Version for compatbility pseudokexts (com.apple.kernel.*),
159 * compatible back to v6.0.
161 #define KERNEL6_LIB "com.apple.kernel.6.0"
162 #define KERNEL6_VERSION "7.9.9"
164 #define KERNEL_LIB_PREFIX "com.apple.kernel."
165 #define KPI_LIB_PREFIX "com.apple.kpi."
167 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0)
169 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
170 #define MINIMUM_WAKEUP_SECONDS (30)
172 /*********************************************************************
173 * infoDict keys for internally-stored data. Saves on ivar slots for
174 * objects we don't keep around past boot time or during active load.
175 *********************************************************************/
177 /* A usable, uncompressed file is stored under this key.
179 #define _kOSKextExecutableKey "_OSKextExecutable"
181 /* An indirect reference to the executable file from an mkext
182 * is stored under this key.
184 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference"
186 /* If the file is contained in a larger buffer laid down by the booter or
187 * sent from user space, the OSKext stores that OSData under this key so that
188 * references are properly tracked. This is always an mkext, right now.
190 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
192 #define OS_LOG_HDR_VERSION 1
193 #define NUM_OS_LOG_SECTIONS 2
195 #define OS_LOG_SECT_IDX 0
196 #define CSTRING_SECT_IDX 1
199 #pragma mark Typedefs
201 /*********************************************************************
203 *********************************************************************/
205 /*********************************************************************
206 * osLogDataHeaderRef describes the header information of an OSData
207 * object that is returned when querying for kOSBundleLogStringsKey.
208 * We currently return information regarding 2 sections - os_log and
209 * cstring. In the case that the os_log section doesn't exist, we just
210 * return an offset and length of 0 for that section.
211 *********************************************************************/
212 typedef struct osLogDataHeader
{
216 uint32_t sect_offset
;
219 } osLogDataHeaderRef
;
221 /*********************************************************************
222 * MkextEntryRef describes the contents of an OSData object
223 * referencing a file entry from an mkext so that we can uncompress
224 * (if necessary) and extract it on demand.
226 * It contains the mkextVersion in case we ever wind up supporting
227 * multiple mkext formats. Mkext format 1 is officially retired as of
229 *********************************************************************/
230 typedef struct MkextEntryRef
{
231 mkext_basic_header
* mkext
; // beginning of whole mkext file
232 void * fileinfo
;// mkext2_file_entry or equiv; see mkext.h
236 #pragma mark Global and static Module Variables
238 /*********************************************************************
239 * Global & static variables, used to keep track of kexts.
240 *********************************************************************/
242 static bool sPrelinkBoot
= false;
243 static bool sSafeBoot
= false;
244 static bool sKeepSymbols
= false;
246 /*********************************************************************
247 * sKextLock is the principal lock for OSKext, and guards all static
248 * and global variables not owned by other locks (declared further
249 * below). It must be taken by any entry-point method or function,
250 * including internal functions called on scheduled threads.
252 * sKextLock and sKextInnerLock are recursive due to multiple functions
253 * that are called both externally and internally. The other locks are
256 * Which locks are taken depends on what they protect, but if more than
257 * one must be taken, they must always be locked in this order
258 * (and unlocked in reverse order) to prevent deadlocks:
262 * 3. sKextSummariesLock
263 * 4. sKextLoggingLock
265 static IORecursiveLock
* sKextLock
= NULL
;
267 static OSDictionary
* sKextsByID
= NULL
;
268 static OSDictionary
* sExcludeListByID
= NULL
;
269 static OSKextVersion sExcludeListVersion
= 0;
270 static OSArray
* sLoadedKexts
= NULL
;
271 static OSArray
* sUnloadedPrelinkedKexts
= NULL
;
273 // Requests to kextd waiting to be picked up.
274 static OSArray
* sKernelRequests
= NULL
;
275 // Identifier of kext load requests in sKernelRequests
276 static OSSet
* sPostedKextLoadIdentifiers
= NULL
;
277 static OSArray
* sRequestCallbackRecords
= NULL
;
279 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
280 static OSSet
* sAllKextLoadIdentifiers
= NULL
;
281 static KXLDContext
* sKxldContext
= NULL
;
282 static uint32_t sNextLoadTag
= 0;
283 static uint32_t sNextRequestTag
= 0;
285 static bool sUserLoadsActive
= false;
286 static bool sKextdActive
= false;
287 static bool sDeferredLoadSucceeded
= false;
288 static bool sConsiderUnloadsExecuted
= false;
291 static bool sKernelRequestsEnabled
= false;
293 static bool sKernelRequestsEnabled
= true;
295 static bool sLoadEnabled
= true;
296 static bool sUnloadEnabled
= true;
298 /*********************************************************************
299 * Stuff for the OSKext representing the kernel itself.
301 static OSKext
* sKernelKext
= NULL
;
303 /* Set up a fake kmod_info struct for the kernel.
304 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
305 * before OSKext is initialized; that call only needs the name
306 * and address to be set correctly.
308 * We don't do much else with the kerne's kmod_info; we never
309 * put it into the kmod list, never adjust the reference count,
310 * and never have kernel components reference it.
311 * For that matter, we don't do much with kmod_info structs
312 * at all anymore! We just keep them filled in for gdb and
313 * binary compability.
315 kmod_info_t g_kernel_kmod_info
= {
317 /* info_version */ KMOD_INFO_VERSION
,
318 /* id */ 0, // loadTag: kernel is always 0
319 /* name */ kOSKextKernelIdentifier
, // bundle identifier
320 /* version */ "0", // filled in in OSKext::initialize()
321 /* reference_count */ -1, // never adjusted; kernel never unloads
322 /* reference_list */ NULL
,
324 /* size */ 0, // filled in in OSKext::initialize()
330 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
332 kmod_info_t invalid_kmod_info
= {
334 /* info_version */ KMOD_INFO_VERSION
,
336 /* name */ "invalid",
338 /* reference_count */ -1,
339 /* reference_list */ NULL
,
348 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
349 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
350 // misc_protos.h, db_low_trace.c, kgmacros
351 // 'kmod' is a holdover from the old kmod system, we can't rename it.
352 kmod_info_t
* kmod
= NULL
;
354 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
357 static char * loaded_kext_paniclist
= NULL
;
358 static uint32_t loaded_kext_paniclist_size
= 0;
360 AbsoluteTime last_loaded_timestamp
;
361 static char last_loaded_str_buf
[2 * KMOD_MAX_NAME
];
362 static u_long last_loaded_strlen
= 0;
363 static void * last_loaded_address
= NULL
;
364 static u_long last_loaded_size
= 0;
366 AbsoluteTime last_unloaded_timestamp
;
367 static char last_unloaded_str_buf
[2 * KMOD_MAX_NAME
];
368 static u_long last_unloaded_strlen
= 0;
369 static void * last_unloaded_address
= NULL
;
370 static u_long last_unloaded_size
= 0;
372 // Statically linked kmods described by several mach-o sections:
374 // kPrelinkInfoSegment:kBuiltinInfoSection
375 // Array of pointers to kmod_info_t structs.
377 // kPrelinkInfoSegment:kBuiltinInfoSection
378 // Array of pointers to an embedded mach-o header.
380 // __DATA:kBuiltinInitSection, kBuiltinTermSection
381 // Structors for all kmods. Has to be filtered by proc address.
384 static uint32_t gBuiltinKmodsCount
;
385 static kernel_section_t
* gBuiltinKmodsSectionInfo
;
386 static kernel_section_t
* gBuiltinKmodsSectionStart
;
388 static const OSSymbol
* gIOSurfaceIdentifier
;
389 vm_tag_t gIOSurfaceTag
;
391 /*********************************************************************
392 * sKextInnerLock protects against cross-calls with IOService and
393 * IOCatalogue, and owns the variables declared immediately below.
395 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
397 * When both sKextLock and sKextInnerLock need to be taken,
398 * always lock sKextLock first and unlock it second. Never take both
399 * locks in an entry point to OSKext; if you need to do so, you must
400 * spawn an independent thread to avoid potential deadlocks for threads
401 * calling into OSKext.
403 static IORecursiveLock
* sKextInnerLock
= NULL
;
405 static bool sAutounloadEnabled
= true;
406 static bool sConsiderUnloadsCalled
= false;
407 static bool sConsiderUnloadsPending
= false;
409 static unsigned int sConsiderUnloadDelay
= 60; // seconds
410 static thread_call_t sUnloadCallout
= 0;
411 static thread_call_t sDestroyLinkContextThread
= 0; // one-shot, one-at-a-time thread
412 static bool sSystemSleep
= false; // true when system going to sleep
413 static AbsoluteTime sLastWakeTime
; // last time we woke up
415 /*********************************************************************
416 * Backtraces can be printed at various times so we need a tight lock
417 * on data used for that. sKextSummariesLock protects the variables
418 * declared immediately below.
420 * gLoadedKextSummaries is accessed by other modules, but only during
421 * a panic so the lock isn't needed then.
423 * gLoadedKextSummaries has the "used" attribute in order to ensure
424 * that it remains visible even when we are performing extremely
425 * aggressive optimizations, as it is needed to allow the debugger
426 * to automatically parse the list of loaded kexts.
428 static IOLock
* sKextSummariesLock
= NULL
;
429 extern "C" lck_spin_t vm_allocation_sites_lock
;
430 static IOSimpleLock
* sKextAccountsLock
= &vm_allocation_sites_lock
;
432 void (*sLoadedKextSummariesUpdated
)(void) = OSKextLoadedKextSummariesUpdated
;
433 OSKextLoadedKextSummaryHeader
* gLoadedKextSummaries
__attribute__((used
)) = NULL
;
434 uint64_t gLoadedKextSummariesTimestamp
__attribute__((used
)) = 0;
435 static size_t sLoadedKextSummariesAllocSize
= 0;
437 static OSKextActiveAccount
* sKextAccounts
;
438 static uint32_t sKextAccountsCount
;
441 /*********************************************************************
442 * sKextLoggingLock protects the logging variables declared immediately below.
444 static IOLock
* sKextLoggingLock
= NULL
;
446 static const OSKextLogSpec kDefaultKernelLogFilter
= kOSKextLogBasicLevel
|
447 kOSKextLogVerboseFlagsMask
;
448 static OSKextLogSpec sKernelLogFilter
= kDefaultKernelLogFilter
;
449 static bool sBootArgLogFilterFound
= false;
450 SYSCTL_UINT(_debug
, OID_AUTO
, kextlog
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &sKernelLogFilter
,
451 0, "kernel kext logging");
453 static OSKextLogSpec sUserSpaceKextLogFilter
= kOSKextLogSilentFilter
;
454 static OSArray
* sUserSpaceLogSpecArray
= NULL
;
455 static OSArray
* sUserSpaceLogMessageArray
= NULL
;
458 * End scope for sKextInnerLock-protected variables.
459 *********************************************************************/
462 /*********************************************************************
463 * helper function used for collecting PGO data upon unload of a kext
466 static int OSKextGrabPgoDataLocked(OSKext
*kext
,
468 uuid_t instance_uuid
,
471 uint64_t bufferSize
);
473 /**********************************************************************/
478 #pragma mark OSData callbacks (need to move to OSData)
480 /*********************************************************************
481 * C functions used for callbacks.
482 *********************************************************************/
485 osdata_kmem_free(void * ptr
, unsigned int length
)
487 kmem_free(kernel_map
, (vm_address_t
)ptr
, length
);
492 osdata_phys_free(void * ptr
, unsigned int length
)
494 ml_static_mfree((vm_offset_t
)ptr
, length
);
499 osdata_vm_deallocate(void * ptr
, unsigned int length
)
501 (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
);
506 osdata_kext_free(void * ptr
, unsigned int length
)
508 (void)kext_free((vm_offset_t
)ptr
, length
);
513 #pragma mark KXLD Allocation Callback
515 /*********************************************************************
516 * KXLD Allocation Callback
517 *********************************************************************/
521 KXLDAllocateFlags
* flags
,
524 vm_address_t result
= 0; // returned
525 kern_return_t mach_result
= KERN_FAILURE
;
526 bool success
= false;
527 OSKext
* theKext
= (OSKext
*)user_data
;
528 u_long roundSize
= round_page(size
);
529 OSData
* linkBuffer
= NULL
;// must release
531 mach_result
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
);
532 if (mach_result
!= KERN_SUCCESS
) {
534 kOSKextLogErrorLevel
|
535 kOSKextLogGeneralFlag
,
536 "Can't allocate kernel memory to link %s.",
537 theKext
->getIdentifierCString());
541 /* Create an OSData wrapper for the allocated buffer.
543 linkBuffer
= OSData::withBytesNoCopy((void *)result
, roundSize
);
546 kOSKextLogErrorLevel
|
547 kOSKextLogGeneralFlag
,
548 "Can't allocate linked executable wrapper for %s.",
549 theKext
->getIdentifierCString());
552 linkBuffer
->setDeallocFunction(osdata_kext_free
);
554 kOSKextLogProgressLevel
|
555 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
556 "Allocated link buffer for kext %s at %p (%lu bytes).",
557 theKext
->getIdentifierCString(),
558 (void *)result
, (unsigned long)roundSize
);
560 theKext
->setLinkedExecutable(linkBuffer
);
562 *flags
= kKxldAllocateWritable
;
566 if (!success
&& result
) {
567 kext_free(result
, roundSize
);
571 OSSafeReleaseNULL(linkBuffer
);
573 return (kxld_addr_t
)result
;
576 /*********************************************************************
577 *********************************************************************/
580 KXLDLogSubsystem subsystem
,
586 OSKext
*theKext
= (OSKext
*) user_data
;
587 OSKextLogSpec logSpec
= 0;
590 case kKxldLogLinking
:
591 logSpec
|= kOSKextLogLinkFlag
;
593 case kKxldLogPatching
:
594 logSpec
|= kOSKextLogPatchFlag
;
599 case kKxldLogExplicit
:
600 logSpec
|= kOSKextLogExplicitLevel
;
603 logSpec
|= kOSKextLogErrorLevel
;
606 logSpec
|= kOSKextLogWarningLevel
;
609 logSpec
|= kOSKextLogProgressLevel
;
612 logSpec
|= kOSKextLogDetailLevel
;
615 logSpec
|= kOSKextLogDebugLevel
;
619 OSKextVLog(theKext
, logSpec
, format
, argList
);
623 #pragma mark IOStatistics defines
628 #define notifyKextLoadObservers(kext, kmod_info) \
630 IOStatistics::onKextLoad(kext, kmod_info); \
633 #define notifyKextUnloadObservers(kext) \
635 IOStatistics::onKextUnload(kext); \
638 #define notifyAddClassObservers(kext, addedClass, flags) \
640 IOStatistics::onClassAdded(kext, addedClass); \
643 #define notifyRemoveClassObservers(kext, removedClass, flags) \
645 IOStatistics::onClassRemoved(kext, removedClass); \
650 #define notifyKextLoadObservers(kext, kmod_info)
651 #define notifyKextUnloadObservers(kext)
652 #define notifyAddClassObservers(kext, addedClass, flags)
653 #define notifyRemoveClassObservers(kext, removedClass, flags)
655 #endif /* IOKITSTATS */
658 #pragma mark Module Config (Startup & Shutdown)
660 /*********************************************************************
661 * Module Config (Class Definition & Class Methods)
662 *********************************************************************/
663 #define super OSObject
664 OSDefineMetaClassAndStructors(OSKext
, OSObject
)
666 /*********************************************************************
667 *********************************************************************/
670 OSKext::initialize(void)
672 OSData
* kernelExecutable
= NULL
;// do not release
673 u_char
* kernelStart
= NULL
;// do not free
674 size_t kernelLength
= 0;
675 OSString
* scratchString
= NULL
;// must release
676 IORegistryEntry
* registryRoot
= NULL
;// do not release
677 OSNumber
* kernelCPUType
= NULL
;// must release
678 OSNumber
* kernelCPUSubtype
= NULL
;// must release
679 OSKextLogSpec bootLogFilter
= kOSKextLogSilentFilter
;
680 bool setResult
= false;
681 uint64_t * timestamp
= 0;
682 char bootArgBuffer
[16];// for PE_parse_boot_argn w/strings
684 /* This must be the first thing allocated. Everything else grabs this lock.
686 sKextLock
= IORecursiveLockAlloc();
687 sKextInnerLock
= IORecursiveLockAlloc();
688 sKextSummariesLock
= IOLockAlloc();
689 sKextLoggingLock
= IOLockAlloc();
691 assert(sKextInnerLock
);
692 assert(sKextSummariesLock
);
693 assert(sKextLoggingLock
);
695 sKextsByID
= OSDictionary::withCapacity(kOSKextTypicalLoadCount
);
696 sLoadedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
);
697 sUnloadedPrelinkedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
/ 10);
698 sKernelRequests
= OSArray::withCapacity(0);
699 sPostedKextLoadIdentifiers
= OSSet::withCapacity(0);
700 sAllKextLoadIdentifiers
= OSSet::withCapacity(kOSKextTypicalLoadCount
);
701 sRequestCallbackRecords
= OSArray::withCapacity(0);
702 assert(sKextsByID
&& sLoadedKexts
&& sKernelRequests
&&
703 sPostedKextLoadIdentifiers
&& sAllKextLoadIdentifiers
&&
704 sRequestCallbackRecords
&& sUnloadedPrelinkedKexts
);
706 /* Read the log flag boot-args and set the log flags.
708 if (PE_parse_boot_argn("kextlog", &bootLogFilter
, sizeof(bootLogFilter
))) {
709 sBootArgLogFilterFound
= true;
710 sKernelLogFilter
= bootLogFilter
;
711 // log this if any flags are set
712 OSKextLog(/* kext */ NULL
,
713 kOSKextLogBasicLevel
|
715 "Kernel kext log filter 0x%x per kextlog boot arg.",
716 (unsigned)sKernelLogFilter
);
719 sSafeBoot
= PE_parse_boot_argn("-x", bootArgBuffer
,
720 sizeof(bootArgBuffer
)) ? true : false;
723 OSKextLog(/* kext */ NULL
,
724 kOSKextLogWarningLevel
|
725 kOSKextLogGeneralFlag
,
726 "SAFE BOOT DETECTED - "
727 "only valid OSBundleRequired kexts will be loaded.");
730 PE_parse_boot_argn("keepsyms", &sKeepSymbols
, sizeof(sKeepSymbols
));
732 if (dtrace_keep_kernel_symbols()) {
735 #endif /* CONFIG_DTRACE */
736 #if KASAN_DYNAMIC_BLACKLIST
737 /* needed for function lookup */
741 /* Set up an OSKext instance to represent the kernel itself.
743 sKernelKext
= new OSKext
;
746 kernelStart
= (u_char
*)&_mh_execute_header
;
747 kernelLength
= getlastaddr() - (vm_offset_t
)kernelStart
;
748 kernelExecutable
= OSData::withBytesNoCopy(
749 kernelStart
, kernelLength
);
750 assert(kernelExecutable
);
753 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %llu (0x%016lx) \n",
754 (unsigned long)kernelStart
,
755 (unsigned long)getlastaddr(),
757 vm_kernel_slide
, vm_kernel_slide
);
760 sKernelKext
->loadTag
= sNextLoadTag
++; // the kernel is load tag 0
761 sKernelKext
->bundleID
= OSSymbol::withCString(kOSKextKernelIdentifier
);
763 sKernelKext
->version
= OSKextParseVersionString(osrelease
);
764 sKernelKext
->compatibleVersion
= sKernelKext
->version
;
765 sKernelKext
->linkedExecutable
= kernelExecutable
;
766 sKernelKext
->interfaceUUID
= sKernelKext
->copyUUID();
768 sKernelKext
->flags
.hasAllDependencies
= 1;
769 sKernelKext
->flags
.kernelComponent
= 1;
770 sKernelKext
->flags
.prelinked
= 0;
771 sKernelKext
->flags
.loaded
= 1;
772 sKernelKext
->flags
.started
= 1;
773 sKernelKext
->flags
.CPPInitialized
= 0;
774 sKernelKext
->flags
.jettisonLinkeditSeg
= 0;
776 sKernelKext
->kmod_info
= &g_kernel_kmod_info
;
777 strlcpy(g_kernel_kmod_info
.version
, osrelease
,
778 sizeof(g_kernel_kmod_info
.version
));
779 g_kernel_kmod_info
.size
= kernelLength
;
780 g_kernel_kmod_info
.id
= sKernelKext
->loadTag
;
782 /* Cons up an info dict, so we don't have to have special-case
785 sKernelKext
->infoDict
= OSDictionary::withCapacity(5);
786 assert(sKernelKext
->infoDict
);
787 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
,
788 sKernelKext
->bundleID
);
790 setResult
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
,
794 scratchString
= OSString::withCStringNoCopy(osrelease
);
795 assert(scratchString
);
796 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
,
799 OSSafeReleaseNULL(scratchString
);
801 scratchString
= OSString::withCStringNoCopy("mach_kernel");
802 assert(scratchString
);
803 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
,
806 OSSafeReleaseNULL(scratchString
);
808 /* Add the kernel kext to the bookkeeping dictionaries. Note that
809 * the kernel kext doesn't have a kmod_info struct. copyInfo()
810 * gathers info from other places anyhow.
812 setResult
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
);
814 setResult
= sLoadedKexts
->setObject(sKernelKext
);
816 sKernelKext
->release();
818 registryRoot
= IORegistryEntry::getRegistryRoot();
819 kernelCPUType
= OSNumber::withNumber(
820 (long long unsigned int)_mh_execute_header
.cputype
,
821 8 * sizeof(_mh_execute_header
.cputype
));
822 kernelCPUSubtype
= OSNumber::withNumber(
823 (long long unsigned int)_mh_execute_header
.cpusubtype
,
824 8 * sizeof(_mh_execute_header
.cpusubtype
));
825 assert(registryRoot
&& kernelCPUSubtype
&& kernelCPUType
);
827 registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
);
828 registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
);
830 OSSafeReleaseNULL(kernelCPUType
);
831 OSSafeReleaseNULL(kernelCPUSubtype
);
833 gBuiltinKmodsSectionInfo
= getsectbyname(kPrelinkInfoSegment
, kBuiltinInfoSection
);
834 if (gBuiltinKmodsSectionInfo
) {
837 assert(gBuiltinKmodsSectionInfo
->addr
);
838 assert(gBuiltinKmodsSectionInfo
->size
);
839 gBuiltinKmodsCount
= (gBuiltinKmodsSectionInfo
->size
/ sizeof(kmod_info_t
*));
841 gBuiltinKmodsSectionStart
= getsectbyname(kPrelinkInfoSegment
, kBuiltinStartSection
);
842 assert(gBuiltinKmodsSectionStart
);
843 assert(gBuiltinKmodsSectionStart
->addr
);
844 assert(gBuiltinKmodsSectionStart
->size
);
845 count
= (gBuiltinKmodsSectionStart
->size
/ sizeof(uintptr_t));
846 // one extra pointer for the end of last kmod
847 assert(count
== (gBuiltinKmodsCount
+ 1));
849 vm_kernel_builtinkmod_text
= ((uintptr_t *)gBuiltinKmodsSectionStart
->addr
)[0];
850 vm_kernel_builtinkmod_text_end
= ((uintptr_t *)gBuiltinKmodsSectionStart
->addr
)[count
- 1];
852 gIOSurfaceIdentifier
= OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface");
854 timestamp
= __OSAbsoluteTimePtr(&last_loaded_timestamp
);
856 timestamp
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
);
858 timestamp
= __OSAbsoluteTimePtr(&sLastWakeTime
);
861 OSKextLog(/* kext */ NULL
,
862 kOSKextLogProgressLevel
|
863 kOSKextLogGeneralFlag
,
864 "Kext system initialized.");
866 notifyKextLoadObservers(sKernelKext
, sKernelKext
->kmod_info
);
871 /*********************************************************************
872 * This is expected to be called exactly once, from exactly one thread
873 * context, during kernel bootstrap.
874 *********************************************************************/
877 OSKext::removeKextBootstrap(void)
879 OSReturn result
= kOSReturnError
;
881 const char * dt_kernel_header_name
= "Kernel-__HEADER";
882 const char * dt_kernel_symtab_name
= "Kernel-__SYMTAB";
883 kernel_mach_header_t
* dt_mach_header
= NULL
;
884 int dt_mach_header_size
= 0;
885 struct symtab_command
* dt_symtab
= NULL
;
886 int dt_symtab_size
= 0;
889 kernel_segment_command_t
* seg_to_remove
= NULL
;
891 #if __arm__ || __arm64__
892 const char * dt_segment_name
= NULL
;
893 void * segment_paddress
= NULL
;
894 int segment_size
= 0;
897 OSKextLog(/* kext */ NULL
,
898 kOSKextLogProgressLevel
|
899 kOSKextLogGeneralFlag
,
900 "Jettisoning kext bootstrap segments.");
903 * Dispose of unnecessary stuff that the booter didn't need to load.
905 dt_result
= IODTGetLoaderInfo(dt_kernel_header_name
,
906 (void **)&dt_mach_header
, &dt_mach_header_size
);
907 if (dt_result
== 0 && dt_mach_header
) {
908 IODTFreeLoaderInfo(dt_kernel_header_name
, (void *)dt_mach_header
,
909 round_page_32(dt_mach_header_size
));
911 dt_result
= IODTGetLoaderInfo(dt_kernel_symtab_name
,
912 (void **)&dt_symtab
, &dt_symtab_size
);
913 if (dt_result
== 0 && dt_symtab
) {
914 IODTFreeLoaderInfo(dt_kernel_symtab_name
, (void *)dt_symtab
,
915 round_page_32(dt_symtab_size
));
919 * KLD bootstrap segment.
921 // xxx - should rename KLD segment
922 seg_to_remove
= getsegbyname("__KLD");
924 OSRuntimeUnloadCPPForSegment(seg_to_remove
);
927 #if __arm__ || __arm64__
928 /* Free the memory that was set up by bootx.
930 dt_segment_name
= "Kernel-__KLD";
931 if (0 == IODTGetLoaderInfo(dt_segment_name
, &segment_paddress
, &segment_size
)) {
932 /* We cannot free this with KTRR enabled, as we cannot
933 * update the permissions on the KLD range this late
934 * in the boot process.
936 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
939 #elif __i386__ || __x86_64__
940 /* On x86, use the mapping data from the segment load command to
941 * unload KLD directly.
942 * This may invalidate any assumptions about "avail_start"
943 * defining the lower bound for valid physical addresses.
945 if (seg_to_remove
&& seg_to_remove
->vmaddr
&& seg_to_remove
->vmsize
) {
946 // 04/18/11 - gab: <rdar://problem/9236163>
947 // overwrite memory occupied by KLD segment with random data before
949 read_frandom((void *) seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
950 ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
956 seg_to_remove
= NULL
;
959 * Prelinked kernel's symtab (if there is one).
961 kernel_section_t
* sect
;
962 sect
= getsectbyname("__PRELINK", "__symtab");
963 if (sect
&& sect
->addr
&& sect
->size
) {
964 ml_static_mfree(sect
->addr
, sect
->size
);
967 seg_to_remove
= (kernel_segment_command_t
*)getsegbyname("__LINKEDIT");
969 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
970 * pageable, unless keepsyms is set. To do that, we have to copy it from
971 * its booter-allocated memory, free the booter memory, reallocate proper
972 * managed memory, then copy the segment back in.
975 #if (__arm__ || __arm64__)
976 #error CONFIG_KXLD not expected for this arch
979 kern_return_t mem_result
;
980 void *seg_copy
= NULL
;
981 void *seg_data
= NULL
;
982 vm_map_offset_t seg_offset
= 0;
983 vm_map_offset_t seg_copy_offset
= 0;
984 vm_map_size_t seg_length
= 0;
986 seg_data
= (void *) seg_to_remove
->vmaddr
;
987 seg_offset
= (vm_map_offset_t
) seg_to_remove
->vmaddr
;
988 seg_length
= (vm_map_size_t
) seg_to_remove
->vmsize
;
990 /* Allocate space for the LINKEDIT copy.
992 mem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*) &seg_copy
,
993 seg_length
, VM_KERN_MEMORY_KEXT
);
994 if (mem_result
!= KERN_SUCCESS
) {
995 OSKextLog(/* kext */ NULL
,
996 kOSKextLogErrorLevel
|
997 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
998 "Can't copy __LINKEDIT segment for VM reassign.");
1001 seg_copy_offset
= (vm_map_offset_t
) seg_copy
;
1005 memcpy(seg_copy
, seg_data
, seg_length
);
1007 /* Dump the booter memory.
1009 ml_static_mfree(seg_offset
, seg_length
);
1011 /* Set up the VM region.
1013 mem_result
= vm_map_enter_mem_object(
1016 seg_length
, /* mask */ 0,
1017 VM_FLAGS_FIXED
| VM_FLAGS_OVERWRITE
,
1018 VM_MAP_KERNEL_FLAGS_NONE
,
1019 VM_KERN_MEMORY_NONE
,
1021 (vm_object_offset_t
) 0,
1023 /* cur_protection */ VM_PROT_READ
| VM_PROT_WRITE
,
1024 /* max_protection */ VM_PROT_ALL
,
1025 /* inheritance */ VM_INHERIT_DEFAULT
);
1026 if ((mem_result
!= KERN_SUCCESS
) ||
1027 (seg_offset
!= (vm_map_offset_t
) seg_data
)) {
1028 OSKextLog(/* kext */ NULL
,
1029 kOSKextLogErrorLevel
|
1030 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
1031 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1032 seg_data
, seg_length
, mem_result
);
1036 /* And copy it back.
1038 memcpy(seg_data
, seg_copy
, seg_length
);
1042 kmem_free(kernel_map
, seg_copy_offset
, seg_length
);
1044 #else /* we are not CONFIG_KXLD */
1045 #if !(__arm__ || __arm64__)
1046 #error CONFIG_KXLD is expected for this arch
1050 * Dump the LINKEDIT segment, unless keepsyms is set.
1052 if (!sKeepSymbols
) {
1053 dt_segment_name
= "Kernel-__LINKEDIT";
1054 if (0 == IODTGetLoaderInfo(dt_segment_name
,
1055 &segment_paddress
, &segment_size
)) {
1056 #ifdef SECURE_KERNEL
1057 vm_offset_t vmaddr
= ml_static_ptovirt((vm_offset_t
)segment_paddress
);
1058 bzero((void*)vmaddr
, segment_size
);
1060 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
1064 OSKextLog(/* kext */ NULL
,
1065 kOSKextLogBasicLevel
|
1066 kOSKextLogGeneralFlag
,
1067 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1069 #endif /* CONFIG_KXLD */
1071 seg_to_remove
= NULL
;
1073 result
= kOSReturnSuccess
;
1078 /*********************************************************************
1079 *********************************************************************/
1081 OSKext::flushNonloadedKexts(
1082 Boolean flushPrelinkedKexts
)
1084 OSSet
* prelinkedKexts
= NULL
;// must release
1085 OSCollectionIterator
* kextIterator
= NULL
;// must release
1086 OSCollectionIterator
* prelinkIterator
= NULL
; // must release
1087 const OSSymbol
* thisID
= NULL
;// do not release
1088 OSKext
* thisKext
= NULL
;// do not release
1091 IORecursiveLockLock(sKextLock
);
1093 OSKextLog(/* kext */ NULL
,
1094 kOSKextLogProgressLevel
|
1095 kOSKextLogKextBookkeepingFlag
,
1096 "Flushing nonloaded kexts and other unused data.");
1098 OSKext::considerDestroyingLinkContext();
1100 /* If we aren't flushing unused prelinked kexts, we have to put them
1101 * aside while we flush everything else so make a container for them.
1103 if (!flushPrelinkedKexts
) {
1104 prelinkedKexts
= OSSet::withCapacity(0);
1105 if (!prelinkedKexts
) {
1110 /* Set aside prelinked kexts (in-use or not) and break
1111 * any lingering inter-kext references for nonloaded kexts
1112 * so they have min. retain counts.
1114 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1115 if (!kextIterator
) {
1119 while ((thisID
= OSDynamicCast(OSSymbol
,
1120 kextIterator
->getNextObject()))) {
1121 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1124 if (prelinkedKexts
&& thisKext
->isPrelinked()) {
1125 prelinkedKexts
->setObject(thisKext
);
1127 thisKext
->flushDependencies(/* forceIfLoaded */ false);
1131 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1133 sKextsByID
->flushCollection();
1135 /* Now put the loaded kexts back into the ID dictionary.
1137 count
= sLoadedKexts
->getCount();
1138 for (i
= 0; i
< count
; i
++) {
1139 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
1140 sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
);
1143 /* Finally, put back the prelinked kexts if we saved any.
1145 if (prelinkedKexts
) {
1146 prelinkIterator
= OSCollectionIterator::withCollection(prelinkedKexts
);
1147 if (!prelinkIterator
) {
1151 while ((thisKext
= OSDynamicCast(OSKext
,
1152 prelinkIterator
->getNextObject()))) {
1153 sKextsByID
->setObject(thisKext
->getIdentifierCString(),
1159 IORecursiveLockUnlock(sKextLock
);
1161 OSSafeReleaseNULL(prelinkedKexts
);
1162 OSSafeReleaseNULL(kextIterator
);
1163 OSSafeReleaseNULL(prelinkIterator
);
1168 /*********************************************************************
1169 *********************************************************************/
1172 OSKext::setKextdActive(Boolean active
)
1174 IORecursiveLockLock(sKextLock
);
1175 sKextdActive
= active
;
1176 if (sKernelRequests
->getCount()) {
1177 OSKext::pingKextd();
1179 IORecursiveLockUnlock(sKextLock
);
1184 /*********************************************************************
1185 * OSKextLib.cpp might need access to this someday but for now it's
1187 *********************************************************************/
1189 extern void ipc_port_release_send(ipc_port_t
);
1194 OSKext::pingKextd(void)
1196 OSReturn result
= kOSReturnError
;
1198 mach_port_t kextd_port
= IPC_PORT_NULL
;
1200 if (!sKextdActive
) {
1201 result
= kOSKextReturnDisabled
; // basically unavailable
1205 result
= host_get_kextd_port(host_priv_self(), &kextd_port
);
1206 if (result
!= KERN_SUCCESS
|| !IPC_PORT_VALID(kextd_port
)) {
1207 OSKextLog(/* kext */ NULL
,
1208 kOSKextLogErrorLevel
|
1210 "Can't get kextd port.");
1214 result
= kextd_ping(kextd_port
);
1215 if (result
!= KERN_SUCCESS
) {
1216 OSKextLog(/* kext */ NULL
,
1217 kOSKextLogErrorLevel
|
1219 "kextd ping failed (0x%x).", (int)result
);
1224 if (IPC_PORT_VALID(kextd_port
)) {
1225 ipc_port_release_send(kextd_port
);
1232 /*********************************************************************
1233 *********************************************************************/
1236 OSKext::setDeferredLoadSucceeded(Boolean succeeded
)
1238 IORecursiveLockLock(sKextLock
);
1239 sDeferredLoadSucceeded
= succeeded
;
1240 IORecursiveLockUnlock(sKextLock
);
1245 /*********************************************************************
1246 * Called from IOSystemShutdownNotification.
1247 *********************************************************************/
1250 OSKext::willShutdown(void)
1253 OSReturn checkResult
= kOSReturnError
;
1255 OSDictionary
* exitRequest
= NULL
; // must release
1257 IORecursiveLockLock(sKextLock
);
1259 OSKext::setLoadEnabled(false);
1260 OSKext::setUnloadEnabled(false);
1261 OSKext::setAutounloadsEnabled(false);
1262 OSKext::setKernelRequestsEnabled(false);
1265 OSKextLog(/* kext */ NULL
,
1266 kOSKextLogProgressLevel
|
1267 kOSKextLogGeneralFlag
,
1268 "System shutdown; requesting immediate kextd exit.");
1270 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
,
1272 if (checkResult
!= kOSReturnSuccess
) {
1275 if (!sKernelRequests
->setObject(exitRequest
)) {
1279 OSKext::pingKextd();
1284 IORecursiveLockUnlock(sKextLock
);
1286 OSSafeReleaseNULL(exitRequest
);
1290 /*********************************************************************
1291 *********************************************************************/
1294 OSKext::getLoadEnabled(void)
1298 IORecursiveLockLock(sKextLock
);
1299 result
= sLoadEnabled
;
1300 IORecursiveLockUnlock(sKextLock
);
1304 /*********************************************************************
1305 *********************************************************************/
1308 OSKext::setLoadEnabled(bool flag
)
1312 IORecursiveLockLock(sKextLock
);
1313 result
= sLoadEnabled
;
1314 sLoadEnabled
= (flag
? true : false);
1316 if (sLoadEnabled
!= result
) {
1317 OSKextLog(/* kext */ NULL
,
1318 kOSKextLogBasicLevel
|
1320 "Kext loading now %sabled.", sLoadEnabled
? "en" : "dis");
1323 IORecursiveLockUnlock(sKextLock
);
1328 /*********************************************************************
1329 *********************************************************************/
1332 OSKext::getUnloadEnabled(void)
1336 IORecursiveLockLock(sKextLock
);
1337 result
= sUnloadEnabled
;
1338 IORecursiveLockUnlock(sKextLock
);
1342 /*********************************************************************
1343 *********************************************************************/
1346 OSKext::setUnloadEnabled(bool flag
)
1350 IORecursiveLockLock(sKextLock
);
1351 result
= sUnloadEnabled
;
1352 sUnloadEnabled
= (flag
? true : false);
1353 IORecursiveLockUnlock(sKextLock
);
1355 if (sUnloadEnabled
!= result
) {
1356 OSKextLog(/* kext */ NULL
,
1357 kOSKextLogBasicLevel
|
1358 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1359 "Kext unloading now %sabled.", sUnloadEnabled
? "en" : "dis");
1365 /*********************************************************************
1366 * Do not call any function that takes sKextLock here!
1367 *********************************************************************/
1370 OSKext::getAutounloadEnabled(void)
1374 IORecursiveLockLock(sKextInnerLock
);
1375 result
= sAutounloadEnabled
? true : false;
1376 IORecursiveLockUnlock(sKextInnerLock
);
1380 /*********************************************************************
1381 * Do not call any function that takes sKextLock here!
1382 *********************************************************************/
1385 OSKext::setAutounloadsEnabled(bool flag
)
1389 IORecursiveLockLock(sKextInnerLock
);
1391 result
= sAutounloadEnabled
;
1392 sAutounloadEnabled
= (flag
? true : false);
1393 if (!sAutounloadEnabled
&& sUnloadCallout
) {
1394 thread_call_cancel(sUnloadCallout
);
1397 if (sAutounloadEnabled
!= result
) {
1398 OSKextLog(/* kext */ NULL
,
1399 kOSKextLogBasicLevel
|
1400 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1401 "Kext autounloading now %sabled.",
1402 sAutounloadEnabled
? "en" : "dis");
1405 IORecursiveLockUnlock(sKextInnerLock
);
1410 /*********************************************************************
1411 *********************************************************************/
1412 /* instance method operating on OSKext field */
1414 OSKext::setAutounloadEnabled(bool flag
)
1416 bool result
= flags
.autounloadEnabled
? true : false;
1417 flags
.autounloadEnabled
= flag
? 1 : 0;
1419 if (result
!= (flag
? true : false)) {
1421 kOSKextLogProgressLevel
|
1422 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
1423 "Autounloading for kext %s now %sabled.",
1424 getIdentifierCString(),
1425 flags
.autounloadEnabled
? "en" : "dis");
1430 /*********************************************************************
1431 *********************************************************************/
1434 OSKext::setKernelRequestsEnabled(bool flag
)
1438 IORecursiveLockLock(sKextLock
);
1439 result
= sKernelRequestsEnabled
;
1440 sKernelRequestsEnabled
= flag
? true : false;
1442 if (sKernelRequestsEnabled
!= result
) {
1443 OSKextLog(/* kext */ NULL
,
1444 kOSKextLogBasicLevel
|
1445 kOSKextLogGeneralFlag
,
1446 "Kernel requests now %sabled.",
1447 sKernelRequestsEnabled
? "en" : "dis");
1449 IORecursiveLockUnlock(sKextLock
);
1453 /*********************************************************************
1454 *********************************************************************/
1457 OSKext::getKernelRequestsEnabled(void)
1461 IORecursiveLockLock(sKextLock
);
1462 result
= sKernelRequestsEnabled
;
1463 IORecursiveLockUnlock(sKextLock
);
1468 #pragma mark Kext Life Cycle
1470 /*********************************************************************
1471 *********************************************************************/
1473 OSKext::withPrelinkedInfoDict(
1474 OSDictionary
* anInfoDict
,
1475 bool doCoalesedSlides
)
1477 OSKext
* newKext
= new OSKext
;
1479 if (newKext
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
, doCoalesedSlides
)) {
1487 /*********************************************************************
1488 *********************************************************************/
1490 OSKext::initWithPrelinkedInfoDict(
1491 OSDictionary
* anInfoDict
,
1492 bool doCoalesedSlides
)
1494 bool result
= false;
1495 OSString
* kextPath
= NULL
;// do not release
1496 OSNumber
* addressNum
= NULL
;// reused; do not release
1497 OSNumber
* lengthNum
= NULL
;// reused; do not release
1498 void * data
= NULL
;// do not free
1499 void * srcData
= NULL
;// do not free
1500 OSData
* prelinkedExecutable
= NULL
;// must release
1501 uint32_t length
= 0; // reused
1503 if (!super::init()) {
1507 /* Get the path. Don't look for an arch-specific path property.
1509 kextPath
= OSDynamicCast(OSString
,
1510 anInfoDict
->getObject(kPrelinkBundlePathKey
));
1512 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
1515 #if KASLR_KEXT_DEBUG
1516 IOLog("kaslr: doCoalesedSlides %d kext %s \n", doCoalesedSlides
, getIdentifierCString());
1519 /* Also get the executable's bundle-relative path if present.
1520 * Don't look for an arch-specific path property.
1522 executableRelPath
= OSDynamicCast(OSString
,
1523 anInfoDict
->getObject(kPrelinkExecutableRelativePathKey
));
1524 if (executableRelPath
) {
1525 executableRelPath
->retain();
1528 /* Don't need the paths to be in the info dictionary any more.
1530 anInfoDict
->removeObject(kPrelinkBundlePathKey
);
1531 anInfoDict
->removeObject(kPrelinkExecutableRelativePathKey
);
1533 /* Create an OSData wrapper around the linked executable.
1535 addressNum
= OSDynamicCast(OSNumber
,
1536 anInfoDict
->getObject(kPrelinkExecutableLoadKey
));
1538 lengthNum
= OSDynamicCast(OSNumber
,
1539 anInfoDict
->getObject(kPrelinkExecutableSizeKey
));
1542 kOSKextLogErrorLevel
|
1543 kOSKextLogArchiveFlag
,
1544 "Kext %s can't find prelinked kext executable size.",
1545 getIdentifierCString());
1549 data
= (void *) ml_static_slide((intptr_t) (addressNum
->unsigned64BitValue()));
1550 length
= (uint32_t) (lengthNum
->unsigned32BitValue());
1552 #if KASLR_KEXT_DEBUG
1553 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1554 (unsigned long)ml_static_unslide(data
),
1555 (unsigned long)data
,
1559 anInfoDict
->removeObject(kPrelinkExecutableLoadKey
);
1560 anInfoDict
->removeObject(kPrelinkExecutableSizeKey
);
1562 /* If the kext's load address differs from its source address, allocate
1563 * space in the kext map at the load address and copy the kext over.
1565 addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
));
1567 srcData
= (void *) ml_static_slide((intptr_t) (addressNum
->unsigned64BitValue()));
1569 #if KASLR_KEXT_DEBUG
1570 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1571 (unsigned long)ml_static_unslide(srcData
),
1572 (unsigned long)srcData
);
1575 if (data
!= srcData
) {
1577 kern_return_t alloc_result
;
1579 alloc_result
= kext_alloc((vm_offset_t
*)&data
, length
, /* fixed */ TRUE
);
1580 if (alloc_result
!= KERN_SUCCESS
) {
1582 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1583 "Failed to allocate space for prelinked kext %s.",
1584 getIdentifierCString());
1587 memcpy(data
, srcData
, length
);
1590 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1591 "Error: prelinked kext %s - source and load addresses "
1592 "differ on ILP32 architecture.",
1593 getIdentifierCString());
1595 #endif /* __LP64__ */
1598 anInfoDict
->removeObject(kPrelinkExecutableSourceKey
);
1601 prelinkedExecutable
= OSData::withBytesNoCopy(data
, length
);
1602 if (!prelinkedExecutable
) {
1604 kOSKextLogErrorLevel
|
1605 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
1606 "Kext %s failed to create executable wrapper.",
1607 getIdentifierCString());
1612 prelinkedExecutable
->setDeallocFunction(osdata_kext_free
);
1614 prelinkedExecutable
->setDeallocFunction(osdata_phys_free
);
1616 setLinkedExecutable(prelinkedExecutable
);
1617 addressNum
= OSDynamicCast(OSNumber
,
1618 anInfoDict
->getObject(kPrelinkKmodInfoKey
));
1621 kOSKextLogErrorLevel
|
1622 kOSKextLogArchiveFlag
,
1623 "Kext %s can't find prelinked kext kmod_info address.",
1624 getIdentifierCString());
1628 if (addressNum
->unsigned64BitValue() != 0) {
1629 kmod_info
= (kmod_info_t
*) ml_static_slide((intptr_t) (addressNum
->unsigned64BitValue()));
1630 kmod_info
->address
= ml_static_slide(kmod_info
->address
);
1631 #if KASLR_KEXT_DEBUG
1632 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1633 (unsigned long)ml_static_unslide(kmod_info
),
1634 (unsigned long)kmod_info
);
1635 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1636 (unsigned long)ml_static_unslide(kmod_info
->address
),
1637 (unsigned long)kmod_info
->address
);
1641 anInfoDict
->removeObject(kPrelinkKmodInfoKey
);
1644 if ((addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject("ModuleIndex")))) {
1645 uintptr_t builtinTextStart
;
1646 uintptr_t builtinTextEnd
;
1648 flags
.builtin
= true;
1649 builtinKmodIdx
= addressNum
->unsigned32BitValue();
1650 assert(builtinKmodIdx
< gBuiltinKmodsCount
);
1652 builtinTextStart
= ((uintptr_t *)gBuiltinKmodsSectionStart
->addr
)[builtinKmodIdx
];
1653 builtinTextEnd
= ((uintptr_t *)gBuiltinKmodsSectionStart
->addr
)[builtinKmodIdx
+ 1];
1655 kmod_info
= ((kmod_info_t
**)gBuiltinKmodsSectionInfo
->addr
)[builtinKmodIdx
];
1656 kmod_info
->address
= builtinTextStart
;
1657 kmod_info
->size
= builtinTextEnd
- builtinTextStart
;
1660 /* If the plist has a UUID for an interface, save that off.
1662 if (isInterface()) {
1663 interfaceUUID
= OSDynamicCast(OSData
,
1664 anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
));
1665 if (interfaceUUID
) {
1666 interfaceUUID
->retain();
1667 anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
);
1671 result
= slidePrelinkedExecutable(doCoalesedSlides
);
1672 if (result
!= kOSReturnSuccess
) {
1676 if (doCoalesedSlides
== false) {
1677 /* set VM protections now, wire later at kext load */
1678 result
= setVMAttributes(true, false);
1679 if (result
!= KERN_SUCCESS
) {
1684 flags
.prelinked
= true;
1686 /* If we created a kext from prelink info,
1687 * we must be booting from a prelinked kernel.
1689 sPrelinkBoot
= true;
1691 result
= registerIdentifier();
1694 OSSafeReleaseNULL(prelinkedExecutable
);
1699 /*********************************************************************
1700 *********************************************************************/
1703 OSKext::setAllVMAttributes(void)
1705 OSCollectionIterator
* kextIterator
= NULL
;// must release
1706 const OSSymbol
* thisID
= NULL
;// do not release
1708 IORecursiveLockLock(sKextLock
);
1710 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1711 if (!kextIterator
) {
1715 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
1716 OSKext
* thisKext
;// do not release
1718 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1719 if (!thisKext
|| thisKext
->isInterface() || !thisKext
->declaresExecutable()) {
1723 /* set VM protections now, wire later at kext load */
1724 thisKext
->setVMAttributes(true, false);
1728 IORecursiveLockUnlock(sKextLock
);
1729 OSSafeReleaseNULL(kextIterator
);
1734 /*********************************************************************
1735 *********************************************************************/
1737 OSKext::withBooterData(
1738 OSString
* deviceTreeName
,
1739 OSData
* booterData
)
1741 OSKext
* newKext
= new OSKext
;
1743 if (newKext
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) {
1751 /*********************************************************************
1752 *********************************************************************/
1753 typedef struct _BooterKextFileInfo
{
1754 uint32_t infoDictPhysAddr
;
1755 uint32_t infoDictLength
;
1756 uint32_t executablePhysAddr
;
1757 uint32_t executableLength
;
1758 uint32_t bundlePathPhysAddr
;
1759 uint32_t bundlePathLength
;
1760 } _BooterKextFileInfo
;
1763 OSKext::initWithBooterData(
1764 OSString
* deviceTreeName
,
1765 OSData
* booterData
)
1767 bool result
= false;
1768 _BooterKextFileInfo
* kextFileInfo
= NULL
;// do not free
1769 char * infoDictAddr
= NULL
;// do not free
1770 void * executableAddr
= NULL
;// do not free
1771 char * bundlePathAddr
= NULL
;// do not free
1773 OSObject
* parsedXML
= NULL
;// must release
1774 OSDictionary
* theInfoDict
= NULL
;// do not release
1775 OSString
* kextPath
= NULL
;// must release
1776 OSString
* errorString
= NULL
;// must release
1777 OSData
* executable
= NULL
;// must release
1779 if (!super::init()) {
1783 kextFileInfo
= (_BooterKextFileInfo
*)booterData
->getBytesNoCopy();
1784 if (!kextFileInfo
) {
1786 kOSKextLogErrorLevel
|
1787 kOSKextLogGeneralFlag
,
1788 "No booter-provided data for kext device tree entry %s.",
1789 deviceTreeName
->getCStringNoCopy());
1793 /* The info plist must exist or we can't read the kext.
1795 if (!kextFileInfo
->infoDictPhysAddr
|| !kextFileInfo
->infoDictLength
) {
1797 kOSKextLogErrorLevel
|
1798 kOSKextLogGeneralFlag
,
1799 "No kext info dictionary for booter device tree entry %s.",
1800 deviceTreeName
->getCStringNoCopy());
1804 infoDictAddr
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
1805 if (!infoDictAddr
) {
1807 kOSKextLogErrorLevel
|
1808 kOSKextLogGeneralFlag
,
1809 "Can't translate physical address 0x%x of kext info dictionary "
1810 "for device tree entry %s.",
1811 (int)kextFileInfo
->infoDictPhysAddr
,
1812 deviceTreeName
->getCStringNoCopy());
1816 parsedXML
= OSUnserializeXML(infoDictAddr
, &errorString
);
1818 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
1821 const char * errorCString
= "(unknown error)";
1823 if (errorString
&& errorString
->getCStringNoCopy()) {
1824 errorCString
= errorString
->getCStringNoCopy();
1825 } else if (parsedXML
) {
1826 errorCString
= "not a dictionary";
1829 kOSKextLogErrorLevel
|
1830 kOSKextLogGeneralFlag
,
1831 "Error unserializing info dictionary for device tree entry %s: %s.",
1832 deviceTreeName
->getCStringNoCopy(), errorCString
);
1836 /* A bundle path is not mandatory.
1838 if (kextFileInfo
->bundlePathPhysAddr
&& kextFileInfo
->bundlePathLength
) {
1839 bundlePathAddr
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
);
1840 if (!bundlePathAddr
) {
1842 kOSKextLogErrorLevel
|
1843 kOSKextLogGeneralFlag
,
1844 "Can't translate physical address 0x%x of kext bundle path "
1845 "for device tree entry %s.",
1846 (int)kextFileInfo
->bundlePathPhysAddr
,
1847 deviceTreeName
->getCStringNoCopy());
1850 bundlePathAddr
[kextFileInfo
->bundlePathLength
- 1] = '\0'; // just in case!
1852 kextPath
= OSString::withCString(bundlePathAddr
);
1855 kOSKextLogErrorLevel
|
1856 kOSKextLogGeneralFlag
,
1857 "Failed to create wrapper for device tree entry %s kext path %s.",
1858 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
);
1863 if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) {
1867 /* An executable is not mandatory.
1869 if (kextFileInfo
->executablePhysAddr
&& kextFileInfo
->executableLength
) {
1870 executableAddr
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
);
1871 if (!executableAddr
) {
1873 kOSKextLogErrorLevel
|
1874 kOSKextLogGeneralFlag
,
1875 "Can't translate physical address 0x%x of kext executable "
1876 "for device tree entry %s.",
1877 (int)kextFileInfo
->executablePhysAddr
,
1878 deviceTreeName
->getCStringNoCopy());
1882 executable
= OSData::withBytesNoCopy(executableAddr
,
1883 kextFileInfo
->executableLength
);
1886 kOSKextLogErrorLevel
|
1887 kOSKextLogGeneralFlag
,
1888 "Failed to create executable wrapper for device tree entry %s.",
1889 deviceTreeName
->getCStringNoCopy());
1893 /* A kext with an executable needs to retain the whole booterData
1894 * object to keep the executable in memory.
1896 if (!setExecutable(executable
, booterData
)) {
1898 kOSKextLogErrorLevel
|
1899 kOSKextLogGeneralFlag
,
1900 "Failed to set kext executable for device tree entry %s.",
1901 deviceTreeName
->getCStringNoCopy());
1906 result
= registerIdentifier();
1909 OSSafeReleaseNULL(parsedXML
);
1910 OSSafeReleaseNULL(kextPath
);
1911 OSSafeReleaseNULL(errorString
);
1912 OSSafeReleaseNULL(executable
);
1917 /*********************************************************************
1918 *********************************************************************/
1920 OSKext::registerIdentifier(void)
1922 bool result
= false;
1923 OSKext
* existingKext
= NULL
;// do not release
1924 bool existingIsLoaded
= false;
1925 bool existingIsPrelinked
= false;
1926 OSKextVersion newVersion
= -1;
1927 OSKextVersion existingVersion
= -1;
1928 char newVersionCString
[kOSKextVersionMaxLength
];
1929 char existingVersionCString
[kOSKextVersionMaxLength
];
1930 OSData
* newUUID
= NULL
;// must release
1931 OSData
* existingUUID
= NULL
;// must release
1933 IORecursiveLockLock(sKextLock
);
1935 /* Get the new kext's version for checks & log messages.
1937 newVersion
= getVersion();
1938 OSKextVersionGetString(newVersion
, newVersionCString
,
1939 kOSKextVersionMaxLength
);
1941 /* If we don't have an existing kext with this identifier,
1942 * just record the new kext and we're done!
1944 existingKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
));
1945 if (!existingKext
) {
1946 sKextsByID
->setObject(bundleID
, this);
1951 /* Get the existing kext's version for checks & log messages.
1953 existingVersion
= existingKext
->getVersion();
1954 OSKextVersionGetString(existingVersion
,
1955 existingVersionCString
, kOSKextVersionMaxLength
);
1957 existingIsLoaded
= existingKext
->isLoaded();
1958 existingIsPrelinked
= existingKext
->isPrelinked();
1960 /* If we have a kext with this identifier that's already loaded/prelinked,
1961 * we can't use the new one, but let's be really thorough and check how
1962 * the two are related for a precise diagnostic log message.
1964 * Note that user space can't find out about nonloaded prelinked kexts,
1965 * so in this case we log a message when new & existing are equivalent
1966 * at the step rather than warning level, because we are always going
1967 * be getting a copy of the kext in the user load request mkext.
1969 if (existingIsLoaded
|| existingIsPrelinked
) {
1970 bool sameVersion
= (newVersion
== existingVersion
);
1971 bool sameExecutable
= true; // assume true unless we have UUIDs
1973 /* Only get the UUID if the existing kext is loaded. Doing so
1974 * might have to uncompress an mkext executable and we shouldn't
1975 * take that hit when neither kext is loaded.
1977 newUUID
= copyUUID();
1978 existingUUID
= existingKext
->copyUUID();
1980 /* I'm entirely too paranoid about checking equivalence of executables,
1981 * but I remember nasty problems with it in the past.
1983 * - If we have UUIDs for both kexts, compare them.
1984 * - If only one kext has a UUID, they're definitely different.
1986 if (newUUID
&& existingUUID
) {
1987 sameExecutable
= newUUID
->isEqualTo(existingUUID
);
1988 } else if (newUUID
|| existingUUID
) {
1989 sameExecutable
= false;
1992 if (!newUUID
&& !existingUUID
) {
1993 /* If there are no UUIDs, we can't really tell that the executables
1994 * are *different* without a lot of work; the loaded kext's
1995 * unrelocated executable is no longer around (and we never had it
1996 * in-kernel for a prelinked kext). We certainly don't want to do
1997 * a whole fake link for the new kext just to compare, either.
2000 OSKextVersionGetString(version
, newVersionCString
,
2001 sizeof(newVersionCString
));
2003 kOSKextLogWarningLevel
|
2004 kOSKextLogKextBookkeepingFlag
,
2005 "Notice - new kext %s, v%s matches %s kext "
2006 "but can't determine if executables are the same (no UUIDs).",
2007 getIdentifierCString(),
2009 (existingIsLoaded
? "loaded" : "prelinked"));
2012 if (sameVersion
&& sameExecutable
) {
2014 (existingIsLoaded
? kOSKextLogWarningLevel
: kOSKextLogStepLevel
) |
2015 kOSKextLogKextBookkeepingFlag
,
2016 "Refusing new kext %s, v%s: a %s copy is already present "
2017 "(same version and executable).",
2018 getIdentifierCString(), newVersionCString
,
2019 (existingIsLoaded
? "loaded" : "prelinked"));
2022 /* This condition is significant so log it under warnings.
2025 kOSKextLogWarningLevel
|
2026 kOSKextLogKextBookkeepingFlag
,
2027 "Refusing new kext %s, v%s: already have %s v%s.",
2028 getIdentifierCString(),
2030 (existingIsLoaded
? "loaded" : "prelinked"),
2031 existingVersionCString
);
2033 /* This condition is significant so log it under warnings.
2036 kOSKextLogWarningLevel
| kOSKextLogKextBookkeepingFlag
,
2037 "Refusing new kext %s, v%s: a %s copy with a different "
2038 "executable UUID is already present.",
2039 getIdentifierCString(), newVersionCString
,
2040 (existingIsLoaded
? "loaded" : "prelinked"));
2044 } /* if (existingIsLoaded || existingIsPrelinked) */
2046 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2047 * user loads are happening or if we're still in early boot. User agents are
2048 * supposed to resolve dependencies topside and include only the exact
2049 * kexts needed; so we always accept the new kext (in fact we should never
2050 * see an older unloaded copy hanging around).
2052 if (sUserLoadsActive
) {
2053 sKextsByID
->setObject(bundleID
, this);
2057 kOSKextLogStepLevel
|
2058 kOSKextLogKextBookkeepingFlag
,
2059 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2060 getIdentifierCString(),
2061 existingVersionCString
,
2067 /* During early boot, the kext with the highest version always wins out.
2068 * Prelinked kernels will never hit this, but mkexts and booter-read
2069 * kexts might have duplicates.
2071 if (newVersion
> existingVersion
) {
2072 sKextsByID
->setObject(bundleID
, this);
2076 kOSKextLogStepLevel
|
2077 kOSKextLogKextBookkeepingFlag
,
2078 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2079 existingVersionCString
,
2080 getIdentifierCString(),
2084 kOSKextLogStepLevel
|
2085 kOSKextLogKextBookkeepingFlag
,
2086 "Kext %s is already registered with a higher/same version (v%s); "
2087 "dropping newly-added (v%s).",
2088 getIdentifierCString(),
2089 existingVersionCString
,
2093 /* result has been set appropriately by now. */
2097 IORecursiveLockUnlock(sKextLock
);
2101 kOSKextLogStepLevel
|
2102 kOSKextLogKextBookkeepingFlag
,
2103 "Kext %s, v%s registered and available for loading.",
2104 getIdentifierCString(), newVersionCString
);
2107 OSSafeReleaseNULL(newUUID
);
2108 OSSafeReleaseNULL(existingUUID
);
2113 /*********************************************************************
2114 * Does the bare minimum validation to look up a kext.
2115 * All other validation is done on the spot as needed.
2116 **********************************************************************/
2118 OSKext::setInfoDictionaryAndPath(
2119 OSDictionary
* aDictionary
,
2122 bool result
= false;
2123 OSString
* bundleIDString
= NULL
;// do not release
2124 OSString
* versionString
= NULL
;// do not release
2125 OSString
* compatibleVersionString
= NULL
;// do not release
2126 const char * versionCString
= NULL
;// do not free
2127 const char * compatibleVersionCString
= NULL
;// do not free
2128 OSBoolean
* scratchBool
= NULL
;// do not release
2129 OSDictionary
* scratchDict
= NULL
;// do not release
2132 panic("Attempt to set info dictionary on a kext "
2133 "that already has one (%s).",
2134 getIdentifierCString());
2137 if (!aDictionary
|| !OSDynamicCast(OSDictionary
, aDictionary
)) {
2141 infoDict
= aDictionary
;
2144 /* Check right away if the info dictionary has any log flags.
2146 scratchBool
= OSDynamicCast(OSBoolean
,
2147 getPropertyForHostArch(kOSBundleEnableKextLoggingKey
));
2148 if (scratchBool
== kOSBooleanTrue
) {
2149 flags
.loggingEnabled
= 1;
2152 /* The very next thing to get is the bundle identifier. Unlike
2153 * in user space, a kext with no bundle identifier gets axed
2156 bundleIDString
= OSDynamicCast(OSString
,
2157 getPropertyForHostArch(kCFBundleIdentifierKey
));
2158 if (!bundleIDString
) {
2160 kOSKextLogErrorLevel
|
2161 kOSKextLogValidationFlag
,
2162 "CFBundleIdentifier missing/invalid type in kext %s.",
2163 aPath
? aPath
->getCStringNoCopy() : "(unknown)");
2166 bundleID
= OSSymbol::withString(bundleIDString
);
2169 kOSKextLogErrorLevel
|
2170 kOSKextLogValidationFlag
,
2171 "Can't copy bundle identifier as symbol for kext %s.",
2172 bundleIDString
->getCStringNoCopy());
2176 /* Save the path if we got one (it should always be available but it's
2177 * just something nice to have for bookkeeping).
2185 * Minimal validation to initialize. We'll do other validation on the spot.
2187 if (bundleID
->getLength() >= KMOD_MAX_NAME
) {
2189 kOSKextLogErrorLevel
|
2190 kOSKextLogValidationFlag
,
2191 "Kext %s error - CFBundleIdentifier over max length %d.",
2192 getIdentifierCString(), KMOD_MAX_NAME
- 1);
2196 version
= compatibleVersion
= -1;
2198 versionString
= OSDynamicCast(OSString
,
2199 getPropertyForHostArch(kCFBundleVersionKey
));
2200 if (!versionString
) {
2202 kOSKextLogErrorLevel
|
2203 kOSKextLogValidationFlag
,
2204 "Kext %s error - CFBundleVersion missing/invalid type.",
2205 getIdentifierCString());
2208 versionCString
= versionString
->getCStringNoCopy();
2209 version
= OSKextParseVersionString(versionCString
);
2212 kOSKextLogErrorLevel
|
2213 kOSKextLogValidationFlag
,
2214 "Kext %s error - CFBundleVersion bad value '%s'.",
2215 getIdentifierCString(), versionCString
);
2219 compatibleVersion
= -1; // set to illegal value for kexts that don't have
2221 compatibleVersionString
= OSDynamicCast(OSString
,
2222 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
2223 if (compatibleVersionString
) {
2224 compatibleVersionCString
= compatibleVersionString
->getCStringNoCopy();
2225 compatibleVersion
= OSKextParseVersionString(compatibleVersionCString
);
2226 if (compatibleVersion
< 0) {
2228 kOSKextLogErrorLevel
|
2229 kOSKextLogValidationFlag
,
2230 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2231 getIdentifierCString(), compatibleVersionCString
);
2235 if (compatibleVersion
> version
) {
2237 kOSKextLogErrorLevel
|
2238 kOSKextLogValidationFlag
,
2239 "Kext %s error - %s %s > %s %s (must be <=).",
2240 getIdentifierCString(),
2241 kOSBundleCompatibleVersionKey
, compatibleVersionCString
,
2242 kCFBundleVersionKey
, versionCString
);
2247 /* Check to see if this kext is in exclude list */
2248 if (isInExcludeList()) {
2250 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
2251 "Kext %s is in exclude list, not loadable",
2252 getIdentifierCString());
2256 /* Set flags for later use if the infoDict gets flushed. We only
2257 * check for true values, not false ones(!)
2259 scratchBool
= OSDynamicCast(OSBoolean
,
2260 getPropertyForHostArch(kOSBundleIsInterfaceKey
));
2261 if (scratchBool
== kOSBooleanTrue
) {
2262 flags
.interface
= 1;
2265 scratchBool
= OSDynamicCast(OSBoolean
,
2266 getPropertyForHostArch(kOSKernelResourceKey
));
2267 if (scratchBool
== kOSBooleanTrue
) {
2268 flags
.kernelComponent
= 1;
2269 flags
.interface
= 1; // xxx - hm. the kernel itself isn't an interface...
2272 /* A kernel component has one implicit dependency on the kernel.
2274 flags
.hasAllDependencies
= 1;
2277 /* Make sure common string values in personalities are uniqued to OSSymbols.
2279 scratchDict
= OSDynamicCast(OSDictionary
,
2280 getPropertyForHostArch(kIOKitPersonalitiesKey
));
2282 uniquePersonalityProperties(scratchDict
);
2292 /*********************************************************************
2293 * Not used for prelinked kernel boot as there is no unrelocated
2295 *********************************************************************/
2297 OSKext::setExecutable(
2298 OSData
* anExecutable
,
2299 OSData
* externalData
,
2300 bool externalDataIsMkext
)
2302 bool result
= false;
2303 const char * executableKey
= NULL
; // do not free
2305 if (!anExecutable
) {
2306 infoDict
->removeObject(_kOSKextExecutableKey
);
2307 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
2308 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
2313 if (infoDict
->getObject(_kOSKextExecutableKey
) ||
2314 infoDict
->getObject(_kOSKextMkextExecutableReferenceKey
)) {
2315 panic("Attempt to set an executable on a kext "
2316 "that already has one (%s).",
2317 getIdentifierCString());
2321 if (externalDataIsMkext
) {
2322 executableKey
= _kOSKextMkextExecutableReferenceKey
;
2324 executableKey
= _kOSKextExecutableKey
;
2328 infoDict
->setObject(executableKey
, anExecutable
);
2330 infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
);
2340 /*********************************************************************
2341 *********************************************************************/
2343 uniqueStringPlistProperty(OSDictionary
* dict
, const char * key
)
2345 OSString
* stringValue
= NULL
;// do not release
2346 const OSSymbol
* symbolValue
= NULL
; // must release
2348 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2353 symbolValue
= OSSymbol::withString(stringValue
);
2358 dict
->setObject(key
, symbolValue
);
2362 symbolValue
->release();
2368 /*********************************************************************
2369 *********************************************************************/
2371 uniqueStringPlistProperty(OSDictionary
* dict
, const OSString
* key
)
2373 OSString
* stringValue
= NULL
;// do not release
2374 const OSSymbol
* symbolValue
= NULL
; // must release
2376 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2381 symbolValue
= OSSymbol::withString(stringValue
);
2386 dict
->setObject(key
, symbolValue
);
2390 symbolValue
->release();
2396 /*********************************************************************
2397 * Replace common personality property values with uniqued instances
2398 * to save on wired memory.
2399 *********************************************************************/
2402 OSKext::uniquePersonalityProperties(OSDictionary
* personalityDict
)
2404 /* Properties every personality has.
2406 uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKey
);
2407 uniqueStringPlistProperty(personalityDict
, kIOProviderClassKey
);
2408 uniqueStringPlistProperty(personalityDict
, gIOClassKey
);
2410 /* Other commonly used properties.
2412 uniqueStringPlistProperty(personalityDict
, gIOMatchCategoryKey
);
2413 uniqueStringPlistProperty(personalityDict
, gIOResourceMatchKey
);
2414 uniqueStringPlistProperty(personalityDict
, gIOUserClientClassKey
);
2416 uniqueStringPlistProperty(personalityDict
, "HIDDefaultBehavior");
2417 uniqueStringPlistProperty(personalityDict
, "HIDPointerAccelerationType");
2418 uniqueStringPlistProperty(personalityDict
, "HIDRemoteControlType");
2419 uniqueStringPlistProperty(personalityDict
, "HIDScrollAccelerationType");
2420 uniqueStringPlistProperty(personalityDict
, "IOPersonalityPublisher");
2421 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect");
2422 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect Location");
2423 uniqueStringPlistProperty(personalityDict
, "Vendor");
2424 uniqueStringPlistProperty(personalityDict
, "Vendor Identification");
2425 uniqueStringPlistProperty(personalityDict
, "Vendor Name");
2426 uniqueStringPlistProperty(personalityDict
, "bConfigurationValue");
2427 uniqueStringPlistProperty(personalityDict
, "bInterfaceNumber");
2428 uniqueStringPlistProperty(personalityDict
, "idProduct");
2433 /*********************************************************************
2434 *********************************************************************/
2439 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2442 OSSafeReleaseNULL(infoDict
);
2443 OSSafeReleaseNULL(bundleID
);
2444 OSSafeReleaseNULL(path
);
2445 OSSafeReleaseNULL(executableRelPath
);
2446 OSSafeReleaseNULL(dependencies
);
2447 OSSafeReleaseNULL(linkedExecutable
);
2448 OSSafeReleaseNULL(metaClasses
);
2449 OSSafeReleaseNULL(interfaceUUID
);
2451 if (isInterface() && kmod_info
) {
2452 kfree(kmod_info
, sizeof(kmod_info_t
));
2460 #pragma mark Mkext files
2462 /*********************************************************************
2463 *********************************************************************/
2465 OSKext::readMkextArchive(OSData
* mkextData
,
2466 uint32_t * checksumPtr
)
2468 OSReturn result
= kOSKextReturnBadData
;
2469 uint32_t mkextLength
= 0;
2470 mkext_header
* mkextHeader
= 0;// do not free
2471 uint32_t mkextVersion
= 0;
2473 /* Note default return of kOSKextReturnBadData above.
2475 mkextLength
= mkextData
->getLength();
2476 if (mkextLength
< sizeof(mkext_basic_header
)) {
2477 OSKextLog(/* kext */ NULL
,
2478 kOSKextLogErrorLevel
|
2479 kOSKextLogArchiveFlag
,
2480 "Mkext archive too small to be valid.");
2484 mkextHeader
= (mkext_header
*)mkextData
->getBytesNoCopy();
2486 if (MKEXT_GET_MAGIC(mkextHeader
) != MKEXT_MAGIC
||
2487 MKEXT_GET_SIGNATURE(mkextHeader
) != MKEXT_SIGN
) {
2488 OSKextLog(/* kext */ NULL
,
2489 kOSKextLogErrorLevel
|
2490 kOSKextLogArchiveFlag
,
2491 "Mkext archive has invalid magic or signature.");
2495 if (MKEXT_GET_LENGTH(mkextHeader
) != mkextLength
) {
2496 OSKextLog(/* kext */ NULL
,
2497 kOSKextLogErrorLevel
|
2498 kOSKextLogArchiveFlag
,
2499 "Mkext archive recorded length doesn't match actual file length.");
2503 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2505 if (mkextVersion
== MKEXT_VERS_2
) {
2506 result
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
);
2508 OSKextLog(/* kext */ NULL
,
2509 kOSKextLogErrorLevel
|
2510 kOSKextLogArchiveFlag
,
2511 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
);
2512 result
= kOSKextReturnUnsupported
;
2519 /*********************************************************************
2520 * Assumes magic, signature, version, length have been checked.
2521 * xxx - need to add further bounds checking for each file entry
2523 * Should keep track of all kexts created so far, and if we hit a
2524 * fatal error halfway through, remove those kexts. If we've dropped
2525 * an older version that had already been read, whoops! Might want to
2526 * add a level of buffering?
2527 *********************************************************************/
2530 OSKext::readMkext2Archive(
2532 OSDictionary
** mkextPlistOut
,
2533 uint32_t * checksumPtr
)
2535 OSReturn result
= kOSReturnError
;
2536 uint32_t mkextLength
;
2537 mkext2_header
* mkextHeader
= NULL
;// do not free
2538 void * mkextEnd
= NULL
;// do not free
2539 uint32_t mkextVersion
;
2540 uint8_t * crc_address
= NULL
;
2542 uint32_t mkextPlistOffset
;
2543 uint32_t mkextPlistCompressedSize
;
2544 char * mkextPlistEnd
= NULL
;// do not free
2545 uint32_t mkextPlistFullSize
;
2546 OSString
* errorString
= NULL
;// must release
2547 OSData
* mkextPlistUncompressedData
= NULL
;// must release
2548 const char * mkextPlistDataBuffer
= NULL
;// do not free
2549 OSObject
* parsedXML
= NULL
;// must release
2550 OSDictionary
* mkextPlist
= NULL
;// do not release
2551 OSArray
* mkextInfoDictArray
= NULL
;// do not release
2554 mkextLength
= mkextData
->getLength();
2555 mkextHeader
= (mkext2_header
*)mkextData
->getBytesNoCopy();
2556 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2557 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2559 crc_address
= (u_int8_t
*)&mkextHeader
->version
;
2560 checksum
= mkext_adler32(crc_address
,
2561 (uintptr_t)mkextHeader
+
2562 MKEXT_GET_LENGTH(mkextHeader
) - (uintptr_t)crc_address
);
2564 if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) {
2565 OSKextLog(/* kext */ NULL
,
2566 kOSKextLogErrorLevel
|
2567 kOSKextLogArchiveFlag
,
2568 "Mkext archive has bad checksum.");
2569 result
= kOSKextReturnBadData
;
2574 *checksumPtr
= checksum
;
2577 /* Check that the CPU type & subtype match that of the running kernel. */
2578 if (MKEXT_GET_CPUTYPE(mkextHeader
) == (UInt32
)CPU_TYPE_ANY
) {
2579 OSKextLog(/* kext */ NULL
,
2580 kOSKextLogErrorLevel
|
2581 kOSKextLogArchiveFlag
,
2582 "Mkext archive must have a specific CPU type.");
2583 result
= kOSKextReturnBadData
;
2586 if ((UInt32
)_mh_execute_header
.cputype
!=
2587 MKEXT_GET_CPUTYPE(mkextHeader
)) {
2588 OSKextLog(/* kext */ NULL
,
2589 kOSKextLogErrorLevel
|
2590 kOSKextLogArchiveFlag
,
2591 "Mkext archive does not match the running kernel's CPU type.");
2592 result
= kOSKextReturnArchNotFound
;
2597 mkextPlistOffset
= MKEXT2_GET_PLIST(mkextHeader
);
2598 mkextPlistCompressedSize
= MKEXT2_GET_PLIST_COMPSIZE(mkextHeader
);
2599 mkextPlistEnd
= (char *)mkextHeader
+ mkextPlistOffset
+
2600 mkextPlistCompressedSize
;
2601 if (mkextPlistEnd
> mkextEnd
) {
2602 OSKextLog(/* kext */ NULL
,
2603 kOSKextLogErrorLevel
|
2604 kOSKextLogArchiveFlag
,
2605 "Mkext archive file overrun.");
2606 result
= kOSKextReturnBadData
;
2609 mkextPlistFullSize
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
);
2610 if (mkextPlistCompressedSize
) {
2611 mkextPlistUncompressedData
= sKernelKext
->extractMkext2FileData(
2612 (UInt8
*)mkextHeader
+ mkextPlistOffset
,
2614 mkextPlistCompressedSize
, mkextPlistFullSize
);
2615 if (!mkextPlistUncompressedData
) {
2618 mkextPlistDataBuffer
= (const char *)
2619 mkextPlistUncompressedData
->getBytesNoCopy();
2621 mkextPlistDataBuffer
= (const char *)mkextHeader
+ mkextPlistOffset
;
2624 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2626 parsedXML
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
);
2628 mkextPlist
= OSDynamicCast(OSDictionary
, parsedXML
);
2631 const char * errorCString
= "(unknown error)";
2633 if (errorString
&& errorString
->getCStringNoCopy()) {
2634 errorCString
= errorString
->getCStringNoCopy();
2635 } else if (parsedXML
) {
2636 errorCString
= "not a dictionary";
2638 OSKextLog(/* kext */ NULL
,
2639 kOSKextLogErrorLevel
|
2640 kOSKextLogArchiveFlag
,
2641 "Error unserializing mkext plist: %s.", errorCString
);
2645 /* If the caller needs the plist, hand it back and retain it.
2646 * (This function releases it at the end.)
2648 if (mkextPlistOut
) {
2649 *mkextPlistOut
= mkextPlist
;
2650 (*mkextPlistOut
)->retain();
2653 mkextInfoDictArray
= OSDynamicCast(OSArray
,
2654 mkextPlist
->getObject(kMKEXTInfoDictionariesKey
));
2655 if (!mkextInfoDictArray
) {
2656 OSKextLog(/* kext */ NULL
,
2657 kOSKextLogErrorLevel
|
2658 kOSKextLogArchiveFlag
,
2659 "Mkext archive contains no kext info dictionaries.");
2663 count
= mkextInfoDictArray
->getCount();
2664 for (i
= 0; i
< count
; i
++) {
2665 OSDictionary
* infoDict
;
2668 infoDict
= OSDynamicCast(OSDictionary
,
2669 mkextInfoDictArray
->getObject(i
));
2671 /* Create the kext for the entry, then release it, because the
2672 * kext system keeps them around until explicitly removed.
2673 * Any creation/registration failures are already logged for us.
2676 OSKext
* newKext
= OSKext::withMkext2Info(infoDict
, mkextData
);
2677 OSSafeReleaseNULL(newKext
);
2681 /* Even if we didn't keep any kexts from the mkext, we may have a load
2682 * request to process, so we are successful (no errors occurred).
2684 result
= kOSReturnSuccess
;
2688 OSSafeReleaseNULL(parsedXML
);
2689 OSSafeReleaseNULL(mkextPlistUncompressedData
);
2690 OSSafeReleaseNULL(errorString
);
2695 /*********************************************************************
2696 *********************************************************************/
2699 OSKext::withMkext2Info(
2700 OSDictionary
* anInfoDict
,
2703 OSKext
* newKext
= new OSKext
;
2705 if (newKext
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) {
2713 /*********************************************************************
2714 *********************************************************************/
2716 OSKext::initWithMkext2Info(
2717 OSDictionary
* anInfoDict
,
2720 bool result
= false;
2721 OSString
* kextPath
= NULL
;// do not release
2722 OSNumber
* executableOffsetNum
= NULL
;// do not release
2723 OSCollectionIterator
* iterator
= NULL
;// must release
2724 OSData
* executable
= NULL
;// must release
2726 if (anInfoDict
== NULL
|| !super::init()) {
2730 /* Get the path. Don't look for an arch-specific path property.
2732 kextPath
= OSDynamicCast(OSString
,
2733 anInfoDict
->getObject(kMKEXTBundlePathKey
));
2735 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
2739 /* If we have a path to the executable, save it.
2741 executableRelPath
= OSDynamicCast(OSString
,
2742 anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
));
2743 if (executableRelPath
) {
2744 executableRelPath
->retain();
2747 /* Don't need the paths to be in the info dictionary any more.
2749 anInfoDict
->removeObject(kMKEXTBundlePathKey
);
2750 anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
);
2752 executableOffsetNum
= OSDynamicCast(OSNumber
,
2753 infoDict
->getObject(kMKEXTExecutableKey
));
2754 if (executableOffsetNum
) {
2755 executable
= createMkext2FileEntry(mkextData
,
2756 executableOffsetNum
, "executable");
2757 infoDict
->removeObject(kMKEXTExecutableKey
);
2761 if (!setExecutable(executable
, mkextData
, true)) {
2766 result
= registerIdentifier();
2770 OSSafeReleaseNULL(executable
);
2771 OSSafeReleaseNULL(iterator
);
2775 /*********************************************************************
2776 *********************************************************************/
2778 OSKext::createMkext2FileEntry(
2780 OSNumber
* offsetNum
,
2783 OSData
* result
= NULL
;
2784 MkextEntryRef entryRef
;
2785 uint8_t * mkextBuffer
= (uint8_t *)mkextData
->getBytesNoCopy();
2786 uint32_t entryOffset
= offsetNum
->unsigned32BitValue();
2788 result
= OSData::withCapacity(sizeof(entryRef
));
2793 entryRef
.mkext
= (mkext_basic_header
*)mkextBuffer
;
2794 entryRef
.fileinfo
= mkextBuffer
+ entryOffset
;
2795 if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) {
2796 OSSafeReleaseNULL(result
);
2803 kOSKextLogErrorLevel
|
2804 kOSKextLogArchiveFlag
,
2805 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2806 name
, getIdentifierCString());
2811 /*********************************************************************
2812 *********************************************************************/
2814 static void * z_alloc(void *, u_int items
, u_int size
);
2815 static void z_free(void *, void *ptr
);
2817 typedef struct z_mem
{
2818 uint32_t alloc_size
;
2823 * Space allocation and freeing routines for use by zlib routines.
2826 z_alloc(void * notused __unused
, u_int num_items
, u_int size
)
2828 void * result
= NULL
;
2829 z_mem
* zmem
= NULL
;
2831 uint64_t total
= ((uint64_t)num_items
) * ((uint64_t)size
);
2832 //Check for overflow due to multiplication
2833 if (total
> UINT32_MAX
) {
2834 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
2835 notused
, num_items
, size
, num_items
, size
);
2838 uint64_t allocSize64
= total
+ ((uint64_t)sizeof(zmem
));
2839 //Check for overflow due to addition
2840 if (allocSize64
> UINT32_MAX
) {
2841 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
2842 notused
, num_items
, size
, (uint32_t)total
, sizeof(zmem
));
2844 uint32_t allocSize
= (uint32_t)allocSize64
;
2846 zmem
= (z_mem
*)kalloc_tag(allocSize
, VM_KERN_MEMORY_OSKEXT
);
2850 zmem
->alloc_size
= allocSize
;
2851 result
= (void *)&(zmem
->data
);
2857 z_free(void * notused __unused
, void * ptr
)
2859 uint32_t * skipper
= (uint32_t *)ptr
- 1;
2860 z_mem
* zmem
= (z_mem
*)skipper
;
2861 kfree(zmem
, zmem
->alloc_size
);
2867 OSKext::extractMkext2FileData(
2870 uint32_t compressedSize
,
2873 OSData
* result
= NULL
;
2875 OSData
* uncompressedData
= NULL
;// release on error
2877 uint8_t * uncompressedDataBuffer
= 0;// do not free
2878 unsigned long uncompressedSize
;
2880 bool zstream_inited
= false;
2883 /* If the file isn't compressed, we want to make a copy
2884 * so that we don't have the tie to the larger mkext file buffer any more.
2886 if (!compressedSize
) {
2887 uncompressedData
= OSData::withBytes(data
, fullSize
);
2888 // xxx - no check for failure?
2889 result
= uncompressedData
;
2893 if (KERN_SUCCESS
!= kmem_alloc(kernel_map
,
2894 (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
, VM_KERN_MEMORY_OSKEXT
)) {
2895 /* How's this for cheesy? The kernel is only asked to extract
2896 * kext plists so we tailor the log messages.
2900 kOSKextLogErrorLevel
|
2901 kOSKextLogArchiveFlag
,
2902 "Allocation failure extracting %s from mkext.", name
);
2905 kOSKextLogErrorLevel
|
2906 kOSKextLogArchiveFlag
,
2907 "Allocation failure extracting %s from mkext for kext %s.",
2908 name
, getIdentifierCString());
2913 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
);
2914 if (!uncompressedData
) {
2917 kOSKextLogErrorLevel
|
2918 kOSKextLogArchiveFlag
,
2919 "Allocation failure extracting %s from mkext.", name
);
2922 kOSKextLogErrorLevel
|
2923 kOSKextLogArchiveFlag
,
2924 "Allocation failure extracting %s from mkext for kext %s.",
2925 name
, getIdentifierCString());
2929 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
2933 kOSKextLogDetailLevel
|
2934 kOSKextLogArchiveFlag
,
2935 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2936 name
, compressedSize
, fullSize
);
2939 kOSKextLogDetailLevel
|
2940 kOSKextLogArchiveFlag
,
2941 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2942 getIdentifierCString(), name
, compressedSize
, fullSize
);
2945 bzero(&zstream
, sizeof(zstream
));
2946 zstream
.next_in
= (UInt8
*)data
;
2947 zstream
.avail_in
= compressedSize
;
2949 zstream
.next_out
= uncompressedDataBuffer
;
2950 zstream
.avail_out
= fullSize
;
2952 zstream
.zalloc
= z_alloc
;
2953 zstream
.zfree
= z_free
;
2955 zlib_result
= inflateInit(&zstream
);
2956 if (Z_OK
!= zlib_result
) {
2959 kOSKextLogErrorLevel
|
2960 kOSKextLogArchiveFlag
,
2961 "Mkext error; zlib inflateInit failed (%d) for %s.",
2965 kOSKextLogErrorLevel
|
2966 kOSKextLogArchiveFlag
,
2967 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2968 getIdentifierCString(), zlib_result
, name
);
2972 zstream_inited
= true;
2975 zlib_result
= inflate(&zstream
, Z_FINISH
);
2977 if (zlib_result
== Z_STREAM_END
|| zlib_result
== Z_OK
) {
2978 uncompressedSize
= zstream
.total_out
;
2982 kOSKextLogErrorLevel
|
2983 kOSKextLogArchiveFlag
,
2984 "Mkext error; zlib inflate failed (%d) for %s.",
2988 kOSKextLogErrorLevel
|
2989 kOSKextLogArchiveFlag
,
2990 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
2991 getIdentifierCString(), zlib_result
, name
);
2995 kOSKextLogErrorLevel
|
2996 kOSKextLogArchiveFlag
,
2997 "zlib error: %s.", zstream
.msg
);
3002 if (uncompressedSize
!= fullSize
) {
3005 kOSKextLogErrorLevel
|
3006 kOSKextLogArchiveFlag
,
3007 "Mkext error; zlib inflate discrepancy for %s, "
3008 "uncompressed size != original size.", name
);
3011 kOSKextLogErrorLevel
|
3012 kOSKextLogArchiveFlag
,
3013 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3014 "uncompressed size != original size.",
3015 getIdentifierCString(), name
);
3020 result
= uncompressedData
;
3023 /* Don't bother checking return, nothing we can do on fail.
3025 if (zstream_inited
) {
3026 inflateEnd(&zstream
);
3030 OSSafeReleaseNULL(uncompressedData
);
3036 /*********************************************************************
3037 *********************************************************************/
3040 OSKext::loadFromMkext(
3041 OSKextLogSpec clientLogFilter
,
3043 uint32_t mkextBufferLength
,
3045 uint32_t * logInfoLengthOut
)
3047 OSReturn result
= kOSReturnError
;
3048 OSReturn tempResult
= kOSReturnError
;
3050 OSData
* mkextData
= NULL
;// must release
3051 OSDictionary
* mkextPlist
= NULL
;// must release
3053 OSArray
* logInfoArray
= NULL
;// must release
3054 OSSerialize
* serializer
= NULL
;// must release
3056 OSString
* predicate
= NULL
;// do not release
3057 OSDictionary
* requestArgs
= NULL
;// do not release
3059 OSString
* kextIdentifier
= NULL
;// do not release
3060 OSNumber
* startKextExcludeNum
= NULL
;// do not release
3061 OSNumber
* startMatchingExcludeNum
= NULL
;// do not release
3062 OSBoolean
* delayAutounloadBool
= NULL
;// do not release
3063 OSArray
* personalityNames
= NULL
;// do not release
3065 /* Default values for these two options: regular autounload behavior,
3066 * load all kexts, send no personalities.
3068 Boolean delayAutounload
= false;
3069 OSKextExcludeLevel startKextExcludeLevel
= kOSKextExcludeNone
;
3070 OSKextExcludeLevel startMatchingExcludeLevel
= kOSKextExcludeAll
;
3072 IORecursiveLockLock(sKextLock
);
3076 *logInfoLengthOut
= 0;
3079 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
3081 OSKextLog(/* kext */ NULL
,
3082 kOSKextLogDebugLevel
|
3084 "Received kext load request from user space.");
3086 /* Regardless of processing, the fact that we have gotten here means some
3087 * user-space program is up and talking to us, so we'll switch our kext
3088 * registration to reflect that.
3090 if (!sUserLoadsActive
) {
3091 OSKextLog(/* kext */ NULL
,
3092 kOSKextLogProgressLevel
|
3093 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
3094 "Switching to late startup (user-space) kext loading policy.");
3096 sUserLoadsActive
= true;
3099 if (!sLoadEnabled
) {
3100 OSKextLog(/* kext */ NULL
,
3101 kOSKextLogErrorLevel
|
3103 "Kext loading is disabled.");
3104 result
= kOSKextReturnDisabled
;
3108 /* Note that we do not set a dealloc function on this OSData
3109 * object! No references to it can remain after the loadFromMkext()
3110 * call since we are in a MIG function, and will vm_deallocate()
3113 mkextData
= OSData::withBytesNoCopy(mkextBuffer
,
3116 OSKextLog(/* kext */ NULL
,
3117 kOSKextLogErrorLevel
|
3118 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3119 "Failed to create wrapper for kext load request.");
3120 result
= kOSKextReturnNoMemory
;
3124 result
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
);
3125 if (result
!= kOSReturnSuccess
) {
3126 OSKextLog(/* kext */ NULL
,
3127 kOSKextLogErrorLevel
|
3129 "Failed to read kext load request.");
3133 predicate
= _OSKextGetRequestPredicate(mkextPlist
);
3134 if (!predicate
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) {
3135 OSKextLog(/* kext */ NULL
,
3136 kOSKextLogErrorLevel
|
3138 "Received kext load request with no predicate; skipping.");
3139 result
= kOSKextReturnInvalidArgument
;
3143 requestArgs
= OSDynamicCast(OSDictionary
,
3144 mkextPlist
->getObject(kKextRequestArgumentsKey
));
3145 if (!requestArgs
|| !requestArgs
->getCount()) {
3146 OSKextLog(/* kext */ NULL
,
3147 kOSKextLogErrorLevel
|
3149 "Received kext load request with no arguments.");
3150 result
= kOSKextReturnInvalidArgument
;
3154 kextIdentifier
= OSDynamicCast(OSString
,
3155 requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
));
3156 if (!kextIdentifier
) {
3157 OSKextLog(/* kext */ NULL
,
3158 kOSKextLogErrorLevel
|
3160 "Received kext load request with no kext identifier.");
3161 result
= kOSKextReturnInvalidArgument
;
3165 startKextExcludeNum
= OSDynamicCast(OSNumber
,
3166 requestArgs
->getObject(kKextRequestArgumentStartExcludeKey
));
3167 startMatchingExcludeNum
= OSDynamicCast(OSNumber
,
3168 requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
));
3169 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
3170 requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
));
3171 personalityNames
= OSDynamicCast(OSArray
,
3172 requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
));
3174 if (delayAutounloadBool
) {
3175 delayAutounload
= delayAutounloadBool
->getValue();
3177 if (startKextExcludeNum
) {
3178 startKextExcludeLevel
= startKextExcludeNum
->unsigned8BitValue();
3180 if (startMatchingExcludeNum
) {
3181 startMatchingExcludeLevel
= startMatchingExcludeNum
->unsigned8BitValue();
3184 OSKextLog(/* kext */ NULL
,
3185 kOSKextLogProgressLevel
|
3187 "Received request from user space to load kext %s.",
3188 kextIdentifier
->getCStringNoCopy());
3190 /* Load the kext, with no deferral, since this is a load from outside
3192 * xxx - Would like a better way to handle the default values for the
3193 * xxx - start/match opt args.
3195 result
= OSKext::loadKextWithIdentifier(
3197 /* allowDefer */ false,
3199 startKextExcludeLevel
,
3200 startMatchingExcludeLevel
,
3202 if (result
!= kOSReturnSuccess
) {
3205 /* If the load came down from kextd, it will shortly inform IOCatalogue
3206 * for matching via a separate IOKit calldown.
3211 /* Gather up the collected log messages for user space. Any
3212 * error messages past this call will not make it up as log messages
3213 * but will be in the system log.
3215 logInfoArray
= OSKext::clearUserSpaceLogFilter();
3217 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
3218 tempResult
= OSKext::serializeLogInfo(logInfoArray
,
3219 logInfoOut
, logInfoLengthOut
);
3220 if (tempResult
!= kOSReturnSuccess
) {
3221 result
= tempResult
;
3225 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3227 /* Note: mkextDataObject will have been retained by every kext w/an
3228 * executable in it. That should all have been flushed out at the
3229 * and of the load operation, but you never know....
3231 if (mkextData
&& mkextData
->getRetainCount() > 1) {
3232 OSKextLog(/* kext */ NULL
,
3233 kOSKextLogErrorLevel
|
3234 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3235 "Kext load request buffer from user space still retained by a kext; "
3236 "probable memory leak.");
3239 IORecursiveLockUnlock(sKextLock
);
3241 OSSafeReleaseNULL(mkextData
);
3242 OSSafeReleaseNULL(mkextPlist
);
3243 OSSafeReleaseNULL(serializer
);
3244 OSSafeReleaseNULL(logInfoArray
);
3249 /*********************************************************************
3250 *********************************************************************/
3253 OSKext::serializeLogInfo(
3254 OSArray
* logInfoArray
,
3256 uint32_t * logInfoLengthOut
)
3258 OSReturn result
= kOSReturnError
;
3259 char * buffer
= NULL
;
3260 kern_return_t kmem_result
= KERN_FAILURE
;
3261 OSSerialize
* serializer
= NULL
;// must release; reused
3262 char * logInfo
= NULL
;// returned by reference
3263 uint32_t logInfoLength
= 0;
3265 if (!logInfoArray
|| !logInfoOut
|| !logInfoLengthOut
) {
3266 OSKextLog(/* kext */ NULL
,
3267 kOSKextLogErrorLevel
|
3269 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3270 /* Bad programmer. */
3271 result
= kOSKextReturnInvalidArgument
;
3275 serializer
= OSSerialize::withCapacity(0);
3277 OSKextLog(/* kext */ NULL
,
3278 kOSKextLogErrorLevel
|
3280 "Failed to create serializer on log info for request from user space.");
3281 /* Incidental error; we're going to (try to) allow the request
3282 * itself to succeed. */
3285 if (!logInfoArray
->serialize(serializer
)) {
3286 OSKextLog(/* kext */ NULL
,
3287 kOSKextLogErrorLevel
|
3289 "Failed to serialize log info for request from user space.");
3290 /* Incidental error; we're going to (try to) allow the request
3291 * itself to succeed. */
3293 logInfo
= serializer
->text();
3294 logInfoLength
= serializer
->getLength();
3296 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
, round_page(logInfoLength
), VM_KERN_MEMORY_OSKEXT
);
3297 if (kmem_result
!= KERN_SUCCESS
) {
3298 OSKextLog(/* kext */ NULL
,
3299 kOSKextLogErrorLevel
|
3301 "Failed to copy log info for request from user space.");
3302 /* Incidental error; we're going to (try to) allow the request
3305 /* 11981737 - clear uninitialized data in last page */
3306 bzero((void *)(buffer
+ logInfoLength
),
3307 (round_page(logInfoLength
) - logInfoLength
));
3308 memcpy(buffer
, logInfo
, logInfoLength
);
3309 *logInfoOut
= buffer
;
3310 *logInfoLengthOut
= logInfoLength
;
3314 result
= kOSReturnSuccess
;
3316 OSSafeReleaseNULL(serializer
);
3321 #pragma mark Instance Management Methods
3323 /*********************************************************************
3324 *********************************************************************/
3326 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
)
3328 OSKext
* foundKext
= NULL
;
3330 IORecursiveLockLock(sKextLock
);
3331 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3333 foundKext
->retain();
3335 IORecursiveLockUnlock(sKextLock
);
3340 /*********************************************************************
3341 *********************************************************************/
3343 OSKext::lookupKextWithIdentifier(OSString
* kextIdentifier
)
3345 return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy());
3348 /*********************************************************************
3349 *********************************************************************/
3351 OSKext::lookupKextWithLoadTag(uint32_t aTag
)
3353 OSKext
* foundKext
= NULL
; // returned
3356 IORecursiveLockLock(sKextLock
);
3358 count
= sLoadedKexts
->getCount();
3359 for (i
= 0; i
< count
; i
++) {
3360 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3361 if (thisKext
->getLoadTag() == aTag
) {
3362 foundKext
= thisKext
;
3363 foundKext
->retain();
3369 IORecursiveLockUnlock(sKextLock
);
3374 /*********************************************************************
3375 *********************************************************************/
3377 OSKext::lookupKextWithAddress(vm_address_t address
)
3379 OSKext
* foundKext
= NULL
; // returned
3382 IORecursiveLockLock(sKextLock
);
3384 count
= sLoadedKexts
->getCount();
3385 for (i
= 0; i
< count
; i
++) {
3386 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3387 if (thisKext
->linkedExecutable
) {
3388 vm_address_t kext_start
=
3389 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy();
3390 vm_address_t kext_end
= kext_start
+
3391 thisKext
->linkedExecutable
->getLength();
3392 if ((kext_start
<= address
) && (address
< kext_end
)) {
3393 foundKext
= thisKext
;
3394 foundKext
->retain();
3401 IORecursiveLockUnlock(sKextLock
);
3407 OSKext::copyKextUUIDForAddress(OSNumber
*address
)
3409 OSData
* uuid
= NULL
;
3410 OSKextActiveAccount
* active
;
3411 OSKext
* kext
= NULL
;
3419 uintptr_t addr
= ml_static_slide((uintptr_t)address
->unsigned64BitValue());
3422 /* Is the calling process allowed to query kext info? */
3423 if (current_task() != kernel_task
) {
3424 int macCheckResult
= 0;
3425 kauth_cred_t cred
= NULL
;
3427 cred
= kauth_cred_get_with_ref();
3428 macCheckResult
= mac_kext_check_query(cred
);
3429 kauth_cred_unref(&cred
);
3431 if (macCheckResult
!= 0) {
3432 OSKextLog(/* kext */ NULL
,
3433 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
3434 "Failed to query kext UUID (MAC policy error 0x%x).",
3441 IOSimpleLockLock(sKextAccountsLock
);
3442 // bsearch sKextAccounts list
3443 for (baseIdx
= 0, lim
= sKextAccountsCount
; lim
; lim
>>= 1) {
3444 active
= &sKextAccounts
[baseIdx
+ (lim
>> 1)];
3445 if ((addr
>= active
->address
) && (addr
< active
->address_end
)) {
3446 kext
= active
->account
->kext
;
3451 } else if (addr
> active
->address
) {
3453 baseIdx
+= (lim
>> 1) + 1;
3458 IOSimpleLockUnlock(sKextAccountsLock
);
3461 uuid
= kext
->copyTextUUID();
3463 } else if (((vm_offset_t
)addr
>= vm_kernel_stext
) && ((vm_offset_t
)addr
< vm_kernel_etext
)) {
3464 uuid
= sKernelKext
->copyTextUUID();
3470 /*********************************************************************
3471 *********************************************************************/
3473 OSKext::lookupKextWithUUID(uuid_t wanted
)
3475 OSKext
* foundKext
= NULL
; // returned
3478 IORecursiveLockLock(sKextLock
);
3480 count
= sLoadedKexts
->getCount();
3482 for (i
= 0; i
< count
; i
++) {
3483 OSKext
* thisKext
= NULL
;
3485 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3490 OSData
*uuid_data
= thisKext
->copyUUID();
3496 memcpy(&uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
3497 uuid_data
->release();
3499 if (0 == uuid_compare(wanted
, uuid
)) {
3500 foundKext
= thisKext
;
3501 foundKext
->retain();
3507 IORecursiveLockUnlock(sKextLock
);
3515 /*********************************************************************
3516 *********************************************************************/
3519 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
)
3521 bool result
= false;
3522 OSKext
* foundKext
= NULL
; // returned
3524 IORecursiveLockLock(sKextLock
);
3526 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3527 if (foundKext
&& foundKext
->isLoaded()) {
3531 IORecursiveLockUnlock(sKextLock
);
3536 /*********************************************************************
3537 * xxx - should spawn a separate thread so a kext can safely have
3538 * xxx - itself unloaded.
3539 *********************************************************************/
3547 bool terminateServicesAndRemovePersonalitiesFlag
)
3551 kOSKextLogErrorLevel
|
3552 kOSKextLogKextBookkeepingFlag
,
3553 "removeKext() called for %s, not supported on embedded",
3554 aKext
->getIdentifier() ? aKext
->getIdentifierCString() : "unknown kext");
3556 return kOSReturnSuccess
;
3557 #else /* CONFIG_EMBEDDED */
3559 OSReturn result
= kOSKextReturnInUse
;
3560 OSKext
* checkKext
= NULL
; // do not release
3562 int macCheckResult
= 0;
3563 kauth_cred_t cred
= NULL
;
3566 IORecursiveLockLock(sKextLock
);
3568 /* If the kext has no identifier, it failed to init
3569 * so isn't in sKextsByID and it isn't loaded.
3571 if (!aKext
->getIdentifier()) {
3572 result
= kOSReturnSuccess
;
3576 checkKext
= OSDynamicCast(OSKext
,
3577 sKextsByID
->getObject(aKext
->getIdentifier()));
3578 if (checkKext
!= aKext
) {
3579 result
= kOSKextReturnNotFound
;
3583 if (aKext
->isLoaded()) {
3585 if (current_task() != kernel_task
) {
3586 cred
= kauth_cred_get_with_ref();
3587 macCheckResult
= mac_kext_check_unload(cred
, aKext
->getIdentifierCString());
3588 kauth_cred_unref(&cred
);
3591 if (macCheckResult
!= 0) {
3592 result
= kOSReturnError
;
3594 kOSKextLogErrorLevel
|
3595 kOSKextLogKextBookkeepingFlag
,
3596 "Failed to remove kext %s (MAC policy error 0x%x).",
3597 aKext
->getIdentifierCString(), macCheckResult
);
3602 /* make sure there are no resource requests in flight - 17187548 */
3603 if (aKext
->countRequestCallbacks()) {
3607 /* If we are terminating, send the request to the IOCatalogue
3608 * (which will actually call us right back but that's ok we have
3609 * a recursive lock don't you know) but do not ask the IOCatalogue
3610 * to call back with an unload, we'll do that right here.
3612 if (terminateServicesAndRemovePersonalitiesFlag
) {
3613 result
= gIOCatalogue
->terminateDriversForModule(
3614 aKext
->getIdentifierCString(), /* unload */ false);
3615 if (result
!= kOSReturnSuccess
) {
3617 kOSKextLogErrorLevel
|
3618 kOSKextLogKextBookkeepingFlag
,
3619 "Can't remove kext %s; services failed to terminate - 0x%x.",
3620 aKext
->getIdentifierCString(), result
);
3625 result
= aKext
->unload();
3626 if (result
!= kOSReturnSuccess
) {
3631 /* Remove personalities as requested. This is a bit redundant for a loaded
3632 * kext as IOCatalogue::terminateDriversForModule() removes driver
3633 * personalities, but it doesn't restart matching, which we always want
3634 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3637 if (terminateServicesAndRemovePersonalitiesFlag
) {
3638 aKext
->removePersonalitiesFromCatalog();
3642 kOSKextLogProgressLevel
|
3643 kOSKextLogKextBookkeepingFlag
,
3644 "Removing kext %s.",
3645 aKext
->getIdentifierCString());
3647 sKextsByID
->removeObject(aKext
->getIdentifier());
3648 result
= kOSReturnSuccess
;
3651 IORecursiveLockUnlock(sKextLock
);
3653 #endif /* CONFIG_EMBEDDED */
3656 /*********************************************************************
3657 *********************************************************************/
3660 OSKext::removeKextWithIdentifier(
3661 const char * kextIdentifier
,
3662 bool terminateServicesAndRemovePersonalitiesFlag
)
3664 OSReturn result
= kOSReturnError
;
3666 IORecursiveLockLock(sKextLock
);
3668 OSKext
* aKext
= OSDynamicCast(OSKext
,
3669 sKextsByID
->getObject(kextIdentifier
));
3671 result
= kOSKextReturnNotFound
;
3672 OSKextLog(/* kext */ NULL
,
3673 kOSKextLogErrorLevel
|
3674 kOSKextLogKextBookkeepingFlag
,
3675 "Can't remove kext %s - not found.",
3680 result
= OSKext::removeKext(aKext
,
3681 terminateServicesAndRemovePersonalitiesFlag
);
3684 IORecursiveLockUnlock(sKextLock
);
3689 /*********************************************************************
3690 *********************************************************************/
3693 OSKext::removeKextWithLoadTag(
3694 OSKextLoadTag loadTag
,
3695 bool terminateServicesAndRemovePersonalitiesFlag
)
3697 OSReturn result
= kOSReturnError
;
3698 OSKext
* foundKext
= NULL
;
3701 IORecursiveLockLock(sKextLock
);
3703 count
= sLoadedKexts
->getCount();
3704 for (i
= 0; i
< count
; i
++) {
3705 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3706 if (thisKext
->loadTag
== loadTag
) {
3707 foundKext
= thisKext
;
3713 result
= kOSKextReturnNotFound
;
3714 OSKextLog(/* kext */ NULL
,
3715 kOSKextLogErrorLevel
|
3716 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
3717 "Can't remove kext with load tag %d - not found.",
3722 result
= OSKext::removeKext(foundKext
,
3723 terminateServicesAndRemovePersonalitiesFlag
);
3726 IORecursiveLockUnlock(sKextLock
);
3731 /*********************************************************************
3732 *********************************************************************/
3734 OSKext::copyKexts(void)
3736 OSDictionary
* result
;
3738 IORecursiveLockLock(sKextLock
);
3739 result
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection());
3740 IORecursiveLockUnlock(sKextLock
);
3745 /*********************************************************************
3746 *********************************************************************/
3747 #define BOOTER_KEXT_PREFIX "Driver-"
3749 typedef struct _DeviceTreeBuffer
{
3752 } _DeviceTreeBuffer
;
3754 /*********************************************************************
3755 * Create a dictionary of excluded kexts from the given booter data.
3756 *********************************************************************/
3759 OSKext::createExcludeListFromBooterData(
3760 OSDictionary
* theDictionary
,
3761 OSCollectionIterator
* theIterator
)
3763 OSString
* deviceTreeName
= NULL
;// do not release
3764 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
;// do not release
3765 char * booterDataPtr
= NULL
;// do not release
3766 _BooterKextFileInfo
* kextFileInfo
= NULL
;// do not release
3767 char * infoDictAddr
= NULL
;// do not release
3768 OSObject
* parsedXML
= NULL
;// must release
3769 OSDictionary
* theInfoDict
= NULL
;// do not release
3771 theIterator
->reset();
3773 /* look for AppleKextExcludeList.kext */
3774 while ((deviceTreeName
=
3775 OSDynamicCast(OSString
, theIterator
->getNextObject()))) {
3776 const char * devTreeNameCString
;
3777 OSData
* deviceTreeEntry
;
3778 OSString
* myBundleID
;// do not release
3780 OSSafeReleaseNULL(parsedXML
);
3783 OSDynamicCast(OSData
, theDictionary
->getObject(deviceTreeName
));
3784 if (!deviceTreeEntry
) {
3788 /* Make sure it is a kext */
3789 devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
3790 if (strncmp(devTreeNameCString
, BOOTER_KEXT_PREFIX
,
3791 (sizeof(BOOTER_KEXT_PREFIX
) - 1)) != 0) {
3793 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3794 "\"%s\" not a kext",
3795 devTreeNameCString
);
3799 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
3800 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
3801 if (!deviceTreeBuffer
) {
3805 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
3806 if (!booterDataPtr
) {
3810 kextFileInfo
= (_BooterKextFileInfo
*) booterDataPtr
;
3811 if (!kextFileInfo
->infoDictPhysAddr
||
3812 !kextFileInfo
->infoDictLength
) {
3816 infoDictAddr
= (char *)
3817 ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
3818 if (!infoDictAddr
) {
3822 parsedXML
= OSUnserializeXML(infoDictAddr
);
3827 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
3833 OSDynamicCast(OSString
,
3834 theInfoDict
->getObject(kCFBundleIdentifierKey
));
3836 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
3837 boolean_t updated
= updateExcludeList(theInfoDict
);
3840 panic("Missing OSKextExcludeList dictionary\n");
3844 } // while ( (deviceTreeName = ...) )
3846 OSSafeReleaseNULL(parsedXML
);
3850 /*********************************************************************
3851 * Create a dictionary of excluded kexts from the given prelink
3852 * info (kernelcache).
3853 *********************************************************************/
3856 OSKext::createExcludeListFromPrelinkInfo( OSArray
* theInfoArray
)
3858 OSDictionary
* myInfoDict
= NULL
;// do not release
3859 OSString
* myBundleID
; // do not release
3862 /* Find com.apple.driver.KextExcludeList. */
3863 for (i
= 0; i
< theInfoArray
->getCount(); i
++) {
3864 myInfoDict
= OSDynamicCast(OSDictionary
, theInfoArray
->getObject(i
));
3869 OSDynamicCast(OSString
,
3870 myInfoDict
->getObject(kCFBundleIdentifierKey
));
3872 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
3873 boolean_t updated
= updateExcludeList(myInfoDict
);
3876 panic("Missing OSKextExcludeList dictionary\n");
3880 } // for (i = 0; i < theInfoArray->getCount()...
3887 OSKext::updateExcludeList(OSDictionary
*infoDict
)
3889 OSDictionary
*myTempDict
= NULL
; // do not free
3890 OSString
*myTempString
= NULL
;// do not free
3891 OSKextVersion newVersion
= 0;
3892 boolean_t updated
= false;
3898 myTempDict
= OSDynamicCast(OSDictionary
, infoDict
->getObject("OSKextExcludeList"));
3903 myTempString
= OSDynamicCast(OSString
, infoDict
->getObject(kCFBundleVersionKey
));
3904 if (!myTempString
) {
3908 newVersion
= OSKextParseVersionString(myTempString
->getCStringNoCopy());
3909 if (newVersion
== 0) {
3913 IORecursiveLockLock(sKextLock
);
3915 if (newVersion
> sExcludeListVersion
) {
3916 OSSafeReleaseNULL(sExcludeListByID
);
3917 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3918 sExcludeListVersion
= newVersion
;
3922 IORecursiveLockUnlock(sKextLock
);
3927 #pragma mark Accessors
3929 /*********************************************************************
3930 *********************************************************************/
3932 OSKext::getIdentifier(void)
3937 /*********************************************************************
3938 * A kext must have a bundle identifier to even survive initialization;
3939 * this is guaranteed to exist past then.
3940 *********************************************************************/
3942 OSKext::getIdentifierCString(void)
3944 return bundleID
->getCStringNoCopy();
3947 /*********************************************************************
3948 *********************************************************************/
3950 OSKext::getVersion(void)
3955 /*********************************************************************
3956 *********************************************************************/
3958 OSKext::getCompatibleVersion(void)
3960 return compatibleVersion
;
3963 /*********************************************************************
3964 *********************************************************************/
3966 OSKext::isLibrary(void)
3968 return getCompatibleVersion() > 0;
3971 /*********************************************************************
3972 *********************************************************************/
3974 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
)
3976 if ((compatibleVersion
> -1 && version
> -1) &&
3977 (compatibleVersion
<= version
&& aVersion
<= version
)) {
3983 /*********************************************************************
3984 *********************************************************************/
3986 OSKext::declaresExecutable(void)
3988 return getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
;
3991 /*********************************************************************
3992 *********************************************************************/
3994 OSKext::getExecutable(void)
3996 OSData
* result
= NULL
;
3997 OSData
* extractedExecutable
= NULL
; // must release
3998 OSData
* mkextExecutableRef
= NULL
;// do not release
4000 if (flags
.builtin
) {
4001 return sKernelKext
->linkedExecutable
;
4004 result
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
));
4009 mkextExecutableRef
= OSDynamicCast(OSData
,
4010 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
));
4012 if (mkextExecutableRef
) {
4013 MkextEntryRef
* mkextEntryRef
= (MkextEntryRef
*)
4014 mkextExecutableRef
->getBytesNoCopy();
4015 uint32_t mkextVersion
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
);
4016 if (mkextVersion
== MKEXT_VERS_2
) {
4017 mkext2_file_entry
* fileinfo
=
4018 (mkext2_file_entry
*)mkextEntryRef
->fileinfo
;
4019 uint32_t compressedSize
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
);
4020 uint32_t fullSize
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
);
4021 extractedExecutable
= extractMkext2FileData(
4022 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable",
4023 compressedSize
, fullSize
);
4025 OSKextLog(this, kOSKextLogErrorLevel
|
4026 kOSKextLogArchiveFlag
,
4027 "Kext %s - unknown mkext version 0x%x for executable.",
4028 getIdentifierCString(), mkextVersion
);
4031 /* Regardless of success, remove the mkext executable,
4032 * and drop one reference on the mkext. (setExecutable() does not
4033 * replace, it removes, or panics if asked to replace.)
4035 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
4036 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
4038 if (extractedExecutable
&& extractedExecutable
->getLength()) {
4039 if (!setExecutable(extractedExecutable
)) {
4042 result
= extractedExecutable
;
4050 OSSafeReleaseNULL(extractedExecutable
);
4055 /*********************************************************************
4056 *********************************************************************/
4058 OSKext::isInterface(void)
4060 return flags
.interface
;
4063 /*********************************************************************
4064 *********************************************************************/
4066 OSKext::isKernel(void)
4068 return this == sKernelKext
;
4071 /*********************************************************************
4072 *********************************************************************/
4074 OSKext::isKernelComponent(void)
4076 return flags
.kernelComponent
? true : false;
4079 /*********************************************************************
4080 *********************************************************************/
4082 OSKext::isExecutable(void)
4084 return !isKernel() && !isInterface() && declaresExecutable();
4087 /*********************************************************************
4088 * We might want to check this recursively for all dependencies,
4089 * since a subtree of dependencies could get loaded before we hit
4090 * a dependency that isn't safe-boot-loadable.
4092 * xxx - Might want to return false if OSBundleEnableKextLogging or
4093 * OSBundleDebugLevel
4094 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4095 * the point except it's usually development drivers, which might
4096 * cause panics on startup, that have those properties). Heh; could
4097 * use a "kx" boot-arg!
4098 *********************************************************************/
4100 OSKext::isLoadableInSafeBoot(void)
4102 bool result
= false;
4103 OSString
* required
= NULL
; // do not release
4110 required
= OSDynamicCast(OSString
,
4111 getPropertyForHostArch(kOSBundleRequiredKey
));
4115 if (required
->isEqualTo(kOSBundleRequiredRoot
) ||
4116 required
->isEqualTo(kOSBundleRequiredLocalRoot
) ||
4117 required
->isEqualTo(kOSBundleRequiredNetworkRoot
) ||
4118 required
->isEqualTo(kOSBundleRequiredSafeBoot
) ||
4119 required
->isEqualTo(kOSBundleRequiredConsole
)) {
4127 /*********************************************************************
4128 *********************************************************************/
4130 OSKext::isPrelinked(void)
4132 return flags
.prelinked
? true : false;
4135 /*********************************************************************
4136 *********************************************************************/
4138 OSKext::isLoaded(void)
4140 return flags
.loaded
? true : false;
4143 /*********************************************************************
4144 *********************************************************************/
4146 OSKext::isStarted(void)
4148 return flags
.started
? true : false;
4151 /*********************************************************************
4152 *********************************************************************/
4154 OSKext::isCPPInitialized(void)
4156 return flags
.CPPInitialized
;
4159 /*********************************************************************
4160 *********************************************************************/
4162 OSKext::setCPPInitialized(bool initialized
)
4164 flags
.CPPInitialized
= initialized
;
4167 /*********************************************************************
4168 *********************************************************************/
4170 OSKext::getLoadTag(void)
4175 /*********************************************************************
4176 *********************************************************************/
4178 OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
)
4180 if (linkedExecutable
) {
4181 *loadSize
= linkedExecutable
->getLength();
4183 /* If we have a kmod_info struct, calculated the wired size
4184 * from that. Otherwise it's the full load size.
4187 *wiredSize
= *loadSize
- kmod_info
->hdr_size
;
4189 *wiredSize
= *loadSize
;
4197 /*********************************************************************
4198 *********************************************************************/
4200 OSKext::copyUUID(void)
4202 OSData
* result
= NULL
;
4203 OSData
* theExecutable
= NULL
;// do not release
4204 const kernel_mach_header_t
* header
;
4206 /* An interface kext doesn't have a linked executable with an LC_UUID,
4207 * we create one when it's linked.
4209 if (interfaceUUID
) {
4210 result
= interfaceUUID
;
4215 if (flags
.builtin
|| isInterface()) {
4216 return sKernelKext
->copyUUID();
4219 /* For real kexts, try to get the UUID from the linked executable,
4220 * or if is hasn't been linked yet, the unrelocated executable.
4222 theExecutable
= linkedExecutable
;
4223 if (!theExecutable
) {
4224 theExecutable
= getExecutable();
4226 if (!theExecutable
) {
4230 header
= (const kernel_mach_header_t
*)theExecutable
->getBytesNoCopy();
4231 result
= copyMachoUUID(header
);
4237 /*********************************************************************
4238 *********************************************************************/
4240 OSKext::copyTextUUID(void)
4242 if (flags
.builtin
) {
4243 return copyMachoUUID((const kernel_mach_header_t
*)kmod_info
->address
);
4248 /*********************************************************************
4249 *********************************************************************/
4251 OSKext::copyMachoUUID(const kernel_mach_header_t
* header
)
4253 OSData
* result
= NULL
;
4254 const struct load_command
* load_cmd
= NULL
;
4255 const struct uuid_command
* uuid_cmd
= NULL
;
4258 load_cmd
= (const struct load_command
*)&header
[1];
4260 if (header
->magic
!= MH_MAGIC_KERNEL
) {
4262 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4263 "%s: bad header %p",
4269 for (i
= 0; i
< header
->ncmds
; i
++) {
4270 if (load_cmd
->cmd
== LC_UUID
) {
4271 uuid_cmd
= (struct uuid_command
*)load_cmd
;
4272 result
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
));
4275 load_cmd
= (struct load_command
*)((caddr_t
)load_cmd
+ load_cmd
->cmdsize
);
4282 /*********************************************************************
4283 *********************************************************************/
4284 #if defined (__arm__)
4285 #include <arm/arch.h>
4288 #if defined (__x86_64__)
4289 #define ARCHNAME "x86_64"
4290 #elif defined (__arm64__)
4291 #define ARCHNAME "arm64"
4292 #elif defined (__arm__)
4294 #if defined (__ARM_ARCH_7S__)
4295 #define ARCHNAME "armv7s"
4296 #elif defined (__ARM_ARCH_7F__)
4297 #define ARCHNAME "armv7f"
4298 #elif defined (__ARM_ARCH_7K__)
4299 #define ARCHNAME "armv7k"
4300 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
4301 #define ARCHNAME "armv7"
4302 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
4303 #define ARCHNAME "armv6"
4306 #elif defined (__arm64__)
4307 #define ARCHNAME "arm64"
4309 #error architecture not supported
4312 #define ARCH_SEPARATOR_CHAR '_'
4315 makeHostArchKey(const char * key
, uint32_t * keySizeOut
)
4317 char * result
= NULL
;
4318 uint32_t keyLength
= strlen(key
);
4321 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4323 keySize
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
);
4324 result
= (char *)kalloc_tag(keySize
, VM_KERN_MEMORY_OSKEXT
);
4328 strlcpy(result
, key
, keySize
);
4329 result
[keyLength
++] = ARCH_SEPARATOR_CHAR
;
4330 result
[keyLength
] = '\0';
4331 strlcat(result
, ARCHNAME
, keySize
);
4332 *keySizeOut
= keySize
;
4338 /*********************************************************************
4339 *********************************************************************/
4341 OSKext::getPropertyForHostArch(const char * key
)
4343 OSObject
* result
= NULL
;// do not release
4344 uint32_t hostArchKeySize
= 0;
4345 char * hostArchKey
= NULL
;// must kfree
4347 if (!key
|| !infoDict
) {
4351 /* Some properties are not allowed to be arch-variant:
4352 * - Any CFBundle... property.
4353 * - OSBundleIsInterface.
4354 * - OSKernelResource.
4356 if (STRING_HAS_PREFIX(key
, "OS") ||
4357 STRING_HAS_PREFIX(key
, "IO")) {
4358 hostArchKey
= makeHostArchKey(key
, &hostArchKeySize
);
4360 OSKextLog(/* kext (this isn't about a kext) */ NULL
,
4361 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4362 "Allocation failure.");
4365 result
= infoDict
->getObject(hostArchKey
);
4369 result
= infoDict
->getObject(key
);
4374 kfree(hostArchKey
, hostArchKeySize
);
4380 #pragma mark Load/Start/Stop/Unload
4383 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4385 /*********************************************************************
4386 * sExcludeListByID is a dictionary with keys / values of:
4387 * key = bundleID string of kext we will not allow to load
4388 * value = version string(s) of the kext that is to be denied loading.
4389 * The version strings can be comma delimited. For example if kext
4390 * com.foocompany.fookext has two versions that we want to deny
4391 * loading then the version strings might look like:
4393 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4394 * not load the kext.
4396 * Value may also be in the form of "LE 2.0.0" (version numbers
4397 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4398 * number less than 2.0.0 will not load)
4400 * NOTE - we cannot use the characters "<=" or "<" because we have code
4401 * that serializes plists and treats '<' as a special character.
4402 *********************************************************************/
4404 OSKext::isInExcludeList(void)
4406 OSString
* versionString
= NULL
;// do not release
4407 char * versionCString
= NULL
;// do not free
4409 boolean_t wantLessThan
= false;
4410 boolean_t wantLessThanEqualTo
= false;
4411 boolean_t isInExcludeList
= true;
4414 IORecursiveLockLock(sKextLock
);
4416 if (!sExcludeListByID
) {
4417 isInExcludeList
= false;
4419 /* look up by bundleID in our exclude list and if found get version
4420 * string (or strings) that we will not allow to load
4422 versionString
= OSDynamicCast(OSString
, sExcludeListByID
->getObject(bundleID
));
4423 if (versionString
== NULL
|| versionString
->getLength() > (sizeof(myBuffer
) - 1)) {
4424 isInExcludeList
= false;
4428 IORecursiveLockUnlock(sKextLock
);
4430 if (!isInExcludeList
) {
4434 /* parse version strings */
4435 versionCString
= (char *) versionString
->getCStringNoCopy();
4437 /* look for "LT" or "LE" form of version string, must be in first two
4440 if (*versionCString
== 'L' && *(versionCString
+ 1) == 'T') {
4441 wantLessThan
= true;
4442 versionCString
+= 2;
4443 } else if (*versionCString
== 'L' && *(versionCString
+ 1) == 'E') {
4444 wantLessThanEqualTo
= true;
4445 versionCString
+= 2;
4448 for (i
= 0; *versionCString
!= 0x00; versionCString
++) {
4449 /* skip whitespace */
4450 if (isWhiteSpace(*versionCString
)) {
4454 /* peek ahead for version string separator or null terminator */
4455 if (*(versionCString
+ 1) == ',' || *(versionCString
+ 1) == 0x00) {
4456 /* OK, we have a version string */
4457 myBuffer
[i
++] = *versionCString
;
4460 OSKextVersion excludeVers
;
4461 excludeVers
= OSKextParseVersionString(myBuffer
);
4463 if (wantLessThanEqualTo
) {
4464 if (version
<= excludeVers
) {
4467 } else if (wantLessThan
) {
4468 if (version
< excludeVers
) {
4471 } else if (version
== excludeVers
) {
4475 /* reset for the next (if any) version string */
4477 wantLessThan
= false;
4478 wantLessThanEqualTo
= false;
4480 /* save valid version character */
4481 myBuffer
[i
++] = *versionCString
;
4483 /* make sure bogus version string doesn't overrun local buffer */
4484 if (i
>= sizeof(myBuffer
)) {
4493 /*********************************************************************
4494 *********************************************************************/
4497 OSKext::loadKextWithIdentifier(
4498 const char * kextIdentifierCString
,
4499 Boolean allowDeferFlag
,
4500 Boolean delayAutounloadFlag
,
4501 OSKextExcludeLevel startOpt
,
4502 OSKextExcludeLevel startMatchingOpt
,
4503 OSArray
* personalityNames
)
4505 OSReturn result
= kOSReturnError
;
4506 OSString
* kextIdentifier
= NULL
; // must release
4508 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
4509 if (!kextIdentifier
) {
4510 result
= kOSKextReturnNoMemory
;
4513 result
= OSKext::loadKextWithIdentifier(kextIdentifier
,
4514 allowDeferFlag
, delayAutounloadFlag
,
4515 startOpt
, startMatchingOpt
, personalityNames
);
4518 OSSafeReleaseNULL(kextIdentifier
);
4522 /*********************************************************************
4523 *********************************************************************/
4525 OSKext::loadKextWithIdentifier(
4526 OSString
* kextIdentifier
,
4527 Boolean allowDeferFlag
,
4528 Boolean delayAutounloadFlag
,
4529 OSKextExcludeLevel startOpt
,
4530 OSKextExcludeLevel startMatchingOpt
,
4531 OSArray
* personalityNames
)
4533 OSReturn result
= kOSReturnError
;
4534 OSReturn pingResult
= kOSReturnError
;
4535 OSKext
* theKext
= NULL
;// do not release
4536 OSDictionary
* loadRequest
= NULL
;// must release
4537 const OSSymbol
* kextIdentifierSymbol
= NULL
;// must release
4539 IORecursiveLockLock(sKextLock
);
4541 if (!kextIdentifier
) {
4542 result
= kOSKextReturnInvalidArgument
;
4546 OSKext::recordIdentifierRequest(kextIdentifier
);
4548 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
4550 if (!allowDeferFlag
) {
4551 OSKextLog(/* kext */ NULL
,
4552 kOSKextLogErrorLevel
|
4554 "Can't load kext %s - not found.",
4555 kextIdentifier
->getCStringNoCopy());
4559 if (!sKernelRequestsEnabled
) {
4561 kOSKextLogErrorLevel
|
4563 "Can't load kext %s - requests to user space are disabled.",
4564 kextIdentifier
->getCStringNoCopy());
4565 result
= kOSKextReturnDisabled
;
4569 /* Create a new request unless one is already sitting
4570 * in sKernelRequests for this bundle identifier
4572 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4573 if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4574 result
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
,
4576 if (result
!= kOSReturnSuccess
) {
4579 if (!_OSKextSetRequestArgument(loadRequest
,
4580 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
4581 result
= kOSKextReturnNoMemory
;
4584 if (!sKernelRequests
->setObject(loadRequest
)) {
4585 result
= kOSKextReturnNoMemory
;
4589 if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4590 result
= kOSKextReturnNoMemory
;
4595 kOSKextLogDebugLevel
|
4597 "Kext %s not found; queued load request to user space.",
4598 kextIdentifier
->getCStringNoCopy());
4601 pingResult
= OSKext::pingKextd();
4602 if (pingResult
== kOSKextReturnDisabled
) {
4603 OSKextLog(/* kext */ NULL
,
4604 ((sPrelinkBoot
) ? kOSKextLogDebugLevel
: kOSKextLogErrorLevel
) |
4606 "Kext %s might not load - kextd is currently unavailable.",
4607 kextIdentifier
->getCStringNoCopy());
4610 result
= kOSKextReturnDeferred
;
4614 result
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
);
4616 if (result
!= kOSReturnSuccess
) {
4618 kOSKextLogErrorLevel
|
4620 "Failed to load kext %s (error 0x%x).",
4621 kextIdentifier
->getCStringNoCopy(), (int)result
);
4623 OSKext::removeKext(theKext
,
4624 /* terminateService/removePersonalities */ true);
4628 if (delayAutounloadFlag
) {
4630 kOSKextLogProgressLevel
|
4631 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4632 "Setting delayed autounload for %s.",
4633 kextIdentifier
->getCStringNoCopy());
4634 theKext
->flags
.delayAutounload
= 1;
4638 OSSafeReleaseNULL(loadRequest
);
4639 OSSafeReleaseNULL(kextIdentifierSymbol
);
4641 IORecursiveLockUnlock(sKextLock
);
4646 /*********************************************************************
4647 *********************************************************************/
4650 OSKext::recordIdentifierRequest(
4651 OSString
* kextIdentifier
)
4653 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4656 if (!sAllKextLoadIdentifiers
|| !kextIdentifier
) {
4660 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4661 if (!kextIdentifierSymbol
) {
4662 // xxx - this is really a basic alloc failure
4667 IORecursiveLockLock(sKextLock
);
4668 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4669 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4672 // xxx - need to find a way to associate this whole func w/the kext
4673 OSKextLog(/* kext */ NULL
,
4674 // xxx - check level
4675 kOSKextLogStepLevel
|
4676 kOSKextLogArchiveFlag
,
4677 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4678 kextIdentifier
->getCStringNoCopy());
4681 IORecursiveLockUnlock(sKextLock
);
4686 OSKextLog(/* kext */ NULL
,
4687 kOSKextLogErrorLevel
|
4688 kOSKextLogArchiveFlag
,
4689 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4690 kextIdentifier
->getCStringNoCopy());
4692 OSSafeReleaseNULL(kextIdentifierSymbol
);
4696 /*********************************************************************
4697 *********************************************************************/
4700 OSKextExcludeLevel startOpt
,
4701 OSKextExcludeLevel startMatchingOpt
,
4702 OSArray
* personalityNames
)
4704 OSReturn result
= kOSReturnError
;
4705 kern_return_t kxldResult
;
4706 OSKextExcludeLevel dependenciesStartOpt
= startOpt
;
4707 OSKextExcludeLevel dependenciesStartMatchingOpt
= startMatchingOpt
;
4708 unsigned int i
, count
;
4709 Boolean alreadyLoaded
= false;
4710 OSKext
* lastLoadedKext
= NULL
;
4712 if (isInExcludeList()) {
4714 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
|
4716 "Kext %s is in exclude list, not loadable",
4717 getIdentifierCString());
4719 result
= kOSKextReturnNotLoadable
;
4724 alreadyLoaded
= true;
4725 result
= kOSReturnSuccess
;
4728 kOSKextLogDebugLevel
|
4729 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4730 "Kext %s is already loaded.",
4731 getIdentifierCString());
4736 if (current_task() != kernel_task
) {
4737 int macCheckResult
= 0;
4738 kauth_cred_t cred
= NULL
;
4740 cred
= kauth_cred_get_with_ref();
4741 macCheckResult
= mac_kext_check_load(cred
, getIdentifierCString());
4742 kauth_cred_unref(&cred
);
4744 if (macCheckResult
!= 0) {
4745 result
= kOSReturnError
;
4747 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4748 "Failed to load kext %s (MAC policy error 0x%x).",
4749 getIdentifierCString(), macCheckResult
);
4755 if (!sLoadEnabled
) {
4757 kOSKextLogErrorLevel
|
4759 "Kext loading is disabled (attempt to load kext %s).",
4760 getIdentifierCString());
4761 result
= kOSKextReturnDisabled
;
4765 /* If we've pushed the next available load tag to the invalid value,
4766 * we can't load any more kexts.
4768 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4770 kOSKextLogErrorLevel
|
4772 "Can't load kext %s - no more load tags to assign.",
4773 getIdentifierCString());
4774 result
= kOSKextReturnNoResources
;
4778 /* This is a bit of a hack, because we shouldn't be handling
4779 * personalities within the load function.
4781 if (!declaresExecutable()) {
4782 /* There is a special case where a non-executable kext can be loaded: the
4783 * AppleKextExcludeList. Detect that special kext by bundle identifier and
4784 * load its metadata into the global data structures, if appropriate
4786 if (strcmp(getIdentifierCString(), "com.apple.driver.KextExcludeList") == 0) {
4787 boolean_t updated
= updateExcludeList(infoDict
);
4790 kOSKextLogDebugLevel
| kOSKextLogLoadFlag
,
4791 "KextExcludeList was updated to version: %lld", sExcludeListVersion
);
4794 result
= kOSReturnSuccess
;
4798 /* Are we in safe boot?
4800 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4802 kOSKextLogErrorLevel
|
4804 "Can't load kext %s - not loadable during safe boot.",
4805 getIdentifierCString());
4806 result
= kOSKextReturnBootLevel
;
4811 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4813 getIdentifierCString());
4815 if (!sKxldContext
) {
4816 kxldResult
= kxld_create_context(&sKxldContext
, &kern_allocate
,
4817 &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,
4818 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
4821 kOSKextLogErrorLevel
|
4822 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4823 "Can't load kext %s - failed to create link context.",
4824 getIdentifierCString());
4825 result
= kOSKextReturnNoMemory
;
4830 /* We only need to resolve dependencies once for the whole graph, but
4831 * resolveDependencies will just return if there's no work to do, so it's
4832 * safe to call it more than once.
4834 if (!resolveDependencies()) {
4835 // xxx - check resolveDependencies() for log msg
4837 kOSKextLogErrorLevel
|
4838 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4839 "Can't load kext %s - failed to resolve library dependencies.",
4840 getIdentifierCString());
4841 result
= kOSKextReturnDependencies
;
4845 /* If we are excluding just the kext being loaded now (and not its
4846 * dependencies), drop the exclusion level to none so dependencies
4847 * start and/or add their personalities.
4849 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4850 dependenciesStartOpt
= kOSKextExcludeNone
;
4853 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4854 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4857 /* Load the dependencies, recursively.
4859 count
= getNumDependencies();
4860 for (i
= 0; i
< count
; i
++) {
4861 OSKext
* dependency
= OSDynamicCast(OSKext
,
4862 dependencies
->getObject(i
));
4863 if (dependency
== NULL
) {
4865 kOSKextLogErrorLevel
|
4866 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4867 "Internal error loading kext %s; dependency disappeared.",
4868 getIdentifierCString());
4869 result
= kOSKextReturnInternalError
;
4873 /* Dependencies must be started accorting to the opt,
4874 * but not given the personality names of the main kext.
4876 result
= dependency
->load(dependenciesStartOpt
,
4877 dependenciesStartMatchingOpt
,
4878 /* personalityNames */ NULL
);
4879 if (result
!= KERN_SUCCESS
) {
4881 kOSKextLogErrorLevel
|
4882 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4883 "Dependency %s of kext %s failed to load.",
4884 dependency
->getIdentifierCString(),
4885 getIdentifierCString());
4887 OSKext::removeKext(dependency
,
4888 /* terminateService/removePersonalities */ true);
4889 result
= kOSKextReturnDependencyLoadError
;
4895 result
= loadExecutable();
4896 if (result
!= KERN_SUCCESS
) {
4900 pendingPgoHead
.next
= &pendingPgoHead
;
4901 pendingPgoHead
.prev
= &pendingPgoHead
;
4903 // The kernel PRNG is not initialized when the first kext is
4904 // loaded, so use early random
4905 uuid_generate_early_random(instance_uuid
);
4906 account
= IONew(OSKextAccount
, 1);
4908 result
= KERN_MEMORY_ERROR
;
4911 bzero(account
, sizeof(*account
));
4912 account
->loadTag
= kmod_info
->id
;
4913 account
->site
.refcount
= 0;
4914 account
->site
.flags
= VM_TAG_KMOD
;
4915 account
->kext
= this;
4916 if (gIOSurfaceIdentifier
== bundleID
) {
4917 vm_tag_alloc(&account
->site
);
4918 gIOSurfaceTag
= account
->site
.tag
;
4921 flags
.loaded
= true;
4923 /* Add the kext to the list of loaded kexts and update the kmod_info
4924 * struct to point to that of the last loaded kext (which is the way
4925 * it's always been done, though I'd rather do them in order now).
4927 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
4928 sLoadedKexts
->setObject(this);
4930 /* Keep the kernel itself out of the kmod list.
4932 if (lastLoadedKext
->isKernel()) {
4933 lastLoadedKext
= NULL
;
4936 if (lastLoadedKext
) {
4937 kmod_info
->next
= lastLoadedKext
->kmod_info
;
4940 notifyKextLoadObservers(this, kmod_info
);
4942 /* Make the global kmod list point at the just-loaded kext. Note that the
4943 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4944 * although we do report it in kextstat these days by using the newer
4945 * OSArray of loaded kexts, which does contain it.
4947 * (The OSKext object representing the kernel doesn't even have a kmod_info
4948 * struct, though I suppose we could stick a pointer to it from the
4949 * static struct in OSRuntime.cpp.)
4953 /* Save the list of loaded kexts in case we panic.
4955 OSKext::saveLoadedKextPanicList();
4957 if (isExecutable()) {
4958 OSKext::updateLoadedKextSummaries();
4959 savePanicString(/* isLoading */ true);
4962 registerWithDTrace();
4964 jettisonLinkeditSegment();
4965 #endif /* CONFIG_DTRACE */
4967 #if !VM_MAPPED_KEXTS
4968 /* If there is a page (or more) worth of padding after the end
4969 * of the last data section but before the end of the data segment
4970 * then free it in the same manner the LinkeditSegment is freed
4972 jettisonDATASegmentPadding();
4977 if (isExecutable() && !flags
.started
) {
4978 if (startOpt
== kOSKextExcludeNone
) {
4980 if (result
!= kOSReturnSuccess
) {
4982 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4983 "Kext %s start failed (result 0x%x).",
4984 getIdentifierCString(), result
);
4985 result
= kOSKextReturnStartStopError
;
4990 /* If not excluding matching, send the personalities to the kernel.
4991 * This never affects the result of the load operation.
4992 * This is a bit of a hack, because we shouldn't be handling
4993 * personalities within the load function.
4995 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
4996 result
= sendPersonalitiesToCatalog(true, personalityNames
);
5001 /* More hack! If the kext doesn't declare an executable, even if we
5002 * "loaded" it, we have to remove any personalities naming it, or we'll
5003 * never see the registry go quiet. Errors here do not count for the
5004 * load operation itself.
5006 * Note that in every other regard it's perfectly ok for a kext to
5007 * not declare an executable and serve only as a package for personalities
5008 * naming another kext, so we do have to allow such kexts to be "loaded"
5009 * so that those other personalities get added & matched.
5011 if (!declaresExecutable()) {
5013 kOSKextLogStepLevel
| kOSKextLogLoadFlag
,
5014 "Kext %s has no executable; removing any personalities naming it.",
5015 getIdentifierCString());
5016 removePersonalitiesFromCatalog();
5019 if (result
!= kOSReturnSuccess
) {
5021 kOSKextLogErrorLevel
|
5023 "Kext %s failed to load (0x%x).",
5024 getIdentifierCString(), (int)result
);
5025 } else if (!alreadyLoaded
) {
5027 kOSKextLogProgressLevel
|
5030 getIdentifierCString());
5032 queueKextNotification(kKextRequestPredicateLoadNotification
,
5033 OSDynamicCast(OSString
, bundleID
));
5038 /*********************************************************************
5040 *********************************************************************/
5042 strdup(const char * string
)
5044 char * result
= NULL
;
5051 size
= 1 + strlen(string
);
5052 result
= (char *)kalloc_tag(size
, VM_KERN_MEMORY_OSKEXT
);
5057 memcpy(result
, string
, size
);
5063 /*********************************************************************
5065 *********************************************************************/
5068 OSKext::lookupSection(const char *segname
, const char *secname
)
5070 kernel_section_t
* found_section
= NULL
;
5071 kernel_mach_header_t
* mh
= NULL
;
5072 kernel_segment_command_t
* seg
= NULL
;
5073 kernel_section_t
* sec
= NULL
;
5075 if (!linkedExecutable
) {
5079 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
5081 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
5082 if (0 != strcmp(seg
->segname
, segname
)) {
5086 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
5087 if (0 == strcmp(sec
->sectname
, secname
)) {
5088 found_section
= sec
;
5095 return found_section
;
5098 /*********************************************************************
5100 *********************************************************************/
5103 OSKext::slidePrelinkedExecutable(bool doCoalesedSlides
)
5105 OSReturn result
= kOSKextReturnBadData
;
5106 kernel_mach_header_t
* mh
= NULL
;
5107 kernel_segment_command_t
* seg
= NULL
;
5108 kernel_segment_command_t
* linkeditSeg
= NULL
;
5109 kernel_section_t
* sec
= NULL
;
5110 char * linkeditBase
= NULL
;
5111 bool haveLinkeditBase
= false;
5112 char * relocBase
= NULL
;
5113 bool haveRelocBase
= false;
5114 struct dysymtab_command
* dysymtab
= NULL
;
5115 struct linkedit_data_command
* segmentSplitInfo
= NULL
;
5116 struct symtab_command
* symtab
= NULL
;
5117 kernel_nlist_t
* sym
= NULL
;
5118 struct relocation_info
* reloc
= NULL
;
5121 vm_offset_t new_kextsize
;
5123 if (linkedExecutable
== NULL
|| flags
.builtin
) {
5124 result
= kOSReturnSuccess
;
5128 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
5129 segmentSplitInfo
= (struct linkedit_data_command
*) getcommandfromheader(mh
, LC_SEGMENT_SPLIT_INFO
);
5131 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
5136 seg
->vmaddr
= ml_static_slide(seg
->vmaddr
);
5138 #if KASLR_KEXT_DEBUG
5139 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
5141 (unsigned long)ml_static_unslide(seg
->vmaddr
),
5142 (unsigned long)seg
->vmaddr
);
5145 if (!haveRelocBase
) {
5146 relocBase
= (char *) seg
->vmaddr
;
5147 haveRelocBase
= true;
5149 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
5150 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
5151 haveLinkeditBase
= true;
5154 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
5155 sec
->addr
= ml_static_slide(sec
->addr
);
5157 #if KASLR_KEXT_DEBUG
5158 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
5160 (unsigned long)ml_static_unslide(sec
->addr
),
5161 (unsigned long)sec
->addr
);
5166 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
5168 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
5170 if (symtab
!= NULL
&& doCoalesedSlides
== false) {
5171 /* Some pseudo-kexts have symbol tables without segments.
5173 if (symtab
->nsyms
> 0 && haveLinkeditBase
) {
5174 sym
= (kernel_nlist_t
*) (linkeditBase
+ symtab
->symoff
);
5175 for (i
= 0; i
< symtab
->nsyms
; i
++) {
5176 if (sym
[i
].n_type
& N_STAB
) {
5179 sym
[i
].n_value
= ml_static_slide(sym
[i
].n_value
);
5181 #if KASLR_KEXT_DEBUG
5182 #define MAX_SYMS_TO_LOG 5
5183 if (i
< MAX_SYMS_TO_LOG
) {
5184 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
5185 (unsigned long)ml_static_unslide(sym
[i
].n_value
),
5186 (unsigned long)sym
[i
].n_value
);
5193 if (dysymtab
!= NULL
&& doCoalesedSlides
== false) {
5194 if (dysymtab
->nextrel
> 0) {
5196 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5198 "Sliding kext %s: External relocations found.",
5199 getIdentifierCString());
5203 if (dysymtab
->nlocrel
> 0) {
5204 if (!haveLinkeditBase
) {
5206 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5208 "Sliding kext %s: No linkedit segment.",
5209 getIdentifierCString());
5213 if (!haveRelocBase
) {
5215 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5218 "Sliding kext %s: No writable segments.",
5220 "Sliding kext %s: No segments.",
5222 getIdentifierCString());
5226 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
5227 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
5229 for (i
= 0; i
< dysymtab
->nlocrel
; i
++) {
5230 if (reloc
[i
].r_extern
!= 0
5231 || reloc
[i
].r_type
!= 0
5232 || reloc
[i
].r_length
!= (sizeof(void *) == 8 ? 3 : 2)
5235 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5237 "Sliding kext %s: Unexpected relocation found.",
5238 getIdentifierCString());
5241 if (reloc
[i
].r_pcrel
!= 0) {
5244 uintptr_t *relocAddr
= (uintptr_t*)(relocBase
+ reloc
[i
].r_address
);
5245 *relocAddr
= ml_static_slide(*relocAddr
);
5247 #if KASLR_KEXT_DEBUG
5248 #define MAX_DYSYMS_TO_LOG 5
5249 if (i
< MAX_DYSYMS_TO_LOG
) {
5250 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
5251 (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr
))),
5252 (unsigned long)*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)));
5257 /* We should free these relocations, not just delete the reference to them.
5258 * <rdar://problem/10535549> Free relocations from PIE kexts.
5260 * For now, we do not free LINKEDIT for kexts with split segments.
5262 new_kextsize
= round_page(kmod_info
->size
- reloc_size
);
5263 if (((kmod_info
->size
- new_kextsize
) > PAGE_SIZE
) && (!segmentSplitInfo
)) {
5264 vm_offset_t endofkext
= kmod_info
->address
+ kmod_info
->size
;
5265 vm_offset_t new_endofkext
= kmod_info
->address
+ new_kextsize
;
5266 vm_offset_t endofrelocInfo
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
);
5267 int bytes_remaining
= endofkext
- endofrelocInfo
;
5268 OSData
* new_osdata
= NULL
;
5270 /* fix up symbol offsets if they are after the dsymtab local relocs */
5272 if (dysymtab
->locreloff
< symtab
->symoff
) {
5273 symtab
->symoff
-= reloc_size
;
5275 if (dysymtab
->locreloff
< symtab
->stroff
) {
5276 symtab
->stroff
-= reloc_size
;
5279 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
5280 dysymtab
->extreloff
-= reloc_size
;
5283 /* move data behind reloc info down to new offset */
5284 if (endofrelocInfo
< endofkext
) {
5285 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
5288 /* Create a new OSData for the smaller kext object and reflect
5289 * new linkedit segment size.
5291 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
5292 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
5294 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
5296 /* Fix up kmod info and linkedExecutable.
5298 kmod_info
->size
= new_kextsize
;
5300 new_osdata
->setDeallocFunction(osdata_kext_free
);
5302 new_osdata
->setDeallocFunction(osdata_phys_free
);
5304 linkedExecutable
->setDeallocFunction(NULL
);
5305 linkedExecutable
->release();
5306 linkedExecutable
= new_osdata
;
5309 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
5311 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
5315 dysymtab
->nlocrel
= 0;
5316 dysymtab
->locreloff
= 0;
5320 result
= kOSReturnSuccess
;
5325 /*********************************************************************
5326 * called only by load()
5327 *********************************************************************/
5329 OSKext::loadExecutable()
5331 OSReturn result
= kOSReturnError
;
5332 kern_return_t kxldResult
;
5333 KXLDDependency
* kxlddeps
= NULL
;// must kfree
5334 uint32_t num_kxlddeps
= 0;
5335 OSArray
* linkDependencies
= NULL
;// must release
5336 uint32_t numDirectDependencies
= 0;
5337 uint32_t num_kmod_refs
= 0;
5338 struct mach_header
** kxldHeaderPtr
= NULL
;// do not free
5339 struct mach_header
* kxld_header
= NULL
;// xxx - need to free here?
5340 OSData
* theExecutable
= NULL
;// do not release
5341 OSString
* versString
= NULL
;// do not release
5342 const char * versCString
= NULL
;// do not free
5343 const char * string
= NULL
;// do not free
5346 /* We need the version string for a variety of bits below.
5348 versString
= OSDynamicCast(OSString
,
5349 getPropertyForHostArch(kCFBundleVersionKey
));
5353 versCString
= versString
->getCStringNoCopy();
5355 if (isKernelComponent()) {
5356 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
5357 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
5359 kOSKextLogErrorLevel
|
5361 "Kernel component %s has incorrect version %s; "
5363 getIdentifierCString(),
5364 versCString
, KERNEL6_VERSION
);
5365 result
= kOSKextReturnInternalError
;
5367 } else if (strcmp(versCString
, osrelease
)) {
5369 kOSKextLogErrorLevel
|
5371 "Kernel component %s has incorrect version %s; "
5373 getIdentifierCString(),
5374 versCString
, osrelease
);
5375 result
= kOSKextReturnInternalError
;
5381 if (isPrelinked()) {
5385 /* <rdar://problem/21444003> all callers must be entitled */
5386 if (FALSE
== IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-secure-management")) {
5388 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5389 "Not entitled to link kext '%s'",
5390 getIdentifierCString());
5391 result
= kOSKextReturnNotPrivileged
;
5395 theExecutable
= getExecutable();
5396 if (!theExecutable
) {
5397 if (declaresExecutable()) {
5399 kOSKextLogErrorLevel
|
5401 "Can't load kext %s - executable is missing.",
5402 getIdentifierCString());
5403 result
= kOSKextReturnValidation
;
5409 if (isInterface()) {
5410 OSData
*executableCopy
= OSData::withData(theExecutable
);
5411 setLinkedExecutable(executableCopy
);
5412 executableCopy
->release();
5416 numDirectDependencies
= getNumDependencies();
5418 if (flags
.hasBleedthrough
) {
5419 linkDependencies
= dependencies
;
5420 linkDependencies
->retain();
5422 linkDependencies
= OSArray::withArray(dependencies
);
5423 if (!linkDependencies
) {
5425 kOSKextLogErrorLevel
|
5426 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5427 "Can't allocate link dependencies to load kext %s.",
5428 getIdentifierCString());
5432 for (i
= 0; i
< numDirectDependencies
; ++i
) {
5433 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
5434 dependencies
->getObject(i
));
5435 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
5439 num_kxlddeps
= linkDependencies
->getCount();
5440 if (!num_kxlddeps
) {
5442 kOSKextLogErrorLevel
|
5443 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
5444 "Can't load kext %s - it has no library dependencies.",
5445 getIdentifierCString());
5449 kxlddeps
= (KXLDDependency
*)kalloc_tag(num_kxlddeps
* sizeof(*kxlddeps
), VM_KERN_MEMORY_OSKEXT
);
5452 kOSKextLogErrorLevel
|
5453 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5454 "Can't allocate link context to load kext %s.",
5455 getIdentifierCString());
5458 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
5460 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5461 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
5463 if (dependency
->isInterface()) {
5464 OSKext
*interfaceTargetKext
= NULL
;
5465 OSData
* interfaceTarget
= NULL
;
5467 if (dependency
->isKernelComponent()) {
5468 interfaceTargetKext
= sKernelKext
;
5469 interfaceTarget
= sKernelKext
->linkedExecutable
;
5471 interfaceTargetKext
= OSDynamicCast(OSKext
,
5472 dependency
->dependencies
->getObject(0));
5474 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
5477 if (!interfaceTarget
) {
5482 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5483 * it will be useful to have them in the debugger.
5484 * strdup() failing isn't critical right here so we don't check that.
5486 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
5487 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
5488 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
5490 kxlddeps
[i
].interface
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5491 kxlddeps
[i
].interface_size
= dependency
->linkedExecutable
->getLength();
5492 kxlddeps
[i
].interface_name
= strdup(dependency
->getIdentifierCString());
5494 kxlddeps
[i
].kext
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5495 kxlddeps
[i
].kext_size
= dependency
->linkedExecutable
->getLength();
5496 kxlddeps
[i
].kext_name
= strdup(dependency
->getIdentifierCString());
5499 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
5502 kxldHeaderPtr
= &kxld_header
;
5506 kOSKextLogExplicitLevel
|
5507 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5508 "Kext %s - calling kxld_link_file:\n"
5509 " kxld_context: %p\n"
5510 " executable: %p executable_length: %d\n"
5512 " kxld_dependencies: %p num_dependencies: %d\n"
5513 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5514 getIdentifierCString(), sKxldContext
,
5515 theExecutable
->getBytesNoCopy(), theExecutable
->getLength(),
5516 this, kxlddeps
, num_kxlddeps
,
5517 kxldHeaderPtr
, &kmod_info
);
5520 /* After this call, the linkedExecutable instance variable
5523 kxldResult
= kxld_link_file(sKxldContext
,
5524 (u_char
*)theExecutable
->getBytesNoCopy(),
5525 theExecutable
->getLength(),
5526 getIdentifierCString(), this, kxlddeps
, num_kxlddeps
,
5527 (u_char
**)kxldHeaderPtr
, (kxld_addr_t
*)&kmod_info
);
5529 if (kxldResult
!= KERN_SUCCESS
) {
5530 // xxx - add kxldResult here?
5532 kOSKextLogErrorLevel
|
5534 "Can't load kext %s - link failed.",
5535 getIdentifierCString());
5536 result
= kOSKextReturnLinkError
;
5540 /* We've written data & instructions into kernel memory, so flush the data
5541 * cache and invalidate the instruction cache.
5542 * I/D caches are coherent on x86
5544 #if !defined(__i386__) && !defined(__x86_64__)
5545 flush_dcache(kmod_info
->address
, kmod_info
->size
, false);
5546 invalidate_icache(kmod_info
->address
, kmod_info
->size
, false);
5550 if (isInterface()) {
5551 /* Whip up a fake kmod_info entry for the interface kext.
5553 kmod_info
= (kmod_info_t
*)kalloc_tag(sizeof(kmod_info_t
), VM_KERN_MEMORY_OSKEXT
);
5555 result
= KERN_MEMORY_ERROR
;
5559 /* A pseudokext has almost nothing in its kmod_info struct.
5561 bzero(kmod_info
, sizeof(kmod_info_t
));
5563 kmod_info
->info_version
= KMOD_INFO_VERSION
;
5565 /* An interface kext doesn't have a linkedExecutable, so save a
5566 * copy of the UUID out of the original executable via copyUUID()
5567 * while we still have the original executable.
5569 interfaceUUID
= copyUUID();
5572 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5573 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5575 /* Stamp the bundle ID and version from the OSKext over anything
5576 * resident inside the kmod_info.
5578 string
= getIdentifierCString();
5579 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5581 string
= versCString
;
5582 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5584 /* Add the dependencies' kmod_info structs as kmod_references.
5586 num_kmod_refs
= getNumDependencies();
5587 if (num_kmod_refs
) {
5588 kmod_info
->reference_list
= (kmod_reference_t
*)kalloc_tag(
5589 num_kmod_refs
* sizeof(kmod_reference_t
), VM_KERN_MEMORY_OSKEXT
);
5590 if (!kmod_info
->reference_list
) {
5591 result
= KERN_MEMORY_ERROR
;
5594 bzero(kmod_info
->reference_list
,
5595 num_kmod_refs
* sizeof(kmod_reference_t
));
5596 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5597 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5598 OSKext
* refKext
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
));
5599 ref
->info
= refKext
->kmod_info
;
5600 ref
->info
->reference_count
++;
5602 if (refIndex
+ 1 < num_kmod_refs
) {
5603 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5608 if (!isInterface() && linkedExecutable
) {
5610 kOSKextLogProgressLevel
|
5612 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5614 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5615 (unsigned long)ml_static_unslide(kmod_info
->address
),
5616 (unsigned)kmod_info
->id
);
5619 /* if prelinked, VM protections are already set */
5620 result
= setVMAttributes(!isPrelinked(), true);
5621 if (result
!= KERN_SUCCESS
) {
5626 if (linkedExecutable
) {
5627 kasan_load_kext((vm_offset_t
)linkedExecutable
->getBytesNoCopy(),
5628 linkedExecutable
->getLength(), getIdentifierCString());
5631 if (lookupSection(KASAN_GLOBAL_SEGNAME
, KASAN_GLOBAL_SECTNAME
)) {
5633 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5634 "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
5635 getIdentifierCString()
5637 result
= KERN_FAILURE
;
5642 result
= kOSReturnSuccess
;
5645 OSSafeReleaseNULL(linkDependencies
);
5647 /* Clear up locally allocated dependency info.
5649 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5652 if (kxlddeps
[i
].kext_name
) {
5653 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5654 kfree(kxlddeps
[i
].kext_name
, size
);
5656 if (kxlddeps
[i
].interface_name
) {
5657 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5658 kfree(kxlddeps
[i
].interface_name
, size
);
5662 kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5665 /* We no longer need the unrelocated executable (which the linker
5666 * has altered anyhow).
5668 setExecutable(NULL
);
5670 if (result
!= kOSReturnSuccess
) {
5672 kOSKextLogErrorLevel
|
5674 "Failed to load executable for kext %s.",
5675 getIdentifierCString());
5677 if (kmod_info
&& kmod_info
->reference_list
) {
5678 kfree(kmod_info
->reference_list
,
5679 num_kmod_refs
* sizeof(kmod_reference_t
));
5681 if (isInterface()) {
5682 kfree(kmod_info
, sizeof(kmod_info_t
));
5685 if (linkedExecutable
) {
5686 linkedExecutable
->release();
5687 linkedExecutable
= NULL
;
5694 /*********************************************************************
5695 * The linkedit segment is used by the kext linker for dependency
5696 * resolution, and by dtrace for probe initialization. We can free it
5697 * for non-library kexts, since no kexts depend on non-library kexts
5698 * by definition, once dtrace has been initialized.
5699 *********************************************************************/
5701 OSKext::jettisonLinkeditSegment(void)
5703 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5704 kernel_segment_command_t
* linkedit
= NULL
;
5706 vm_size_t linkeditsize
, kextsize
;
5707 OSData
* data
= NULL
;
5710 /* We can free symbol tables for all embedded kexts because we don't
5711 * support runtime kext linking.
5713 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5715 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5720 /* Find the linkedit segment. If it's not the last segment, then freeing
5721 * it will fragment the kext into multiple VM regions, which OSKext is not
5722 * designed to handle, so we'll have to skip it.
5724 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5729 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5730 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
)) {
5734 /* Create a new OSData for the smaller kext object.
5736 linkeditsize
= round_page(linkedit
->vmsize
);
5737 kextsize
= kmod_info
->size
- linkeditsize
;
5738 start
= linkedit
->vmaddr
;
5740 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5745 /* Fix the kmod info and linkedExecutable.
5747 kmod_info
->size
= kextsize
;
5750 data
->setDeallocFunction(osdata_kext_free
);
5752 data
->setDeallocFunction(osdata_phys_free
);
5754 linkedExecutable
->setDeallocFunction(NULL
);
5755 linkedExecutable
->release();
5756 linkedExecutable
= data
;
5757 flags
.jettisonLinkeditSeg
= 1;
5759 /* Free the linkedit segment.
5762 kext_free(start
, linkeditsize
);
5764 ml_static_mfree(start
, linkeditsize
);
5771 /*********************************************************************
5772 * If there are whole pages that are unused betweem the last section
5773 * of the DATA segment and the end of the DATA segment then we can free
5775 *********************************************************************/
5777 OSKext::jettisonDATASegmentPadding(void)
5779 kernel_mach_header_t
* mh
;
5780 kernel_segment_command_t
* dataSeg
;
5781 kernel_section_t
* sec
, * lastSec
;
5782 vm_offset_t dataSegEnd
, lastSecEnd
;
5785 if (flags
.builtin
) {
5788 mh
= (kernel_mach_header_t
*)kmod_info
->address
;
5790 dataSeg
= getsegbynamefromheader(mh
, SEG_DATA
);
5791 if (dataSeg
== NULL
) {
5796 sec
= firstsect(dataSeg
);
5797 while (sec
!= NULL
) {
5799 sec
= nextsect(dataSeg
, sec
);
5802 if (lastSec
== NULL
) {
5806 if ((dataSeg
->vmaddr
!= round_page(dataSeg
->vmaddr
)) ||
5807 (dataSeg
->vmsize
!= round_page(dataSeg
->vmsize
))) {
5811 dataSegEnd
= dataSeg
->vmaddr
+ dataSeg
->vmsize
;
5812 lastSecEnd
= round_page(lastSec
->addr
+ lastSec
->size
);
5814 if (dataSegEnd
<= lastSecEnd
) {
5818 padSize
= dataSegEnd
- lastSecEnd
;
5820 if (padSize
>= PAGE_SIZE
) {
5822 kext_free(lastSecEnd
, padSize
);
5824 ml_static_mfree(lastSecEnd
, padSize
);
5829 /*********************************************************************
5830 *********************************************************************/
5832 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5834 if (linkedExecutable
) {
5835 panic("Attempt to set linked executable on kext "
5836 "that already has one (%s).\n",
5837 getIdentifierCString());
5839 linkedExecutable
= anExecutable
;
5840 linkedExecutable
->retain();
5845 /*********************************************************************
5846 * Go through all loaded kexts and tell them to register with dtrace.
5847 * The instance method only registers if necessary.
5848 *********************************************************************/
5851 OSKext::registerKextsWithDTrace(void)
5853 uint32_t count
= sLoadedKexts
->getCount();
5856 IORecursiveLockLock(sKextLock
);
5858 for (i
= 0; i
< count
; i
++) {
5859 OSKext
* thisKext
= NULL
;// do not release
5861 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5862 if (!thisKext
|| !thisKext
->isExecutable()) {
5866 thisKext
->registerWithDTrace();
5869 IORecursiveLockUnlock(sKextLock
);
5875 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5876 extern int (*dtrace_modunload
)(struct kmod_info
*);
5879 /*********************************************************************
5880 *********************************************************************/
5882 OSKext::registerWithDTrace(void)
5884 /* Register kext with dtrace. A dtrace_modload failure should not
5885 * prevent a kext from loading, so we ignore the return code.
5887 if (!flags
.dtraceInitialized
&& (dtrace_modload
!= NULL
)) {
5888 uint32_t modflag
= 0;
5889 OSObject
* forceInit
= getPropertyForHostArch("OSBundleForceDTraceInit");
5890 if (forceInit
== kOSBooleanTrue
) {
5891 modflag
|= KMOD_DTRACE_FORCE_INIT
;
5893 if (flags
.builtin
) {
5894 modflag
|= KMOD_DTRACE_STATIC_KEXT
;
5897 (void)(*dtrace_modload
)(kmod_info
, modflag
);
5898 flags
.dtraceInitialized
= true;
5899 jettisonLinkeditSegment();
5903 /*********************************************************************
5904 *********************************************************************/
5906 OSKext::unregisterWithDTrace(void)
5908 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5909 * prevent a kext from loading, so we ignore the return code.
5911 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
5912 (void)(*dtrace_modunload
)(kmod_info
);
5913 flags
.dtraceInitialized
= false;
5917 #endif /* CONFIG_DTRACE */
5920 /*********************************************************************
5921 * called only by loadExecutable()
5922 *********************************************************************/
5923 #if !VM_MAPPED_KEXTS
5924 #if defined(__arm__) || defined(__arm64__)
5925 static inline kern_return_t
5928 vm_map_offset_t start
,
5929 vm_map_offset_t end
,
5934 assert(map
== kernel_map
); // we can handle KEXTs arising from the PRELINK segment and no others
5935 assert(start
<= end
);
5937 return KERN_SUCCESS
; // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
5938 } else if (set_max
) {
5939 return KERN_SUCCESS
; // Punt set_max, as there's no mechanism to record that state
5941 return ml_static_protect(start
, end
- start
, new_prot
);
5945 static inline kern_return_t
5948 vm_map_offset_t start
,
5949 vm_map_offset_t end
,
5950 vm_prot_t access_type
,
5951 boolean_t user_wire
)
5953 #pragma unused(map,start,end,access_type,user_wire)
5954 return KERN_SUCCESS
; // No-op as PRELINK kexts are cemented into physical memory at boot
5957 #error Unrecognized architecture
5960 static inline kern_return_t
5963 vm_map_offset_t start
,
5964 vm_map_offset_t end
,
5968 if (start
== end
) { // 10538581
5969 return KERN_SUCCESS
;
5971 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
5974 static inline kern_return_t
5977 vm_map_offset_t start
,
5978 vm_map_offset_t end
,
5979 vm_prot_t access_type
,
5980 boolean_t user_wire
)
5982 return vm_map_wire_kernel(map
, start
, end
, access_type
, VM_KERN_MEMORY_KEXT
, user_wire
);
5987 OSKext::setVMAttributes(bool protect
, bool wire
)
5989 vm_map_t kext_map
= NULL
;
5990 kernel_segment_command_t
* seg
= NULL
;
5991 vm_map_offset_t start
= 0;
5992 vm_map_offset_t end
= 0;
5993 OSReturn result
= kOSReturnError
;
5995 if (isInterface() || !declaresExecutable() || flags
.builtin
) {
5996 result
= kOSReturnSuccess
;
6000 /* Get the kext's vm map */
6001 kext_map
= kext_get_vm_map(kmod_info
);
6003 result
= KERN_MEMORY_ERROR
;
6007 #if !VM_MAPPED_KEXTS
6008 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
6009 /* This is a split kext in a prelinked kernelcache; we'll let the
6010 * platform code take care of protecting it. It is already wired.
6012 /* TODO: Should this still allow protections for the first segment
6013 * to go through, in the event that we have a mix of split and
6016 result
= KERN_SUCCESS
;
6021 /* Protect the headers as read-only; they do not need to be wired */
6022 result
= (protect
) ? OSKext_protect(kext_map
, kmod_info
->address
,
6023 kmod_info
->address
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
)
6025 if (result
!= KERN_SUCCESS
) {
6029 /* Set the VM protections and wire down each of the segments */
6030 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6033 /* We build all ARM kexts, so we can ensure they are aligned */
6034 assert((seg
->vmaddr
& PAGE_MASK
) == 0);
6035 assert((seg
->vmsize
& PAGE_MASK
) == 0);
6038 start
= round_page(seg
->vmaddr
);
6039 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
6042 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
6043 if (result
!= KERN_SUCCESS
) {
6045 kOSKextLogErrorLevel
|
6047 "Kext %s failed to set maximum VM protections "
6048 "for segment %s - 0x%x.",
6049 getIdentifierCString(), seg
->segname
, (int)result
);
6053 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
6054 if (result
!= KERN_SUCCESS
) {
6056 kOSKextLogErrorLevel
|
6058 "Kext %s failed to set initial VM protections "
6059 "for segment %s - 0x%x.",
6060 getIdentifierCString(), seg
->segname
, (int)result
);
6065 if (segmentShouldBeWired(seg
) && wire
) {
6066 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
6067 if (result
!= KERN_SUCCESS
) {
6072 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6079 /*********************************************************************
6080 *********************************************************************/
6082 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
6084 return sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
));
6087 /*********************************************************************
6088 *********************************************************************/
6090 OSKext::validateKextMapping(bool startFlag
)
6092 OSReturn result
= kOSReturnError
;
6093 const char * whichOp
= startFlag
? "start" : "stop";
6094 kern_return_t kern_result
= 0;
6095 vm_map_t kext_map
= NULL
;
6096 kernel_segment_command_t
* seg
= NULL
;
6097 mach_vm_address_t address
= 0;
6098 mach_vm_size_t size
= 0;
6100 mach_msg_type_number_t count
;
6101 vm_region_submap_short_info_data_64_t info
;
6103 if (flags
.builtin
) {
6104 return kOSReturnSuccess
;
6107 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
6108 bzero(&info
, sizeof(info
));
6110 // xxx - do we need a distinct OSReturn value for these or is "bad data"
6111 // xxx - sufficient?
6113 /* Verify that the kmod_info and start/stop pointers are non-NULL.
6117 kOSKextLogErrorLevel
|
6119 "Kext %s - NULL kmod_info pointer.",
6120 getIdentifierCString());
6121 result
= kOSKextReturnBadData
;
6126 address
= (mach_vm_address_t
)kmod_info
->start
;
6128 address
= (mach_vm_address_t
)kmod_info
->stop
;
6133 kOSKextLogErrorLevel
|
6135 "Kext %s - NULL module %s pointer.",
6136 getIdentifierCString(), whichOp
);
6137 result
= kOSKextReturnBadData
;
6141 kext_map
= kext_get_vm_map(kmod_info
);
6142 depth
= (kernel_map
== kext_map
) ? 1 : 2;
6144 /* Verify that the start/stop function lies within the kext's address range.
6146 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
6147 /* This will likely be how we deal with split kexts; walk the segments to
6148 * check that the function lies inside one of the segments of this kext.
6150 for (seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6152 seg
= nextsegfromheader((kernel_mach_header_t
*)kmod_info
->address
, seg
)) {
6153 if ((address
>= seg
->vmaddr
) && address
< (seg
->vmaddr
+ seg
->vmsize
)) {
6160 kOSKextLogErrorLevel
|
6162 "Kext %s module %s pointer is outside of kext range "
6163 "(%s %p - kext starts at %p).",
6164 getIdentifierCString(),
6167 (void *)ml_static_unslide(address
),
6168 (void *)ml_static_unslide(kmod_info
->address
));
6169 result
= kOSKextReturnBadData
;
6175 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
6176 kmod_info
->address
+ kmod_info
->size
<= address
) {
6178 kOSKextLogErrorLevel
|
6180 "Kext %s module %s pointer is outside of kext range "
6181 "(%s %p - kext at %p-%p).",
6182 getIdentifierCString(),
6185 (void *)ml_static_unslide(address
),
6186 (void *)ml_static_unslide(kmod_info
->address
),
6187 (void *)(ml_static_unslide(kmod_info
->address
) + kmod_info
->size
));
6188 result
= kOSKextReturnBadData
;
6193 /* Only do these checks before calling the start function;
6194 * If anything goes wrong with the mapping while the kext is running,
6195 * we'll likely have panicked well before any attempt to stop the kext.
6198 /* Verify that the start/stop function is executable.
6200 kern_result
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
,
6201 (vm_region_recurse_info_t
)&info
, &count
);
6202 if (kern_result
!= KERN_SUCCESS
) {
6204 kOSKextLogErrorLevel
|
6206 "Kext %s - bad %s pointer %p.",
6207 getIdentifierCString(),
6208 whichOp
, (void *)ml_static_unslide(address
));
6209 result
= kOSKextReturnBadData
;
6214 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
6216 kOSKextLogErrorLevel
|
6218 "Kext %s - memory region containing module %s function "
6219 "is not executable.",
6220 getIdentifierCString(), whichOp
);
6221 result
= kOSKextReturnBadData
;
6226 /* Verify that the kext's segments are backed by physical memory.
6228 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6230 if (!verifySegmentMapping(seg
)) {
6231 result
= kOSKextReturnBadData
;
6235 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6239 result
= kOSReturnSuccess
;
6244 /*********************************************************************
6245 *********************************************************************/
6247 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
6249 mach_vm_address_t address
= 0;
6251 if (!segmentShouldBeWired(seg
)) {
6255 for (address
= seg
->vmaddr
;
6256 address
< round_page(seg
->vmaddr
+ seg
->vmsize
);
6257 address
+= PAGE_SIZE
) {
6258 if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) {
6260 kOSKextLogErrorLevel
|
6262 "Kext %s - page %p is not backed by physical memory.",
6263 getIdentifierCString(),
6272 /*********************************************************************
6273 *********************************************************************/
6275 OSKextLogKextInfo(OSKext
*aKext
, uint64_t address
, uint64_t size
, firehose_tracepoint_code_t code
)
6278 firehose_tracepoint_id_u trace_id
;
6279 struct firehose_trace_uuid_info_s uuid_info_s
;
6280 firehose_trace_uuid_info_t uuid_info
= &uuid_info_s
;
6281 size_t uuid_info_len
= sizeof(struct firehose_trace_uuid_info_s
);
6284 stamp
= firehose_tracepoint_time(firehose_activity_flags_default
);
6285 trace_id
.ftid_value
= FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata
, _firehose_tracepoint_type_metadata_kext
, (firehose_tracepoint_flags_t
)0, code
);
6287 uuid_data
= aKext
->copyTextUUID();
6289 memcpy(uuid_info
->ftui_uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_info
->ftui_uuid
));
6290 OSSafeReleaseNULL(uuid_data
);
6293 uuid_info
->ftui_size
= size
;
6294 uuid_info
->ftui_address
= ml_static_unslide(address
);
6296 firehose_trace_metadata(firehose_stream_metadata
, trace_id
, stamp
, uuid_info
, uuid_info_len
);
6300 /*********************************************************************
6301 *********************************************************************/
6303 OSKext::start(bool startDependenciesFlag
)
6305 OSReturn result
= kOSReturnError
;
6306 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
6307 unsigned int i
, count
;
6308 void * kmodStartData
= NULL
;
6310 if (isStarted() || isInterface() || isKernelComponent()) {
6311 result
= kOSReturnSuccess
;
6317 kOSKextLogErrorLevel
|
6319 "Attempt to start nonloaded kext %s.",
6320 getIdentifierCString());
6321 result
= kOSKextReturnInvalidArgument
;
6325 if (!sLoadEnabled
) {
6327 kOSKextLogErrorLevel
|
6329 "Kext loading is disabled (attempt to start kext %s).",
6330 getIdentifierCString());
6331 result
= kOSKextReturnDisabled
;
6335 result
= validateKextMapping(/* start? */ true);
6336 if (result
!= kOSReturnSuccess
) {
6340 startfunc
= kmod_info
->start
;
6342 count
= getNumDependencies();
6343 for (i
= 0; i
< count
; i
++) {
6344 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
6345 if (dependency
== NULL
) {
6347 kOSKextLogErrorLevel
|
6349 "Kext %s start - internal error, dependency disappeared.",
6350 getIdentifierCString());
6353 if (!dependency
->isStarted()) {
6354 if (startDependenciesFlag
) {
6355 OSReturn dependencyResult
=
6356 dependency
->start(startDependenciesFlag
);
6357 if (dependencyResult
!= KERN_SUCCESS
) {
6359 kOSKextLogErrorLevel
|
6361 "Kext %s start - dependency %s failed to start (error 0x%x).",
6362 getIdentifierCString(),
6363 dependency
->getIdentifierCString(),
6369 kOSKextLogErrorLevel
|
6371 "Not starting %s - dependency %s not started yet.",
6372 getIdentifierCString(),
6373 dependency
->getIdentifierCString());
6374 result
= kOSKextReturnStartStopError
; // xxx - make new return?
6381 kOSKextLogDetailLevel
|
6383 "Kext %s calling module start function.",
6384 getIdentifierCString());
6388 // Drop a log message so logd can grab the needed information to decode this kext
6389 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_load
);
6390 result
= OSRuntimeInitializeCPP(this);
6391 if (result
== KERN_SUCCESS
) {
6392 result
= startfunc(kmod_info
, kmodStartData
);
6397 /* On success overlap the setting of started/starting. On failure just
6400 if (result
== KERN_SUCCESS
) {
6403 // xxx - log start error from kernel?
6405 kOSKextLogProgressLevel
|
6407 "Kext %s is now started.",
6408 getIdentifierCString());
6410 invokeOrCancelRequestCallbacks(
6411 /* result not actually used */ kOSKextReturnStartStopError
,
6412 /* invokeFlag */ false);
6414 kOSKextLogProgressLevel
|
6416 "Kext %s did not start (return code 0x%x).",
6417 getIdentifierCString(), result
);
6424 /*********************************************************************
6425 *********************************************************************/
6428 OSKext::canUnloadKextWithIdentifier(
6429 OSString
* kextIdentifier
,
6430 bool checkClassesFlag
)
6432 bool result
= false;
6433 OSKext
* aKext
= NULL
;// do not release
6435 IORecursiveLockLock(sKextLock
);
6437 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
6440 goto finish
; // can't unload what's not loaded
6443 if (aKext
->isLoaded()) {
6444 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
6447 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
6455 IORecursiveLockUnlock(sKextLock
);
6459 /*********************************************************************
6460 *********************************************************************/
6464 OSReturn result
= kOSReturnError
;
6465 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
6467 if (!isStarted() || isInterface()) {
6468 result
= kOSReturnSuccess
;
6474 kOSKextLogErrorLevel
|
6476 "Attempt to stop nonloaded kext %s.",
6477 getIdentifierCString());
6478 result
= kOSKextReturnInvalidArgument
;
6482 /* Refuse to stop if we have clients or instances. It is up to
6483 * the caller to make sure those aren't true.
6485 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6487 kOSKextLogErrorLevel
|
6489 "Kext %s - C++ instances; can't stop.",
6490 getIdentifierCString());
6491 result
= kOSKextReturnInUse
;
6495 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6497 kOSKextLogErrorLevel
|
6499 "Kext %s - has references (linkage or tracking object); "
6501 getIdentifierCString());
6502 result
= kOSKextReturnInUse
;
6506 /* Note: If validateKextMapping fails on the stop & unload path,
6507 * we are in serious trouble and a kernel panic is likely whether
6508 * we stop & unload the kext or not.
6510 result
= validateKextMapping(/* start? */ false);
6511 if (result
!= kOSReturnSuccess
) {
6515 stopfunc
= kmod_info
->stop
;
6518 kOSKextLogDetailLevel
|
6520 "Kext %s calling module stop function.",
6521 getIdentifierCString());
6525 result
= stopfunc(kmod_info
, /* userData */ NULL
);
6526 if (result
== KERN_SUCCESS
) {
6527 result
= OSRuntimeFinalizeCPP(this);
6532 if (result
== KERN_SUCCESS
) {
6536 kOSKextLogDetailLevel
|
6538 "Kext %s is now stopped and ready to unload.",
6539 getIdentifierCString());
6542 kOSKextLogErrorLevel
|
6544 "Kext %s did not stop (return code 0x%x).",
6545 getIdentifierCString(), result
);
6546 result
= kOSKextReturnStartStopError
;
6551 // Drop a log message so logd can update this kext's metadata
6552 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_unload
);
6556 /*********************************************************************
6557 *********************************************************************/
6559 OSKext::unload(void)
6561 OSReturn result
= kOSReturnError
;
6563 uint32_t num_kmod_refs
= 0;
6564 OSKextAccount
* freeAccount
;
6566 if (!sUnloadEnabled
) {
6568 kOSKextLogErrorLevel
|
6570 "Kext unloading is disabled (%s).",
6571 this->getIdentifierCString());
6573 result
= kOSKextReturnDisabled
;
6577 /* Refuse to unload if we have clients or instances. It is up to
6578 * the caller to make sure those aren't true.
6580 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6581 // xxx - Don't log under errors? this is more of an info thing
6583 kOSKextLogErrorLevel
|
6584 kOSKextLogKextBookkeepingFlag
,
6585 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6586 getIdentifierCString());
6587 result
= kOSKextReturnInUse
;
6592 result
= kOSReturnSuccess
;
6596 if (isKernelComponent()) {
6597 result
= kOSKextReturnInvalidArgument
;
6601 if (metaClasses
&& !OSMetaClass::removeClasses(metaClasses
)) {
6603 kOSKextLogErrorLevel
|
6604 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6605 "Can't unload kext %s; classes have instances:",
6606 getIdentifierCString());
6607 reportOSMetaClassInstances(kOSKextLogErrorLevel
|
6608 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
);
6609 result
= kOSKextReturnInUse
;
6613 /* Note that the kext is unloading before running any code that
6614 * might be in the kext (request callbacks, module stop function).
6615 * We will deny certain requests made against a kext in the process
6618 flags
.unloading
= 1;
6620 /* Update the string describing the last kext to unload in case we panic.
6622 savePanicString(/* isLoading */ false);
6626 if (result
!= KERN_SUCCESS
) {
6628 kOSKextLogErrorLevel
|
6630 "Kext %s can't unload - module stop returned 0x%x.",
6631 getIdentifierCString(), (unsigned)result
);
6632 result
= kOSKextReturnStartStopError
;
6638 kOSKextLogProgressLevel
|
6640 "Kext %s unloading.",
6641 getIdentifierCString());
6644 struct list_head
*p
;
6645 struct list_head
*prev
;
6646 struct list_head
*next
;
6647 for (p
= pendingPgoHead
.next
; p
!= &pendingPgoHead
; p
= next
) {
6648 OSKextGrabPgoStruct
*s
= container_of(p
, OSKextGrabPgoStruct
, list_head
);
6649 s
->err
= OSKextGrabPgoDataLocked(this, s
->metadata
, instance_uuid
, s
->pSize
, s
->pBuffer
, s
->bufferSize
);
6656 IORecursiveLockWakeup(sKextLock
, s
, false);
6661 /* Even if we don't call the stop function, we want to be sure we
6662 * have no OSMetaClass references before unloading the kext executable
6663 * from memory. OSMetaClasses may have pointers into the kext executable
6664 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6667 metaClasses
->flushCollection();
6669 (void) OSRuntimeFinalizeCPP(this);
6671 /* Remove the kext from the list of loaded kexts, patch the gap
6672 * in the kmod_info_t linked list, and reset "kmod" to point to the
6673 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6675 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
6676 if (index
!= (unsigned int)-1) {
6677 sLoadedKexts
->removeObject(index
);
6679 OSKext
* nextKext
= OSDynamicCast(OSKext
,
6680 sLoadedKexts
->getObject(index
));
6684 OSKext
* gapKext
= OSDynamicCast(OSKext
,
6685 sLoadedKexts
->getObject(index
- 1));
6687 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
6688 } else { /* index == 0 */
6689 nextKext
->kmod_info
->next
= NULL
;
6693 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
6694 if (lastKext
&& !lastKext
->isKernel()) {
6695 kmod
= lastKext
->kmod_info
;
6697 kmod
= NULL
; // clear the global kmod variable
6701 /* Clear out the kmod references that we're keeping for compatibility
6702 * with current panic backtrace code & kgmacros.
6703 * xxx - will want to update those bits sometime and remove this.
6705 num_kmod_refs
= getNumDependencies();
6706 if (num_kmod_refs
&& kmod_info
&& kmod_info
->reference_list
) {
6707 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
6708 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
6709 ref
->info
->reference_count
--;
6711 kfree(kmod_info
->reference_list
,
6712 num_kmod_refs
* sizeof(kmod_reference_t
));
6716 unregisterWithDTrace();
6717 #endif /* CONFIG_DTRACE */
6719 notifyKextUnloadObservers(this);
6722 IOSimpleLockLock(sKextAccountsLock
);
6723 account
->kext
= NULL
;
6724 if (account
->site
.tag
) {
6725 account
->site
.flags
|= VM_TAG_UNLOAD
;
6727 freeAccount
= account
;
6729 IOSimpleLockUnlock(sKextAccountsLock
);
6731 IODelete(freeAccount
, OSKextAccount
, 1);
6734 /* Unwire and free the linked executable.
6736 if (linkedExecutable
) {
6738 kasan_unload_kext((vm_offset_t
)linkedExecutable
->getBytesNoCopy(), linkedExecutable
->getLength());
6742 if (!isInterface()) {
6743 kernel_segment_command_t
*seg
= NULL
;
6744 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6748 kOSKextLogErrorLevel
|
6750 "Failed to free kext %s; couldn't find the kext map.",
6751 getIdentifierCString());
6752 result
= kOSKextReturnInternalError
;
6757 kOSKextLogProgressLevel
|
6759 "Kext %s unwiring and unmapping linked executable.",
6760 getIdentifierCString());
6762 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6764 if (segmentShouldBeWired(seg
)) {
6765 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6766 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6767 if (result
!= KERN_SUCCESS
) {
6769 kOSKextLogErrorLevel
|
6771 "Failed to unwire kext %s.",
6772 getIdentifierCString());
6773 result
= kOSKextReturnInternalError
;
6778 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6782 OSSafeReleaseNULL(linkedExecutable
);
6785 /* An interface kext has a fake kmod_info that was allocated,
6786 * so we have to free it.
6788 if (isInterface()) {
6789 kfree(kmod_info
, sizeof(kmod_info_t
));
6794 flags
.loaded
= false;
6795 flushDependencies();
6797 /* save a copy of the bundle ID for us to check when deciding to
6798 * rebuild the kernel cache file. If a kext was already in the kernel
6799 * cache and unloaded then later loaded we do not need to rebuild the
6800 * kernel cache. 9055303
6802 if (isPrelinked()) {
6803 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6804 IORecursiveLockLock(sKextLock
);
6805 if (sUnloadedPrelinkedKexts
) {
6806 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6808 IORecursiveLockUnlock(sKextLock
);
6813 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6814 "Kext %s unloaded.", getIdentifierCString());
6816 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6817 OSDynamicCast(OSString
, bundleID
));
6820 OSKext::saveLoadedKextPanicList();
6821 OSKext::updateLoadedKextSummaries();
6823 flags
.unloading
= 0;
6827 /*********************************************************************
6828 * Assumes sKextLock is held.
6829 *********************************************************************/
6832 OSKext::queueKextNotification(
6833 const char * notificationName
,
6834 OSString
* kextIdentifier
)
6836 OSReturn result
= kOSReturnError
;
6837 OSDictionary
* loadRequest
= NULL
;// must release
6839 if (!kextIdentifier
) {
6840 result
= kOSKextReturnInvalidArgument
;
6844 /* Create a new request unless one is already sitting
6845 * in sKernelRequests for this bundle identifier
6847 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6848 if (result
!= kOSReturnSuccess
) {
6851 if (!_OSKextSetRequestArgument(loadRequest
,
6852 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6853 result
= kOSKextReturnNoMemory
;
6856 if (!sKernelRequests
->setObject(loadRequest
)) {
6857 result
= kOSKextReturnNoMemory
;
6861 /* We might want to only queue the notification if kextd is active,
6862 * but that wouldn't work for embedded. Note that we don't care if
6863 * the ping immediately succeeds here so don't do anything with the
6864 * result of this call.
6866 OSKext::pingKextd();
6868 result
= kOSReturnSuccess
;
6871 OSSafeReleaseNULL(loadRequest
);
6876 /*********************************************************************
6877 *********************************************************************/
6879 _OSKextConsiderDestroyingLinkContext(
6880 __unused thread_call_param_t p0
,
6881 __unused thread_call_param_t p1
)
6883 /* Take multiple locks in the correct order.
6885 IORecursiveLockLock(sKextLock
);
6886 IORecursiveLockLock(sKextInnerLock
);
6888 /* The first time we destroy the kxldContext is in the first
6889 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6890 * before calling this function. Thereafter any call to this function
6891 * will actually destroy the context.
6893 if (sConsiderUnloadsCalled
&& sKxldContext
) {
6894 kxld_destroy_context(sKxldContext
);
6895 sKxldContext
= NULL
;
6898 /* Free the thread_call that was allocated to execute this function.
6900 if (sDestroyLinkContextThread
) {
6901 if (!thread_call_free(sDestroyLinkContextThread
)) {
6902 OSKextLog(/* kext */ NULL
,
6903 kOSKextLogErrorLevel
|
6904 kOSKextLogGeneralFlag
,
6905 "thread_call_free() failed for kext link context.");
6907 sDestroyLinkContextThread
= 0;
6910 IORecursiveLockUnlock(sKextInnerLock
);
6911 IORecursiveLockUnlock(sKextLock
);
6916 /*********************************************************************
6917 * Destroying the kxldContext requires checking variables under both
6918 * sKextInnerLock and sKextLock, so we do it on a separate thread
6919 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6920 * call relationship.
6922 * This function must be invoked with sKextInnerLock held.
6923 * Do not call any function that takes sKextLock here!
6924 *********************************************************************/
6927 OSKext::considerDestroyingLinkContext(void)
6929 IORecursiveLockLock(sKextInnerLock
);
6931 /* If we have already queued a thread to destroy the link context,
6932 * don't bother resetting; that thread will take care of it.
6934 if (sDestroyLinkContextThread
) {
6938 /* The function to be invoked in the thread will deallocate
6939 * this thread_call, so don't share it around.
6941 sDestroyLinkContextThread
= thread_call_allocate(
6942 &_OSKextConsiderDestroyingLinkContext
, 0);
6943 if (!sDestroyLinkContextThread
) {
6944 OSKextLog(/* kext */ NULL
,
6945 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
| kOSKextLogLinkFlag
,
6946 "Can't create thread to destroy kext link context.");
6950 thread_call_enter(sDestroyLinkContextThread
);
6953 IORecursiveLockUnlock(sKextInnerLock
);
6958 #pragma mark Autounload
6960 /*********************************************************************
6961 * This is a static method because the kext will be deallocated if it
6963 *********************************************************************/
6966 OSKext::autounloadKext(OSKext
* aKext
)
6968 OSReturn result
= kOSKextReturnInUse
;
6970 /* Check for external references to this kext (usu. dependents),
6971 * instances of defined classes (or classes derived from them),
6972 * outstanding requests.
6974 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
6975 !aKext
->flags
.autounloadEnabled
||
6976 aKext
->isKernelComponent()) {
6980 /* Skip a delay-autounload kext, once.
6982 if (aKext
->flags
.delayAutounload
) {
6984 kOSKextLogProgressLevel
|
6985 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6986 "Kext %s has delayed autounload set; skipping and clearing flag.",
6987 aKext
->getIdentifierCString());
6988 aKext
->flags
.delayAutounload
= 0;
6992 if (aKext
->hasOSMetaClassInstances() ||
6993 aKext
->countRequestCallbacks()) {
6997 result
= OSKext::removeKext(aKext
);
7003 /*********************************************************************
7004 *********************************************************************/
7006 _OSKextConsiderUnloads(
7007 __unused thread_call_param_t p0
,
7008 __unused thread_call_param_t p1
)
7010 bool didUnload
= false;
7011 unsigned int count
, i
;
7013 /* Take multiple locks in the correct order
7014 * (note also sKextSummaries lock further down).
7016 IORecursiveLockLock(sKextLock
);
7017 IORecursiveLockLock(sKextInnerLock
);
7019 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
7021 /* If the system is powering down, don't try to unload anything.
7027 OSKextLog(/* kext */ NULL
,
7028 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
7029 "Checking for unused kexts to autounload.");
7032 * Remove any request callbacks marked as stale,
7033 * and mark as stale any currently in flight.
7035 count
= sRequestCallbackRecords
->getCount();
7039 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
7040 sRequestCallbackRecords
->getObject(i
));
7041 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
7042 callbackRecord
->getObject(kKextRequestStaleKey
));
7044 if (stale
== kOSBooleanTrue
) {
7045 OSKext::invokeRequestCallback(callbackRecord
,
7046 kOSKextReturnTimeout
);
7048 callbackRecord
->setObject(kKextRequestStaleKey
,
7055 * Make multiple passes through the array of loaded kexts until
7056 * we don't unload any. This handles unwinding of dependency
7057 * chains. We have to go *backwards* through the array because
7058 * kexts are removed from it when unloaded, and we cannot make
7059 * a copy or we'll mess up the retain counts we rely on to
7060 * check whether a kext will unload. If only we could have
7061 * nonretaining collections like CF has....
7066 count
= sLoadedKexts
->getCount();
7070 OSKext
* thisKext
= OSDynamicCast(OSKext
,
7071 sLoadedKexts
->getObject(i
));
7072 didUnload
|= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
7075 } while (didUnload
);
7078 sConsiderUnloadsPending
= false;
7079 sConsiderUnloadsExecuted
= true;
7081 (void) OSKext::considerRebuildOfPrelinkedKernel();
7083 IORecursiveLockUnlock(sKextInnerLock
);
7084 IORecursiveLockUnlock(sKextLock
);
7089 /*********************************************************************
7090 * Do not call any function that takes sKextLock here!
7091 *********************************************************************/
7093 OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
7097 IORecursiveLockLock(sKextInnerLock
);
7099 if (!sUnloadCallout
) {
7100 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, 0);
7103 /* we only reset delay value for unloading if we already have something
7104 * pending. rescheduleOnlyFlag should not start the count down.
7106 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
7110 thread_call_cancel(sUnloadCallout
);
7111 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
7112 clock_interval_to_deadline(sConsiderUnloadDelay
,
7113 1000 * 1000 * 1000, &when
);
7115 OSKextLog(/* kext */ NULL
,
7116 kOSKextLogProgressLevel
|
7118 "%scheduling %sscan for unused kexts in %lu seconds.",
7119 sConsiderUnloadsPending
? "Res" : "S",
7120 sConsiderUnloadsCalled
? "" : "initial ",
7121 (unsigned long)sConsiderUnloadDelay
);
7123 sConsiderUnloadsPending
= true;
7124 thread_call_enter_delayed(sUnloadCallout
, when
);
7128 /* The kxld context should be reused throughout boot. We mark the end of
7129 * period as the first time considerUnloads() is called, and we destroy
7130 * the first kxld context in that function. Afterwards, it will be
7131 * destroyed in flushNonloadedKexts.
7133 if (!sConsiderUnloadsCalled
) {
7134 sConsiderUnloadsCalled
= true;
7135 OSKext::considerDestroyingLinkContext();
7138 IORecursiveLockUnlock(sKextInnerLock
);
7142 /*********************************************************************
7143 * Do not call any function that takes sKextLock here!
7144 *********************************************************************/
7146 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
);
7148 OSKextSystemSleepOrWake(UInt32 messageType
)
7150 IORecursiveLockLock(sKextInnerLock
);
7152 /* If the system is going to sleep, cancel the reaper thread timer,
7153 * and note that we're in a sleep state in case it just fired but hasn't
7154 * taken the lock yet. If we are coming back from sleep, just
7155 * clear the sleep flag; IOService's normal operation will cause
7156 * unloads to be considered soon enough.
7158 if (messageType
== kIOMessageSystemWillSleep
) {
7159 if (sUnloadCallout
) {
7160 thread_call_cancel(sUnloadCallout
);
7162 sSystemSleep
= true;
7163 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
7164 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
7165 sSystemSleep
= false;
7166 clock_get_uptime(&sLastWakeTime
);
7168 IORecursiveLockUnlock(sKextInnerLock
);
7170 return kIOReturnSuccess
;
7176 #pragma mark Prelinked Kernel
7178 /*********************************************************************
7179 * Do not access sConsiderUnloads... variables other than
7180 * sConsiderUnloadsExecuted in this function. They are guarded by a
7182 *********************************************************************/
7185 OSKext::considerRebuildOfPrelinkedKernel(void)
7187 static bool requestedPrelink
= false;
7188 OSReturn checkResult
= kOSReturnError
;
7189 OSDictionary
* prelinkRequest
= NULL
;// must release
7190 OSCollectionIterator
* kextIterator
= NULL
;// must release
7191 const OSSymbol
* thisID
= NULL
;// do not release
7192 bool doRebuild
= false;
7193 AbsoluteTime my_abstime
;
7197 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
7198 if (requestedPrelink
|| !sPrelinkBoot
) {
7202 /* no direct return from this point */
7203 IORecursiveLockLock(sKextLock
);
7205 /* We need to wait for kextd to get up and running with unloads already done
7206 * and any new startup kexts loaded.
7208 if (!sConsiderUnloadsExecuted
||
7209 !sDeferredLoadSucceeded
) {
7213 /* we really only care about boot / system start up related kexts so bail
7214 * if we're here after REBUILD_MAX_TIME.
7216 if (!_OSKextInPrelinkRebuildWindow()) {
7217 OSKextLog(/* kext */ NULL
,
7218 kOSKextLogArchiveFlag
,
7219 "%s prebuild rebuild has expired",
7221 requestedPrelink
= true;
7225 /* we do not want to trigger a rebuild if we get here too close to waking
7226 * up. (see radar 10233768)
7228 IORecursiveLockLock(sKextInnerLock
);
7230 clock_get_uptime(&my_abstime
);
7231 delta_secs
= MINIMUM_WAKEUP_SECONDS
+ 1;
7232 if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) {
7233 SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
);
7234 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
7235 delta_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
7237 IORecursiveLockUnlock(sKextInnerLock
);
7239 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
7240 /* too close to time of last wake from sleep */
7243 requestedPrelink
= true;
7245 /* Now it's time to see if we have a reason to rebuild. We may have done
7246 * some loads and unloads but the kernel cache didn't actually change.
7247 * We will rebuild if any kext is not marked prelinked AND is not in our
7248 * list of prelinked kexts that got unloaded. (see radar 9055303)
7250 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
7251 if (!kextIterator
) {
7255 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
7256 OSKext
* thisKext
;// do not release
7258 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
7259 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
7263 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
7266 /* kext is loaded and was not in current kernel cache so let's rebuild
7269 OSKextLog(/* kext */ NULL
,
7270 kOSKextLogArchiveFlag
,
7271 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
7272 thisKext
->bundleID
->getCStringNoCopy());
7275 sUnloadedPrelinkedKexts
->flushCollection();
7281 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
7283 if (checkResult
!= kOSReturnSuccess
) {
7287 if (!sKernelRequests
->setObject(prelinkRequest
)) {
7291 OSKext::pingKextd();
7294 IORecursiveLockUnlock(sKextLock
);
7295 OSSafeReleaseNULL(prelinkRequest
);
7296 OSSafeReleaseNULL(kextIterator
);
7302 #pragma mark Dependencies
7304 /*********************************************************************
7305 *********************************************************************/
7307 OSKext::resolveDependencies(
7308 OSArray
* loopStack
)
7310 bool result
= false;
7311 OSArray
* localLoopStack
= NULL
;// must release
7312 bool addedToLoopStack
= false;
7313 OSDictionary
* libraries
= NULL
;// do not release
7314 OSCollectionIterator
* libraryIterator
= NULL
;// must release
7315 OSString
* libraryID
= NULL
;// do not release
7316 OSString
* infoString
= NULL
;// do not release
7317 OSString
* readableString
= NULL
;// do not release
7318 OSKext
* libraryKext
= NULL
;// do not release
7319 bool hasRawKernelDependency
= false;
7320 bool hasKernelDependency
= false;
7321 bool hasKPIDependency
= false;
7322 bool hasPrivateKPIDependency
= false;
7325 /* A kernel component will automatically have this flag set,
7326 * and a loaded kext should also have it set (as should all its
7327 * loaded dependencies).
7329 if (flags
.hasAllDependencies
) {
7334 /* Check for loops in the dependency graph.
7337 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
7339 kOSKextLogErrorLevel
|
7340 kOSKextLogDependenciesFlag
,
7341 "Kext %s has a dependency loop; can't resolve dependencies.",
7342 getIdentifierCString());
7347 kOSKextLogStepLevel
|
7348 kOSKextLogDependenciesFlag
,
7349 "Kext %s resolving dependencies.",
7350 getIdentifierCString());
7352 loopStack
= OSArray::withCapacity(6); // any small capacity will do
7355 kOSKextLogErrorLevel
|
7356 kOSKextLogDependenciesFlag
,
7357 "Kext %s can't create bookkeeping stack to resolve dependencies.",
7358 getIdentifierCString());
7361 localLoopStack
= loopStack
;
7363 if (!loopStack
->setObject(this)) {
7365 kOSKextLogErrorLevel
|
7366 kOSKextLogDependenciesFlag
,
7367 "Kext %s - internal error resolving dependencies.",
7368 getIdentifierCString());
7371 addedToLoopStack
= true;
7373 /* Purge any existing kexts in the dependency list and start over.
7375 flushDependencies();
7378 kOSKextLogErrorLevel
|
7379 kOSKextLogDependenciesFlag
,
7380 "Kext %s - internal error resolving dependencies.",
7381 getIdentifierCString());
7384 libraries
= OSDynamicCast(OSDictionary
,
7385 getPropertyForHostArch(kOSBundleLibrariesKey
));
7386 if (libraries
== NULL
|| libraries
->getCount() == 0) {
7388 kOSKextLogErrorLevel
|
7389 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7390 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7391 getIdentifierCString(), kOSBundleLibrariesKey
);
7395 /* Make a new array to hold the dependencies (flush freed the old one).
7397 dependencies
= OSArray::withCapacity(libraries
->getCount());
7398 if (!dependencies
) {
7400 kOSKextLogErrorLevel
|
7401 kOSKextLogDependenciesFlag
,
7402 "Kext %s - can't allocate dependencies array.",
7403 getIdentifierCString());
7407 // xxx - compat: We used to add an implicit dependency on kernel 6.0
7408 // xxx - compat: if none were declared.
7410 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
7411 if (!libraryIterator
) {
7413 kOSKextLogErrorLevel
|
7414 kOSKextLogDependenciesFlag
,
7415 "Kext %s - can't allocate dependencies iterator.",
7416 getIdentifierCString());
7420 while ((libraryID
= OSDynamicCast(OSString
,
7421 libraryIterator
->getNextObject()))) {
7422 const char * library_id
= libraryID
->getCStringNoCopy();
7424 OSString
* libraryVersion
= OSDynamicCast(OSString
,
7425 libraries
->getObject(libraryID
));
7426 if (libraryVersion
== NULL
) {
7428 kOSKextLogErrorLevel
|
7429 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7430 "Kext %s - illegal type in OSBundleLibraries.",
7431 getIdentifierCString());
7435 OSKextVersion libraryVers
=
7436 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
7437 if (libraryVers
== -1) {
7439 kOSKextLogErrorLevel
|
7440 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7441 "Kext %s - invalid library version %s.",
7442 getIdentifierCString(),
7443 libraryVersion
->getCStringNoCopy());
7447 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
7448 if (libraryKext
== NULL
) {
7450 kOSKextLogErrorLevel
|
7451 kOSKextLogDependenciesFlag
,
7452 "Kext %s - library kext %s not found.",
7453 getIdentifierCString(), library_id
);
7457 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
7459 kOSKextLogErrorLevel
|
7460 kOSKextLogDependenciesFlag
,
7461 "Kext %s - library kext %s not compatible "
7462 "with requested version %s.",
7463 getIdentifierCString(), library_id
,
7464 libraryVersion
->getCStringNoCopy());
7468 /* If a nonprelinked library somehow got into the mix for a
7469 * prelinked kext, at any point in the chain, we must fail
7470 * because the prelinked relocs for the library will be all wrong.
7472 if (this->isPrelinked() &&
7473 libraryKext
->declaresExecutable() &&
7474 !libraryKext
->isPrelinked()) {
7476 kOSKextLogErrorLevel
|
7477 kOSKextLogDependenciesFlag
,
7478 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7479 getIdentifierCString(), library_id
,
7480 libraryVersion
->getCStringNoCopy());
7484 if (!libraryKext
->resolveDependencies(loopStack
)) {
7488 /* Add the library directly only if it has an executable to link.
7489 * Otherwise it's just used to collect other dependencies, so put
7490 * *its* dependencies on the list for this kext.
7492 // xxx - We are losing info here; would like to make fake entries or
7493 // xxx - keep these in the dependency graph for loaded kexts.
7494 // xxx - I really want to make kernel components not a special case!
7495 if (libraryKext
->declaresExecutable() ||
7496 libraryKext
->isInterface()) {
7497 if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) {
7498 dependencies
->setObject(libraryKext
);
7501 kOSKextLogDetailLevel
|
7502 kOSKextLogDependenciesFlag
,
7503 "Kext %s added dependency %s.",
7504 getIdentifierCString(),
7505 libraryKext
->getIdentifierCString());
7508 int numLibDependencies
= libraryKext
->getNumDependencies();
7509 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
7512 if (numLibDependencies
) {
7513 // xxx - this msg level should be 1 lower than the per-kext one
7515 kOSKextLogDetailLevel
|
7516 kOSKextLogDependenciesFlag
,
7517 "Kext %s pulling %d dependencies from codeless library %s.",
7518 getIdentifierCString(),
7520 libraryKext
->getIdentifierCString());
7522 for (index
= 0; index
< numLibDependencies
; index
++) {
7523 OSKext
* thisLibDependency
= OSDynamicCast(OSKext
,
7524 libraryDependencies
->getObject(index
));
7525 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) {
7526 dependencies
->setObject(thisLibDependency
);
7528 kOSKextLogDetailLevel
|
7529 kOSKextLogDependenciesFlag
,
7530 "Kext %s added dependency %s from codeless library %s.",
7531 getIdentifierCString(),
7532 thisLibDependency
->getIdentifierCString(),
7533 libraryKext
->getIdentifierCString());
7538 if ((strlen(library_id
) == strlen(KERNEL_LIB
)) &&
7539 0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
) - 1)) {
7540 hasRawKernelDependency
= true;
7541 } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) {
7542 hasKernelDependency
= true;
7543 } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) {
7544 hasKPIDependency
= true;
7545 if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
) - 1)) {
7546 hasPrivateKPIDependency
= true;
7551 if (hasRawKernelDependency
) {
7553 kOSKextLogErrorLevel
|
7554 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7555 "Error - kext %s declares a dependency on %s, which is not permitted.",
7556 getIdentifierCString(), KERNEL_LIB
);
7560 if (hasKernelDependency
) {
7562 kOSKextLogErrorLevel
|
7563 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7564 "Error - kext %s declares %s dependencies. "
7565 "Only %s* dependencies are supported for 64-bit kexts.",
7566 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7569 if (!hasKPIDependency
) {
7571 kOSKextLogWarningLevel
|
7572 kOSKextLogDependenciesFlag
,
7573 "Warning - kext %s declares no %s* dependencies. "
7574 "If it uses any KPIs, the link may fail with undefined symbols.",
7575 getIdentifierCString(), KPI_LIB_PREFIX
);
7577 #else /* __LP64__ */
7578 // xxx - will change to flatly disallow "kernel" dependencies at some point
7579 // xxx - is it invalid to do both "com.apple.kernel" and any
7580 // xxx - "com.apple.kernel.*"?
7582 if (hasKernelDependency
&& hasKPIDependency
) {
7584 kOSKextLogWarningLevel
|
7585 kOSKextLogDependenciesFlag
,
7586 "Warning - kext %s has immediate dependencies on both "
7587 "%s* and %s* components; use only one style.",
7588 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7591 if (!hasKernelDependency
&& !hasKPIDependency
) {
7592 // xxx - do we want to use validation flag for these too?
7594 kOSKextLogWarningLevel
|
7595 kOSKextLogDependenciesFlag
,
7596 "Warning - %s declares no kernel dependencies; using %s.",
7597 getIdentifierCString(), KERNEL6_LIB
);
7598 OSKext
* kernelKext
= OSDynamicCast(OSKext
,
7599 sKextsByID
->getObject(KERNEL6_LIB
));
7601 dependencies
->setObject(kernelKext
);
7604 kOSKextLogErrorLevel
|
7605 kOSKextLogDependenciesFlag
,
7606 "Error - Library %s not found for %s.",
7607 KERNEL6_LIB
, getIdentifierCString());
7611 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7612 * its indirect dependencies to simulate old-style linking. XXX - Should
7613 * check for duplicates.
7615 if (!hasKPIDependency
) {
7618 flags
.hasBleedthrough
= true;
7620 count
= getNumDependencies();
7622 /* We add to the dependencies array in this loop, but do not iterate
7623 * past its original count.
7625 for (i
= 0; i
< count
; i
++) {
7626 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
7627 dependencies
->getObject(i
));
7628 dependencyKext
->addBleedthroughDependencies(dependencies
);
7631 #endif /* __LP64__ */
7633 if (hasPrivateKPIDependency
) {
7634 bool hasApplePrefix
= false;
7635 bool infoCopyrightIsValid
= false;
7636 bool readableCopyrightIsValid
= false;
7638 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
7641 infoString
= OSDynamicCast(OSString
,
7642 getPropertyForHostArch("CFBundleGetInfoString"));
7644 infoCopyrightIsValid
=
7645 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
7648 readableString
= OSDynamicCast(OSString
,
7649 getPropertyForHostArch("NSHumanReadableCopyright"));
7650 if (readableString
) {
7651 readableCopyrightIsValid
=
7652 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
7655 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
7657 kOSKextLogErrorLevel
|
7658 kOSKextLogDependenciesFlag
,
7659 "Error - kext %s declares a dependency on %s. "
7660 "Only Apple kexts may declare a dependency on %s.",
7661 getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
);
7667 flags
.hasAllDependencies
= 1;
7671 if (addedToLoopStack
) {
7672 count
= loopStack
->getCount();
7673 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
7674 loopStack
->removeObject(count
- 1);
7677 kOSKextLogErrorLevel
|
7678 kOSKextLogDependenciesFlag
,
7679 "Kext %s - internal error resolving dependencies.",
7680 getIdentifierCString());
7684 if (result
&& localLoopStack
) {
7686 kOSKextLogStepLevel
|
7687 kOSKextLogDependenciesFlag
,
7688 "Kext %s successfully resolved dependencies.",
7689 getIdentifierCString());
7692 OSSafeReleaseNULL(localLoopStack
);
7693 OSSafeReleaseNULL(libraryIterator
);
7698 /*********************************************************************
7699 *********************************************************************/
7701 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
7703 bool result
= false;
7704 unsigned int dependencyIndex
, dependencyCount
;
7706 dependencyCount
= getNumDependencies();
7708 for (dependencyIndex
= 0;
7709 dependencyIndex
< dependencyCount
;
7710 dependencyIndex
++) {
7711 OSKext
* dependency
= OSDynamicCast(OSKext
,
7712 dependencies
->getObject(dependencyIndex
));
7715 kOSKextLogErrorLevel
|
7716 kOSKextLogDependenciesFlag
,
7717 "Kext %s - internal error propagating compatibility dependencies.",
7718 getIdentifierCString());
7721 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7722 anArray
->setObject(dependency
);
7724 dependency
->addBleedthroughDependencies(anArray
);
7733 /*********************************************************************
7734 *********************************************************************/
7736 OSKext::flushDependencies(bool forceFlag
)
7738 bool result
= false;
7740 /* Only clear the dependencies if the kext isn't loaded;
7741 * we need the info for loaded kexts to track references.
7743 if (!isLoaded() || forceFlag
) {
7745 // xxx - check level
7747 kOSKextLogProgressLevel
|
7748 kOSKextLogDependenciesFlag
,
7749 "Kext %s flushing dependencies.",
7750 getIdentifierCString());
7751 OSSafeReleaseNULL(dependencies
);
7753 if (!isKernelComponent()) {
7754 flags
.hasAllDependencies
= 0;
7762 /*********************************************************************
7763 *********************************************************************/
7765 OSKext::getNumDependencies(void)
7767 if (!dependencies
) {
7770 return dependencies
->getCount();
7773 /*********************************************************************
7774 *********************************************************************/
7776 OSKext::getDependencies(void)
7778 return dependencies
;
7782 #pragma mark OSMetaClass Support
7784 /*********************************************************************
7785 *********************************************************************/
7788 OSMetaClass
* aClass
,
7789 uint32_t numClasses
)
7791 OSReturn result
= kOSMetaClassNoInsKModSet
;
7794 metaClasses
= OSSet::withCapacity(numClasses
);
7800 if (metaClasses
->containsObject(aClass
)) {
7802 kOSKextLogWarningLevel
|
7804 "Notice - kext %s has already registered class %s.",
7805 getIdentifierCString(),
7806 aClass
->getClassName());
7807 result
= kOSReturnSuccess
;
7811 if (!metaClasses
->setObject(aClass
)) {
7815 kOSKextLogDetailLevel
|
7817 "Kext %s registered class %s.",
7818 getIdentifierCString(),
7819 aClass
->getClassName());
7822 if (!flags
.autounloadEnabled
) {
7823 const OSMetaClass
* metaScan
= NULL
;// do not release
7825 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7826 if (metaScan
== OSTypeID(IOService
)) {
7828 kOSKextLogProgressLevel
|
7830 "Kext %s has IOService subclass %s; enabling autounload.",
7831 getIdentifierCString(),
7832 aClass
->getClassName());
7834 flags
.autounloadEnabled
= 1;
7840 notifyAddClassObservers(this, aClass
, flags
);
7842 result
= kOSReturnSuccess
;
7845 if (result
!= kOSReturnSuccess
) {
7847 kOSKextLogErrorLevel
|
7849 "Kext %s failed to register class %s.",
7850 getIdentifierCString(),
7851 aClass
->getClassName());
7857 /*********************************************************************
7858 *********************************************************************/
7860 OSKext::removeClass(
7861 OSMetaClass
* aClass
)
7863 OSReturn result
= kOSMetaClassNoKModSet
;
7869 if (!metaClasses
->containsObject(aClass
)) {
7871 kOSKextLogWarningLevel
|
7873 "Notice - kext %s asked to unregister unknown class %s.",
7874 getIdentifierCString(),
7875 aClass
->getClassName());
7876 result
= kOSReturnSuccess
;
7881 kOSKextLogDetailLevel
|
7883 "Kext %s unregistering class %s.",
7884 getIdentifierCString(),
7885 aClass
->getClassName());
7887 metaClasses
->removeObject(aClass
);
7889 notifyRemoveClassObservers(this, aClass
, flags
);
7891 result
= kOSReturnSuccess
;
7894 if (result
!= kOSReturnSuccess
) {
7896 kOSKextLogErrorLevel
|
7898 "Failed to unregister kext %s class %s.",
7899 getIdentifierCString(),
7900 aClass
->getClassName());
7905 /*********************************************************************
7906 *********************************************************************/
7908 OSKext::getMetaClasses(void)
7913 /*********************************************************************
7914 *********************************************************************/
7916 OSKext::hasOSMetaClassInstances(void)
7918 bool result
= false;
7919 OSCollectionIterator
* classIterator
= NULL
; // must release
7920 OSMetaClass
* checkClass
= NULL
;// do not release
7926 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7927 if (!classIterator
) {
7928 // xxx - log alloc failure?
7931 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7932 if (checkClass
->getInstanceCount()) {
7940 OSSafeReleaseNULL(classIterator
);
7944 /*********************************************************************
7945 *********************************************************************/
7948 OSKext::reportOSMetaClassInstances(
7949 const char * kextIdentifier
,
7950 OSKextLogSpec msgLogSpec
)
7952 OSKext
* theKext
= NULL
; // must release
7954 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
7959 theKext
->reportOSMetaClassInstances(msgLogSpec
);
7961 OSSafeReleaseNULL(theKext
);
7965 /*********************************************************************
7966 *********************************************************************/
7968 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
7970 OSCollectionIterator
* classIterator
= NULL
; // must release
7971 OSMetaClass
* checkClass
= NULL
;// do not release
7977 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7978 if (!classIterator
) {
7981 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7982 if (checkClass
->getInstanceCount()) {
7985 " Kext %s class %s has %d instance%s.",
7986 getIdentifierCString(),
7987 checkClass
->getClassName(),
7988 checkClass
->getInstanceCount(),
7989 checkClass
->getInstanceCount() == 1 ? "" : "s");
7994 OSSafeReleaseNULL(classIterator
);
7999 #pragma mark User-Space Requests
8001 /*********************************************************************
8002 * XXX - this function is a big ugly mess
8003 *********************************************************************/
8006 OSKext::handleRequest(
8007 host_priv_t hostPriv
,
8008 OSKextLogSpec clientLogFilter
,
8009 char * requestBuffer
,
8010 uint32_t requestLength
,
8011 char ** responseOut
,
8012 uint32_t * responseLengthOut
,
8014 uint32_t * logInfoLengthOut
)
8016 OSReturn result
= kOSReturnError
;
8017 kern_return_t kmem_result
= KERN_FAILURE
;
8019 char * response
= NULL
;// returned by reference
8020 uint32_t responseLength
= 0;
8022 OSObject
* parsedXML
= NULL
;// must release
8023 OSDictionary
* requestDict
= NULL
;// do not release
8024 OSString
* errorString
= NULL
;// must release
8026 OSObject
* responseObject
= NULL
;// must release
8028 OSSerialize
* serializer
= NULL
;// must release
8030 OSArray
* logInfoArray
= NULL
;// must release
8032 OSString
* predicate
= NULL
;// do not release
8033 OSString
* kextIdentifier
= NULL
;// do not release
8034 OSArray
* kextIdentifiers
= NULL
;// do not release
8035 OSKext
* theKext
= NULL
;// do not release
8036 OSBoolean
* boolArg
= NULL
;// do not release
8038 IORecursiveLockLock(sKextLock
);
8041 *responseOut
= NULL
;
8042 *responseLengthOut
= 0;
8046 *logInfoLengthOut
= 0;
8049 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
8051 /* XML must be nul-terminated.
8053 if (requestBuffer
[requestLength
- 1] != '\0') {
8054 OSKextLog(/* kext */ NULL
,
8055 kOSKextLogErrorLevel
|
8057 "Invalid request from user space (not nul-terminated).");
8058 result
= kOSKextReturnBadData
;
8061 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
8063 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
8066 const char * errorCString
= "(unknown error)";
8068 if (errorString
&& errorString
->getCStringNoCopy()) {
8069 errorCString
= errorString
->getCStringNoCopy();
8070 } else if (parsedXML
) {
8071 errorCString
= "not a dictionary";
8073 OSKextLog(/* kext */ NULL
,
8074 kOSKextLogErrorLevel
|
8076 "Error unserializing request from user space: %s.",
8078 result
= kOSKextReturnSerialization
;
8082 predicate
= _OSKextGetRequestPredicate(requestDict
);
8084 OSKextLog(/* kext */ NULL
,
8085 kOSKextLogErrorLevel
|
8087 "Recieved kext request from user space with no predicate.");
8088 result
= kOSKextReturnInvalidArgument
;
8092 OSKextLog(/* kext */ NULL
,
8093 kOSKextLogDebugLevel
|
8095 "Received '%s' request from user space.",
8096 predicate
->getCStringNoCopy());
8098 result
= kOSKextReturnNotPrivileged
;
8099 if (hostPriv
== HOST_PRIV_NULL
) {
8100 /* must be root to use these kext requests */
8101 if (predicate
->isEqualTo(kKextRequestPredicateUnload
) ||
8102 predicate
->isEqualTo(kKextRequestPredicateStart
) ||
8103 predicate
->isEqualTo(kKextRequestPredicateStop
) ||
8104 predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
) ||
8105 predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
8106 OSKextLog(/* kext */ NULL
,
8107 kOSKextLogErrorLevel
|
8109 "Access Failure - must be root user.");
8114 /* Get common args in anticipation of use.
8116 kextIdentifier
= OSDynamicCast(OSString
, _OSKextGetRequestArgument(
8117 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
8118 kextIdentifiers
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument(
8119 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
8120 if (kextIdentifier
) {
8121 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
8123 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
8124 requestDict
, kKextRequestArgumentValueKey
));
8126 result
= kOSKextReturnInvalidArgument
;
8128 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
8129 if (!kextIdentifier
) {
8130 OSKextLog(/* kext */ NULL
,
8131 kOSKextLogErrorLevel
|
8133 "Invalid arguments to kext start request.");
8134 } else if (!theKext
) {
8135 OSKextLog(/* kext */ NULL
,
8136 kOSKextLogErrorLevel
|
8138 "Kext %s not found for start request.",
8139 kextIdentifier
->getCStringNoCopy());
8140 result
= kOSKextReturnNotFound
;
8142 result
= theKext
->start();
8144 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
8145 if (!kextIdentifier
) {
8146 OSKextLog(/* kext */ NULL
,
8147 kOSKextLogErrorLevel
|
8149 "Invalid arguments to kext stop request.");
8150 } else if (!theKext
) {
8151 OSKextLog(/* kext */ NULL
,
8152 kOSKextLogErrorLevel
|
8154 "Kext %s not found for stop request.",
8155 kextIdentifier
->getCStringNoCopy());
8156 result
= kOSKextReturnNotFound
;
8158 result
= theKext
->stop();
8160 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
8161 if (!kextIdentifier
) {
8162 OSKextLog(/* kext */ NULL
,
8163 kOSKextLogErrorLevel
|
8165 "Invalid arguments to kext unload request.");
8166 } else if (!theKext
) {
8167 OSKextLog(/* kext */ NULL
,
8168 kOSKextLogErrorLevel
|
8170 "Kext %s not found for unload request.",
8171 kextIdentifier
->getCStringNoCopy());
8172 result
= kOSKextReturnNotFound
;
8174 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
8175 _OSKextGetRequestArgument(requestDict
,
8176 kKextRequestArgumentTerminateIOServicesKey
));
8177 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
8179 } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
8180 result
= OSKext::dispatchResource(requestDict
);
8181 } else if (predicate
->isEqualTo(kKextRequestPredicateGetUUIDByAddress
)) {
8182 OSNumber
*lookupNum
= NULL
;
8183 lookupNum
= OSDynamicCast(OSNumber
,
8184 _OSKextGetRequestArgument(requestDict
,
8185 kKextRequestArgumentLookupAddressKey
));
8187 responseObject
= OSKext::copyKextUUIDForAddress(lookupNum
);
8188 if (responseObject
) {
8189 result
= kOSReturnSuccess
;
8193 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
) ||
8194 predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
8195 OSBoolean
* delayAutounloadBool
= NULL
;
8196 OSObject
* infoKeysRaw
= NULL
;
8197 OSArray
* infoKeys
= NULL
;
8198 uint32_t infoKeysCount
= 0;
8200 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
8201 _OSKextGetRequestArgument(requestDict
,
8202 kKextRequestArgumentDelayAutounloadKey
));
8204 /* If asked to delay autounload, reset the timer if it's currently set.
8205 * (That is, don't schedule an unload if one isn't already pending.
8207 if (delayAutounloadBool
== kOSBooleanTrue
) {
8208 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8211 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
8212 kKextRequestArgumentInfoKeysKey
);
8213 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
8214 if (infoKeysRaw
&& !infoKeys
) {
8215 OSKextLog(/* kext */ NULL
,
8216 kOSKextLogErrorLevel
|
8218 "Invalid arguments to kext info request.");
8223 infoKeysCount
= infoKeys
->getCount();
8224 for (uint32_t i
= 0; i
< infoKeysCount
; i
++) {
8225 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) {
8226 OSKextLog(/* kext */ NULL
,
8227 kOSKextLogErrorLevel
|
8229 "Invalid arguments to kext info request.");
8235 if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
8236 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
8237 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
8238 responseObject
= OSKext::copyLoadedKextInfoByUUID(kextIdentifiers
, infoKeys
);
8240 if (!responseObject
) {
8241 result
= kOSKextReturnInternalError
;
8243 OSKextLog(/* kext */ NULL
,
8244 kOSKextLogDebugLevel
|
8246 "Returning loaded kext info.");
8247 result
= kOSReturnSuccess
;
8249 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) {
8250 /* Hand the current sKernelRequests array to the caller
8251 * (who must release it), and make a new one.
8253 responseObject
= sKernelRequests
;
8254 sKernelRequests
= OSArray::withCapacity(0);
8255 sPostedKextLoadIdentifiers
->flushCollection();
8256 OSKextLog(/* kext */ NULL
,
8257 kOSKextLogDebugLevel
|
8259 "Returning kernel requests.");
8260 result
= kOSReturnSuccess
;
8261 } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) {
8262 /* Return the set of all requested bundle identifiers */
8263 responseObject
= sAllKextLoadIdentifiers
;
8264 responseObject
->retain();
8265 OSKextLog(/* kext */ NULL
,
8266 kOSKextLogDebugLevel
|
8268 "Returning load requests.");
8269 result
= kOSReturnSuccess
;
8271 OSKextLog(/* kext */ NULL
,
8272 kOSKextLogDebugLevel
|
8274 "Received '%s' invalid request from user space.",
8275 predicate
->getCStringNoCopy());
8280 * Now we have handle the request, or not. Gather up the response & logging
8281 * info to ship to user space.
8284 /* Note: Nothing in OSKext is supposed to retain requestDict,
8285 * but you never know....
8287 if (requestDict
->getRetainCount() > 1) {
8288 OSKextLog(/* kext */ NULL
,
8289 kOSKextLogWarningLevel
|
8291 "Request from user space still retained by a kext; "
8292 "probable memory leak.");
8295 if (responseOut
&& responseObject
) {
8296 serializer
= OSSerialize::withCapacity(0);
8298 result
= kOSKextReturnNoMemory
;
8302 if (!responseObject
->serialize(serializer
)) {
8303 OSKextLog(/* kext */ NULL
,
8304 kOSKextLogGeneralFlag
| kOSKextLogErrorLevel
,
8305 "Failed to serialize response to request from user space.");
8306 result
= kOSKextReturnSerialization
;
8310 response
= (char *)serializer
->text();
8311 responseLength
= serializer
->getLength();
8314 if (responseOut
&& response
) {
8317 /* This kmem_alloc sets the return value of the function.
8319 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
,
8320 round_page(responseLength
), VM_KERN_MEMORY_OSKEXT
);
8321 if (kmem_result
!= KERN_SUCCESS
) {
8322 OSKextLog(/* kext */ NULL
,
8323 kOSKextLogErrorLevel
|
8325 "Failed to copy response to request from user space.");
8326 result
= kmem_result
;
8329 /* 11981737 - clear uninitialized data in last page */
8330 bzero((void *)(buffer
+ responseLength
),
8331 (round_page(responseLength
) - responseLength
));
8332 memcpy(buffer
, response
, responseLength
);
8333 *responseOut
= buffer
;
8334 *responseLengthOut
= responseLength
;
8340 /* Gather up the collected log messages for user space. Any messages
8341 * messages past this call will not make it up as log messages but
8342 * will be in the system log. Note that we ignore the return of the
8343 * serialize; it has no bearing on the operation at hand even if we
8344 * fail to get the log messages.
8346 logInfoArray
= OSKext::clearUserSpaceLogFilter();
8348 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
8349 (void)OSKext::serializeLogInfo(logInfoArray
,
8350 logInfoOut
, logInfoLengthOut
);
8353 IORecursiveLockUnlock(sKextLock
);
8355 OSSafeReleaseNULL(parsedXML
);
8356 OSSafeReleaseNULL(errorString
);
8357 OSSafeReleaseNULL(responseObject
);
8358 OSSafeReleaseNULL(serializer
);
8359 OSSafeReleaseNULL(logInfoArray
);
8365 // #include <InstrProfiling.h>
8367 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin
,
8368 const char *DataEnd
,
8369 const char *CountersBegin
,
8370 const char *CountersEnd
,
8371 const char *NamesBegin
,
8372 const char *NamesEnd
);
8373 int __llvm_profile_write_buffer_internal(char *Buffer
,
8374 const char *DataBegin
,
8375 const char *DataEnd
,
8376 const char *CountersBegin
,
8377 const char *CountersEnd
,
8378 const char *NamesBegin
,
8379 const char *NamesEnd
);
8385 OSKextPgoMetadataPut(char *pBuffer
,
8388 uint32_t *num_pairs
,
8392 size_t strlen_key
= strlen(key
);
8393 size_t strlen_value
= strlen(value
);
8394 size_t len
= strlen(key
) + 1 + strlen(value
) + 1;
8395 char *pos
= pBuffer
+ *position
;
8397 if (pBuffer
&& bufferSize
&& *position
<= bufferSize
) {
8398 memcpy(pos
, key
, strlen_key
); pos
+= strlen_key
;
8400 memcpy(pos
, value
, strlen_value
); pos
+= strlen_value
;
8411 OSKextPgoMetadataPutMax(size_t *position
, const char *key
, size_t value_max
)
8413 *position
+= strlen(key
) + 1 + value_max
+ 1;
8419 OSKextPgoMetadataPutAll(OSKext
*kext
,
8420 uuid_t instance_uuid
,
8424 uint32_t *num_pairs
)
8426 _static_assert_1_arg(sizeof(clock_sec_t
) % 2 == 0);
8427 //log_10 2^16 ≈ 4.82
8428 const size_t max_secs_string_size
= 5 * sizeof(clock_sec_t
) / 2;
8429 const size_t max_timestamp_string_size
= max_secs_string_size
+ 1 + 6;
8432 OSKextPgoMetadataPutMax(position
, "INSTANCE", 36);
8433 OSKextPgoMetadataPutMax(position
, "UUID", 36);
8434 OSKextPgoMetadataPutMax(position
, "TIMESTAMP", max_timestamp_string_size
);
8436 uuid_string_t instance_uuid_string
;
8437 uuid_unparse(instance_uuid
, instance_uuid_string
);
8438 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8439 "INSTANCE", instance_uuid_string
);
8443 uuid_string_t uuid_string
;
8444 uuid_data
= kext
->copyUUID();
8446 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
8447 OSSafeReleaseNULL(uuid_data
);
8448 uuid_unparse(uuid
, uuid_string
);
8449 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8450 "UUID", uuid_string
);
8455 clock_get_calendar_microtime(&secs
, &usecs
);
8456 assert(usecs
< 1000000);
8457 char timestamp
[max_timestamp_string_size
+ 1];
8458 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t
));
8459 snprintf(timestamp
, sizeof(timestamp
), "%lu.%06d", (unsigned long)secs
, (int)usecs
);
8460 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8461 "TIMESTAMP", timestamp
);
8464 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8465 "NAME", kext
->getIdentifierCString());
8467 char versionCString
[kOSKextVersionMaxLength
];
8468 OSKextVersionGetString(kext
->getVersion(), versionCString
, kOSKextVersionMaxLength
);
8469 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8470 "VERSION", versionCString
);
8475 OSKextPgoMetadataSize(OSKext
*kext
)
8477 size_t position
= 0;
8478 uuid_t fakeuuid
= {};
8479 OSKextPgoMetadataPutAll(kext
, fakeuuid
, NULL
, &position
, 0, NULL
);
8484 OSKextGrabPgoDataLocked(OSKext
*kext
,
8486 uuid_t instance_uuid
,
8489 uint64_t bufferSize
)
8493 kernel_section_t
*sect_prf_data
= NULL
;
8494 kernel_section_t
*sect_prf_name
= NULL
;
8495 kernel_section_t
*sect_prf_cnts
= NULL
;
8497 size_t metadata_size
= 0;
8499 sect_prf_data
= kext
->lookupSection("__DATA", "__llvm_prf_data");
8500 sect_prf_name
= kext
->lookupSection("__DATA", "__llvm_prf_name");
8501 sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8503 if (!sect_prf_data
|| !sect_prf_name
|| !sect_prf_cnts
) {
8508 size
= __llvm_profile_get_size_for_buffer_internal(
8509 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8510 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8511 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8514 metadata_size
= OSKextPgoMetadataSize(kext
);
8515 size
+= metadata_size
;
8516 size
+= sizeof(pgo_metadata_footer
);
8524 if (pBuffer
&& bufferSize
) {
8525 if (bufferSize
< size
) {
8530 err
= __llvm_profile_write_buffer_internal(
8532 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8533 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8534 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8542 char *end_of_buffer
= pBuffer
+ size
;
8543 struct pgo_metadata_footer
*footerp
= (struct pgo_metadata_footer
*) (end_of_buffer
- sizeof(struct pgo_metadata_footer
));
8544 char *metadata_buffer
= end_of_buffer
- (sizeof(struct pgo_metadata_footer
) + metadata_size
);
8546 size_t metadata_position
= 0;
8547 uint32_t num_pairs
= 0;
8548 OSKextPgoMetadataPutAll(kext
, instance_uuid
, metadata_buffer
, &metadata_position
, metadata_size
, &num_pairs
);
8549 while (metadata_position
< metadata_size
) {
8550 metadata_buffer
[metadata_position
++] = 0;
8553 struct pgo_metadata_footer footer
;
8554 footer
.magic
= htonl(0x6d657461);
8555 footer
.number_of_pairs
= htonl( num_pairs
);
8556 footer
.offset_to_pairs
= htonl( sizeof(struct pgo_metadata_footer
) + metadata_size
);
8557 memcpy(footerp
, &footer
, sizeof(footer
));
8567 OSKextGrabPgoData(uuid_t uuid
,
8570 uint64_t bufferSize
,
8571 int wait_for_unload
,
8575 OSKext
*kext
= NULL
;
8578 IORecursiveLockLock(sKextLock
);
8580 kext
= OSKext::lookupKextWithUUID(uuid
);
8586 if (wait_for_unload
) {
8587 OSKextGrabPgoStruct s
;
8589 s
.metadata
= metadata
;
8591 s
.pBuffer
= pBuffer
;
8592 s
.bufferSize
= bufferSize
;
8595 struct list_head
*prev
= &kext
->pendingPgoHead
;
8596 struct list_head
*next
= kext
->pendingPgoHead
.next
;
8598 s
.list_head
.prev
= prev
;
8599 s
.list_head
.next
= next
;
8601 prev
->next
= &s
.list_head
;
8602 next
->prev
= &s
.list_head
;
8607 IORecursiveLockSleep(sKextLock
, &s
, THREAD_ABORTSAFE
);
8609 prev
= s
.list_head
.prev
;
8610 next
= s
.list_head
.next
;
8617 err
= OSKextGrabPgoDataLocked(kext
, metadata
, kext
->instance_uuid
, pSize
, pBuffer
, bufferSize
);
8625 IORecursiveLockUnlock(sKextLock
);
8631 OSKextResetPgoCountersLock()
8633 IORecursiveLockLock(sKextLock
);
8637 OSKextResetPgoCountersUnlock()
8639 IORecursiveLockUnlock(sKextLock
);
8643 extern unsigned int not_in_kdp
;
8646 OSKextResetPgoCounters()
8648 assert(!not_in_kdp
);
8649 uint32_t count
= sLoadedKexts
->getCount();
8650 for (uint32_t i
= 0; i
< count
; i
++) {
8651 OSKext
*kext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8652 kernel_section_t
*sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8653 if (!sect_prf_cnts
) {
8656 memset((void*)sect_prf_cnts
->addr
, 0, sect_prf_cnts
->size
);
8661 OSKext::copyLoadedKextInfoByUUID(
8662 OSArray
* kextIdentifiers
,
8665 OSDictionary
* result
= NULL
;
8666 OSDictionary
* kextInfo
= NULL
; // must release
8668 uint32_t idCount
= 0;
8669 uint32_t idIndex
= 0;
8671 IORecursiveLockLock(sKextLock
);
8674 /* Is the calling process allowed to query kext info? */
8675 if (current_task() != kernel_task
) {
8676 int macCheckResult
= 0;
8677 kauth_cred_t cred
= NULL
;
8679 cred
= kauth_cred_get_with_ref();
8680 macCheckResult
= mac_kext_check_query(cred
);
8681 kauth_cred_unref(&cred
);
8683 if (macCheckResult
!= 0) {
8684 OSKextLog(/* kext */ NULL
,
8685 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8686 "Failed to query kext info (MAC policy error 0x%x).",
8693 /* Empty list of UUIDs is equivalent to no list (get all).
8695 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8696 kextIdentifiers
= NULL
;
8697 } else if (kextIdentifiers
) {
8698 idCount
= kextIdentifiers
->getCount();
8703 if (infoKeys
&& !infoKeys
->getCount()) {
8707 count
= sLoadedKexts
->getCount();
8708 result
= OSDictionary::withCapacity(count
);
8713 for (i
= 0; i
< count
; i
++) {
8714 OSKext
*thisKext
= NULL
;// do not release
8715 Boolean includeThis
= true;
8716 uuid_t thisKextUUID
;
8717 uuid_t thisKextTextUUID
;
8719 uuid_string_t uuid_key
;
8721 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8726 uuid_data
= thisKext
->copyUUID();
8731 memcpy(&thisKextUUID
, uuid_data
->getBytesNoCopy(), sizeof(thisKextUUID
));
8732 OSSafeReleaseNULL(uuid_data
);
8734 uuid_unparse(thisKextUUID
, uuid_key
);
8736 uuid_data
= thisKext
->copyTextUUID();
8740 memcpy(&thisKextTextUUID
, uuid_data
->getBytesNoCopy(), sizeof(thisKextTextUUID
));
8741 OSSafeReleaseNULL(uuid_data
);
8743 /* Skip current kext if we have a list of UUIDs and
8744 * it isn't in the list.
8746 if (kextIdentifiers
) {
8747 includeThis
= false;
8749 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8750 const OSString
* wantedUUID
= OSDynamicCast(OSString
,
8751 kextIdentifiers
->getObject(idIndex
));
8754 uuid_parse(wantedUUID
->getCStringNoCopy(), uuid
);
8756 if ((0 == uuid_compare(uuid
, thisKextUUID
))
8757 || (0 == uuid_compare(uuid
, thisKextTextUUID
))) {
8759 /* Only need to find the first kext if multiple match,
8760 * ie. asking for the kernel uuid does not need to find
8761 * interface kexts or builtin static kexts.
8763 kextIdentifiers
->removeObject(idIndex
);
8764 uuid_unparse(uuid
, uuid_key
);
8774 kextInfo
= thisKext
->copyInfo(infoKeys
);
8776 result
->setObject(uuid_key
, kextInfo
);
8777 kextInfo
->release();
8780 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8786 IORecursiveLockUnlock(sKextLock
);
8791 /*********************************************************************
8792 *********************************************************************/
8795 OSKext::copyLoadedKextInfo(
8796 OSArray
* kextIdentifiers
,
8799 OSDictionary
* result
= NULL
;
8800 uint32_t idCount
= 0;
8803 IORecursiveLockLock(sKextLock
);
8806 /* Is the calling process allowed to query kext info? */
8807 if (current_task() != kernel_task
) {
8808 int macCheckResult
= 0;
8809 kauth_cred_t cred
= NULL
;
8811 cred
= kauth_cred_get_with_ref();
8812 macCheckResult
= mac_kext_check_query(cred
);
8813 kauth_cred_unref(&cred
);
8815 if (macCheckResult
!= 0) {
8816 OSKextLog(/* kext */ NULL
,
8817 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8818 "Failed to query kext info (MAC policy error 0x%x).",
8825 /* Empty list of bundle ids is equivalent to no list (get all).
8827 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8828 kextIdentifiers
= NULL
;
8829 } else if (kextIdentifiers
) {
8830 idCount
= kextIdentifiers
->getCount();
8835 if (infoKeys
&& !infoKeys
->getCount()) {
8839 onlyLoaded
= (!infoKeys
|| !_OSArrayContainsCString(infoKeys
, kOSBundleAllPrelinkedKey
));
8841 result
= OSDictionary::withCapacity(128);
8847 OSKextLog(/* kext */ NULL
,
8848 kOSKextLogErrorLevel
|
8849 kOSKextLogGeneralFlag
,
8850 "kaslr: vm_kernel_slide 0x%lx \n",
8852 OSKextLog(/* kext */ NULL
,
8853 kOSKextLogErrorLevel
|
8854 kOSKextLogGeneralFlag
,
8855 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
8856 vm_kernel_stext
, vm_kernel_etext
);
8857 OSKextLog(/* kext */ NULL
,
8858 kOSKextLogErrorLevel
|
8859 kOSKextLogGeneralFlag
,
8860 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
8861 vm_kernel_base
, vm_kernel_top
);
8862 OSKextLog(/* kext */ NULL
,
8863 kOSKextLogErrorLevel
|
8864 kOSKextLogGeneralFlag
,
8865 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
8866 vm_kext_base
, vm_kext_top
);
8867 OSKextLog(/* kext */ NULL
,
8868 kOSKextLogErrorLevel
|
8869 kOSKextLogGeneralFlag
,
8870 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
8871 vm_prelink_stext
, vm_prelink_etext
);
8872 OSKextLog(/* kext */ NULL
,
8873 kOSKextLogErrorLevel
|
8874 kOSKextLogGeneralFlag
,
8875 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
8876 vm_prelink_sinfo
, vm_prelink_einfo
);
8877 OSKextLog(/* kext */ NULL
,
8878 kOSKextLogErrorLevel
|
8879 kOSKextLogGeneralFlag
,
8880 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
8881 vm_slinkedit
, vm_elinkedit
);
8884 sKextsByID
->iterateObjects(^bool (const OSSymbol
* thisKextID
, OSObject
* obj
)
8886 OSKext
* thisKext
= NULL
;// do not release
8887 Boolean includeThis
= true;
8888 OSDictionary
* kextInfo
= NULL
;// must release
8890 thisKext
= OSDynamicCast(OSKext
, obj
);
8895 /* Skip current kext if not yet started and caller didn't request all.
8897 if (onlyLoaded
&& (-1U == sLoadedKexts
->getNextIndexOfObject(thisKext
, 0))) {
8901 /* Skip current kext if we have a list of bundle IDs and
8902 * it isn't in the list.
8904 if (kextIdentifiers
) {
8905 includeThis
= false;
8907 for (uint32_t idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8908 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
8909 kextIdentifiers
->getObject(idIndex
));
8910 if (thisKextID
->isEqualTo(thisRequestID
)) {
8921 kextInfo
= thisKext
->copyInfo(infoKeys
);
8923 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
8924 kextInfo
->release();
8930 IORecursiveLockUnlock(sKextLock
);
8935 /*********************************************************************
8936 * Any info that needs to do allocations must goto finish on alloc
8937 * failure. Info that is just a lookup should just not set the object
8938 * if the info does not exist.
8939 *********************************************************************/
8940 #define _OSKextLoadInfoDictCapacity (12)
8943 OSKext::copyInfo(OSArray
* infoKeys
)
8945 OSDictionary
* result
= NULL
;
8946 bool success
= false;
8947 OSData
* headerData
= NULL
;// must release
8948 OSData
* logData
= NULL
;// must release
8949 OSNumber
* cpuTypeNumber
= NULL
;// must release
8950 OSNumber
* cpuSubtypeNumber
= NULL
;// must release
8951 OSString
* versionString
= NULL
;// do not release
8952 uint32_t executablePathCStringSize
= 0;
8953 char * executablePathCString
= NULL
;// must release
8954 OSString
* executablePathString
= NULL
;// must release
8955 OSData
* uuid
= NULL
;// must release
8956 OSNumber
* scratchNumber
= NULL
;// must release
8957 OSArray
* dependencyLoadTags
= NULL
;// must release
8958 OSCollectionIterator
* metaClassIterator
= NULL
;// must release
8959 OSArray
* metaClassInfo
= NULL
;// must release
8960 OSDictionary
* metaClassDict
= NULL
;// must release
8961 OSMetaClass
* thisMetaClass
= NULL
;// do not release
8962 OSString
* metaClassName
= NULL
;// must release
8963 OSString
* superclassName
= NULL
;// must release
8966 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
8972 /* Empty keys means no keys, but NULL is quicker to check.
8974 if (infoKeys
&& !infoKeys
->getCount()) {
8978 /* Headers, CPU type, and CPU subtype.
8981 _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) ||
8982 _OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
) ||
8983 _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) ||
8984 _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
8985 if (linkedExecutable
&& !isInterface()) {
8986 kernel_mach_header_t
*kext_mach_hdr
= (kernel_mach_header_t
*)
8987 linkedExecutable
->getBytesNoCopy();
8990 // do not return macho header info on shipping iOS - 19095897
8991 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) {
8992 kernel_mach_header_t
* temp_kext_mach_hdr
;
8993 struct load_command
* lcp
;
8995 headerData
= OSData::withBytes(kext_mach_hdr
,
8996 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
9001 // unslide any vmaddrs we return to userspace - 10726716
9002 temp_kext_mach_hdr
= (kernel_mach_header_t
*)
9003 headerData
->getBytesNoCopy();
9004 if (temp_kext_mach_hdr
== NULL
) {
9008 lcp
= (struct load_command
*) (temp_kext_mach_hdr
+ 1);
9009 for (i
= 0; i
< temp_kext_mach_hdr
->ncmds
; i
++) {
9010 if (lcp
->cmd
== LC_SEGMENT_KERNEL
) {
9011 kernel_segment_command_t
* segp
;
9012 kernel_section_t
* secp
;
9014 segp
= (kernel_segment_command_t
*) lcp
;
9015 // 10543468 - if we jettisoned __LINKEDIT clear size info
9016 if (flags
.jettisonLinkeditSeg
) {
9017 if (strncmp(segp
->segname
, SEG_LINKEDIT
, sizeof(segp
->segname
)) == 0) {
9025 OSKextLog(/* kext */ NULL
,
9026 kOSKextLogErrorLevel
|
9027 kOSKextLogGeneralFlag
,
9028 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
9029 __FUNCTION__
, segp
->segname
, segp
->vmaddr
,
9030 VM_KERNEL_UNSLIDE(segp
->vmaddr
),
9031 segp
->vmsize
, segp
->nsects
);
9032 if ((VM_KERNEL_IS_SLID(segp
->vmaddr
) == false) &&
9033 (VM_KERNEL_IS_KEXT(segp
->vmaddr
) == false) &&
9034 (VM_KERNEL_IS_PRELINKTEXT(segp
->vmaddr
) == false) &&
9035 (VM_KERNEL_IS_PRELINKINFO(segp
->vmaddr
) == false) &&
9036 (VM_KERNEL_IS_KEXT_LINKEDIT(segp
->vmaddr
) == false)) {
9037 OSKextLog(/* kext */ NULL
,
9038 kOSKextLogErrorLevel
|
9039 kOSKextLogGeneralFlag
,
9040 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
9041 __FUNCTION__
, segp
->vmaddr
, vm_kext_base
, vm_kext_top
);
9044 segp
->vmaddr
= ml_static_unslide(segp
->vmaddr
);
9046 for (secp
= firstsect(segp
); secp
!= NULL
; secp
= nextsect(segp
, secp
)) {
9047 secp
->addr
= ml_static_unslide(secp
->addr
);
9050 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
9052 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
9054 #endif // SECURE_KERNEL
9056 if (_OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
)) {
9057 osLogDataHeaderRef
*header
;
9058 char headerBytes
[offsetof(osLogDataHeaderRef
, sections
) + NUM_OS_LOG_SECTIONS
* sizeof(header
->sections
[0])];
9060 void *os_log_data
= NULL
;
9061 void *cstring_data
= NULL
;
9062 unsigned long os_log_size
= 0;
9063 unsigned long cstring_size
= 0;
9064 uint32_t os_log_offset
= 0;
9065 uint32_t cstring_offset
= 0;
9068 os_log_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__os_log", &os_log_size
);
9069 os_log_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__os_log");
9070 cstring_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__cstring", &cstring_size
);
9071 cstring_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__cstring");
9073 header
= (osLogDataHeaderRef
*) headerBytes
;
9074 header
->version
= OS_LOG_HDR_VERSION
;
9075 header
->sect_count
= NUM_OS_LOG_SECTIONS
;
9076 header
->sections
[OS_LOG_SECT_IDX
].sect_offset
= os_log_offset
;
9077 header
->sections
[OS_LOG_SECT_IDX
].sect_size
= (uint32_t) os_log_size
;
9078 header
->sections
[CSTRING_SECT_IDX
].sect_offset
= cstring_offset
;
9079 header
->sections
[CSTRING_SECT_IDX
].sect_size
= (uint32_t) cstring_size
;
9082 logData
= OSData::withBytes(header
, (u_int
) (sizeof(osLogDataHeaderRef
)));
9086 res
= logData
->appendBytes(&(header
->sections
[0]), (u_int
)(header
->sect_count
* sizeof(header
->sections
[0])));
9091 res
= logData
->appendBytes(os_log_data
, (u_int
)header
->sections
[OS_LOG_SECT_IDX
].sect_size
);
9097 res
= logData
->appendBytes(cstring_data
, (u_int
)header
->sections
[CSTRING_SECT_IDX
].sect_size
);
9102 result
->setObject(kOSBundleLogStringsKey
, logData
);
9105 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) {
9106 cpuTypeNumber
= OSNumber::withNumber(
9107 (uint64_t) kext_mach_hdr
->cputype
,
9108 8 * sizeof(kext_mach_hdr
->cputype
));
9109 if (!cpuTypeNumber
) {
9112 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
9115 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
9116 cpuSubtypeNumber
= OSNumber::withNumber(
9117 (uint64_t) kext_mach_hdr
->cpusubtype
,
9118 8 * sizeof(kext_mach_hdr
->cpusubtype
));
9119 if (!cpuSubtypeNumber
) {
9122 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
9127 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
9129 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
9133 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
9134 versionString
= OSDynamicCast(OSString
,
9135 getPropertyForHostArch(kCFBundleVersionKey
));
9136 if (versionString
) {
9137 result
->setObject(kCFBundleVersionKey
, versionString
);
9141 /* OSBundleCompatibleVersion.
9143 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
9144 versionString
= OSDynamicCast(OSString
,
9145 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
9146 if (versionString
) {
9147 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
9153 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
9155 result
->setObject(kOSBundlePathKey
, path
);
9160 /* OSBundleExecutablePath.
9162 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
9163 if (path
&& executableRelPath
) {
9164 uint32_t pathLength
= path
->getLength(); // gets incremented below
9166 // +1 for slash, +1 for \0
9167 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
9169 executablePathCString
= (char *)kalloc_tag((executablePathCStringSize
) *
9170 sizeof(char), VM_KERN_MEMORY_OSKEXT
); // +1 for \0
9171 if (!executablePathCString
) {
9174 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
9175 executablePathCStringSize
);
9176 executablePathCString
[pathLength
++] = '/';
9177 executablePathCString
[pathLength
++] = '\0';
9178 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
9179 executablePathCStringSize
);
9181 executablePathString
= OSString::withCString(executablePathCString
);
9183 if (!executablePathString
) {
9187 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
9188 } else if (flags
.builtin
) {
9189 result
->setObject(kOSBundleExecutablePathKey
, bundleID
);
9193 /* UUID, if the kext has one.
9195 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
9198 result
->setObject(kOSBundleUUIDKey
, uuid
);
9202 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleTextUUIDKey
)) {
9203 uuid
= copyTextUUID();
9205 result
->setObject(kOSBundleTextUUIDKey
, uuid
); uuid
->release();
9210 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
9212 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSKernelResourceKey
)) {
9213 result
->setObject(kOSKernelResourceKey
,
9214 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
9217 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
9218 result
->setObject(kOSBundleIsInterfaceKey
,
9219 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
9222 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
9223 result
->setObject(kOSBundlePrelinkedKey
,
9224 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
9227 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
9228 result
->setObject(kOSBundleStartedKey
,
9229 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
9234 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
9235 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
9236 /* numBits */ 8 * sizeof(loadTag
));
9237 if (!scratchNumber
) {
9240 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
9241 OSSafeReleaseNULL(scratchNumber
);
9244 /* LoadAddress, LoadSize.
9247 _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) ||
9248 _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) ||
9249 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
) ||
9250 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
) ||
9251 _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
9252 if (isInterface() || flags
.builtin
|| linkedExecutable
) {
9253 /* These go to userspace via serialization, so we don't want any doubts
9256 uint64_t loadAddress
= 0;
9257 uint32_t loadSize
= 0;
9258 uint32_t wiredSize
= 0;
9259 uint64_t execLoadAddress
= 0;
9260 uint32_t execLoadSize
= 0;
9262 /* Interfaces always report 0 load address & size.
9263 * Just the way they roll.
9265 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
9266 * xxx - shouldn't have one!
9269 if (flags
.builtin
|| linkedExecutable
) {
9270 kernel_mach_header_t
*mh
= NULL
;
9271 kernel_segment_command_t
*seg
= NULL
;
9273 if (flags
.builtin
) {
9274 loadAddress
= kmod_info
->address
;
9275 loadSize
= kmod_info
->size
;
9277 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
9278 loadSize
= linkedExecutable
->getLength();
9280 mh
= (kernel_mach_header_t
*)loadAddress
;
9281 loadAddress
= ml_static_unslide(loadAddress
);
9283 /* Walk through the kext, looking for the first executable
9284 * segment in case we were asked for its size/address.
9286 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
9287 if (seg
->initprot
& VM_PROT_EXECUTE
) {
9288 execLoadAddress
= ml_static_unslide(seg
->vmaddr
);
9289 execLoadSize
= seg
->vmsize
;
9294 /* If we have a kmod_info struct, calculated the wired size
9295 * from that. Otherwise it's the full load size.
9298 wiredSize
= loadSize
- kmod_info
->hdr_size
;
9300 wiredSize
= loadSize
;
9304 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
9305 scratchNumber
= OSNumber::withNumber(
9306 (unsigned long long)(loadAddress
),
9307 /* numBits */ 8 * sizeof(loadAddress
));
9308 if (!scratchNumber
) {
9311 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
9312 OSSafeReleaseNULL(scratchNumber
);
9315 if ((!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCacheLoadAddressKey
))
9316 && loadAddress
&& loadSize
) {
9317 scratchNumber
= OSNumber::withNumber(
9318 (unsigned long long)ml_static_unslide((uintptr_t)segLOWESTTEXT
),
9319 /* numBits */ 8 * sizeof(loadAddress
));
9320 if (!scratchNumber
) {
9323 result
->setObject(kOSBundleCacheLoadAddressKey
, scratchNumber
);
9324 OSSafeReleaseNULL(scratchNumber
);
9326 if ((!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleKextsInKernelTextKey
))
9327 && (this == sKernelKext
) && gBuiltinKmodsCount
) {
9328 result
->setObject(kOSBundleKextsInKernelTextKey
, kOSBooleanTrue
);
9330 #endif /* CONFIG_EMBEDDED */
9331 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
)) {
9332 scratchNumber
= OSNumber::withNumber(
9333 (unsigned long long)(execLoadAddress
),
9334 /* numBits */ 8 * sizeof(execLoadAddress
));
9335 if (!scratchNumber
) {
9338 result
->setObject(kOSBundleExecLoadAddressKey
, scratchNumber
);
9339 OSSafeReleaseNULL(scratchNumber
);
9341 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
9342 scratchNumber
= OSNumber::withNumber(
9343 (unsigned long long)(loadSize
),
9344 /* numBits */ 8 * sizeof(loadSize
));
9345 if (!scratchNumber
) {
9348 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
9349 OSSafeReleaseNULL(scratchNumber
);
9351 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
)) {
9352 scratchNumber
= OSNumber::withNumber(
9353 (unsigned long long)(execLoadSize
),
9354 /* numBits */ 8 * sizeof(execLoadSize
));
9355 if (!scratchNumber
) {
9358 result
->setObject(kOSBundleExecLoadSizeKey
, scratchNumber
);
9359 OSSafeReleaseNULL(scratchNumber
);
9361 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
9362 scratchNumber
= OSNumber::withNumber(
9363 (unsigned long long)(wiredSize
),
9364 /* numBits */ 8 * sizeof(wiredSize
));
9365 if (!scratchNumber
) {
9368 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
9369 OSSafeReleaseNULL(scratchNumber
);
9374 /* OSBundleDependencies. In descending order for
9375 * easy compatibility with kextstat(8).
9377 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
9378 if ((count
= getNumDependencies())) {
9379 dependencyLoadTags
= OSArray::withCapacity(count
);
9380 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
9384 OSKext
* dependency
= OSDynamicCast(OSKext
,
9385 dependencies
->getObject(i
));
9387 OSSafeReleaseNULL(scratchNumber
);
9392 scratchNumber
= OSNumber::withNumber(
9393 (unsigned long long)dependency
->getLoadTag(),
9394 /* numBits*/ 8 * sizeof(loadTag
));
9395 if (!scratchNumber
) {
9398 dependencyLoadTags
->setObject(scratchNumber
);
9403 OSSafeReleaseNULL(scratchNumber
);
9405 /* OSBundleMetaClasses.
9407 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) {
9408 if (metaClasses
&& metaClasses
->getCount()) {
9409 metaClassIterator
= OSCollectionIterator::withCollection(metaClasses
);
9410 metaClassInfo
= OSArray::withCapacity(metaClasses
->getCount());
9411 if (!metaClassIterator
|| !metaClassInfo
) {
9414 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
9416 while ((thisMetaClass
= OSDynamicCast(OSMetaClass
,
9417 metaClassIterator
->getNextObject()))) {
9418 OSSafeReleaseNULL(metaClassDict
);
9419 OSSafeReleaseNULL(scratchNumber
);
9420 OSSafeReleaseNULL(metaClassName
);
9421 OSSafeReleaseNULL(superclassName
);
9423 metaClassDict
= OSDictionary::withCapacity(3);
9424 if (!metaClassDict
) {
9428 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
9429 if (thisMetaClass
->getSuperClass()) {
9430 superclassName
= OSString::withCString(
9431 thisMetaClass
->getSuperClass()->getClassName());
9433 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
9434 8 * sizeof(unsigned int));
9436 /* Bail if any of the essentials is missing. The root class lacks a superclass,
9439 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
9443 metaClassInfo
->setObject(metaClassDict
);
9444 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
9445 if (superclassName
) {
9446 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
9448 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
9453 /* OSBundleRetainCount.
9455 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
9456 OSSafeReleaseNULL(scratchNumber
);
9458 int kextRetainCount
= getRetainCount() - 1;
9462 scratchNumber
= OSNumber::withNumber(
9463 (int)kextRetainCount
,
9464 /* numBits*/ 8 * sizeof(int));
9465 if (scratchNumber
) {
9466 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
9474 OSSafeReleaseNULL(headerData
);
9475 OSSafeReleaseNULL(logData
);
9476 OSSafeReleaseNULL(cpuTypeNumber
);
9477 OSSafeReleaseNULL(cpuSubtypeNumber
);
9478 OSSafeReleaseNULL(executablePathString
);
9479 if (executablePathCString
) {
9480 kfree(executablePathCString
, executablePathCStringSize
);
9482 OSSafeReleaseNULL(scratchNumber
);
9483 OSSafeReleaseNULL(dependencyLoadTags
);
9484 OSSafeReleaseNULL(metaClassIterator
);
9485 OSSafeReleaseNULL(metaClassInfo
);
9486 OSSafeReleaseNULL(metaClassDict
);
9487 OSSafeReleaseNULL(metaClassName
);
9488 OSSafeReleaseNULL(superclassName
);
9490 OSSafeReleaseNULL(result
);
9495 /*********************************************************************
9496 *********************************************************************/
9499 OSKext::requestResource(
9500 const char * kextIdentifierCString
,
9501 const char * resourceNameCString
,
9502 OSKextRequestResourceCallback callback
,
9504 OSKextRequestTag
* requestTagOut
)
9506 OSReturn result
= kOSReturnError
;
9507 OSKext
* callbackKext
= NULL
;// must release (looked up)
9509 OSKextRequestTag requestTag
= -1;
9510 OSNumber
* requestTagNum
= NULL
;// must release
9512 OSDictionary
* requestDict
= NULL
;// must release
9513 OSString
* kextIdentifier
= NULL
;// must release
9514 OSString
* resourceName
= NULL
;// must release
9516 OSDictionary
* callbackRecord
= NULL
;// must release
9517 OSData
* callbackWrapper
= NULL
;// must release
9519 OSData
* contextWrapper
= NULL
;// must release
9521 IORecursiveLockLock(sKextLock
);
9523 if (requestTagOut
) {
9524 *requestTagOut
= kOSKextRequestTagInvalid
;
9527 /* If requests to user space are disabled, don't go any further */
9528 if (!sKernelRequestsEnabled
) {
9529 OSKextLog(/* kext */ NULL
,
9530 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9531 "Can't request resource %s for %s - requests to user space are disabled.",
9532 resourceNameCString
,
9533 kextIdentifierCString
);
9534 result
= kOSKextReturnDisabled
;
9538 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
9539 result
= kOSKextReturnInvalidArgument
;
9543 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9544 if (!callbackKext
) {
9545 OSKextLog(/* kext */ NULL
,
9546 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9547 "Resource request has bad callback address.");
9548 result
= kOSKextReturnInvalidArgument
;
9551 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9552 OSKextLog(/* kext */ NULL
,
9553 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9554 "Resource request callback is in a kext that is not started.");
9555 result
= kOSKextReturnInvalidArgument
;
9559 /* Do not allow any new requests to be made on a kext that is unloading.
9561 if (callbackKext
->flags
.stopping
) {
9562 result
= kOSKextReturnStopping
;
9566 /* If we're wrapped the next available request tag around to the negative
9567 * numbers, we can't service any more requests.
9569 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
9570 OSKextLog(/* kext */ NULL
,
9571 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9572 "No more request tags available; restart required.");
9573 result
= kOSKextReturnNoResources
;
9576 requestTag
= sNextRequestTag
++;
9578 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
9580 if (result
!= kOSReturnSuccess
) {
9584 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
9585 resourceName
= OSString::withCString(resourceNameCString
);
9586 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9587 8 * sizeof(requestTag
));
9588 if (!kextIdentifier
||
9591 !_OSKextSetRequestArgument(requestDict
,
9592 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
9593 !_OSKextSetRequestArgument(requestDict
,
9594 kKextRequestArgumentNameKey
, resourceName
) ||
9595 !_OSKextSetRequestArgument(requestDict
,
9596 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
9597 result
= kOSKextReturnNoMemory
;
9601 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
9602 if (!callbackRecord
) {
9603 result
= kOSKextReturnNoMemory
;
9606 // we validate callback address at call time
9607 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
9609 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
9611 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9612 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
9613 result
= kOSKextReturnNoMemory
;
9618 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9619 kKextRequestArgumentContextKey
, contextWrapper
)) {
9620 result
= kOSKextReturnNoMemory
;
9625 /* Only post the requests after all the other potential failure points
9628 if (!sKernelRequests
->setObject(requestDict
) ||
9629 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
9630 result
= kOSKextReturnNoMemory
;
9634 OSKext::pingKextd();
9636 result
= kOSReturnSuccess
;
9637 if (requestTagOut
) {
9638 *requestTagOut
= requestTag
;
9643 /* If we didn't succeed, yank the request & callback
9644 * from their holding arrays.
9646 if (result
!= kOSReturnSuccess
) {
9649 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
9650 if (index
!= (unsigned int)-1) {
9651 sKernelRequests
->removeObject(index
);
9653 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
9654 if (index
!= (unsigned int)-1) {
9655 sRequestCallbackRecords
->removeObject(index
);
9659 OSKext::considerUnloads(/* rescheduleOnly? */ true);
9661 IORecursiveLockUnlock(sKextLock
);
9664 callbackKext
->release();
9666 if (requestTagNum
) {
9667 requestTagNum
->release();
9671 requestDict
->release();
9673 if (kextIdentifier
) {
9674 kextIdentifier
->release();
9677 resourceName
->release();
9680 if (callbackRecord
) {
9681 callbackRecord
->release();
9683 if (callbackWrapper
) {
9684 callbackWrapper
->release();
9686 if (contextWrapper
) {
9687 contextWrapper
->release();
9693 /*********************************************************************
9694 * Assumes sKextLock is held.
9695 *********************************************************************/
9698 OSKext::dequeueCallbackForRequestTag(
9699 OSKextRequestTag requestTag
,
9700 OSDictionary
** callbackRecordOut
)
9702 OSReturn result
= kOSReturnError
;
9703 OSNumber
* requestTagNum
= NULL
;// must release
9705 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9706 8 * sizeof(requestTag
));
9707 if (!requestTagNum
) {
9711 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
9715 OSSafeReleaseNULL(requestTagNum
);
9720 /*********************************************************************
9721 * Assumes sKextLock is held.
9722 *********************************************************************/
9725 OSKext::dequeueCallbackForRequestTag(
9726 OSNumber
* requestTagNum
,
9727 OSDictionary
** callbackRecordOut
)
9729 OSReturn result
= kOSKextReturnInvalidArgument
;
9730 OSDictionary
* callbackRecord
= NULL
;// retain if matched!
9731 OSNumber
* callbackTagNum
= NULL
;// do not release
9732 unsigned int count
, i
;
9734 result
= kOSReturnError
;
9735 count
= sRequestCallbackRecords
->getCount();
9736 for (i
= 0; i
< count
; i
++) {
9737 callbackRecord
= OSDynamicCast(OSDictionary
,
9738 sRequestCallbackRecords
->getObject(i
));
9739 if (!callbackRecord
) {
9743 /* If we don't find a tag, we basically have a leak here. Maybe
9744 * we should just remove it.
9746 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
9747 callbackRecord
, kKextRequestArgumentRequestTagKey
));
9748 if (!callbackTagNum
) {
9752 /* We could be even more paranoid and check that all the incoming
9753 * args match what's in the callback record.
9755 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
9756 if (callbackRecordOut
) {
9757 *callbackRecordOut
= callbackRecord
;
9758 callbackRecord
->retain();
9760 sRequestCallbackRecords
->removeObject(i
);
9761 result
= kOSReturnSuccess
;
9765 result
= kOSKextReturnNotFound
;
9772 /*********************************************************************
9773 * Busy timeout triage
9774 *********************************************************************/
9777 OSKext::isWaitingKextd(void)
9779 return sRequestCallbackRecords
&& sRequestCallbackRecords
->getCount();
9782 /*********************************************************************
9783 * Assumes sKextLock is held.
9784 *********************************************************************/
9787 OSKext::dispatchResource(OSDictionary
* requestDict
)
9789 OSReturn result
= kOSReturnError
;
9790 OSDictionary
* callbackRecord
= NULL
;// must release
9791 OSNumber
* requestTag
= NULL
;// do not release
9792 OSNumber
* requestResult
= NULL
;// do not release
9793 OSData
* dataObj
= NULL
;// do not release
9794 uint32_t dataLength
= 0;
9795 const void * dataPtr
= NULL
;// do not free
9796 OSData
* callbackWrapper
= NULL
;// do not release
9797 OSKextRequestResourceCallback callback
= NULL
;
9798 OSData
* contextWrapper
= NULL
;// do not release
9799 void * context
= NULL
;// do not free
9800 OSKext
* callbackKext
= NULL
;// must release (looked up)
9802 /* Get the args from the request. Right now we need the tag
9803 * to look up the callback record, and the result for invoking the callback.
9805 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9806 kKextRequestArgumentRequestTagKey
));
9807 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9808 kKextRequestArgumentResultKey
));
9809 if (!requestTag
|| !requestResult
) {
9810 result
= kOSKextReturnInvalidArgument
;
9814 /* Look for a callback record matching this request's tag.
9816 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
9817 if (result
!= kOSReturnSuccess
) {
9822 * Get the context pointer of the callback record (if there is one).
9824 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
9825 kKextRequestArgumentContextKey
));
9826 context
= _OSKextExtractPointer(contextWrapper
);
9827 if (contextWrapper
&& !context
) {
9831 callbackWrapper
= OSDynamicCast(OSData
,
9832 _OSKextGetRequestArgument(callbackRecord
,
9833 kKextRequestArgumentCallbackKey
));
9834 callback
= (OSKextRequestResourceCallback
)
9835 _OSKextExtractPointer(callbackWrapper
);
9840 /* Check for a data obj. We might not have one and that's ok, that means
9841 * we didn't find the requested resource, and we still have to tell the
9842 * caller that via the callback.
9844 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
9845 kKextRequestArgumentValueKey
));
9847 dataPtr
= dataObj
->getBytesNoCopy();
9848 dataLength
= dataObj
->getLength();
9851 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9852 if (!callbackKext
) {
9853 OSKextLog(/* kext */ NULL
,
9854 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9855 "Can't invoke callback for resource request; ");
9858 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9859 OSKextLog(/* kext */ NULL
,
9860 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9861 "Can't invoke kext resource callback; ");
9865 (void)callback(requestTag
->unsigned32BitValue(),
9866 (OSReturn
)requestResult
->unsigned32BitValue(),
9867 dataPtr
, dataLength
, context
);
9869 result
= kOSReturnSuccess
;
9873 callbackKext
->release();
9875 if (callbackRecord
) {
9876 callbackRecord
->release();
9882 /*********************************************************************
9883 *********************************************************************/
9886 OSKext::invokeRequestCallback(
9887 OSDictionary
* callbackRecord
,
9888 OSReturn callbackResult
)
9890 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
9891 OSNumber
* resultNum
= NULL
;// must release
9897 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
9898 8 * sizeof(callbackResult
));
9903 /* Insert the result into the callback record and dispatch it as if it
9904 * were the reply coming down from user space.
9906 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
9909 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
9910 /* This removes the pending callback record.
9912 OSKext::dispatchResource(callbackRecord
);
9917 resultNum
->release();
9922 /*********************************************************************
9923 * Assumes sKextLock is held.
9924 *********************************************************************/
9927 OSKext::cancelRequest(
9928 OSKextRequestTag requestTag
,
9931 OSReturn result
= kOSKextReturnNoMemory
;
9932 OSDictionary
* callbackRecord
= NULL
; // must release
9933 OSData
* contextWrapper
= NULL
;// do not release
9935 IORecursiveLockLock(sKextLock
);
9936 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
9938 IORecursiveLockUnlock(sKextLock
);
9940 if (result
== kOSReturnSuccess
&& contextOut
) {
9941 contextWrapper
= OSDynamicCast(OSData
,
9942 _OSKextGetRequestArgument(callbackRecord
,
9943 kKextRequestArgumentContextKey
));
9944 *contextOut
= _OSKextExtractPointer(contextWrapper
);
9947 if (callbackRecord
) {
9948 callbackRecord
->release();
9954 /*********************************************************************
9955 * Assumes sKextLock is held.
9956 *********************************************************************/
9958 OSKext::invokeOrCancelRequestCallbacks(
9959 OSReturn callbackResult
,
9962 unsigned int count
, i
;
9964 count
= sRequestCallbackRecords
->getCount();
9971 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9972 sRequestCallbackRecords
->getObject(i
));
9977 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9978 _OSKextGetRequestArgument(request
,
9979 kKextRequestArgumentCallbackKey
));
9981 if (!callbackWrapper
) {
9982 sRequestCallbackRecords
->removeObject(i
);
9986 vm_address_t callbackAddress
= (vm_address_t
)
9987 _OSKextExtractPointer(callbackWrapper
);
9989 if ((kmod_info
->address
<= callbackAddress
) &&
9990 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9992 /* This removes the callback record.
9994 invokeRequestCallback(request
, callbackResult
);
9996 sRequestCallbackRecords
->removeObject(i
);
10005 /*********************************************************************
10006 * Assumes sKextLock is held.
10007 *********************************************************************/
10009 OSKext::countRequestCallbacks(void)
10011 uint32_t result
= 0;
10012 unsigned int count
, i
;
10014 count
= sRequestCallbackRecords
->getCount();
10021 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
10022 sRequestCallbackRecords
->getObject(i
));
10027 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
10028 _OSKextGetRequestArgument(request
,
10029 kKextRequestArgumentCallbackKey
));
10031 if (!callbackWrapper
) {
10035 vm_address_t callbackAddress
= (vm_address_t
)
10036 _OSKextExtractPointer(callbackWrapper
);
10038 if ((kmod_info
->address
<= callbackAddress
) &&
10039 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
10048 /*********************************************************************
10049 *********************************************************************/
10051 _OSKextCreateRequest(
10052 const char * predicate
,
10053 OSDictionary
** requestP
)
10055 OSReturn result
= kOSKextReturnNoMemory
;
10056 OSDictionary
* request
= NULL
; // must release on error
10058 request
= OSDictionary::withCapacity(2);
10062 result
= _OSDictionarySetCStringValue(request
,
10063 kKextRequestPredicateKey
, predicate
);
10064 if (result
!= kOSReturnSuccess
) {
10067 result
= kOSReturnSuccess
;
10070 if (result
!= kOSReturnSuccess
) {
10072 request
->release();
10075 *requestP
= request
;
10081 /*********************************************************************
10082 *********************************************************************/
10084 _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
10086 return OSDynamicCast(OSString
,
10087 requestDict
->getObject(kKextRequestPredicateKey
));
10090 /*********************************************************************
10091 *********************************************************************/
10093 _OSKextGetRequestArgument(
10094 OSDictionary
* requestDict
,
10095 const char * argName
)
10097 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
10098 requestDict
->getObject(kKextRequestArgumentsKey
));
10100 return args
->getObject(argName
);
10105 /*********************************************************************
10106 *********************************************************************/
10108 _OSKextSetRequestArgument(
10109 OSDictionary
* requestDict
,
10110 const char * argName
,
10113 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
10114 requestDict
->getObject(kKextRequestArgumentsKey
));
10116 args
= OSDictionary::withCapacity(2);
10120 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
10124 return args
->setObject(argName
, value
);
10130 /*********************************************************************
10131 *********************************************************************/
10133 _OSKextExtractPointer(OSData
* wrapper
)
10135 void * result
= NULL
;
10136 const void * resultPtr
= NULL
;
10141 resultPtr
= wrapper
->getBytesNoCopy();
10142 result
= *(void **)resultPtr
;
10147 /*********************************************************************
10148 *********************************************************************/
10150 _OSDictionarySetCStringValue(
10151 OSDictionary
* dict
,
10153 const char * cValue
)
10155 OSReturn result
= kOSKextReturnNoMemory
;
10156 const OSSymbol
* key
= NULL
; // must release
10157 OSString
* value
= NULL
; // must release
10159 key
= OSSymbol::withCString(cKey
);
10160 value
= OSString::withCString(cValue
);
10161 if (!key
|| !value
) {
10164 if (dict
->setObject(key
, value
)) {
10165 result
= kOSReturnSuccess
;
10179 /*********************************************************************
10180 *********************************************************************/
10182 _OSArrayContainsCString(
10184 const char * cString
)
10186 bool result
= false;
10187 const OSSymbol
* symbol
= NULL
;
10190 if (!array
|| !cString
) {
10194 symbol
= OSSymbol::withCStringNoCopy(cString
);
10199 count
= array
->getCount();
10200 for (i
= 0; i
< count
; i
++) {
10201 OSObject
* thisObject
= array
->getObject(i
);
10202 if (symbol
->isEqualTo(thisObject
)) {
10215 /*********************************************************************
10216 * We really only care about boot / system start up related kexts.
10217 * We return true if we're less than REBUILD_MAX_TIME since start up,
10218 * otherwise return false.
10219 *********************************************************************/
10221 _OSKextInPrelinkRebuildWindow(void)
10223 static bool outside_the_window
= false;
10224 AbsoluteTime my_abstime
;
10228 if (outside_the_window
) {
10231 clock_get_uptime(&my_abstime
);
10232 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
10233 my_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
10234 if (my_secs
> REBUILD_MAX_TIME
) {
10235 outside_the_window
= true;
10241 /*********************************************************************
10242 *********************************************************************/
10244 _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
10246 int unLoadedCount
, i
;
10247 bool result
= false;
10249 IORecursiveLockLock(sKextLock
);
10251 if (sUnloadedPrelinkedKexts
== NULL
) {
10254 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
10255 if (unLoadedCount
== 0) {
10259 for (i
= 0; i
< unLoadedCount
; i
++) {
10260 const OSSymbol
* myBundleID
;// do not release
10262 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
10266 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
10272 IORecursiveLockUnlock(sKextLock
);
10277 #pragma mark Personalities (IOKit Drivers)
10279 /*********************************************************************
10280 *********************************************************************/
10283 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
10285 OSArray
* result
= NULL
;// returned
10286 OSCollectionIterator
* kextIterator
= NULL
;// must release
10287 OSArray
* personalities
= NULL
;// must release
10288 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
10290 OSString
* kextID
= NULL
;// do not release
10291 OSKext
* theKext
= NULL
;// do not release
10293 IORecursiveLockLock(sKextLock
);
10295 /* Let's conservatively guess that any given kext has around 3
10296 * personalities for now.
10298 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
10303 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
10304 if (!kextIterator
) {
10308 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
10309 if (personalitiesIterator
) {
10310 personalitiesIterator
->release();
10311 personalitiesIterator
= NULL
;
10313 if (personalities
) {
10314 personalities
->release();
10315 personalities
= NULL
;
10318 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
10319 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
10320 personalities
= theKext
->copyPersonalitiesArray();
10321 if (!personalities
) {
10324 result
->merge(personalities
);
10326 // xxx - check for better place to put this log msg
10328 kOSKextLogWarningLevel
|
10329 kOSKextLogLoadFlag
,
10330 "Kext %s is not loadable during safe boot; "
10331 "omitting its personalities.",
10332 theKext
->getIdentifierCString());
10337 IORecursiveLockUnlock(sKextLock
);
10339 if (kextIterator
) {
10340 kextIterator
->release();
10342 if (personalitiesIterator
) {
10343 personalitiesIterator
->release();
10345 if (personalities
) {
10346 personalities
->release();
10352 /*********************************************************************
10353 *********************************************************************/
10356 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
10358 int numPersonalities
= 0;
10360 OSKextLog(/* kext */ NULL
,
10361 kOSKextLogStepLevel
|
10362 kOSKextLogLoadFlag
,
10363 "Sending all eligible registered kexts' personalities "
10364 "to the IOCatalogue %s.",
10365 startMatching
? "and starting matching" : "but not starting matching");
10367 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
10368 /* filterSafeBootFlag */ true);
10370 if (personalities
) {
10371 gIOCatalogue
->addDrivers(personalities
, startMatching
);
10372 numPersonalities
= personalities
->getCount();
10373 personalities
->release();
10376 OSKextLog(/* kext */ NULL
,
10377 kOSKextLogStepLevel
|
10378 kOSKextLogLoadFlag
,
10379 "%d kext personalit%s sent to the IOCatalogue; %s.",
10380 numPersonalities
, numPersonalities
> 0 ? "ies" : "y",
10381 startMatching
? "matching started" : "matching not started");
10385 /*********************************************************************
10386 * Do not make a deep copy, just convert the IOKitPersonalities dict
10387 * to an array for sending to the IOCatalogue.
10388 *********************************************************************/
10390 OSKext::copyPersonalitiesArray(void)
10392 OSArray
* result
= NULL
;
10393 OSDictionary
* personalities
= NULL
;// do not release
10394 OSCollectionIterator
* personalitiesIterator
= NULL
;// must release
10396 OSString
* personalityName
= NULL
;// do not release
10397 OSString
* personalityBundleIdentifier
= NULL
;// do not release
10399 personalities
= OSDynamicCast(OSDictionary
,
10400 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10401 if (!personalities
) {
10405 result
= OSArray::withCapacity(personalities
->getCount());
10410 personalitiesIterator
=
10411 OSCollectionIterator::withCollection(personalities
);
10412 if (!personalitiesIterator
) {
10415 while ((personalityName
= OSDynamicCast(OSString
,
10416 personalitiesIterator
->getNextObject()))) {
10417 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10418 personalities
->getObject(personalityName
));
10421 * If the personality doesn't have a CFBundleIdentifier, or if it
10422 * differs from the kext's, insert the kext's ID so we can find it.
10423 * The publisher ID is used to remove personalities from bundles
10426 personalityBundleIdentifier
= OSDynamicCast(OSString
,
10427 personality
->getObject(kCFBundleIdentifierKey
));
10429 if (!personalityBundleIdentifier
) {
10430 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
10431 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
10432 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
10435 result
->setObject(personality
);
10439 if (personalitiesIterator
) {
10440 personalitiesIterator
->release();
10446 /*********************************************************************
10447 * Might want to change this to a bool return?
10448 *********************************************************************/
10450 OSKext::sendPersonalitiesToCatalog(
10451 bool startMatching
,
10452 OSArray
* personalityNames
)
10454 OSReturn result
= kOSReturnSuccess
;
10455 OSArray
* personalitiesToSend
= NULL
;// must release
10456 OSDictionary
* kextPersonalities
= NULL
;// do not release
10459 if (!sLoadEnabled
) {
10461 kOSKextLogErrorLevel
|
10462 kOSKextLogLoadFlag
,
10463 "Kext loading is disabled (attempt to start matching for kext %s).",
10464 getIdentifierCString());
10465 result
= kOSKextReturnDisabled
;
10469 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
10471 kOSKextLogErrorLevel
|
10472 kOSKextLogLoadFlag
,
10473 "Kext %s is not loadable during safe boot; "
10474 "not sending personalities to the IOCatalogue.",
10475 getIdentifierCString());
10476 result
= kOSKextReturnNotLoadable
;
10480 if (!personalityNames
|| !personalityNames
->getCount()) {
10481 personalitiesToSend
= copyPersonalitiesArray();
10483 kextPersonalities
= OSDynamicCast(OSDictionary
,
10484 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10485 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
10489 personalitiesToSend
= OSArray::withCapacity(0);
10490 if (!personalitiesToSend
) {
10491 result
= kOSKextReturnNoMemory
;
10494 count
= personalityNames
->getCount();
10495 for (i
= 0; i
< count
; i
++) {
10496 OSString
* name
= OSDynamicCast(OSString
,
10497 personalityNames
->getObject(i
));
10501 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10502 kextPersonalities
->getObject(name
));
10504 personalitiesToSend
->setObject(personality
);
10508 if (personalitiesToSend
) {
10509 unsigned numPersonalities
= personalitiesToSend
->getCount();
10511 kOSKextLogStepLevel
|
10512 kOSKextLogLoadFlag
,
10513 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
10514 getIdentifierCString(),
10516 numPersonalities
> 1 ? "ies" : "y",
10517 startMatching
? " and starting matching" : " but not starting matching");
10518 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
10521 if (personalitiesToSend
) {
10522 personalitiesToSend
->release();
10527 /*********************************************************************
10528 * xxx - We should allow removing the kext's declared personalities,
10529 * xxx - even with other bundle identifiers.
10530 *********************************************************************/
10532 OSKext::removePersonalitiesFromCatalog(void)
10534 OSDictionary
* personality
= NULL
; // do not release
10536 personality
= OSDictionary::withCapacity(1);
10537 if (!personality
) {
10540 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
10543 kOSKextLogStepLevel
|
10544 kOSKextLogLoadFlag
,
10545 "Kext %s removing all personalities naming it from the IOCatalogue.",
10546 getIdentifierCString());
10548 /* Have the IOCatalog remove all personalities matching this kext's
10549 * bundle ID and trigger matching anew.
10551 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
10555 personality
->release();
10563 #pragma mark Logging
10565 /*********************************************************************
10566 * Do not call any function that takes sKextLock here!
10567 *********************************************************************/
10570 OSKext::setUserSpaceLogFilter(
10571 OSKextLogSpec newUserLogFilter
,
10574 OSKextLogSpec result
;
10575 bool allocError
= false;
10577 /* Do not call any function that takes sKextLoggingLock during
10578 * this critical block. That means do logging after.
10580 IOLockLock(sKextLoggingLock
);
10582 result
= sUserSpaceKextLogFilter
;
10583 sUserSpaceKextLogFilter
= newUserLogFilter
;
10585 if (newUserLogFilter
&& captureFlag
&&
10586 !sUserSpaceLogSpecArray
&& !sUserSpaceLogMessageArray
) {
10587 // xxx - do some measurements for a good initial capacity?
10588 sUserSpaceLogSpecArray
= OSArray::withCapacity(0);
10589 sUserSpaceLogMessageArray
= OSArray::withCapacity(0);
10591 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
10592 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10593 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10598 IOLockUnlock(sKextLoggingLock
);
10600 /* If the config flag itself is changing, log the state change
10601 * going both ways, before setting up the user-space log arrays,
10602 * so that this is only logged in the kernel.
10604 if (result
!= newUserLogFilter
) {
10605 OSKextLog(/* kext */ NULL
,
10606 kOSKextLogDebugLevel
|
10607 kOSKextLogGeneralFlag
,
10608 "User-space log flags changed from 0x%x to 0x%x.",
10609 result
, newUserLogFilter
);
10612 OSKextLog(/* kext */ NULL
,
10613 kOSKextLogErrorLevel
|
10614 kOSKextLogGeneralFlag
,
10615 "Failed to allocate user-space log message arrays.");
10621 /*********************************************************************
10622 * Do not call any function that takes sKextLock here!
10623 *********************************************************************/
10626 OSKext::clearUserSpaceLogFilter(void)
10628 OSArray
* result
= NULL
;
10629 OSKextLogSpec oldLogFilter
;
10630 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
10632 /* Do not call any function that takes sKextLoggingLock during
10633 * this critical block. That means do logging after.
10635 IOLockLock(sKextLoggingLock
);
10637 result
= OSArray::withCapacity(2);
10639 result
->setObject(sUserSpaceLogSpecArray
);
10640 result
->setObject(sUserSpaceLogMessageArray
);
10642 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10643 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10645 oldLogFilter
= sUserSpaceKextLogFilter
;
10646 sUserSpaceKextLogFilter
= newLogFilter
;
10648 IOLockUnlock(sKextLoggingLock
);
10650 /* If the config flag itself is changing, log the state change
10651 * going both ways, after tearing down the user-space log
10652 * arrays, so this is only logged within the kernel.
10654 if (oldLogFilter
!= newLogFilter
) {
10655 OSKextLog(/* kext */ NULL
,
10656 kOSKextLogDebugLevel
|
10657 kOSKextLogGeneralFlag
,
10658 "User-space log flags changed from 0x%x to 0x%x.",
10659 oldLogFilter
, newLogFilter
);
10666 /*********************************************************************
10667 * Do not call any function that takes sKextLock here!
10668 *********************************************************************/
10671 OSKext::getUserSpaceLogFilter(void)
10673 OSKextLogSpec result
;
10675 IOLockLock(sKextLoggingLock
);
10676 result
= sUserSpaceKextLogFilter
;
10677 IOLockUnlock(sKextLoggingLock
);
10682 /*********************************************************************
10683 * This function is called by OSMetaClass during kernel C++ setup.
10684 * Be careful what you access here; assume only OSKext::initialize()
10687 * Do not call any function that takes sKextLock here!
10688 *********************************************************************/
10689 #define VTRESET "\033[0m"
10691 #define VTBOLD "\033[1m"
10692 #define VTUNDER "\033[4m"
10694 #define VTRED "\033[31m"
10695 #define VTGREEN "\033[32m"
10696 #define VTYELLOW "\033[33m"
10697 #define VTBLUE "\033[34m"
10698 #define VTMAGENTA "\033[35m"
10699 #define VTCYAN "\033[36m"
10701 inline const char *
10702 colorForFlags(OSKextLogSpec flags
)
10704 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
10706 switch (logLevel
) {
10707 case kOSKextLogErrorLevel
:
10708 return VTRED VTBOLD
;
10709 case kOSKextLogWarningLevel
:
10711 case kOSKextLogBasicLevel
:
10712 return VTYELLOW VTUNDER
;
10713 case kOSKextLogProgressLevel
:
10715 case kOSKextLogStepLevel
:
10717 case kOSKextLogDetailLevel
:
10719 case kOSKextLogDebugLevel
:
10722 return ""; // white
10728 OSKextLogSpec msgLogSpec
,
10729 OSKextLogSpec logFilter
)
10731 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
10732 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
10733 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
10735 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
10736 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
10737 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
10739 /* Explicit messages always get logged.
10741 if (msgLevel
== kOSKextLogExplicitLevel
) {
10745 /* Warnings and errors are logged regardless of the flags.
10747 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
10751 /* A verbose message that isn't for a logging-enabled kext and isn't global
10752 * does *not* get logged.
10754 if (!msgKextGlobal
&& !filterKextGlobal
) {
10758 /* Warnings and errors are logged regardless of the flags.
10759 * All other messages must fit the flags and
10760 * have a level at or below the filter.
10763 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
10773 OSKextLogSpec msgLogSpec
,
10774 const char * format
, ...)
10778 va_start(argList
, format
);
10779 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
10786 OSKextLogSpec msgLogSpec
,
10787 const char * format
,
10788 va_list srcArgList
)
10790 extern int disableConsoleOutput
;
10792 bool logForKernel
= false;
10793 bool logForUser
= false;
10795 char stackBuffer
[120];
10796 uint32_t length
= 0;
10797 char * allocBuffer
= NULL
; // must kfree
10798 OSNumber
* logSpecNum
= NULL
; // must release
10799 OSString
* logString
= NULL
; // must release
10800 char * buffer
= stackBuffer
;// do not free
10802 IOLockLock(sKextLoggingLock
);
10804 /* Set the kext/global bit in the message spec if we have no
10805 * kext or if the kext requests logging.
10807 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
10808 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
10811 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
10812 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10813 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
10816 if (!(logForKernel
|| logForUser
)) {
10820 /* No goto from here until past va_end()!
10822 va_copy(argList
, srcArgList
);
10823 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
10826 if (length
+ 1 >= sizeof(stackBuffer
)) {
10827 allocBuffer
= (char *)kalloc_tag((length
+ 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT
);
10828 if (!allocBuffer
) {
10832 /* No goto from here until past va_end()!
10834 va_copy(argList
, srcArgList
);
10835 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
10838 buffer
= allocBuffer
;
10841 /* If user space wants the log message, queue it up.
10843 if (logForUser
&& sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10844 logSpecNum
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
));
10845 logString
= OSString::withCString(buffer
);
10846 if (logSpecNum
&& logString
) {
10847 sUserSpaceLogSpecArray
->setObject(logSpecNum
);
10848 sUserSpaceLogMessageArray
->setObject(logString
);
10852 /* Always log messages from the kernel according to the kernel's
10855 if (logForKernel
) {
10856 /* If we are in console mode and have a custom log filter,
10857 * colorize the log message.
10859 if (!disableConsoleOutput
&& sBootArgLogFilterFound
) {
10860 const char * color
= ""; // do not free
10861 color
= colorForFlags(msgLogSpec
);
10862 printf("%s%s%s\n", colorForFlags(msgLogSpec
),
10863 buffer
, color
[0] ? VTRESET
: "");
10865 printf("%s\n", buffer
);
10870 IOLockUnlock(sKextLoggingLock
);
10873 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
10875 OSSafeReleaseNULL(logString
);
10876 OSSafeReleaseNULL(logSpecNum
);
10880 #if KASLR_IOREG_DEBUG
10882 #define IOLOG_INDENT( the_indention ) \
10885 for ( i = 0; i < (the_indention); i++ ) { \
10890 extern vm_offset_t vm_kernel_stext
;
10891 extern vm_offset_t vm_kernel_etext
;
10892 extern mach_vm_offset_t kext_alloc_base
;
10893 extern mach_vm_offset_t kext_alloc_max
;
10895 bool ScanForAddrInObject(OSObject
* theObject
,
10899 ScanForAddrInObject(OSObject
* theObject
,
10902 const OSMetaClass
* myTypeID
;
10903 OSCollectionIterator
* myIter
;
10905 OSObject
* myValue
;
10906 bool myResult
= false;
10908 if (theObject
== NULL
) {
10909 IOLog("%s: theObject is NULL \n",
10914 myTypeID
= OSTypeIDInst(theObject
);
10916 if (myTypeID
== OSTypeID(OSDictionary
)) {
10917 OSDictionary
* myDictionary
;
10919 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
10920 myIter
= OSCollectionIterator::withCollection( myDictionary
);
10921 if (myIter
== NULL
) {
10926 while ((myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject()))) {
10929 myValue
= myDictionary
->getObject(myKey
);
10930 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10931 if (myTempResult
) {
10932 // if we ever get a true result return true
10934 IOLOG_INDENT(indent
);
10935 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
10939 } else if (myTypeID
== OSTypeID(OSArray
)) {
10942 myArray
= OSDynamicCast(OSArray
, theObject
);
10943 myIter
= OSCollectionIterator::withCollection(myArray
);
10944 if (myIter
== NULL
) {
10949 while ((myValue
= myIter
->getNextObject())) {
10951 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10952 if (myTempResult
) {
10953 // if we ever get a true result return true
10955 IOLOG_INDENT(indent
);
10956 IOLog("OSArray: \n");
10960 } else if (myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
)) {
10961 // should we look for addresses in strings?
10962 } else if (myTypeID
== OSTypeID(OSData
)) {
10964 unsigned int myLen
;
10965 OSData
* myDataObj
;
10967 myDataObj
= OSDynamicCast(OSData
, theObject
);
10968 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
10969 myLen
= myDataObj
->getLength();
10971 if (myPtrPtr
&& myLen
&& myLen
> 7) {
10973 int myPtrCount
= (myLen
/ sizeof(void *));
10975 for (i
= 0; i
< myPtrCount
; i
++) {
10976 UInt64 numberValue
= (UInt64
) * (myPtrPtr
);
10978 if (kext_alloc_max
!= 0 &&
10979 numberValue
>= kext_alloc_base
&&
10980 numberValue
< kext_alloc_max
) {
10981 OSKext
* myKext
= NULL
;// must release (looked up)
10982 // IOLog("found OSData %p in kext map %p to %p \n",
10984 // (void *) kext_alloc_base,
10985 // (void *) kext_alloc_max);
10987 myKext
= OSKext::lookupKextWithAddress((vm_address_t
) *(myPtrPtr
));
10989 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
10991 myKext
->getIdentifierCString());
10996 if (vm_kernel_etext
!= 0 &&
10997 numberValue
>= vm_kernel_stext
&&
10998 numberValue
< vm_kernel_etext
) {
10999 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
11001 (void *) vm_kernel_stext
,
11002 (void *) vm_kernel_etext
);
11008 } else if (myTypeID
== OSTypeID(OSBoolean
)) {
11009 // do nothing here...
11010 } else if (myTypeID
== OSTypeID(OSNumber
)) {
11011 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
11013 UInt64 numberValue
= number
->unsigned64BitValue();
11015 if (kext_alloc_max
!= 0 &&
11016 numberValue
>= kext_alloc_base
&&
11017 numberValue
< kext_alloc_max
) {
11018 OSKext
* myKext
= NULL
;// must release (looked up)
11019 IOLog("found OSNumber in kext map %p to %p \n",
11020 (void *) kext_alloc_base
,
11021 (void *) kext_alloc_max
);
11022 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
11024 myKext
= OSKext::lookupKextWithAddress((vm_address_t
) numberValue
);
11026 IOLog("found in kext \"%s\" \n",
11027 myKext
->getIdentifierCString());
11033 if (vm_kernel_etext
!= 0 &&
11034 numberValue
>= vm_kernel_stext
&&
11035 numberValue
< vm_kernel_etext
) {
11036 IOLog("found OSNumber in kernel text segment %p to %p \n",
11037 (void *) vm_kernel_stext
,
11038 (void *) vm_kernel_etext
);
11039 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
11045 const OSMetaClass
* myMetaClass
= NULL
;
11047 myMetaClass
= theObject
->getMetaClass();
11049 IOLog("class %s \n", myMetaClass
->getClassName());
11051 IOLog("Unknown object \n" );
11058 #endif // KASLR_KEXT_DEBUG
11059 }; /* extern "C" */
11062 #pragma mark Backtrace Dump & kmod_get_info() support
11064 /*********************************************************************
11065 * This function must be safe to call in panic context.
11066 *********************************************************************/
11069 OSKext::printKextsInBacktrace(
11070 vm_offset_t
* addr __unused
,
11071 unsigned int cnt __unused
,
11072 int (* printf_func
)(const char *fmt
, ...) __unused
,
11073 uint32_t flags __unused
)
11075 addr64_t summary_page
= 0;
11076 addr64_t last_summary_page
= 0;
11077 bool found_kmod
= false;
11080 if (kPrintKextsLock
& flags
) {
11081 if (!sKextSummariesLock
) {
11084 IOLockLock(sKextSummariesLock
);
11087 if (!gLoadedKextSummaries
) {
11088 (*printf_func
)(" can't perform kext scan: no kext summary");
11092 summary_page
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
);
11093 last_summary_page
= round_page(summary_page
+ sLoadedKextSummariesAllocSize
);
11094 for (; summary_page
< last_summary_page
; summary_page
+= PAGE_SIZE
) {
11095 if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) {
11096 (*printf_func
)(" can't perform kext scan: "
11097 "missing kext summary page %p", summary_page
);
11102 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
11103 OSKextLoadedKextSummary
* summary
;
11105 summary
= gLoadedKextSummaries
->summaries
+ i
;
11106 if (!summary
->address
) {
11110 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
11115 if (!(kPrintKextsTerse
& flags
)) {
11116 (*printf_func
)(" Kernel Extensions in backtrace:\n");
11121 printSummary(summary
, printf_func
, flags
);
11125 if (kPrintKextsLock
& flags
) {
11126 IOLockUnlock(sKextSummariesLock
);
11132 /*********************************************************************
11133 * This function must be safe to call in panic context.
11134 *********************************************************************/
11137 OSKext::summaryIsInBacktrace(
11138 OSKextLoadedKextSummary
* summary
,
11139 vm_offset_t
* addr
,
11144 for (i
= 0; i
< cnt
; i
++) {
11145 vm_offset_t kscan_addr
= addr
[i
];
11146 if ((kscan_addr
>= summary
->address
) &&
11147 (kscan_addr
< (summary
->address
+ summary
->size
))) {
11156 * Get the kext summary object for the kext where 'addr' lies. Must be called with
11157 * sKextSummariesLock held.
11159 OSKextLoadedKextSummary
*
11160 OSKext::summaryForAddress(const uintptr_t addr
)
11162 for (unsigned i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
11163 OSKextLoadedKextSummary
*summary
= &gLoadedKextSummaries
->summaries
[i
];
11164 if (!summary
->address
) {
11168 #if VM_MAPPED_KEXTS
11169 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not
11170 * support split kexts, but we also may unmap the kexts, which can
11171 * race with the above codepath (see OSKext::unload). As such,
11172 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
11174 if ((addr
>= summary
->address
) && (addr
< (summary
->address
+ summary
->size
))) {
11178 kernel_mach_header_t
*mh
= (kernel_mach_header_t
*)summary
->address
;
11179 kernel_segment_command_t
*seg
;
11181 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
11182 if ((addr
>= seg
->vmaddr
) && (addr
< (seg
->vmaddr
+ seg
->vmsize
))) {
11189 /* addr did not map to any kext */
11195 OSKext::kextForAddress(const void *address
)
11197 void * image
= NULL
;
11198 OSKextActiveAccount
* active
;
11199 OSKext
* kext
= NULL
;
11202 uintptr_t addr
= (uintptr_t) address
;
11208 if (sKextAccountsCount
) {
11209 IOSimpleLockLock(sKextAccountsLock
);
11210 // bsearch sKextAccounts list
11211 for (baseIdx
= 0, lim
= sKextAccountsCount
; lim
; lim
>>= 1) {
11212 active
= &sKextAccounts
[baseIdx
+ (lim
>> 1)];
11213 if ((addr
>= active
->address
) && (addr
< active
->address_end
)) {
11214 kext
= active
->account
->kext
;
11215 if (kext
&& kext
->kmod_info
) {
11216 image
= (void *) kext
->kmod_info
->address
;
11219 } else if (addr
> active
->address
) {
11221 baseIdx
+= (lim
>> 1) + 1;
11226 IOSimpleLockUnlock(sKextAccountsLock
);
11228 if (!image
&& (addr
>= vm_kernel_stext
) && (addr
< vm_kernel_etext
)) {
11229 image
= (void *) &_mh_execute_header
;
11235 /*********************************************************************
11236 * scan list of loaded kext summaries looking for a load address match and if
11237 * found return the UUID C string. If not found then set empty string.
11238 *********************************************************************/
11239 static void findSummaryUUID(
11241 uuid_string_t uuid
);
11246 uuid_string_t uuid
)
11250 uuid
[0] = 0x00; // default to no UUID
11252 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
11253 OSKextLoadedKextSummary
* summary
;
11255 summary
= gLoadedKextSummaries
->summaries
+ i
;
11257 if (summary
->loadTag
== tag_ID
) {
11258 (void) uuid_unparse(summary
->uuid
, uuid
);
11265 /*********************************************************************
11266 * This function must be safe to call in panic context.
11267 *********************************************************************/
11269 OSKext::printSummary(
11270 OSKextLoadedKextSummary
* summary
,
11271 int (* printf_func
)(const char *fmt
, ...),
11274 kmod_reference_t
* kmod_ref
= NULL
;
11275 uuid_string_t uuid
;
11276 char version
[kOSKextVersionMaxLength
];
11279 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
11280 strlcpy(version
, "unknown version", sizeof(version
));
11282 (void) uuid_unparse(summary
->uuid
, uuid
);
11284 if (kPrintKextsUnslide
& flags
) {
11285 tmpAddr
= ml_static_unslide(summary
->address
);
11287 tmpAddr
= summary
->address
;
11289 (*printf_func
)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
11290 (kPrintKextsTerse
& flags
) ? "" : " ",
11291 summary
->name
, version
, uuid
,
11292 tmpAddr
, tmpAddr
+ summary
->size
- 1);
11294 if (kPrintKextsTerse
& flags
) {
11298 /* print dependency info */
11299 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
11301 kmod_ref
= kmod_ref
->next
) {
11302 kmod_info_t
* rinfo
;
11304 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) {
11305 (*printf_func
)(" kmod dependency scan stopped "
11306 "due to missing dependency page: %p\n",
11307 (kPrintKextsUnslide
& flags
) ? (void *)ml_static_unslide((vm_offset_t
)kmod_ref
) : kmod_ref
);
11310 rinfo
= kmod_ref
->info
;
11312 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) {
11313 (*printf_func
)(" kmod dependency scan stopped "
11314 "due to missing kmod page: %p\n",
11315 (kPrintKextsUnslide
& flags
) ? (void *)ml_static_unslide((vm_offset_t
)rinfo
) : rinfo
);
11319 if (!rinfo
->address
) {
11320 continue; // skip fake entries for built-ins
11323 /* locate UUID in gLoadedKextSummaries */
11324 findSummaryUUID(rinfo
->id
, uuid
);
11326 if (kPrintKextsUnslide
& flags
) {
11327 tmpAddr
= ml_static_unslide(rinfo
->address
);
11329 tmpAddr
= rinfo
->address
;
11331 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
11332 rinfo
->name
, rinfo
->version
, uuid
, tmpAddr
);
11338 /*******************************************************************************
11339 * substitute() looks at an input string (a pointer within a larger buffer)
11340 * for a match to a substring, and on match it writes the marker & substitution
11341 * character to an output string, updating the scan (from) and
11342 * output (to) indexes as appropriate.
11343 *******************************************************************************/
11344 static int substitute(
11345 const char * scan_string
,
11347 uint32_t * to_index
,
11348 uint32_t * from_index
,
11349 const char * substring
,
11351 char substitution
);
11353 /* string_out must be at least KMOD_MAX_NAME bytes.
11357 const char * scan_string
,
11359 uint32_t * to_index
,
11360 uint32_t * from_index
,
11361 const char * substring
,
11365 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
11367 /* On a substring match, append the marker (if there is one) and then
11368 * the substitution character, updating the output (to) index accordingly.
11369 * Then update the input (from) length by the length of the substring
11370 * that got replaced.
11372 if (!strncmp(scan_string
, substring
, substring_length
)) {
11374 string_out
[(*to_index
)++] = marker
;
11376 string_out
[(*to_index
)++] = substitution
;
11377 (*from_index
) += substring_length
;
11383 /*******************************************************************************
11384 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
11385 * KMOD_MAX_NAME characters and performs various substitutions of common
11386 * prefixes & substrings as defined by tables in kext_panic_report.h.
11387 *******************************************************************************/
11388 static void compactIdentifier(
11389 const char * identifier
,
11390 char * identifier_out
,
11391 char ** identifier_out_end
);
11395 const char * identifier
,
11396 char * identifier_out
,
11397 char ** identifier_out_end
)
11399 uint32_t from_index
, to_index
;
11400 uint32_t scan_from_index
= 0;
11401 uint32_t scan_to_index
= 0;
11402 subs_entry_t
* subs_entry
= NULL
;
11405 from_index
= to_index
= 0;
11406 identifier_out
[0] = '\0';
11408 /* Replace certain identifier prefixes with shorter @+character sequences.
11409 * Check the return value of substitute() so we only replace the prefix.
11411 for (subs_entry
= &kext_identifier_prefix_subs
[0];
11412 subs_entry
->substring
&& !did_sub
;
11414 did_sub
= substitute(identifier
, identifier_out
,
11415 &scan_to_index
, &scan_from_index
,
11416 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
11420 /* Now scan through the identifier looking for the common substrings
11421 * and replacing them with shorter !+character sequences via substitute().
11423 for (/* see above */;
11424 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
11426 const char * scan_string
= &identifier
[scan_from_index
];
11430 if (scan_from_index
) {
11431 for (subs_entry
= &kext_identifier_substring_subs
[0];
11432 subs_entry
->substring
&& !did_sub
;
11434 did_sub
= substitute(scan_string
, identifier_out
,
11435 &scan_to_index
, &scan_from_index
,
11436 subs_entry
->substring
, '!', subs_entry
->substitute
);
11440 /* If we didn't substitute, copy the input character to the output.
11443 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
11447 identifier_out
[scan_to_index
] = '\0';
11448 if (identifier_out_end
) {
11449 *identifier_out_end
= &identifier_out
[scan_to_index
];
11455 /*******************************************************************************
11456 * assemble_identifier_and_version() adds to a string buffer a compacted
11457 * bundle identifier followed by a version string.
11458 *******************************************************************************/
11460 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
11462 static int assemble_identifier_and_version(
11463 kmod_info_t
* kmod_info
,
11464 char * identPlusVers
,
11468 assemble_identifier_and_version(
11469 kmod_info_t
* kmod_info
,
11470 char * identPlusVers
,
11475 compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
);
11476 result
= strnlen(identPlusVers
, KMOD_MAX_NAME
- 1);
11477 identPlusVers
[result
++] = '\t'; // increment for real char
11478 identPlusVers
[result
] = '\0'; // don't increment for nul char
11479 result
= strlcat(identPlusVers
, kmod_info
->version
, bufSize
);
11480 if (result
>= bufSize
) {
11481 identPlusVers
[bufSize
- 1] = '\0';
11482 result
= bufSize
- 1;
11488 /*******************************************************************************
11489 * Assumes sKextLock is held.
11490 *******************************************************************************/
11493 OSKext::saveLoadedKextPanicListTyped(
11494 const char * prefix
,
11498 uint32_t list_size
)
11501 unsigned int count
, i
;
11503 count
= sLoadedKexts
->getCount();
11510 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
11511 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
11513 uint32_t identPlusVersLength
;
11515 char identPlusVers
[2 * KMOD_MAX_NAME
];
11518 printf("OSKext::saveLoadedKextPanicListTyped - "
11519 "NULL kext in loaded kext list; continuing\n");
11524 printf("OSKext::saveLoadedKextPanicListTyped - "
11525 "Kext type cast failed in loaded kext list; continuing\n");
11529 /* Skip all built-in kexts.
11531 if (theKext
->isKernelComponent()) {
11535 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
11537 /* Filter for kmod name (bundle identifier).
11539 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
11540 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
11544 /* Filter for libraries (kexts that have a compatible version).
11546 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
11547 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
11552 !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) {
11553 printf("kext scan stopped due to missing kmod_info page: %p\n",
11558 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
11560 sizeof(identPlusVers
));
11561 if (!identPlusVersLength
) {
11562 printf("error saving loaded kext info\n");
11566 /* make sure everything fits and we null terminate.
11568 tempLen
= strlcat(paniclist
, identPlusVers
, list_size
);
11569 if (tempLen
>= list_size
) {
11570 // panic list is full, keep it and null terminate
11571 paniclist
[list_size
- 1] = 0x00;
11575 tempLen
= strlcat(paniclist
, "\n", list_size
);
11576 if (tempLen
>= list_size
) {
11577 // panic list is full, keep it and null terminate
11578 paniclist
[list_size
- 1] = 0x00;
11590 /*********************************************************************
11591 *********************************************************************/
11594 OSKext::saveLoadedKextPanicList(void)
11596 char * newlist
= NULL
;
11597 uint32_t newlist_size
= 0;
11599 newlist_size
= KEXT_PANICLIST_SIZE
;
11600 newlist
= (char *)kalloc_tag(newlist_size
, VM_KERN_MEMORY_OSKEXT
);
11603 OSKextLog(/* kext */ NULL
,
11604 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
11605 "Couldn't allocate kext panic log buffer.");
11611 // non-"com.apple." kexts
11612 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
11613 /* libs? */ -1, newlist
, newlist_size
) != 0) {
11616 // "com.apple." nonlibrary kexts
11617 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11618 /* libs? */ 0, newlist
, newlist_size
) != 0) {
11621 // "com.apple." library kexts
11622 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11623 /* libs? */ 1, newlist
, newlist_size
) != 0) {
11627 if (loaded_kext_paniclist
) {
11628 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
11630 loaded_kext_paniclist
= newlist
;
11632 loaded_kext_paniclist_size
= newlist_size
;
11636 kfree(newlist
, newlist_size
);
11641 /*********************************************************************
11642 * Assumes sKextLock is held.
11643 *********************************************************************/
11645 OSKext::savePanicString(bool isLoading
)
11650 return; // do not goto finish here b/c of lock
11653 len
= assemble_identifier_and_version( kmod_info
,
11654 (isLoading
) ? last_loaded_str_buf
: last_unloaded_str_buf
,
11655 (isLoading
) ? sizeof(last_loaded_str_buf
) : sizeof(last_unloaded_str_buf
));
11657 printf("error saving unloaded kext info\n");
11662 last_loaded_strlen
= len
;
11663 last_loaded_address
= (void *)kmod_info
->address
;
11664 last_loaded_size
= kmod_info
->size
;
11665 clock_get_uptime(&last_loaded_timestamp
);
11667 last_unloaded_strlen
= len
;
11668 last_unloaded_address
= (void *)kmod_info
->address
;
11669 last_unloaded_size
= kmod_info
->size
;
11670 clock_get_uptime(&last_unloaded_timestamp
);
11677 /*********************************************************************
11678 *********************************************************************/
11681 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
11683 if (last_loaded_strlen
) {
11684 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
11685 AbsoluteTime_to_scalar(&last_loaded_timestamp
),
11686 last_loaded_strlen
, last_loaded_str_buf
,
11687 last_loaded_address
, last_loaded_size
);
11690 if (last_unloaded_strlen
) {
11691 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
11692 AbsoluteTime_to_scalar(&last_unloaded_timestamp
),
11693 last_unloaded_strlen
, last_unloaded_str_buf
,
11694 last_unloaded_address
, last_unloaded_size
);
11697 printf_func("loaded kexts:\n");
11698 if (loaded_kext_paniclist
&&
11699 pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) &&
11700 loaded_kext_paniclist
[0]) {
11701 printf_func("%.*s",
11702 strnlen(loaded_kext_paniclist
, loaded_kext_paniclist_size
),
11703 loaded_kext_paniclist
);
11705 printf_func("(none)\n");
11710 /*********************************************************************
11711 * Assumes sKextLock is held.
11712 *********************************************************************/
11715 OSKext::updateLoadedKextSummaries(void)
11717 kern_return_t result
= KERN_FAILURE
;
11718 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
11719 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
11721 vm_map_offset_t start
, end
;
11722 size_t summarySize
= 0;
11727 OSKextActiveAccount
* accountingList
;
11728 OSKextActiveAccount
* prevAccountingList
;
11729 uint32_t idx
, accountingListAlloc
, accountingListCount
, prevAccountingListCount
;
11731 prevAccountingList
= NULL
;
11732 prevAccountingListCount
= 0;
11734 #if DEVELOPMENT || DEBUG
11735 if (IORecursiveLockHaveLock(sKextLock
) == false) {
11736 panic("sKextLock must be held");
11740 IOLockLock(sKextSummariesLock
);
11742 count
= sLoadedKexts
->getCount();
11743 for (i
= 0, maxKexts
= 0; i
< count
; ++i
) {
11744 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11745 maxKexts
+= (aKext
&& aKext
->isExecutable());
11751 if (maxKexts
< kOSKextTypicalLoadCount
) {
11752 maxKexts
= kOSKextTypicalLoadCount
;
11755 /* Calculate the size needed for the new summary headers.
11758 size
= sizeof(*gLoadedKextSummaries
);
11759 size
+= maxKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
11760 size
= round_page(size
);
11762 if (gLoadedKextSummaries
== NULL
|| sLoadedKextSummariesAllocSize
< size
) {
11763 if (gLoadedKextSummaries
) {
11764 kmem_free(kernel_map
, (vm_offset_t
)gLoadedKextSummaries
, sLoadedKextSummariesAllocSize
);
11765 gLoadedKextSummaries
= NULL
;
11766 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11767 sLoadedKextSummariesAllocSize
= 0;
11769 result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&summaryHeaderAlloc
, size
, VM_KERN_MEMORY_OSKEXT
);
11770 if (result
!= KERN_SUCCESS
) {
11773 summaryHeader
= summaryHeaderAlloc
;
11774 summarySize
= size
;
11776 summaryHeader
= gLoadedKextSummaries
;
11777 summarySize
= sLoadedKextSummariesAllocSize
;
11779 start
= (vm_map_offset_t
) summaryHeader
;
11780 end
= start
+ summarySize
;
11781 result
= vm_map_protect(kernel_map
,
11786 if (result
!= KERN_SUCCESS
) {
11791 /* Populate the summary header.
11794 bzero(summaryHeader
, summarySize
);
11795 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
11796 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
11798 /* Populate each kext summary.
11801 count
= sLoadedKexts
->getCount();
11802 accountingListAlloc
= 0;
11803 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11804 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11805 if (!aKext
|| !aKext
->isExecutable()) {
11809 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
11810 summaryHeader
->numSummaries
++;
11811 accountingListAlloc
++;
11814 accountingList
= IONew(typeof(accountingList
[0]), accountingListAlloc
);
11815 accountingListCount
= 0;
11816 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11817 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11818 if (!aKext
|| !aKext
->isExecutable()) {
11822 OSKextActiveAccount activeAccount
;
11823 aKext
->updateActiveAccount(&activeAccount
);
11824 // order by address
11825 for (idx
= 0; idx
< accountingListCount
; idx
++) {
11826 if (activeAccount
.address
< accountingList
[idx
].address
) {
11830 bcopy(&accountingList
[idx
], &accountingList
[idx
+ 1], (accountingListCount
- idx
) * sizeof(accountingList
[0]));
11831 accountingList
[idx
] = activeAccount
;
11832 accountingListCount
++;
11834 assert(accountingListCount
== accountingListAlloc
);
11835 /* Write protect the buffer and move it into place.
11838 start
= (vm_map_offset_t
) summaryHeader
;
11839 end
= start
+ summarySize
;
11841 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_READ
, FALSE
);
11842 if (result
!= KERN_SUCCESS
) {
11846 gLoadedKextSummaries
= summaryHeader
;
11847 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11848 sLoadedKextSummariesAllocSize
= summarySize
;
11849 summaryHeaderAlloc
= NULL
;
11851 /* Call the magic breakpoint function through a static function pointer so
11852 * the compiler can't optimize the function away.
11854 if (sLoadedKextSummariesUpdated
) {
11855 (*sLoadedKextSummariesUpdated
)();
11858 IOSimpleLockLock(sKextAccountsLock
);
11859 prevAccountingList
= sKextAccounts
;
11860 prevAccountingListCount
= sKextAccountsCount
;
11861 sKextAccounts
= accountingList
;
11862 sKextAccountsCount
= accountingListCount
;
11863 IOSimpleLockUnlock(sKextAccountsLock
);
11866 IOLockUnlock(sKextSummariesLock
);
11868 /* If we had to allocate a new buffer but failed to generate the summaries,
11871 if (summaryHeaderAlloc
) {
11872 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
11874 if (prevAccountingList
) {
11875 IODelete(prevAccountingList
, typeof(accountingList
[0]), prevAccountingListCount
);
11881 /*********************************************************************
11882 *********************************************************************/
11884 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
11888 strlcpy(summary
->name
, getIdentifierCString(),
11889 sizeof(summary
->name
));
11893 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
11894 OSSafeReleaseNULL(uuid
);
11897 if (flags
.builtin
) {
11898 // this value will stop lldb from parsing the mach-o header
11899 // summary->address = UINT64_MAX;
11900 // summary->size = 0;
11901 summary
->address
= kmod_info
->address
;
11902 summary
->size
= kmod_info
->size
;
11904 summary
->address
= kmod_info
->address
;
11905 summary
->size
= kmod_info
->size
;
11907 summary
->version
= getVersion();
11908 summary
->loadTag
= kmod_info
->id
;
11909 summary
->flags
= 0;
11910 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
11915 /*********************************************************************
11916 *********************************************************************/
11919 OSKext::updateActiveAccount(OSKextActiveAccount
*accountp
)
11921 kernel_mach_header_t
*hdr
= NULL
;
11922 kernel_segment_command_t
*seg
= NULL
;
11924 bzero(accountp
, sizeof(*accountp
));
11926 hdr
= (kernel_mach_header_t
*)kmod_info
->address
;
11927 if (getcommandfromheader(hdr
, LC_SEGMENT_SPLIT_INFO
)) {
11928 /* If this kext supports split segments, use the first
11929 * executable segment as the range for instructions
11930 * (and thus for backtracing.
11932 for (seg
= firstsegfromheader(hdr
); seg
!= NULL
; seg
= nextsegfromheader(hdr
, seg
)) {
11933 if (seg
->initprot
& VM_PROT_EXECUTE
) {
11939 accountp
->address
= seg
->vmaddr
;
11940 if (accountp
->address
) {
11941 accountp
->address_end
= seg
->vmaddr
+ seg
->vmsize
;
11944 /* For non-split kexts and for kexts without executable
11945 * segments, just use the kmod_info range (as the kext
11946 * is either all in one range or should not show up in
11947 * instruction backtraces).
11949 accountp
->address
= kmod_info
->address
;
11950 if (accountp
->address
) {
11951 accountp
->address_end
= kmod_info
->address
+ kmod_info
->size
;
11955 accountp
->account
= this->account
;
11958 extern "C" const vm_allocation_site_t
*
11959 OSKextGetAllocationSiteForCaller(uintptr_t address
)
11961 OSKextActiveAccount
* active
;
11962 vm_allocation_site_t
* site
;
11963 vm_allocation_site_t
* releasesite
;
11968 IOSimpleLockLock(sKextAccountsLock
);
11969 site
= releasesite
= NULL
;
11971 // bsearch sKextAccounts list
11972 for (baseIdx
= 0, lim
= sKextAccountsCount
; lim
; lim
>>= 1) {
11973 active
= &sKextAccounts
[baseIdx
+ (lim
>> 1)];
11974 if ((address
>= active
->address
) && (address
< active
->address_end
)) {
11975 site
= &active
->account
->site
;
11977 vm_tag_alloc_locked(site
, &releasesite
);
11980 } else if (address
> active
->address
) {
11982 baseIdx
+= (lim
>> 1) + 1;
11987 IOSimpleLockUnlock(sKextAccountsLock
);
11989 kern_allocation_name_release(releasesite
);
11995 extern "C" uint32_t
11996 OSKextGetKmodIDForSite(const vm_allocation_site_t
* site
, char * name
, vm_size_t namelen
)
11998 OSKextAccount
* account
= (typeof(account
))site
;
11999 const char * kname
;
12002 if (account
->kext
) {
12003 kname
= account
->kext
->getIdentifierCString();
12007 strlcpy(name
, kname
, namelen
);
12010 return account
->loadTag
;
12014 OSKextFreeSite(vm_allocation_site_t
* site
)
12016 OSKextAccount
* freeAccount
= (typeof(freeAccount
))site
;
12017 IODelete(freeAccount
, OSKextAccount
, 1);
12020 /*********************************************************************
12021 *********************************************************************/
12023 #if CONFIG_IMAGEBOOT
12025 OSKextGetUUIDForName(const char *name
, uuid_t uuid
)
12027 OSKext
*kext
= OSKext::lookupKextWithIdentifier(name
);
12032 OSData
*uuid_data
= kext
->copyUUID();
12034 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_t
));
12035 OSSafeReleaseNULL(uuid_data
);