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 // 04/18/11 - gab: <rdar://problem/9236163>
52 #include <sys/random.h>
57 #include <sys/kauth.h>
58 #include <security/mac_framework.h>
62 #include <libkern/OSKextLibPrivate.h>
63 #include <libkern/c++/OSKext.h>
64 #include <libkern/c++/OSLib.h>
66 #include <IOKit/IOLib.h>
67 #include <IOKit/IOCatalogue.h>
68 #include <IOKit/IORegistryEntry.h>
69 #include <IOKit/IOService.h>
71 #include <IOKit/IOStatisticsPrivate.h>
72 #include <IOKit/IOBSD.h>
74 #include <san/kasan.h>
77 #pragma mark External & Internal Function Protos
79 /*********************************************************************
80 *********************************************************************/
82 extern int IODTGetLoaderInfo(const char * key
, void ** infoAddr
, int * infoSize
);
83 extern void IODTFreeLoaderInfo(const char * key
, void * infoAddr
, int infoSize
);
84 extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t
* segment
);
85 extern void OSRuntimeUnloadCPP(kmod_info_t
* ki
, void * data
);
87 extern ppnum_t
pmap_find_phys(pmap_t pmap
, addr64_t va
); /* osfmk/machine/pmap.h */
90 static OSReturn
_OSKextCreateRequest(
91 const char * predicate
,
92 OSDictionary
** requestP
);
93 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
);
94 static OSObject
* _OSKextGetRequestArgument(
95 OSDictionary
* requestDict
,
96 const char * argName
);
97 static bool _OSKextSetRequestArgument(
98 OSDictionary
* requestDict
,
101 static void * _OSKextExtractPointer(OSData
* wrapper
);
102 static OSReturn
_OSDictionarySetCStringValue(
106 static bool _OSKextInPrelinkRebuildWindow(void);
107 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol
* theBundleID
);
109 // We really should add containsObject() & containsCString to OSCollection & subclasses.
110 // So few pad slots, though....
111 static bool _OSArrayContainsCString(OSArray
* array
, const char * cString
);
114 static void * GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
);
115 #endif // CONFIG_KEC_FIPS
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 OSArray
* sLoadedKexts
= NULL
;
270 static OSArray
* sUnloadedPrelinkedKexts
= NULL
;
272 // Requests to kextd waiting to be picked up.
273 static OSArray
* sKernelRequests
= NULL
;
274 // Identifier of kext load requests in sKernelRequests
275 static OSSet
* sPostedKextLoadIdentifiers
= NULL
;
276 static OSArray
* sRequestCallbackRecords
= NULL
;
278 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
279 static OSSet
* sAllKextLoadIdentifiers
= NULL
;
280 static KXLDContext
* sKxldContext
= NULL
;
281 static uint32_t sNextLoadTag
= 0;
282 static uint32_t sNextRequestTag
= 0;
284 static bool sUserLoadsActive
= false;
285 static bool sKextdActive
= false;
286 static bool sDeferredLoadSucceeded
= false;
287 static bool sConsiderUnloadsExecuted
= false;
290 static bool sKernelRequestsEnabled
= false;
292 static bool sKernelRequestsEnabled
= true;
294 static bool sLoadEnabled
= true;
295 static bool sUnloadEnabled
= true;
297 /*********************************************************************
298 * Stuff for the OSKext representing the kernel itself.
300 static OSKext
* sKernelKext
= NULL
;
302 /* Set up a fake kmod_info struct for the kernel.
303 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
304 * before OSKext is initialized; that call only needs the name
305 * and address to be set correctly.
307 * We don't do much else with the kerne's kmod_info; we never
308 * put it into the kmod list, never adjust the reference count,
309 * and never have kernel components reference it.
310 * For that matter, we don't do much with kmod_info structs
311 * at all anymore! We just keep them filled in for gdb and
312 * binary compability.
314 kmod_info_t g_kernel_kmod_info
= {
316 /* info_version */ KMOD_INFO_VERSION
,
317 /* id */ 0, // loadTag: kernel is always 0
318 /* name */ kOSKextKernelIdentifier
, // bundle identifier
319 /* version */ "0", // filled in in OSKext::initialize()
320 /* reference_count */ -1, // never adjusted; kernel never unloads
321 /* reference_list */ NULL
,
323 /* size */ 0, // filled in in OSKext::initialize()
330 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
331 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
332 // misc_protos.h, db_low_trace.c, kgmacros
333 // 'kmod' is a holdover from the old kmod system, we can't rename it.
334 kmod_info_t
* kmod
= NULL
;
336 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
339 static char * loaded_kext_paniclist
= NULL
;
340 static uint32_t loaded_kext_paniclist_size
= 0;
342 AbsoluteTime last_loaded_timestamp
;
343 static char last_loaded_str_buf
[2*KMOD_MAX_NAME
];
344 static u_long last_loaded_strlen
= 0;
345 static void * last_loaded_address
= NULL
;
346 static u_long last_loaded_size
= 0;
348 AbsoluteTime last_unloaded_timestamp
;
349 static char last_unloaded_str_buf
[2*KMOD_MAX_NAME
];
350 static u_long last_unloaded_strlen
= 0;
351 static void * last_unloaded_address
= NULL
;
352 static u_long last_unloaded_size
= 0;
354 /*********************************************************************
355 * sKextInnerLock protects against cross-calls with IOService and
356 * IOCatalogue, and owns the variables declared immediately below.
358 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
360 * When both sKextLock and sKextInnerLock need to be taken,
361 * always lock sKextLock first and unlock it second. Never take both
362 * locks in an entry point to OSKext; if you need to do so, you must
363 * spawn an independent thread to avoid potential deadlocks for threads
364 * calling into OSKext.
366 static IORecursiveLock
* sKextInnerLock
= NULL
;
368 static bool sAutounloadEnabled
= true;
369 static bool sConsiderUnloadsCalled
= false;
370 static bool sConsiderUnloadsPending
= false;
372 static unsigned int sConsiderUnloadDelay
= 60; // seconds
373 static thread_call_t sUnloadCallout
= 0;
374 static thread_call_t sDestroyLinkContextThread
= 0; // one-shot, one-at-a-time thread
375 static bool sSystemSleep
= false; // true when system going to sleep
376 static AbsoluteTime sLastWakeTime
; // last time we woke up
378 /*********************************************************************
379 * Backtraces can be printed at various times so we need a tight lock
380 * on data used for that. sKextSummariesLock protects the variables
381 * declared immediately below.
383 * gLoadedKextSummaries is accessed by other modules, but only during
384 * a panic so the lock isn't needed then.
386 * gLoadedKextSummaries has the "used" attribute in order to ensure
387 * that it remains visible even when we are performing extremely
388 * aggressive optimizations, as it is needed to allow the debugger
389 * to automatically parse the list of loaded kexts.
391 static IOLock
* sKextSummariesLock
= NULL
;
392 extern "C" lck_spin_t vm_allocation_sites_lock
;
393 static IOSimpleLock
* sKextAccountsLock
= &vm_allocation_sites_lock
;
395 void (*sLoadedKextSummariesUpdated
)(void) = OSKextLoadedKextSummariesUpdated
;
396 OSKextLoadedKextSummaryHeader
* gLoadedKextSummaries
__attribute__((used
)) = NULL
;
397 uint64_t gLoadedKextSummariesTimestamp
__attribute__((used
)) = 0;
398 static size_t sLoadedKextSummariesAllocSize
= 0;
400 static OSKextActiveAccount
* sKextAccounts
;
401 static uint32_t sKextAccountsCount
;
404 /*********************************************************************
405 * sKextLoggingLock protects the logging variables declared immediately below.
407 static IOLock
* sKextLoggingLock
= NULL
;
409 static const OSKextLogSpec kDefaultKernelLogFilter
= kOSKextLogBasicLevel
|
410 kOSKextLogVerboseFlagsMask
;
411 static OSKextLogSpec sKernelLogFilter
= kDefaultKernelLogFilter
;
412 static bool sBootArgLogFilterFound
= false;
413 SYSCTL_UINT(_debug
, OID_AUTO
, kextlog
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &sKernelLogFilter
,
414 0, "kernel kext logging");
416 static OSKextLogSpec sUserSpaceKextLogFilter
= kOSKextLogSilentFilter
;
417 static OSArray
* sUserSpaceLogSpecArray
= NULL
;
418 static OSArray
* sUserSpaceLogMessageArray
= NULL
;
421 * End scope for sKextInnerLock-protected variables.
422 *********************************************************************/
425 /*********************************************************************
426 helper function used for collecting PGO data upon unload of a kext
429 static int OSKextGrabPgoDataLocked(OSKext
*kext
,
431 uuid_t instance_uuid
,
434 uint64_t bufferSize
);
436 /**********************************************************************/
441 #pragma mark OSData callbacks (need to move to OSData)
443 /*********************************************************************
444 * C functions used for callbacks.
445 *********************************************************************/
447 void osdata_kmem_free(void * ptr
, unsigned int length
) {
448 kmem_free(kernel_map
, (vm_address_t
)ptr
, length
);
452 void osdata_phys_free(void * ptr
, unsigned int length
) {
453 ml_static_mfree((vm_offset_t
)ptr
, length
);
457 void osdata_vm_deallocate(void * ptr
, unsigned int length
)
459 (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
);
463 void osdata_kext_free(void * ptr
, unsigned int length
)
465 (void)kext_free((vm_offset_t
)ptr
, length
);
471 #pragma mark KXLD Allocation Callback
473 /*********************************************************************
474 * KXLD Allocation Callback
475 *********************************************************************/
479 KXLDAllocateFlags
* flags
,
482 vm_address_t result
= 0; // returned
483 kern_return_t mach_result
= KERN_FAILURE
;
484 bool success
= false;
485 OSKext
* theKext
= (OSKext
*)user_data
;
486 u_long roundSize
= round_page(size
);
487 OSData
* linkBuffer
= NULL
; // must release
489 mach_result
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
);
490 if (mach_result
!= KERN_SUCCESS
) {
492 kOSKextLogErrorLevel
|
493 kOSKextLogGeneralFlag
,
494 "Can't allocate kernel memory to link %s.",
495 theKext
->getIdentifierCString());
499 /* Create an OSData wrapper for the allocated buffer.
501 linkBuffer
= OSData::withBytesNoCopy((void *)result
, roundSize
);
504 kOSKextLogErrorLevel
|
505 kOSKextLogGeneralFlag
,
506 "Can't allocate linked executable wrapper for %s.",
507 theKext
->getIdentifierCString());
510 linkBuffer
->setDeallocFunction(osdata_kext_free
);
512 kOSKextLogProgressLevel
|
513 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
514 "Allocated link buffer for kext %s at %p (%lu bytes).",
515 theKext
->getIdentifierCString(),
516 (void *)result
, (unsigned long)roundSize
);
518 theKext
->setLinkedExecutable(linkBuffer
);
520 *flags
= kKxldAllocateWritable
;
524 if (!success
&& result
) {
525 kext_free(result
, roundSize
);
529 OSSafeReleaseNULL(linkBuffer
);
531 return (kxld_addr_t
)result
;
534 /*********************************************************************
535 *********************************************************************/
538 KXLDLogSubsystem subsystem
,
544 OSKext
*theKext
= (OSKext
*) user_data
;
545 OSKextLogSpec logSpec
= 0;
548 case kKxldLogLinking
:
549 logSpec
|= kOSKextLogLinkFlag
;
551 case kKxldLogPatching
:
552 logSpec
|= kOSKextLogPatchFlag
;
557 case kKxldLogExplicit
:
558 logSpec
|= kOSKextLogExplicitLevel
;
561 logSpec
|= kOSKextLogErrorLevel
;
564 logSpec
|= kOSKextLogWarningLevel
;
567 logSpec
|= kOSKextLogProgressLevel
;
570 logSpec
|= kOSKextLogDetailLevel
;
573 logSpec
|= kOSKextLogDebugLevel
;
577 OSKextVLog(theKext
, logSpec
, format
, argList
);
581 #pragma mark IOStatistics defines
586 #define notifyKextLoadObservers(kext, kmod_info) \
588 IOStatistics::onKextLoad(kext, kmod_info); \
591 #define notifyKextUnloadObservers(kext) \
593 IOStatistics::onKextUnload(kext); \
596 #define notifyAddClassObservers(kext, addedClass, flags) \
598 IOStatistics::onClassAdded(kext, addedClass); \
601 #define notifyRemoveClassObservers(kext, removedClass, flags) \
603 IOStatistics::onClassRemoved(kext, removedClass); \
608 #define notifyKextLoadObservers(kext, kmod_info)
609 #define notifyKextUnloadObservers(kext)
610 #define notifyAddClassObservers(kext, addedClass, flags)
611 #define notifyRemoveClassObservers(kext, removedClass, flags)
613 #endif /* IOKITSTATS */
616 #pragma mark Module Config (Startup & Shutdown)
618 /*********************************************************************
619 * Module Config (Class Definition & Class Methods)
620 *********************************************************************/
621 #define super OSObject
622 OSDefineMetaClassAndStructors(OSKext
, OSObject
)
624 /*********************************************************************
625 *********************************************************************/
628 OSKext::initialize(void)
630 OSData
* kernelExecutable
= NULL
; // do not release
631 u_char
* kernelStart
= NULL
; // do not free
632 size_t kernelLength
= 0;
633 OSString
* scratchString
= NULL
; // must release
634 IORegistryEntry
* registryRoot
= NULL
; // do not release
635 OSNumber
* kernelCPUType
= NULL
; // must release
636 OSNumber
* kernelCPUSubtype
= NULL
; // must release
637 OSKextLogSpec bootLogFilter
= kOSKextLogSilentFilter
;
638 bool setResult
= false;
639 uint64_t * timestamp
= 0;
640 char bootArgBuffer
[16]; // for PE_parse_boot_argn w/strings
642 /* This must be the first thing allocated. Everything else grabs this lock.
644 sKextLock
= IORecursiveLockAlloc();
645 sKextInnerLock
= IORecursiveLockAlloc();
646 sKextSummariesLock
= IOLockAlloc();
647 sKextLoggingLock
= IOLockAlloc();
649 assert(sKextInnerLock
);
650 assert(sKextSummariesLock
);
651 assert(sKextLoggingLock
);
653 sKextsByID
= OSDictionary::withCapacity(kOSKextTypicalLoadCount
);
654 sLoadedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
);
655 sUnloadedPrelinkedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
/ 10);
656 sKernelRequests
= OSArray::withCapacity(0);
657 sPostedKextLoadIdentifiers
= OSSet::withCapacity(0);
658 sAllKextLoadIdentifiers
= OSSet::withCapacity(kOSKextTypicalLoadCount
);
659 sRequestCallbackRecords
= OSArray::withCapacity(0);
660 assert(sKextsByID
&& sLoadedKexts
&& sKernelRequests
&&
661 sPostedKextLoadIdentifiers
&& sAllKextLoadIdentifiers
&&
662 sRequestCallbackRecords
&& sUnloadedPrelinkedKexts
);
664 /* Read the log flag boot-args and set the log flags.
666 if (PE_parse_boot_argn("kextlog", &bootLogFilter
, sizeof(bootLogFilter
))) {
667 sBootArgLogFilterFound
= true;
668 sKernelLogFilter
= bootLogFilter
;
669 // log this if any flags are set
670 OSKextLog(/* kext */ NULL
,
671 kOSKextLogBasicLevel
|
673 "Kernel kext log filter 0x%x per kextlog boot arg.",
674 (unsigned)sKernelLogFilter
);
677 sSafeBoot
= PE_parse_boot_argn("-x", bootArgBuffer
,
678 sizeof(bootArgBuffer
)) ? true : false;
681 OSKextLog(/* kext */ NULL
,
682 kOSKextLogWarningLevel
|
683 kOSKextLogGeneralFlag
,
684 "SAFE BOOT DETECTED - "
685 "only valid OSBundleRequired kexts will be loaded.");
688 PE_parse_boot_argn("keepsyms", &sKeepSymbols
, sizeof(sKeepSymbols
));
689 #if KASAN_DYNAMIC_BLACKLIST
690 /* needed for function lookup */
694 /* Set up an OSKext instance to represent the kernel itself.
696 sKernelKext
= new OSKext
;
699 kernelStart
= (u_char
*)&_mh_execute_header
;
700 kernelLength
= getlastaddr() - (vm_offset_t
)kernelStart
;
701 kernelExecutable
= OSData::withBytesNoCopy(
702 kernelStart
, kernelLength
);
703 assert(kernelExecutable
);
706 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %llu (0x%016lx) \n",
707 (unsigned long)kernelStart
,
708 (unsigned long)getlastaddr(),
710 vm_kernel_slide
, vm_kernel_slide
);
713 sKernelKext
->loadTag
= sNextLoadTag
++; // the kernel is load tag 0
714 sKernelKext
->bundleID
= OSSymbol::withCString(kOSKextKernelIdentifier
);
716 sKernelKext
->version
= OSKextParseVersionString(osrelease
);
717 sKernelKext
->compatibleVersion
= sKernelKext
->version
;
718 sKernelKext
->linkedExecutable
= kernelExecutable
;
720 sKernelKext
->flags
.hasAllDependencies
= 1;
721 sKernelKext
->flags
.kernelComponent
= 1;
722 sKernelKext
->flags
.prelinked
= 0;
723 sKernelKext
->flags
.loaded
= 1;
724 sKernelKext
->flags
.started
= 1;
725 sKernelKext
->flags
.CPPInitialized
= 0;
726 sKernelKext
->flags
.jettisonLinkeditSeg
= 0;
728 sKernelKext
->kmod_info
= &g_kernel_kmod_info
;
729 strlcpy(g_kernel_kmod_info
.version
, osrelease
,
730 sizeof(g_kernel_kmod_info
.version
));
731 g_kernel_kmod_info
.size
= kernelLength
;
732 g_kernel_kmod_info
.id
= sKernelKext
->loadTag
;
734 /* Cons up an info dict, so we don't have to have special-case
737 sKernelKext
->infoDict
= OSDictionary::withCapacity(5);
738 assert(sKernelKext
->infoDict
);
739 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
,
740 sKernelKext
->bundleID
);
742 setResult
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
,
746 scratchString
= OSString::withCStringNoCopy(osrelease
);
747 assert(scratchString
);
748 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
,
751 OSSafeReleaseNULL(scratchString
);
753 scratchString
= OSString::withCStringNoCopy("mach_kernel");
754 assert(scratchString
);
755 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
,
758 OSSafeReleaseNULL(scratchString
);
760 /* Add the kernel kext to the bookkeeping dictionaries. Note that
761 * the kernel kext doesn't have a kmod_info struct. copyInfo()
762 * gathers info from other places anyhow.
764 setResult
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
);
766 setResult
= sLoadedKexts
->setObject(sKernelKext
);
768 sKernelKext
->release();
770 registryRoot
= IORegistryEntry::getRegistryRoot();
771 kernelCPUType
= OSNumber::withNumber(
772 (long long unsigned int)_mh_execute_header
.cputype
,
773 8 * sizeof(_mh_execute_header
.cputype
));
774 kernelCPUSubtype
= OSNumber::withNumber(
775 (long long unsigned int)_mh_execute_header
.cpusubtype
,
776 8 * sizeof(_mh_execute_header
.cpusubtype
));
777 assert(registryRoot
&& kernelCPUSubtype
&& kernelCPUType
);
779 registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
);
780 registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
);
782 OSSafeReleaseNULL(kernelCPUType
);
783 OSSafeReleaseNULL(kernelCPUSubtype
);
785 timestamp
= __OSAbsoluteTimePtr(&last_loaded_timestamp
);
787 timestamp
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
);
789 timestamp
= __OSAbsoluteTimePtr(&sLastWakeTime
);
792 OSKextLog(/* kext */ NULL
,
793 kOSKextLogProgressLevel
|
794 kOSKextLogGeneralFlag
,
795 "Kext system initialized.");
797 notifyKextLoadObservers(sKernelKext
, sKernelKext
->kmod_info
);
802 /*********************************************************************
803 * This could be in OSKextLib.cpp but we need to hold a lock
804 * while removing all the segments and sKextLock will do.
805 *********************************************************************/
808 OSKext::removeKextBootstrap(void)
810 OSReturn result
= kOSReturnError
;
812 static bool alreadyDone
= false;
814 const char * dt_kernel_header_name
= "Kernel-__HEADER";
815 const char * dt_kernel_symtab_name
= "Kernel-__SYMTAB";
816 kernel_mach_header_t
* dt_mach_header
= NULL
;
817 int dt_mach_header_size
= 0;
818 struct symtab_command
* dt_symtab
= NULL
;
819 int dt_symtab_size
= 0;
822 kernel_segment_command_t
* seg_to_remove
= NULL
;
824 #if __arm__ || __arm64__
825 const char * dt_segment_name
= NULL
;
826 void * segment_paddress
= NULL
;
827 int segment_size
= 0;
830 /* This must be the very first thing done by this function.
832 IORecursiveLockLock(sKextLock
);
834 /* If we already did this, it's a success.
837 result
= kOSReturnSuccess
;
841 OSKextLog(/* kext */ NULL
,
842 kOSKextLogProgressLevel
|
843 kOSKextLogGeneralFlag
,
844 "Jettisoning kext bootstrap segments.");
847 * Dispose of unnecessary stuff that the booter didn't need to load.
849 dt_result
= IODTGetLoaderInfo(dt_kernel_header_name
,
850 (void **)&dt_mach_header
, &dt_mach_header_size
);
851 if (dt_result
== 0 && dt_mach_header
) {
852 IODTFreeLoaderInfo(dt_kernel_header_name
, (void *)dt_mach_header
,
853 round_page_32(dt_mach_header_size
));
855 dt_result
= IODTGetLoaderInfo(dt_kernel_symtab_name
,
856 (void **)&dt_symtab
, &dt_symtab_size
);
857 if (dt_result
== 0 && dt_symtab
) {
858 IODTFreeLoaderInfo(dt_kernel_symtab_name
, (void *)dt_symtab
,
859 round_page_32(dt_symtab_size
));
863 * KLD bootstrap segment.
865 // xxx - should rename KLD segment
866 seg_to_remove
= getsegbyname("__KLD");
868 OSRuntimeUnloadCPPForSegment(seg_to_remove
);
871 #if __arm__ || __arm64__
872 #if !(defined(KERNEL_INTEGRITY_KTRR))
873 /* Free the memory that was set up by bootx.
875 dt_segment_name
= "Kernel-__KLD";
876 if (0 == IODTGetLoaderInfo(dt_segment_name
, &segment_paddress
, &segment_size
)) {
877 /* We cannot free this with KTRR enabled, as we cannot
878 * update the permissions on the KLD range this late
879 * in the boot process.
881 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
884 #endif /* !(defined(KERNEL_INTEGRITY_KTRR)) */
885 #elif __i386__ || __x86_64__
886 /* On x86, use the mapping data from the segment load command to
887 * unload KLD directly.
888 * This may invalidate any assumptions about "avail_start"
889 * defining the lower bound for valid physical addresses.
891 if (seg_to_remove
&& seg_to_remove
->vmaddr
&& seg_to_remove
->vmsize
) {
892 // 04/18/11 - gab: <rdar://problem/9236163>
893 // overwrite memory occupied by KLD segment with random data before
895 read_frandom((void *) seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
896 ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
902 seg_to_remove
= NULL
;
905 * Prelinked kernel's symtab (if there is one).
907 kernel_section_t
* sect
;
908 sect
= getsectbyname("__PRELINK", "__symtab");
909 if (sect
&& sect
->addr
&& sect
->size
) {
910 ml_static_mfree(sect
->addr
, sect
->size
);
913 seg_to_remove
= (kernel_segment_command_t
*)getsegbyname("__LINKEDIT");
915 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
916 * pageable, unless keepsyms is set. To do that, we have to copy it from
917 * its booter-allocated memory, free the booter memory, reallocate proper
918 * managed memory, then copy the segment back in.
921 #if (__arm__ || __arm64__)
922 #error CONFIG_KXLD not expected for this arch
925 kern_return_t mem_result
;
926 void *seg_copy
= NULL
;
927 void *seg_data
= NULL
;
928 vm_map_offset_t seg_offset
= 0;
929 vm_map_offset_t seg_copy_offset
= 0;
930 vm_map_size_t seg_length
= 0;
932 seg_data
= (void *) seg_to_remove
->vmaddr
;
933 seg_offset
= (vm_map_offset_t
) seg_to_remove
->vmaddr
;
934 seg_length
= (vm_map_size_t
) seg_to_remove
->vmsize
;
936 /* Allocate space for the LINKEDIT copy.
938 mem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*) &seg_copy
,
939 seg_length
, VM_KERN_MEMORY_KEXT
);
940 if (mem_result
!= KERN_SUCCESS
) {
941 OSKextLog(/* kext */ NULL
,
942 kOSKextLogErrorLevel
|
943 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
944 "Can't copy __LINKEDIT segment for VM reassign.");
947 seg_copy_offset
= (vm_map_offset_t
) seg_copy
;
951 memcpy(seg_copy
, seg_data
, seg_length
);
953 /* Dump the booter memory.
955 ml_static_mfree(seg_offset
, seg_length
);
957 /* Set up the VM region.
959 mem_result
= vm_map_enter_mem_object(
962 seg_length
, /* mask */ 0,
963 VM_FLAGS_FIXED
| VM_FLAGS_OVERWRITE
,
964 VM_MAP_KERNEL_FLAGS_NONE
,
967 (vm_object_offset_t
) 0,
969 /* cur_protection */ VM_PROT_READ
| VM_PROT_WRITE
,
970 /* max_protection */ VM_PROT_ALL
,
971 /* inheritance */ VM_INHERIT_DEFAULT
);
972 if ((mem_result
!= KERN_SUCCESS
) ||
973 (seg_offset
!= (vm_map_offset_t
) seg_data
))
975 OSKextLog(/* kext */ NULL
,
976 kOSKextLogErrorLevel
|
977 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
978 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
979 seg_data
, seg_length
, mem_result
);
985 memcpy(seg_data
, seg_copy
, seg_length
);
989 kmem_free(kernel_map
, seg_copy_offset
, seg_length
);
991 #else /* we are not CONFIG_KXLD */
992 #if !(__arm__ || __arm64__)
993 #error CONFIG_KXLD is expected for this arch
997 * Dump the LINKEDIT segment, unless keepsyms is set.
1000 dt_segment_name
= "Kernel-__LINKEDIT";
1001 if (0 == IODTGetLoaderInfo(dt_segment_name
,
1002 &segment_paddress
, &segment_size
)) {
1003 #ifdef SECURE_KERNEL
1004 vm_offset_t vmaddr
= ml_static_ptovirt((vm_offset_t
)segment_paddress
);
1005 bzero((void*)vmaddr
, segment_size
);
1007 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
1011 OSKextLog(/* kext */ NULL
,
1012 kOSKextLogBasicLevel
|
1013 kOSKextLogGeneralFlag
,
1014 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1016 #endif /* CONFIG_KXLD */
1018 seg_to_remove
= NULL
;
1021 result
= kOSReturnSuccess
;
1025 /* This must be the very last thing done before returning.
1027 IORecursiveLockUnlock(sKextLock
);
1032 /*********************************************************************
1033 *********************************************************************/
1035 OSKext::flushNonloadedKexts(
1036 Boolean flushPrelinkedKexts
)
1038 OSSet
* prelinkedKexts
= NULL
; // must release
1039 OSCollectionIterator
* kextIterator
= NULL
; // must release
1040 OSCollectionIterator
* prelinkIterator
= NULL
; // must release
1041 const OSSymbol
* thisID
= NULL
; // do not release
1042 OSKext
* thisKext
= NULL
; // do not release
1045 IORecursiveLockLock(sKextLock
);
1047 OSKextLog(/* kext */ NULL
,
1048 kOSKextLogProgressLevel
|
1049 kOSKextLogKextBookkeepingFlag
,
1050 "Flushing nonloaded kexts and other unused data.");
1052 OSKext::considerDestroyingLinkContext();
1054 /* If we aren't flushing unused prelinked kexts, we have to put them
1055 * aside while we flush everything else so make a container for them.
1057 if (!flushPrelinkedKexts
) {
1058 prelinkedKexts
= OSSet::withCapacity(0);
1059 if (!prelinkedKexts
) {
1064 /* Set aside prelinked kexts (in-use or not) and break
1065 * any lingering inter-kext references for nonloaded kexts
1066 * so they have min. retain counts.
1068 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1069 if (!kextIterator
) {
1073 while ((thisID
= OSDynamicCast(OSSymbol
,
1074 kextIterator
->getNextObject()))) {
1076 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1079 if (prelinkedKexts
&& thisKext
->isPrelinked()) {
1080 prelinkedKexts
->setObject(thisKext
);
1082 thisKext
->flushDependencies(/* forceIfLoaded */ false);
1086 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1088 sKextsByID
->flushCollection();
1090 /* Now put the loaded kexts back into the ID dictionary.
1092 count
= sLoadedKexts
->getCount();
1093 for (i
= 0; i
< count
; i
++) {
1094 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
1095 sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
);
1098 /* Finally, put back the prelinked kexts if we saved any.
1100 if (prelinkedKexts
) {
1101 prelinkIterator
= OSCollectionIterator::withCollection(prelinkedKexts
);
1102 if (!prelinkIterator
) {
1106 while ((thisKext
= OSDynamicCast(OSKext
,
1107 prelinkIterator
->getNextObject()))) {
1109 sKextsByID
->setObject(thisKext
->getIdentifierCString(),
1115 IORecursiveLockUnlock(sKextLock
);
1117 OSSafeReleaseNULL(prelinkedKexts
);
1118 OSSafeReleaseNULL(kextIterator
);
1119 OSSafeReleaseNULL(prelinkIterator
);
1124 /*********************************************************************
1125 *********************************************************************/
1128 OSKext::setKextdActive(Boolean active
)
1130 IORecursiveLockLock(sKextLock
);
1131 sKextdActive
= active
;
1132 if (sKernelRequests
->getCount()) {
1133 OSKext::pingKextd();
1135 IORecursiveLockUnlock(sKextLock
);
1140 /*********************************************************************
1141 * OSKextLib.cpp might need access to this someday but for now it's
1143 *********************************************************************/
1145 extern void ipc_port_release_send(ipc_port_t
);
1150 OSKext::pingKextd(void)
1152 OSReturn result
= kOSReturnError
;
1154 mach_port_t kextd_port
= IPC_PORT_NULL
;
1156 if (!sKextdActive
) {
1157 result
= kOSKextReturnDisabled
; // basically unavailable
1161 result
= host_get_kextd_port(host_priv_self(), &kextd_port
);
1162 if (result
!= KERN_SUCCESS
|| !IPC_PORT_VALID(kextd_port
)) {
1163 OSKextLog(/* kext */ NULL
,
1164 kOSKextLogErrorLevel
|
1166 "Can't get kextd port.");
1170 result
= kextd_ping(kextd_port
);
1171 if (result
!= KERN_SUCCESS
) {
1172 OSKextLog(/* kext */ NULL
,
1173 kOSKextLogErrorLevel
|
1175 "kextd ping failed (0x%x).", (int)result
);
1180 if (IPC_PORT_VALID(kextd_port
)) {
1181 ipc_port_release_send(kextd_port
);
1188 /*********************************************************************
1189 *********************************************************************/
1192 OSKext::setDeferredLoadSucceeded(Boolean succeeded
)
1194 IORecursiveLockLock(sKextLock
);
1195 sDeferredLoadSucceeded
= succeeded
;
1196 IORecursiveLockUnlock(sKextLock
);
1201 /*********************************************************************
1202 * Called from IOSystemShutdownNotification.
1203 *********************************************************************/
1206 OSKext::willShutdown(void)
1209 OSReturn checkResult
= kOSReturnError
;
1211 OSDictionary
* exitRequest
= NULL
; // must release
1213 IORecursiveLockLock(sKextLock
);
1215 OSKext::setLoadEnabled(false);
1216 OSKext::setUnloadEnabled(false);
1217 OSKext::setAutounloadsEnabled(false);
1218 OSKext::setKernelRequestsEnabled(false);
1221 OSKextLog(/* kext */ NULL
,
1222 kOSKextLogProgressLevel
|
1223 kOSKextLogGeneralFlag
,
1224 "System shutdown; requesting immediate kextd exit.");
1226 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
,
1228 if (checkResult
!= kOSReturnSuccess
) {
1231 if (!sKernelRequests
->setObject(exitRequest
)) {
1235 OSKext::pingKextd();
1240 IORecursiveLockUnlock(sKextLock
);
1242 OSSafeReleaseNULL(exitRequest
);
1246 /*********************************************************************
1247 *********************************************************************/
1250 OSKext::getLoadEnabled(void)
1254 IORecursiveLockLock(sKextLock
);
1255 result
= sLoadEnabled
;
1256 IORecursiveLockUnlock(sKextLock
);
1260 /*********************************************************************
1261 *********************************************************************/
1264 OSKext::setLoadEnabled(bool flag
)
1268 IORecursiveLockLock(sKextLock
);
1269 result
= sLoadEnabled
;
1270 sLoadEnabled
= (flag
? true : false);
1272 if (sLoadEnabled
!= result
) {
1273 OSKextLog(/* kext */ NULL
,
1274 kOSKextLogBasicLevel
|
1276 "Kext loading now %sabled.", sLoadEnabled
? "en" : "dis");
1279 IORecursiveLockUnlock(sKextLock
);
1284 /*********************************************************************
1285 *********************************************************************/
1288 OSKext::getUnloadEnabled(void)
1292 IORecursiveLockLock(sKextLock
);
1293 result
= sUnloadEnabled
;
1294 IORecursiveLockUnlock(sKextLock
);
1298 /*********************************************************************
1299 *********************************************************************/
1302 OSKext::setUnloadEnabled(bool flag
)
1306 IORecursiveLockLock(sKextLock
);
1307 result
= sUnloadEnabled
;
1308 sUnloadEnabled
= (flag
? true : false);
1309 IORecursiveLockUnlock(sKextLock
);
1311 if (sUnloadEnabled
!= result
) {
1312 OSKextLog(/* kext */ NULL
,
1313 kOSKextLogBasicLevel
|
1314 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1315 "Kext unloading now %sabled.", sUnloadEnabled
? "en" : "dis");
1321 /*********************************************************************
1322 * Do not call any function that takes sKextLock here!
1323 *********************************************************************/
1326 OSKext::getAutounloadEnabled(void)
1330 IORecursiveLockLock(sKextInnerLock
);
1331 result
= sAutounloadEnabled
? true : false;
1332 IORecursiveLockUnlock(sKextInnerLock
);
1336 /*********************************************************************
1337 * Do not call any function that takes sKextLock here!
1338 *********************************************************************/
1341 OSKext::setAutounloadsEnabled(bool flag
)
1345 IORecursiveLockLock(sKextInnerLock
);
1347 result
= sAutounloadEnabled
;
1348 sAutounloadEnabled
= (flag
? true : false);
1349 if (!sAutounloadEnabled
&& sUnloadCallout
) {
1350 thread_call_cancel(sUnloadCallout
);
1353 if (sAutounloadEnabled
!= result
) {
1354 OSKextLog(/* kext */ NULL
,
1355 kOSKextLogBasicLevel
|
1356 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1357 "Kext autounloading now %sabled.",
1358 sAutounloadEnabled
? "en" : "dis");
1361 IORecursiveLockUnlock(sKextInnerLock
);
1366 /*********************************************************************
1367 *********************************************************************/
1368 /* instance method operating on OSKext field */
1370 OSKext::setAutounloadEnabled(bool flag
)
1372 bool result
= flags
.autounloadEnabled
? true : false;
1373 flags
.autounloadEnabled
= flag
? 1 : 0;
1375 if (result
!= (flag
? true : false)) {
1377 kOSKextLogProgressLevel
|
1378 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
1379 "Autounloading for kext %s now %sabled.",
1380 getIdentifierCString(),
1381 flags
.autounloadEnabled
? "en" : "dis");
1386 /*********************************************************************
1387 *********************************************************************/
1390 OSKext::setKernelRequestsEnabled(bool flag
)
1394 IORecursiveLockLock(sKextLock
);
1395 result
= sKernelRequestsEnabled
;
1396 sKernelRequestsEnabled
= flag
? true : false;
1398 if (sKernelRequestsEnabled
!= result
) {
1399 OSKextLog(/* kext */ NULL
,
1400 kOSKextLogBasicLevel
|
1401 kOSKextLogGeneralFlag
,
1402 "Kernel requests now %sabled.",
1403 sKernelRequestsEnabled
? "en" : "dis");
1405 IORecursiveLockUnlock(sKextLock
);
1409 /*********************************************************************
1410 *********************************************************************/
1413 OSKext::getKernelRequestsEnabled(void)
1417 IORecursiveLockLock(sKextLock
);
1418 result
= sKernelRequestsEnabled
;
1419 IORecursiveLockUnlock(sKextLock
);
1424 #pragma mark Kext Life Cycle
1426 /*********************************************************************
1427 *********************************************************************/
1429 OSKext::withPrelinkedInfoDict(
1430 OSDictionary
* anInfoDict
,
1431 bool doCoalesedSlides
)
1433 OSKext
* newKext
= new OSKext
;
1435 if (newKext
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
, doCoalesedSlides
)) {
1443 /*********************************************************************
1444 *********************************************************************/
1446 OSKext::initWithPrelinkedInfoDict(
1447 OSDictionary
* anInfoDict
,
1448 bool doCoalesedSlides
)
1450 bool result
= false;
1451 OSString
* kextPath
= NULL
; // do not release
1452 OSNumber
* addressNum
= NULL
; // reused; do not release
1453 OSNumber
* lengthNum
= NULL
; // reused; do not release
1454 void * data
= NULL
; // do not free
1455 void * srcData
= NULL
; // do not free
1456 OSData
* prelinkedExecutable
= NULL
; // must release
1457 uint32_t length
= 0; // reused
1459 if (!super::init()) {
1463 /* Get the path. Don't look for an arch-specific path property.
1465 kextPath
= OSDynamicCast(OSString
,
1466 anInfoDict
->getObject(kPrelinkBundlePathKey
));
1468 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
1471 #if KASLR_KEXT_DEBUG
1472 IOLog("kaslr: doCoalesedSlides %d kext %s \n", doCoalesedSlides
, getIdentifierCString());
1475 /* Also get the executable's bundle-relative path if present.
1476 * Don't look for an arch-specific path property.
1478 executableRelPath
= OSDynamicCast(OSString
,
1479 anInfoDict
->getObject(kPrelinkExecutableRelativePathKey
));
1480 if (executableRelPath
) {
1481 executableRelPath
->retain();
1484 /* Don't need the paths to be in the info dictionary any more.
1486 anInfoDict
->removeObject(kPrelinkBundlePathKey
);
1487 anInfoDict
->removeObject(kPrelinkExecutableRelativePathKey
);
1489 /* Create an OSData wrapper around the linked executable.
1491 addressNum
= OSDynamicCast(OSNumber
,
1492 anInfoDict
->getObject(kPrelinkExecutableLoadKey
));
1494 lengthNum
= OSDynamicCast(OSNumber
,
1495 anInfoDict
->getObject(kPrelinkExecutableSizeKey
));
1498 kOSKextLogErrorLevel
|
1499 kOSKextLogArchiveFlag
,
1500 "Kext %s can't find prelinked kext executable size.",
1501 getIdentifierCString());
1505 data
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1506 length
= (uint32_t) (lengthNum
->unsigned32BitValue());
1508 #if KASLR_KEXT_DEBUG
1509 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1510 (unsigned long)VM_KERNEL_UNSLIDE(data
),
1511 (unsigned long)data
,
1515 anInfoDict
->removeObject(kPrelinkExecutableLoadKey
);
1516 anInfoDict
->removeObject(kPrelinkExecutableSizeKey
);
1518 /* If the kext's load address differs from its source address, allocate
1519 * space in the kext map at the load address and copy the kext over.
1521 addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
));
1523 srcData
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1525 #if KASLR_KEXT_DEBUG
1526 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1527 (unsigned long)VM_KERNEL_UNSLIDE(srcData
),
1528 (unsigned long)srcData
);
1531 if (data
!= srcData
) {
1533 kern_return_t alloc_result
;
1535 alloc_result
= kext_alloc((vm_offset_t
*)&data
, length
, /* fixed */ TRUE
);
1536 if (alloc_result
!= KERN_SUCCESS
) {
1538 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1539 "Failed to allocate space for prelinked kext %s.",
1540 getIdentifierCString());
1543 memcpy(data
, srcData
, length
);
1546 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1547 "Error: prelinked kext %s - source and load addresses "
1548 "differ on ILP32 architecture.",
1549 getIdentifierCString());
1551 #endif /* __LP64__ */
1554 anInfoDict
->removeObject(kPrelinkExecutableSourceKey
);
1557 prelinkedExecutable
= OSData::withBytesNoCopy(data
, length
);
1558 if (!prelinkedExecutable
) {
1560 kOSKextLogErrorLevel
|
1561 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
1562 "Kext %s failed to create executable wrapper.",
1563 getIdentifierCString());
1568 prelinkedExecutable
->setDeallocFunction(osdata_kext_free
);
1570 prelinkedExecutable
->setDeallocFunction(osdata_phys_free
);
1572 setLinkedExecutable(prelinkedExecutable
);
1573 addressNum
= OSDynamicCast(OSNumber
,
1574 anInfoDict
->getObject(kPrelinkKmodInfoKey
));
1577 kOSKextLogErrorLevel
|
1578 kOSKextLogArchiveFlag
,
1579 "Kext %s can't find prelinked kext kmod_info address.",
1580 getIdentifierCString());
1584 if (addressNum
->unsigned64BitValue() != 0) {
1585 kmod_info
= (kmod_info_t
*) (intptr_t) (addressNum
->unsigned64BitValue() + vm_kernel_slide
);
1586 kmod_info
->address
+= vm_kernel_slide
;
1587 #if KASLR_KEXT_DEBUG
1588 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1589 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
),
1590 (unsigned long)kmod_info
);
1591 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1592 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
1593 (unsigned long)kmod_info
->address
);
1597 anInfoDict
->removeObject(kPrelinkKmodInfoKey
);
1600 /* If the plist has a UUID for an interface, save that off.
1602 if (isInterface()) {
1603 interfaceUUID
= OSDynamicCast(OSData
,
1604 anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
));
1605 if (interfaceUUID
) {
1606 interfaceUUID
->retain();
1607 anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
);
1611 result
= slidePrelinkedExecutable(doCoalesedSlides
);
1612 if (result
!= kOSReturnSuccess
) {
1616 if (doCoalesedSlides
== false) {
1617 /* set VM protections now, wire later at kext load */
1618 result
= setVMAttributes(true, false);
1619 if (result
!= KERN_SUCCESS
) {
1624 flags
.prelinked
= true;
1626 /* If we created a kext from prelink info,
1627 * we must be booting from a prelinked kernel.
1629 sPrelinkBoot
= true;
1631 result
= registerIdentifier();
1634 OSSafeReleaseNULL(prelinkedExecutable
);
1639 /*********************************************************************
1640 *********************************************************************/
1642 void OSKext::setAllVMAttributes(void)
1644 OSCollectionIterator
* kextIterator
= NULL
; // must release
1645 const OSSymbol
* thisID
= NULL
; // do not release
1647 IORecursiveLockLock(sKextLock
);
1649 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1650 if (!kextIterator
) {
1654 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
1655 OSKext
* thisKext
; // do not release
1657 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1658 if (!thisKext
|| thisKext
->isInterface() || !thisKext
->declaresExecutable()) {
1662 /* set VM protections now, wire later at kext load */
1663 thisKext
->setVMAttributes(true, false);
1667 IORecursiveLockUnlock(sKextLock
);
1668 OSSafeReleaseNULL(kextIterator
);
1673 /*********************************************************************
1674 *********************************************************************/
1676 OSKext::withBooterData(
1677 OSString
* deviceTreeName
,
1678 OSData
* booterData
)
1680 OSKext
* newKext
= new OSKext
;
1682 if (newKext
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) {
1690 /*********************************************************************
1691 *********************************************************************/
1692 typedef struct _BooterKextFileInfo
{
1693 uint32_t infoDictPhysAddr
;
1694 uint32_t infoDictLength
;
1695 uint32_t executablePhysAddr
;
1696 uint32_t executableLength
;
1697 uint32_t bundlePathPhysAddr
;
1698 uint32_t bundlePathLength
;
1699 } _BooterKextFileInfo
;
1702 OSKext::initWithBooterData(
1703 OSString
* deviceTreeName
,
1704 OSData
* booterData
)
1706 bool result
= false;
1707 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not free
1708 char * infoDictAddr
= NULL
; // do not free
1709 void * executableAddr
= NULL
; // do not free
1710 char * bundlePathAddr
= NULL
; // do not free
1712 OSObject
* parsedXML
= NULL
; // must release
1713 OSDictionary
* theInfoDict
= NULL
; // do not release
1714 OSString
* kextPath
= NULL
; // must release
1715 OSString
* errorString
= NULL
; // must release
1716 OSData
* executable
= NULL
; // must release
1718 if (!super::init()) {
1722 kextFileInfo
= (_BooterKextFileInfo
*)booterData
->getBytesNoCopy();
1723 if (!kextFileInfo
) {
1725 kOSKextLogErrorLevel
|
1726 kOSKextLogGeneralFlag
,
1727 "No booter-provided data for kext device tree entry %s.",
1728 deviceTreeName
->getCStringNoCopy());
1732 /* The info plist must exist or we can't read the kext.
1734 if (!kextFileInfo
->infoDictPhysAddr
|| !kextFileInfo
->infoDictLength
) {
1736 kOSKextLogErrorLevel
|
1737 kOSKextLogGeneralFlag
,
1738 "No kext info dictionary for booter device tree entry %s.",
1739 deviceTreeName
->getCStringNoCopy());
1743 infoDictAddr
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
1744 if (!infoDictAddr
) {
1746 kOSKextLogErrorLevel
|
1747 kOSKextLogGeneralFlag
,
1748 "Can't translate physical address 0x%x of kext info dictionary "
1749 "for device tree entry %s.",
1750 (int)kextFileInfo
->infoDictPhysAddr
,
1751 deviceTreeName
->getCStringNoCopy());
1755 parsedXML
= OSUnserializeXML(infoDictAddr
, &errorString
);
1757 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
1760 const char * errorCString
= "(unknown error)";
1762 if (errorString
&& errorString
->getCStringNoCopy()) {
1763 errorCString
= errorString
->getCStringNoCopy();
1764 } else if (parsedXML
) {
1765 errorCString
= "not a dictionary";
1768 kOSKextLogErrorLevel
|
1769 kOSKextLogGeneralFlag
,
1770 "Error unserializing info dictionary for device tree entry %s: %s.",
1771 deviceTreeName
->getCStringNoCopy(), errorCString
);
1775 /* A bundle path is not mandatory.
1777 if (kextFileInfo
->bundlePathPhysAddr
&& kextFileInfo
->bundlePathLength
) {
1778 bundlePathAddr
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
);
1779 if (!bundlePathAddr
) {
1781 kOSKextLogErrorLevel
|
1782 kOSKextLogGeneralFlag
,
1783 "Can't translate physical address 0x%x of kext bundle path "
1784 "for device tree entry %s.",
1785 (int)kextFileInfo
->bundlePathPhysAddr
,
1786 deviceTreeName
->getCStringNoCopy());
1789 bundlePathAddr
[kextFileInfo
->bundlePathLength
-1] = '\0'; // just in case!
1791 kextPath
= OSString::withCString(bundlePathAddr
);
1794 kOSKextLogErrorLevel
|
1795 kOSKextLogGeneralFlag
,
1796 "Failed to create wrapper for device tree entry %s kext path %s.",
1797 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
);
1802 if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) {
1806 /* An executable is not mandatory.
1808 if (kextFileInfo
->executablePhysAddr
&& kextFileInfo
->executableLength
) {
1809 executableAddr
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
);
1810 if (!executableAddr
) {
1812 kOSKextLogErrorLevel
|
1813 kOSKextLogGeneralFlag
,
1814 "Can't translate physical address 0x%x of kext executable "
1815 "for device tree entry %s.",
1816 (int)kextFileInfo
->executablePhysAddr
,
1817 deviceTreeName
->getCStringNoCopy());
1821 executable
= OSData::withBytesNoCopy(executableAddr
,
1822 kextFileInfo
->executableLength
);
1825 kOSKextLogErrorLevel
|
1826 kOSKextLogGeneralFlag
,
1827 "Failed to create executable wrapper for device tree entry %s.",
1828 deviceTreeName
->getCStringNoCopy());
1832 /* A kext with an executable needs to retain the whole booterData
1833 * object to keep the executable in memory.
1835 if (!setExecutable(executable
, booterData
)) {
1837 kOSKextLogErrorLevel
|
1838 kOSKextLogGeneralFlag
,
1839 "Failed to set kext executable for device tree entry %s.",
1840 deviceTreeName
->getCStringNoCopy());
1845 result
= registerIdentifier();
1848 OSSafeReleaseNULL(parsedXML
);
1849 OSSafeReleaseNULL(kextPath
);
1850 OSSafeReleaseNULL(errorString
);
1851 OSSafeReleaseNULL(executable
);
1856 /*********************************************************************
1857 *********************************************************************/
1859 OSKext::registerIdentifier(void)
1861 bool result
= false;
1862 OSKext
* existingKext
= NULL
; // do not release
1863 bool existingIsLoaded
= false;
1864 bool existingIsPrelinked
= false;
1865 OSKextVersion newVersion
= -1;
1866 OSKextVersion existingVersion
= -1;
1867 char newVersionCString
[kOSKextVersionMaxLength
];
1868 char existingVersionCString
[kOSKextVersionMaxLength
];
1869 OSData
* newUUID
= NULL
; // must release
1870 OSData
* existingUUID
= NULL
; // must release
1872 IORecursiveLockLock(sKextLock
);
1874 /* Get the new kext's version for checks & log messages.
1876 newVersion
= getVersion();
1877 OSKextVersionGetString(newVersion
, newVersionCString
,
1878 kOSKextVersionMaxLength
);
1880 /* If we don't have an existing kext with this identifier,
1881 * just record the new kext and we're done!
1883 existingKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
));
1884 if (!existingKext
) {
1885 sKextsByID
->setObject(bundleID
, this);
1890 /* Get the existing kext's version for checks & log messages.
1892 existingVersion
= existingKext
->getVersion();
1893 OSKextVersionGetString(existingVersion
,
1894 existingVersionCString
, kOSKextVersionMaxLength
);
1896 existingIsLoaded
= existingKext
->isLoaded();
1897 existingIsPrelinked
= existingKext
->isPrelinked();
1899 /* If we have a kext with this identifier that's already loaded/prelinked,
1900 * we can't use the new one, but let's be really thorough and check how
1901 * the two are related for a precise diagnostic log message.
1903 * Note that user space can't find out about nonloaded prelinked kexts,
1904 * so in this case we log a message when new & existing are equivalent
1905 * at the step rather than warning level, because we are always going
1906 * be getting a copy of the kext in the user load request mkext.
1908 if (existingIsLoaded
|| existingIsPrelinked
) {
1909 bool sameVersion
= (newVersion
== existingVersion
);
1910 bool sameExecutable
= true; // assume true unless we have UUIDs
1912 /* Only get the UUID if the existing kext is loaded. Doing so
1913 * might have to uncompress an mkext executable and we shouldn't
1914 * take that hit when neither kext is loaded.
1916 newUUID
= copyUUID();
1917 existingUUID
= existingKext
->copyUUID();
1919 /* I'm entirely too paranoid about checking equivalence of executables,
1920 * but I remember nasty problems with it in the past.
1922 * - If we have UUIDs for both kexts, compare them.
1923 * - If only one kext has a UUID, they're definitely different.
1925 if (newUUID
&& existingUUID
) {
1926 sameExecutable
= newUUID
->isEqualTo(existingUUID
);
1927 } else if (newUUID
|| existingUUID
) {
1928 sameExecutable
= false;
1931 if (!newUUID
&& !existingUUID
) {
1933 /* If there are no UUIDs, we can't really tell that the executables
1934 * are *different* without a lot of work; the loaded kext's
1935 * unrelocated executable is no longer around (and we never had it
1936 * in-kernel for a prelinked kext). We certainly don't want to do
1937 * a whole fake link for the new kext just to compare, either.
1940 OSKextVersionGetString(version
, newVersionCString
,
1941 sizeof(newVersionCString
));
1943 kOSKextLogWarningLevel
|
1944 kOSKextLogKextBookkeepingFlag
,
1945 "Notice - new kext %s, v%s matches %s kext "
1946 "but can't determine if executables are the same (no UUIDs).",
1947 getIdentifierCString(),
1949 (existingIsLoaded
? "loaded" : "prelinked"));
1952 if (sameVersion
&& sameExecutable
) {
1954 (existingIsLoaded
? kOSKextLogWarningLevel
: kOSKextLogStepLevel
) |
1955 kOSKextLogKextBookkeepingFlag
,
1956 "Refusing new kext %s, v%s: a %s copy is already present "
1957 "(same version and executable).",
1958 getIdentifierCString(), newVersionCString
,
1959 (existingIsLoaded
? "loaded" : "prelinked"));
1962 /* This condition is significant so log it under warnings.
1965 kOSKextLogWarningLevel
|
1966 kOSKextLogKextBookkeepingFlag
,
1967 "Refusing new kext %s, v%s: already have %s v%s.",
1968 getIdentifierCString(),
1970 (existingIsLoaded
? "loaded" : "prelinked"),
1971 existingVersionCString
);
1973 /* This condition is significant so log it under warnings.
1976 kOSKextLogWarningLevel
| kOSKextLogKextBookkeepingFlag
,
1977 "Refusing new kext %s, v%s: a %s copy with a different "
1978 "executable UUID is already present.",
1979 getIdentifierCString(), newVersionCString
,
1980 (existingIsLoaded
? "loaded" : "prelinked"));
1984 } /* if (existingIsLoaded || existingIsPrelinked) */
1986 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
1987 * user loads are happening or if we're still in early boot. User agents are
1988 * supposed to resolve dependencies topside and include only the exact
1989 * kexts needed; so we always accept the new kext (in fact we should never
1990 * see an older unloaded copy hanging around).
1992 if (sUserLoadsActive
) {
1993 sKextsByID
->setObject(bundleID
, this);
1997 kOSKextLogStepLevel
|
1998 kOSKextLogKextBookkeepingFlag
,
1999 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2000 getIdentifierCString(),
2001 existingVersionCString
,
2007 /* During early boot, the kext with the highest version always wins out.
2008 * Prelinked kernels will never hit this, but mkexts and booter-read
2009 * kexts might have duplicates.
2011 if (newVersion
> existingVersion
) {
2012 sKextsByID
->setObject(bundleID
, this);
2016 kOSKextLogStepLevel
|
2017 kOSKextLogKextBookkeepingFlag
,
2018 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2019 existingVersionCString
,
2020 getIdentifierCString(),
2025 kOSKextLogStepLevel
|
2026 kOSKextLogKextBookkeepingFlag
,
2027 "Kext %s is already registered with a higher/same version (v%s); "
2028 "dropping newly-added (v%s).",
2029 getIdentifierCString(),
2030 existingVersionCString
,
2034 /* result has been set appropriately by now. */
2038 IORecursiveLockUnlock(sKextLock
);
2042 kOSKextLogStepLevel
|
2043 kOSKextLogKextBookkeepingFlag
,
2044 "Kext %s, v%s registered and available for loading.",
2045 getIdentifierCString(), newVersionCString
);
2048 OSSafeReleaseNULL(newUUID
);
2049 OSSafeReleaseNULL(existingUUID
);
2054 /*********************************************************************
2055 * Does the bare minimum validation to look up a kext.
2056 * All other validation is done on the spot as needed.
2057 **********************************************************************/
2059 OSKext::setInfoDictionaryAndPath(
2060 OSDictionary
* aDictionary
,
2063 bool result
= false;
2064 OSString
* bundleIDString
= NULL
; // do not release
2065 OSString
* versionString
= NULL
; // do not release
2066 OSString
* compatibleVersionString
= NULL
; // do not release
2067 const char * versionCString
= NULL
; // do not free
2068 const char * compatibleVersionCString
= NULL
; // do not free
2069 OSBoolean
* scratchBool
= NULL
; // do not release
2070 OSDictionary
* scratchDict
= NULL
; // do not release
2073 panic("Attempt to set info dictionary on a kext "
2074 "that already has one (%s).",
2075 getIdentifierCString());
2078 if (!aDictionary
|| !OSDynamicCast(OSDictionary
, aDictionary
)) {
2082 infoDict
= aDictionary
;
2085 /* Check right away if the info dictionary has any log flags.
2087 scratchBool
= OSDynamicCast(OSBoolean
,
2088 getPropertyForHostArch(kOSBundleEnableKextLoggingKey
));
2089 if (scratchBool
== kOSBooleanTrue
) {
2090 flags
.loggingEnabled
= 1;
2093 /* The very next thing to get is the bundle identifier. Unlike
2094 * in user space, a kext with no bundle identifier gets axed
2097 bundleIDString
= OSDynamicCast(OSString
,
2098 getPropertyForHostArch(kCFBundleIdentifierKey
));
2099 if (!bundleIDString
) {
2101 kOSKextLogErrorLevel
|
2102 kOSKextLogValidationFlag
,
2103 "CFBundleIdentifier missing/invalid type in kext %s.",
2104 aPath
? aPath
->getCStringNoCopy() : "(unknown)");
2107 bundleID
= OSSymbol::withString(bundleIDString
);
2110 kOSKextLogErrorLevel
|
2111 kOSKextLogValidationFlag
,
2112 "Can't copy bundle identifier as symbol for kext %s.",
2113 bundleIDString
->getCStringNoCopy());
2117 /* Save the path if we got one (it should always be available but it's
2118 * just something nice to have for bookkeeping).
2126 * Minimal validation to initialize. We'll do other validation on the spot.
2128 if (bundleID
->getLength() >= KMOD_MAX_NAME
) {
2130 kOSKextLogErrorLevel
|
2131 kOSKextLogValidationFlag
,
2132 "Kext %s error - CFBundleIdentifier over max length %d.",
2133 getIdentifierCString(), KMOD_MAX_NAME
- 1);
2137 version
= compatibleVersion
= -1;
2139 versionString
= OSDynamicCast(OSString
,
2140 getPropertyForHostArch(kCFBundleVersionKey
));
2141 if (!versionString
) {
2143 kOSKextLogErrorLevel
|
2144 kOSKextLogValidationFlag
,
2145 "Kext %s error - CFBundleVersion missing/invalid type.",
2146 getIdentifierCString());
2149 versionCString
= versionString
->getCStringNoCopy();
2150 version
= OSKextParseVersionString(versionCString
);
2153 kOSKextLogErrorLevel
|
2154 kOSKextLogValidationFlag
,
2155 "Kext %s error - CFBundleVersion bad value '%s'.",
2156 getIdentifierCString(), versionCString
);
2160 compatibleVersion
= -1; // set to illegal value for kexts that don't have
2162 compatibleVersionString
= OSDynamicCast(OSString
,
2163 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
2164 if (compatibleVersionString
) {
2165 compatibleVersionCString
= compatibleVersionString
->getCStringNoCopy();
2166 compatibleVersion
= OSKextParseVersionString(compatibleVersionCString
);
2167 if (compatibleVersion
< 0) {
2169 kOSKextLogErrorLevel
|
2170 kOSKextLogValidationFlag
,
2171 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2172 getIdentifierCString(), compatibleVersionCString
);
2176 if (compatibleVersion
> version
) {
2178 kOSKextLogErrorLevel
|
2179 kOSKextLogValidationFlag
,
2180 "Kext %s error - %s %s > %s %s (must be <=).",
2181 getIdentifierCString(),
2182 kOSBundleCompatibleVersionKey
, compatibleVersionCString
,
2183 kCFBundleVersionKey
, versionCString
);
2188 /* Check to see if this kext is in exclude list */
2189 if ( isInExcludeList() ) {
2191 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
2192 "Kext %s is in exclude list, not loadable",
2193 getIdentifierCString());
2197 /* Set flags for later use if the infoDict gets flushed. We only
2198 * check for true values, not false ones(!)
2200 scratchBool
= OSDynamicCast(OSBoolean
,
2201 getPropertyForHostArch(kOSBundleIsInterfaceKey
));
2202 if (scratchBool
== kOSBooleanTrue
) {
2203 flags
.interface
= 1;
2206 scratchBool
= OSDynamicCast(OSBoolean
,
2207 getPropertyForHostArch(kOSKernelResourceKey
));
2208 if (scratchBool
== kOSBooleanTrue
) {
2209 flags
.kernelComponent
= 1;
2210 flags
.interface
= 1; // xxx - hm. the kernel itself isn't an interface...
2213 /* A kernel component has one implicit dependency on the kernel.
2215 flags
.hasAllDependencies
= 1;
2218 /* Make sure common string values in personalities are uniqued to OSSymbols.
2220 scratchDict
= OSDynamicCast(OSDictionary
,
2221 getPropertyForHostArch(kIOKitPersonalitiesKey
));
2223 uniquePersonalityProperties(scratchDict
);
2233 /*********************************************************************
2234 * Not used for prelinked kernel boot as there is no unrelocated
2236 *********************************************************************/
2238 OSKext::setExecutable(
2239 OSData
* anExecutable
,
2240 OSData
* externalData
,
2241 bool externalDataIsMkext
)
2243 bool result
= false;
2244 const char * executableKey
= NULL
; // do not free
2246 if (!anExecutable
) {
2247 infoDict
->removeObject(_kOSKextExecutableKey
);
2248 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
2249 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
2254 if (infoDict
->getObject(_kOSKextExecutableKey
) ||
2255 infoDict
->getObject(_kOSKextMkextExecutableReferenceKey
)) {
2257 panic("Attempt to set an executable on a kext "
2258 "that already has one (%s).",
2259 getIdentifierCString());
2263 if (externalDataIsMkext
) {
2264 executableKey
= _kOSKextMkextExecutableReferenceKey
;
2266 executableKey
= _kOSKextExecutableKey
;
2270 infoDict
->setObject(executableKey
, anExecutable
);
2272 infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
);
2282 /*********************************************************************
2283 *********************************************************************/
2285 uniqueStringPlistProperty(OSDictionary
* dict
, const char * key
)
2287 OSString
* stringValue
= NULL
; // do not release
2288 const OSSymbol
* symbolValue
= NULL
; // must release
2290 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2295 symbolValue
= OSSymbol::withString(stringValue
);
2300 dict
->setObject(key
, symbolValue
);
2303 if (symbolValue
) symbolValue
->release();
2308 /*********************************************************************
2309 *********************************************************************/
2311 uniqueStringPlistProperty(OSDictionary
* dict
, const OSString
* key
)
2313 OSString
* stringValue
= NULL
; // do not release
2314 const OSSymbol
* symbolValue
= NULL
; // must release
2316 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2321 symbolValue
= OSSymbol::withString(stringValue
);
2326 dict
->setObject(key
, symbolValue
);
2329 if (symbolValue
) symbolValue
->release();
2334 /*********************************************************************
2335 * Replace common personality property values with uniqued instances
2336 * to save on wired memory.
2337 *********************************************************************/
2340 OSKext::uniquePersonalityProperties(OSDictionary
* personalityDict
)
2342 /* Properties every personality has.
2344 uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKey
);
2345 uniqueStringPlistProperty(personalityDict
, kIOProviderClassKey
);
2346 uniqueStringPlistProperty(personalityDict
, gIOClassKey
);
2348 /* Other commonly used properties.
2350 uniqueStringPlistProperty(personalityDict
, gIOMatchCategoryKey
);
2351 uniqueStringPlistProperty(personalityDict
, gIOResourceMatchKey
);
2352 uniqueStringPlistProperty(personalityDict
, gIOUserClientClassKey
);
2354 uniqueStringPlistProperty(personalityDict
, "HIDDefaultBehavior");
2355 uniqueStringPlistProperty(personalityDict
, "HIDPointerAccelerationType");
2356 uniqueStringPlistProperty(personalityDict
, "HIDRemoteControlType");
2357 uniqueStringPlistProperty(personalityDict
, "HIDScrollAccelerationType");
2358 uniqueStringPlistProperty(personalityDict
, "IOPersonalityPublisher");
2359 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect");
2360 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect Location");
2361 uniqueStringPlistProperty(personalityDict
, "Vendor");
2362 uniqueStringPlistProperty(personalityDict
, "Vendor Identification");
2363 uniqueStringPlistProperty(personalityDict
, "Vendor Name");
2364 uniqueStringPlistProperty(personalityDict
, "bConfigurationValue");
2365 uniqueStringPlistProperty(personalityDict
, "bInterfaceNumber");
2366 uniqueStringPlistProperty(personalityDict
, "idProduct");
2371 /*********************************************************************
2372 *********************************************************************/
2377 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2380 OSSafeReleaseNULL(infoDict
);
2381 OSSafeReleaseNULL(bundleID
);
2382 OSSafeReleaseNULL(path
);
2383 OSSafeReleaseNULL(executableRelPath
);
2384 OSSafeReleaseNULL(dependencies
);
2385 OSSafeReleaseNULL(linkedExecutable
);
2386 OSSafeReleaseNULL(metaClasses
);
2387 OSSafeReleaseNULL(interfaceUUID
);
2389 if (isInterface() && kmod_info
) {
2390 kfree(kmod_info
, sizeof(kmod_info_t
));
2398 #pragma mark Mkext files
2400 /*********************************************************************
2401 *********************************************************************/
2403 OSKext::readMkextArchive(OSData
* mkextData
,
2404 uint32_t * checksumPtr
)
2406 OSReturn result
= kOSKextReturnBadData
;
2407 uint32_t mkextLength
= 0;
2408 mkext_header
* mkextHeader
= 0; // do not free
2409 uint32_t mkextVersion
= 0;
2411 /* Note default return of kOSKextReturnBadData above.
2413 mkextLength
= mkextData
->getLength();
2414 if (mkextLength
< sizeof(mkext_basic_header
)) {
2415 OSKextLog(/* kext */ NULL
,
2416 kOSKextLogErrorLevel
|
2417 kOSKextLogArchiveFlag
,
2418 "Mkext archive too small to be valid.");
2422 mkextHeader
= (mkext_header
*)mkextData
->getBytesNoCopy();
2424 if (MKEXT_GET_MAGIC(mkextHeader
) != MKEXT_MAGIC
||
2425 MKEXT_GET_SIGNATURE(mkextHeader
) != MKEXT_SIGN
) {
2426 OSKextLog(/* kext */ NULL
,
2427 kOSKextLogErrorLevel
|
2428 kOSKextLogArchiveFlag
,
2429 "Mkext archive has invalid magic or signature.");
2433 if (MKEXT_GET_LENGTH(mkextHeader
) != mkextLength
) {
2434 OSKextLog(/* kext */ NULL
,
2435 kOSKextLogErrorLevel
|
2436 kOSKextLogArchiveFlag
,
2437 "Mkext archive recorded length doesn't match actual file length.");
2441 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2443 if (mkextVersion
== MKEXT_VERS_2
) {
2444 result
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
);
2446 OSKextLog(/* kext */ NULL
,
2447 kOSKextLogErrorLevel
|
2448 kOSKextLogArchiveFlag
,
2449 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
);
2450 result
= kOSKextReturnUnsupported
;
2457 /*********************************************************************
2458 * Assumes magic, signature, version, length have been checked.
2459 * xxx - need to add further bounds checking for each file entry
2461 * Should keep track of all kexts created so far, and if we hit a
2462 * fatal error halfway through, remove those kexts. If we've dropped
2463 * an older version that had already been read, whoops! Might want to
2464 * add a level of buffering?
2465 *********************************************************************/
2468 OSKext::readMkext2Archive(
2470 OSDictionary
** mkextPlistOut
,
2471 uint32_t * checksumPtr
)
2473 OSReturn result
= kOSReturnError
;
2474 uint32_t mkextLength
;
2475 mkext2_header
* mkextHeader
= NULL
; // do not free
2476 void * mkextEnd
= NULL
; // do not free
2477 uint32_t mkextVersion
;
2478 uint8_t * crc_address
= NULL
;
2480 uint32_t mkextPlistOffset
;
2481 uint32_t mkextPlistCompressedSize
;
2482 char * mkextPlistEnd
= NULL
; // do not free
2483 uint32_t mkextPlistFullSize
;
2484 OSString
* errorString
= NULL
; // must release
2485 OSData
* mkextPlistUncompressedData
= NULL
; // must release
2486 const char * mkextPlistDataBuffer
= NULL
; // do not free
2487 OSObject
* parsedXML
= NULL
; // must release
2488 OSDictionary
* mkextPlist
= NULL
; // do not release
2489 OSArray
* mkextInfoDictArray
= NULL
; // do not release
2492 mkextLength
= mkextData
->getLength();
2493 mkextHeader
= (mkext2_header
*)mkextData
->getBytesNoCopy();
2494 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2495 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2497 crc_address
= (u_int8_t
*)&mkextHeader
->version
;
2498 checksum
= mkext_adler32(crc_address
,
2499 (uintptr_t)mkextHeader
+
2500 MKEXT_GET_LENGTH(mkextHeader
) - (uintptr_t)crc_address
);
2502 if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) {
2503 OSKextLog(/* kext */ NULL
,
2504 kOSKextLogErrorLevel
|
2505 kOSKextLogArchiveFlag
,
2506 "Mkext archive has bad checksum.");
2507 result
= kOSKextReturnBadData
;
2512 *checksumPtr
= checksum
;
2515 /* Check that the CPU type & subtype match that of the running kernel. */
2516 if (MKEXT_GET_CPUTYPE(mkextHeader
) == (UInt32
)CPU_TYPE_ANY
) {
2517 OSKextLog(/* kext */ NULL
,
2518 kOSKextLogErrorLevel
|
2519 kOSKextLogArchiveFlag
,
2520 "Mkext archive must have a specific CPU type.");
2521 result
= kOSKextReturnBadData
;
2524 if ((UInt32
)_mh_execute_header
.cputype
!=
2525 MKEXT_GET_CPUTYPE(mkextHeader
)) {
2527 OSKextLog(/* kext */ NULL
,
2528 kOSKextLogErrorLevel
|
2529 kOSKextLogArchiveFlag
,
2530 "Mkext archive does not match the running kernel's CPU type.");
2531 result
= kOSKextReturnArchNotFound
;
2536 mkextPlistOffset
= MKEXT2_GET_PLIST(mkextHeader
);
2537 mkextPlistCompressedSize
= MKEXT2_GET_PLIST_COMPSIZE(mkextHeader
);
2538 mkextPlistEnd
= (char *)mkextHeader
+ mkextPlistOffset
+
2539 mkextPlistCompressedSize
;
2540 if (mkextPlistEnd
> mkextEnd
) {
2541 OSKextLog(/* kext */ NULL
,
2542 kOSKextLogErrorLevel
|
2543 kOSKextLogArchiveFlag
,
2544 "Mkext archive file overrun.");
2545 result
= kOSKextReturnBadData
;
2548 mkextPlistFullSize
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
);
2549 if (mkextPlistCompressedSize
) {
2550 mkextPlistUncompressedData
= sKernelKext
->extractMkext2FileData(
2551 (UInt8
*)mkextHeader
+ mkextPlistOffset
,
2553 mkextPlistCompressedSize
, mkextPlistFullSize
);
2554 if (!mkextPlistUncompressedData
) {
2557 mkextPlistDataBuffer
= (const char *)
2558 mkextPlistUncompressedData
->getBytesNoCopy();
2560 mkextPlistDataBuffer
= (const char *)mkextHeader
+ mkextPlistOffset
;
2563 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2565 parsedXML
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
);
2567 mkextPlist
= OSDynamicCast(OSDictionary
, parsedXML
);
2570 const char * errorCString
= "(unknown error)";
2572 if (errorString
&& errorString
->getCStringNoCopy()) {
2573 errorCString
= errorString
->getCStringNoCopy();
2574 } else if (parsedXML
) {
2575 errorCString
= "not a dictionary";
2577 OSKextLog(/* kext */ NULL
,
2578 kOSKextLogErrorLevel
|
2579 kOSKextLogArchiveFlag
,
2580 "Error unserializing mkext plist: %s.", errorCString
);
2584 /* If the caller needs the plist, hand it back and retain it.
2585 * (This function releases it at the end.)
2587 if (mkextPlistOut
) {
2588 *mkextPlistOut
= mkextPlist
;
2589 (*mkextPlistOut
)->retain();
2592 mkextInfoDictArray
= OSDynamicCast(OSArray
,
2593 mkextPlist
->getObject(kMKEXTInfoDictionariesKey
));
2594 if (!mkextInfoDictArray
) {
2595 OSKextLog(/* kext */ NULL
,
2596 kOSKextLogErrorLevel
|
2597 kOSKextLogArchiveFlag
,
2598 "Mkext archive contains no kext info dictionaries.");
2602 count
= mkextInfoDictArray
->getCount();
2603 for (i
= 0; i
< count
; i
++) {
2604 OSDictionary
* infoDict
;
2607 infoDict
= OSDynamicCast(OSDictionary
,
2608 mkextInfoDictArray
->getObject(i
));
2610 /* Create the kext for the entry, then release it, because the
2611 * kext system keeps them around until explicitly removed.
2612 * Any creation/registration failures are already logged for us.
2615 OSKext
* newKext
= OSKext::withMkext2Info(infoDict
, mkextData
);
2616 OSSafeReleaseNULL(newKext
);
2620 /* Even if we didn't keep any kexts from the mkext, we may have a load
2621 * request to process, so we are successful (no errors occurred).
2623 result
= kOSReturnSuccess
;
2627 OSSafeReleaseNULL(parsedXML
);
2628 OSSafeReleaseNULL(mkextPlistUncompressedData
);
2629 OSSafeReleaseNULL(errorString
);
2634 /*********************************************************************
2635 *********************************************************************/
2638 OSKext::withMkext2Info(
2639 OSDictionary
* anInfoDict
,
2642 OSKext
* newKext
= new OSKext
;
2644 if (newKext
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) {
2652 /*********************************************************************
2653 *********************************************************************/
2655 OSKext::initWithMkext2Info(
2656 OSDictionary
* anInfoDict
,
2659 bool result
= false;
2660 OSString
* kextPath
= NULL
; // do not release
2661 OSNumber
* executableOffsetNum
= NULL
; // do not release
2662 OSCollectionIterator
* iterator
= NULL
; // must release
2663 OSData
* executable
= NULL
; // must release
2665 if (anInfoDict
== NULL
|| !super::init()) {
2669 /* Get the path. Don't look for an arch-specific path property.
2671 kextPath
= OSDynamicCast(OSString
,
2672 anInfoDict
->getObject(kMKEXTBundlePathKey
));
2674 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
2678 /* If we have a path to the executable, save it.
2680 executableRelPath
= OSDynamicCast(OSString
,
2681 anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
));
2682 if (executableRelPath
) {
2683 executableRelPath
->retain();
2686 /* Don't need the paths to be in the info dictionary any more.
2688 anInfoDict
->removeObject(kMKEXTBundlePathKey
);
2689 anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
);
2691 executableOffsetNum
= OSDynamicCast(OSNumber
,
2692 infoDict
->getObject(kMKEXTExecutableKey
));
2693 if (executableOffsetNum
) {
2694 executable
= createMkext2FileEntry(mkextData
,
2695 executableOffsetNum
, "executable");
2696 infoDict
->removeObject(kMKEXTExecutableKey
);
2700 if (!setExecutable(executable
, mkextData
, true)) {
2705 result
= registerIdentifier();
2709 OSSafeReleaseNULL(executable
);
2710 OSSafeReleaseNULL(iterator
);
2714 /*********************************************************************
2715 *********************************************************************/
2717 OSKext::createMkext2FileEntry(
2719 OSNumber
* offsetNum
,
2722 OSData
* result
= NULL
;
2723 MkextEntryRef entryRef
;
2724 uint8_t * mkextBuffer
= (uint8_t *)mkextData
->getBytesNoCopy();
2725 uint32_t entryOffset
= offsetNum
->unsigned32BitValue();
2727 result
= OSData::withCapacity(sizeof(entryRef
));
2732 entryRef
.mkext
= (mkext_basic_header
*)mkextBuffer
;
2733 entryRef
.fileinfo
= mkextBuffer
+ entryOffset
;
2734 if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) {
2735 OSSafeReleaseNULL(result
);
2742 kOSKextLogErrorLevel
|
2743 kOSKextLogArchiveFlag
,
2744 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2745 name
, getIdentifierCString());
2750 /*********************************************************************
2751 *********************************************************************/
2753 static void * z_alloc(void *, u_int items
, u_int size
);
2754 static void z_free(void *, void *ptr
);
2756 typedef struct z_mem
{
2757 uint32_t alloc_size
;
2762 * Space allocation and freeing routines for use by zlib routines.
2765 z_alloc(void * notused __unused
, u_int num_items
, u_int size
)
2767 void * result
= NULL
;
2768 z_mem
* zmem
= NULL
;
2770 uint64_t total
= ((uint64_t)num_items
) * ((uint64_t)size
);
2771 //Check for overflow due to multiplication
2772 if (total
> UINT32_MAX
){
2773 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
2774 notused
, num_items
, size
, num_items
, size
);
2777 uint64_t allocSize64
= total
+ ((uint64_t)sizeof(zmem
));
2778 //Check for overflow due to addition
2779 if (allocSize64
> UINT32_MAX
){
2780 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
2781 notused
, num_items
, size
, (uint32_t)total
, sizeof(zmem
));
2783 uint32_t allocSize
= (uint32_t)allocSize64
;
2785 zmem
= (z_mem
*)kalloc_tag(allocSize
, VM_KERN_MEMORY_OSKEXT
);
2789 zmem
->alloc_size
= allocSize
;
2790 result
= (void *)&(zmem
->data
);
2796 z_free(void * notused __unused
, void * ptr
)
2798 uint32_t * skipper
= (uint32_t *)ptr
- 1;
2799 z_mem
* zmem
= (z_mem
*)skipper
;
2800 kfree((void *)zmem
, zmem
->alloc_size
);
2806 OSKext::extractMkext2FileData(
2809 uint32_t compressedSize
,
2812 OSData
* result
= NULL
;
2814 OSData
* uncompressedData
= NULL
; // release on error
2816 uint8_t * uncompressedDataBuffer
= 0; // do not free
2817 unsigned long uncompressedSize
;
2819 bool zstream_inited
= false;
2822 /* If the file isn't compressed, we want to make a copy
2823 * so that we don't have the tie to the larger mkext file buffer any more.
2825 if (!compressedSize
) {
2826 uncompressedData
= OSData::withBytes(data
, fullSize
);
2827 // xxx - no check for failure?
2828 result
= uncompressedData
;
2832 if (KERN_SUCCESS
!= kmem_alloc(kernel_map
,
2833 (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
, VM_KERN_MEMORY_OSKEXT
)) {
2835 /* How's this for cheesy? The kernel is only asked to extract
2836 * kext plists so we tailor the log messages.
2840 kOSKextLogErrorLevel
|
2841 kOSKextLogArchiveFlag
,
2842 "Allocation failure extracting %s from mkext.", name
);
2845 kOSKextLogErrorLevel
|
2846 kOSKextLogArchiveFlag
,
2847 "Allocation failure extracting %s from mkext for kext %s.",
2848 name
, getIdentifierCString());
2853 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
);
2854 if (!uncompressedData
) {
2857 kOSKextLogErrorLevel
|
2858 kOSKextLogArchiveFlag
,
2859 "Allocation failure extracting %s from mkext.", name
);
2862 kOSKextLogErrorLevel
|
2863 kOSKextLogArchiveFlag
,
2864 "Allocation failure extracting %s from mkext for kext %s.",
2865 name
, getIdentifierCString());
2869 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
2873 kOSKextLogDetailLevel
|
2874 kOSKextLogArchiveFlag
,
2875 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2876 name
, compressedSize
, fullSize
);
2879 kOSKextLogDetailLevel
|
2880 kOSKextLogArchiveFlag
,
2881 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2882 getIdentifierCString(), name
, compressedSize
, fullSize
);
2885 bzero(&zstream
, sizeof(zstream
));
2886 zstream
.next_in
= (UInt8
*)data
;
2887 zstream
.avail_in
= compressedSize
;
2889 zstream
.next_out
= uncompressedDataBuffer
;
2890 zstream
.avail_out
= fullSize
;
2892 zstream
.zalloc
= z_alloc
;
2893 zstream
.zfree
= z_free
;
2895 zlib_result
= inflateInit(&zstream
);
2896 if (Z_OK
!= zlib_result
) {
2899 kOSKextLogErrorLevel
|
2900 kOSKextLogArchiveFlag
,
2901 "Mkext error; zlib inflateInit failed (%d) for %s.",
2905 kOSKextLogErrorLevel
|
2906 kOSKextLogArchiveFlag
,
2907 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2908 getIdentifierCString(), zlib_result
, name
);
2912 zstream_inited
= true;
2915 zlib_result
= inflate(&zstream
, Z_FINISH
);
2917 if (zlib_result
== Z_STREAM_END
|| zlib_result
== Z_OK
) {
2918 uncompressedSize
= zstream
.total_out
;
2922 kOSKextLogErrorLevel
|
2923 kOSKextLogArchiveFlag
,
2924 "Mkext error; zlib inflate failed (%d) for %s.",
2928 kOSKextLogErrorLevel
|
2929 kOSKextLogArchiveFlag
,
2930 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
2931 getIdentifierCString(), zlib_result
, name
);
2935 kOSKextLogErrorLevel
|
2936 kOSKextLogArchiveFlag
,
2937 "zlib error: %s.", zstream
.msg
);
2942 if (uncompressedSize
!= fullSize
) {
2945 kOSKextLogErrorLevel
|
2946 kOSKextLogArchiveFlag
,
2947 "Mkext error; zlib inflate discrepancy for %s, "
2948 "uncompressed size != original size.", name
);
2951 kOSKextLogErrorLevel
|
2952 kOSKextLogArchiveFlag
,
2953 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
2954 "uncompressed size != original size.",
2955 getIdentifierCString(), name
);
2960 result
= uncompressedData
;
2963 /* Don't bother checking return, nothing we can do on fail.
2965 if (zstream_inited
) inflateEnd(&zstream
);
2968 OSSafeReleaseNULL(uncompressedData
);
2974 /*********************************************************************
2975 *********************************************************************/
2978 OSKext::loadFromMkext(
2979 OSKextLogSpec clientLogFilter
,
2981 uint32_t mkextBufferLength
,
2983 uint32_t * logInfoLengthOut
)
2985 OSReturn result
= kOSReturnError
;
2986 OSReturn tempResult
= kOSReturnError
;
2988 OSData
* mkextData
= NULL
; // must release
2989 OSDictionary
* mkextPlist
= NULL
; // must release
2991 OSArray
* logInfoArray
= NULL
; // must release
2992 OSSerialize
* serializer
= NULL
; // must release
2994 OSString
* predicate
= NULL
; // do not release
2995 OSDictionary
* requestArgs
= NULL
; // do not release
2997 OSString
* kextIdentifier
= NULL
; // do not release
2998 OSNumber
* startKextExcludeNum
= NULL
; // do not release
2999 OSNumber
* startMatchingExcludeNum
= NULL
; // do not release
3000 OSBoolean
* delayAutounloadBool
= NULL
; // do not release
3001 OSArray
* personalityNames
= NULL
; // do not release
3003 /* Default values for these two options: regular autounload behavior,
3004 * load all kexts, send no personalities.
3006 Boolean delayAutounload
= false;
3007 OSKextExcludeLevel startKextExcludeLevel
= kOSKextExcludeNone
;
3008 OSKextExcludeLevel startMatchingExcludeLevel
= kOSKextExcludeAll
;
3010 IORecursiveLockLock(sKextLock
);
3014 *logInfoLengthOut
= 0;
3017 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
3019 OSKextLog(/* kext */ NULL
,
3020 kOSKextLogDebugLevel
|
3022 "Received kext load request from user space.");
3024 /* Regardless of processing, the fact that we have gotten here means some
3025 * user-space program is up and talking to us, so we'll switch our kext
3026 * registration to reflect that.
3028 if (!sUserLoadsActive
) {
3029 OSKextLog(/* kext */ NULL
,
3030 kOSKextLogProgressLevel
|
3031 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
3032 "Switching to late startup (user-space) kext loading policy.");
3034 sUserLoadsActive
= true;
3037 if (!sLoadEnabled
) {
3038 OSKextLog(/* kext */ NULL
,
3039 kOSKextLogErrorLevel
|
3041 "Kext loading is disabled.");
3042 result
= kOSKextReturnDisabled
;
3046 /* Note that we do not set a dealloc function on this OSData
3047 * object! No references to it can remain after the loadFromMkext()
3048 * call since we are in a MIG function, and will vm_deallocate()
3051 mkextData
= OSData::withBytesNoCopy(mkextBuffer
,
3054 OSKextLog(/* kext */ NULL
,
3055 kOSKextLogErrorLevel
|
3056 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3057 "Failed to create wrapper for kext load request.");
3058 result
= kOSKextReturnNoMemory
;
3062 result
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
);
3063 if (result
!= kOSReturnSuccess
) {
3064 OSKextLog(/* kext */ NULL
,
3065 kOSKextLogErrorLevel
|
3067 "Failed to read kext load request.");
3071 predicate
= _OSKextGetRequestPredicate(mkextPlist
);
3072 if (!predicate
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) {
3073 OSKextLog(/* kext */ NULL
,
3074 kOSKextLogErrorLevel
|
3076 "Received kext load request with no predicate; skipping.");
3077 result
= kOSKextReturnInvalidArgument
;
3081 requestArgs
= OSDynamicCast(OSDictionary
,
3082 mkextPlist
->getObject(kKextRequestArgumentsKey
));
3083 if (!requestArgs
|| !requestArgs
->getCount()) {
3084 OSKextLog(/* kext */ NULL
,
3085 kOSKextLogErrorLevel
|
3087 "Received kext load request with no arguments.");
3088 result
= kOSKextReturnInvalidArgument
;
3092 kextIdentifier
= OSDynamicCast(OSString
,
3093 requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
));
3094 if (!kextIdentifier
) {
3095 OSKextLog(/* kext */ NULL
,
3096 kOSKextLogErrorLevel
|
3098 "Received kext load request with no kext identifier.");
3099 result
= kOSKextReturnInvalidArgument
;
3103 startKextExcludeNum
= OSDynamicCast(OSNumber
,
3104 requestArgs
->getObject(kKextRequestArgumentStartExcludeKey
));
3105 startMatchingExcludeNum
= OSDynamicCast(OSNumber
,
3106 requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
));
3107 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
3108 requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
));
3109 personalityNames
= OSDynamicCast(OSArray
,
3110 requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
));
3112 if (delayAutounloadBool
) {
3113 delayAutounload
= delayAutounloadBool
->getValue();
3115 if (startKextExcludeNum
) {
3116 startKextExcludeLevel
= startKextExcludeNum
->unsigned8BitValue();
3118 if (startMatchingExcludeNum
) {
3119 startMatchingExcludeLevel
= startMatchingExcludeNum
->unsigned8BitValue();
3122 OSKextLog(/* kext */ NULL
,
3123 kOSKextLogProgressLevel
|
3125 "Received request from user space to load kext %s.",
3126 kextIdentifier
->getCStringNoCopy());
3128 /* Load the kext, with no deferral, since this is a load from outside
3130 * xxx - Would like a better way to handle the default values for the
3131 * xxx - start/match opt args.
3133 result
= OSKext::loadKextWithIdentifier(
3135 /* allowDefer */ false,
3137 startKextExcludeLevel
,
3138 startMatchingExcludeLevel
,
3140 if (result
!= kOSReturnSuccess
) {
3143 /* If the load came down from kextd, it will shortly inform IOCatalogue
3144 * for matching via a separate IOKit calldown.
3149 /* Gather up the collected log messages for user space. Any
3150 * error messages past this call will not make it up as log messages
3151 * but will be in the system log.
3153 logInfoArray
= OSKext::clearUserSpaceLogFilter();
3155 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
3156 tempResult
= OSKext::serializeLogInfo(logInfoArray
,
3157 logInfoOut
, logInfoLengthOut
);
3158 if (tempResult
!= kOSReturnSuccess
) {
3159 result
= tempResult
;
3163 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3165 /* Note: mkextDataObject will have been retained by every kext w/an
3166 * executable in it. That should all have been flushed out at the
3167 * and of the load operation, but you never know....
3169 if (mkextData
&& mkextData
->getRetainCount() > 1) {
3170 OSKextLog(/* kext */ NULL
,
3171 kOSKextLogErrorLevel
|
3172 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3173 "Kext load request buffer from user space still retained by a kext; "
3174 "probable memory leak.");
3177 IORecursiveLockUnlock(sKextLock
);
3179 OSSafeReleaseNULL(mkextData
);
3180 OSSafeReleaseNULL(mkextPlist
);
3181 OSSafeReleaseNULL(serializer
);
3182 OSSafeReleaseNULL(logInfoArray
);
3187 /*********************************************************************
3188 *********************************************************************/
3191 OSKext::serializeLogInfo(
3192 OSArray
* logInfoArray
,
3194 uint32_t * logInfoLengthOut
)
3196 OSReturn result
= kOSReturnError
;
3197 char * buffer
= NULL
;
3198 kern_return_t kmem_result
= KERN_FAILURE
;
3199 OSSerialize
* serializer
= NULL
; // must release; reused
3200 char * logInfo
= NULL
; // returned by reference
3201 uint32_t logInfoLength
= 0;
3203 if (!logInfoArray
|| !logInfoOut
|| !logInfoLengthOut
) {
3204 OSKextLog(/* kext */ NULL
,
3205 kOSKextLogErrorLevel
|
3207 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3208 /* Bad programmer. */
3209 result
= kOSKextReturnInvalidArgument
;
3213 serializer
= OSSerialize::withCapacity(0);
3215 OSKextLog(/* kext */ NULL
,
3216 kOSKextLogErrorLevel
|
3218 "Failed to create serializer on log info for request from user space.");
3219 /* Incidental error; we're going to (try to) allow the request
3220 * itself to succeed. */
3223 if (!logInfoArray
->serialize(serializer
)) {
3224 OSKextLog(/* kext */ NULL
,
3225 kOSKextLogErrorLevel
|
3227 "Failed to serialize log info for request from user space.");
3228 /* Incidental error; we're going to (try to) allow the request
3229 * itself to succeed. */
3231 logInfo
= serializer
->text();
3232 logInfoLength
= serializer
->getLength();
3234 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
, round_page(logInfoLength
), VM_KERN_MEMORY_OSKEXT
);
3235 if (kmem_result
!= KERN_SUCCESS
) {
3236 OSKextLog(/* kext */ NULL
,
3237 kOSKextLogErrorLevel
|
3239 "Failed to copy log info for request from user space.");
3240 /* Incidental error; we're going to (try to) allow the request
3243 /* 11981737 - clear uninitialized data in last page */
3244 bzero((void *)(buffer
+ logInfoLength
),
3245 (round_page(logInfoLength
) - logInfoLength
));
3246 memcpy(buffer
, logInfo
, logInfoLength
);
3247 *logInfoOut
= buffer
;
3248 *logInfoLengthOut
= logInfoLength
;
3252 result
= kOSReturnSuccess
;
3254 OSSafeReleaseNULL(serializer
);
3259 #pragma mark Instance Management Methods
3261 /*********************************************************************
3262 *********************************************************************/
3264 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
)
3266 OSKext
* foundKext
= NULL
;
3268 IORecursiveLockLock(sKextLock
);
3269 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3271 foundKext
->retain();
3273 IORecursiveLockUnlock(sKextLock
);
3278 /*********************************************************************
3279 *********************************************************************/
3281 OSKext::lookupKextWithIdentifier(OSString
* kextIdentifier
)
3283 return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy());
3286 /*********************************************************************
3287 *********************************************************************/
3289 OSKext::lookupKextWithLoadTag(uint32_t aTag
)
3291 OSKext
* foundKext
= NULL
; // returned
3294 IORecursiveLockLock(sKextLock
);
3296 count
= sLoadedKexts
->getCount();
3297 for (i
= 0; i
< count
; i
++) {
3298 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3299 if (thisKext
->getLoadTag() == aTag
) {
3300 foundKext
= thisKext
;
3301 foundKext
->retain();
3307 IORecursiveLockUnlock(sKextLock
);
3312 /*********************************************************************
3313 *********************************************************************/
3315 OSKext::lookupKextWithAddress(vm_address_t address
)
3317 OSKext
* foundKext
= NULL
; // returned
3320 IORecursiveLockLock(sKextLock
);
3322 count
= sLoadedKexts
->getCount();
3323 for (i
= 0; i
< count
; i
++) {
3324 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3325 if (thisKext
->linkedExecutable
) {
3326 vm_address_t kext_start
=
3327 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy();
3328 vm_address_t kext_end
= kext_start
+
3329 thisKext
->linkedExecutable
->getLength();
3330 if ((kext_start
<= address
) && (address
< kext_end
)) {
3331 foundKext
= thisKext
;
3332 foundKext
->retain();
3339 IORecursiveLockUnlock(sKextLock
);
3345 OSKext::copyKextUUIDForAddress(OSNumber
*address
)
3347 OSData
*uuid
= NULL
;
3353 uintptr_t addr
= (uintptr_t)address
->unsigned64BitValue() + vm_kernel_slide
;
3356 /* Is the calling process allowed to query kext info? */
3357 if (current_task() != kernel_task
) {
3358 int macCheckResult
= 0;
3359 kauth_cred_t cred
= NULL
;
3361 cred
= kauth_cred_get_with_ref();
3362 macCheckResult
= mac_kext_check_query(cred
);
3363 kauth_cred_unref(&cred
);
3365 if (macCheckResult
!= 0) {
3366 OSKextLog(/* kext */ NULL
,
3367 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
3368 "Failed to query kext UUID (MAC policy error 0x%x).",
3375 if (((vm_offset_t
)addr
>= vm_kernel_stext
) && ((vm_offset_t
)addr
< vm_kernel_etext
)) {
3376 /* address in xnu proper */
3377 unsigned long uuid_len
= 0;
3378 uuid
= OSData::withBytes(getuuidfromheader(&_mh_execute_header
, &uuid_len
), uuid_len
);
3380 IOLockLock(sKextSummariesLock
);
3381 OSKextLoadedKextSummary
*summary
= OSKext::summaryForAddress(addr
);
3383 uuid
= OSData::withBytes(summary
->uuid
, sizeof(uuid_t
));
3385 IOLockUnlock(sKextSummariesLock
);
3391 /*********************************************************************
3392 *********************************************************************/
3394 OSKext::lookupKextWithUUID(uuid_t wanted
)
3396 OSKext
* foundKext
= NULL
; // returned
3399 IORecursiveLockLock(sKextLock
);
3401 count
= sLoadedKexts
->getCount();
3403 for (i
= 0; i
< count
; i
++) {
3404 OSKext
* thisKext
= NULL
;
3406 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3411 OSData
*uuid_data
= thisKext
->copyUUID();
3417 memcpy(&uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
3418 uuid_data
->release();
3420 if (0 == uuid_compare(wanted
, uuid
)) {
3421 foundKext
= thisKext
;
3422 foundKext
->retain();
3429 IORecursiveLockUnlock(sKextLock
);
3437 /*********************************************************************
3438 *********************************************************************/
3440 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
)
3442 bool result
= false;
3443 OSKext
* foundKext
= NULL
; // returned
3445 IORecursiveLockLock(sKextLock
);
3447 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3448 if (foundKext
&& foundKext
->isLoaded()) {
3452 IORecursiveLockUnlock(sKextLock
);
3457 /*********************************************************************
3458 * xxx - should spawn a separate thread so a kext can safely have
3459 * xxx - itself unloaded.
3460 *********************************************************************/
3468 bool terminateServicesAndRemovePersonalitiesFlag
)
3472 kOSKextLogErrorLevel
|
3473 kOSKextLogKextBookkeepingFlag
,
3474 "removeKext() called for %s, not supported on embedded",
3475 aKext
->getIdentifier() ? aKext
->getIdentifierCString() : "unknown kext");
3477 return kOSReturnSuccess
;
3478 #else /* CONFIG_EMBEDDED */
3480 OSReturn result
= kOSKextReturnInUse
;
3481 OSKext
* checkKext
= NULL
; // do not release
3483 int macCheckResult
= 0;
3484 kauth_cred_t cred
= NULL
;
3487 IORecursiveLockLock(sKextLock
);
3489 /* If the kext has no identifier, it failed to init
3490 * so isn't in sKextsByID and it isn't loaded.
3492 if (!aKext
->getIdentifier()) {
3493 result
= kOSReturnSuccess
;
3497 checkKext
= OSDynamicCast(OSKext
,
3498 sKextsByID
->getObject(aKext
->getIdentifier()));
3499 if (checkKext
!= aKext
) {
3500 result
= kOSKextReturnNotFound
;
3504 if (aKext
->isLoaded()) {
3506 if (current_task() != kernel_task
) {
3507 cred
= kauth_cred_get_with_ref();
3508 macCheckResult
= mac_kext_check_unload(cred
, aKext
->getIdentifierCString());
3509 kauth_cred_unref(&cred
);
3512 if (macCheckResult
!= 0) {
3513 result
= kOSReturnError
;
3515 kOSKextLogErrorLevel
|
3516 kOSKextLogKextBookkeepingFlag
,
3517 "Failed to remove kext %s (MAC policy error 0x%x).",
3518 aKext
->getIdentifierCString(), macCheckResult
);
3523 /* make sure there are no resource requests in flight - 17187548 */
3524 if (aKext
->countRequestCallbacks()) {
3528 /* If we are terminating, send the request to the IOCatalogue
3529 * (which will actually call us right back but that's ok we have
3530 * a recursive lock don't you know) but do not ask the IOCatalogue
3531 * to call back with an unload, we'll do that right here.
3533 if (terminateServicesAndRemovePersonalitiesFlag
) {
3534 result
= gIOCatalogue
->terminateDriversForModule(
3535 aKext
->getIdentifierCString(), /* unload */ false);
3536 if (result
!= kOSReturnSuccess
) {
3538 kOSKextLogErrorLevel
|
3539 kOSKextLogKextBookkeepingFlag
,
3540 "Can't remove kext %s; services failed to terminate - 0x%x.",
3541 aKext
->getIdentifierCString(), result
);
3546 result
= aKext
->unload();
3547 if (result
!= kOSReturnSuccess
) {
3552 /* Remove personalities as requested. This is a bit redundant for a loaded
3553 * kext as IOCatalogue::terminateDriversForModule() removes driver
3554 * personalities, but it doesn't restart matching, which we always want
3555 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3558 if (terminateServicesAndRemovePersonalitiesFlag
) {
3559 aKext
->removePersonalitiesFromCatalog();
3563 kOSKextLogProgressLevel
|
3564 kOSKextLogKextBookkeepingFlag
,
3565 "Removing kext %s.",
3566 aKext
->getIdentifierCString());
3568 sKextsByID
->removeObject(aKext
->getIdentifier());
3569 result
= kOSReturnSuccess
;
3572 IORecursiveLockUnlock(sKextLock
);
3574 #endif /* CONFIG_EMBEDDED */
3577 /*********************************************************************
3578 *********************************************************************/
3581 OSKext::removeKextWithIdentifier(
3582 const char * kextIdentifier
,
3583 bool terminateServicesAndRemovePersonalitiesFlag
)
3585 OSReturn result
= kOSReturnError
;
3587 IORecursiveLockLock(sKextLock
);
3589 OSKext
* aKext
= OSDynamicCast(OSKext
,
3590 sKextsByID
->getObject(kextIdentifier
));
3592 result
= kOSKextReturnNotFound
;
3593 OSKextLog(/* kext */ NULL
,
3594 kOSKextLogErrorLevel
|
3595 kOSKextLogKextBookkeepingFlag
,
3596 "Can't remove kext %s - not found.",
3601 result
= OSKext::removeKext(aKext
,
3602 terminateServicesAndRemovePersonalitiesFlag
);
3605 IORecursiveLockUnlock(sKextLock
);
3610 /*********************************************************************
3611 *********************************************************************/
3614 OSKext::removeKextWithLoadTag(
3615 OSKextLoadTag loadTag
,
3616 bool terminateServicesAndRemovePersonalitiesFlag
)
3618 OSReturn result
= kOSReturnError
;
3619 OSKext
* foundKext
= NULL
;
3622 IORecursiveLockLock(sKextLock
);
3624 count
= sLoadedKexts
->getCount();
3625 for (i
= 0; i
< count
; i
++) {
3626 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3627 if (thisKext
->loadTag
== loadTag
) {
3628 foundKext
= thisKext
;
3634 result
= kOSKextReturnNotFound
;
3635 OSKextLog(/* kext */ NULL
,
3636 kOSKextLogErrorLevel
|
3637 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
3638 "Can't remove kext with load tag %d - not found.",
3643 result
= OSKext::removeKext(foundKext
,
3644 terminateServicesAndRemovePersonalitiesFlag
);
3647 IORecursiveLockUnlock(sKextLock
);
3652 /*********************************************************************
3653 *********************************************************************/
3655 OSKext::copyKexts(void)
3657 OSDictionary
* result
;
3659 IORecursiveLockLock(sKextLock
);
3660 result
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection());
3661 IORecursiveLockUnlock(sKextLock
);
3666 /*********************************************************************
3667 *********************************************************************/
3668 #define BOOTER_KEXT_PREFIX "Driver-"
3670 typedef struct _DeviceTreeBuffer
{
3673 } _DeviceTreeBuffer
;
3675 /*********************************************************************
3676 * Create a dictionary of excluded kexts from the given booter data.
3677 *********************************************************************/
3680 OSKext::createExcludeListFromBooterData(
3681 OSDictionary
* theDictionary
,
3682 OSCollectionIterator
* theIterator
)
3684 OSString
* deviceTreeName
= NULL
; // do not release
3685 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not release
3686 char * booterDataPtr
= NULL
; // do not release
3687 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not release
3688 char * infoDictAddr
= NULL
; // do not release
3689 OSObject
* parsedXML
= NULL
; // must release
3690 OSDictionary
* theInfoDict
= NULL
; // do not release
3692 theIterator
->reset();
3694 /* look for AppleKextExcludeList.kext */
3695 while ( (deviceTreeName
=
3696 OSDynamicCast(OSString
, theIterator
->getNextObject())) ) {
3698 const char * devTreeNameCString
;
3699 OSData
* deviceTreeEntry
;
3700 OSString
* myBundleID
; // do not release
3702 OSSafeReleaseNULL(parsedXML
);
3705 OSDynamicCast(OSData
, theDictionary
->getObject(deviceTreeName
));
3706 if (!deviceTreeEntry
) {
3710 /* Make sure it is a kext */
3711 devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
3712 if (strncmp(devTreeNameCString
, BOOTER_KEXT_PREFIX
,
3713 (sizeof(BOOTER_KEXT_PREFIX
) - 1)) != 0) {
3715 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3716 "\"%s\" not a kext",
3717 devTreeNameCString
);
3721 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
3722 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
3723 if (!deviceTreeBuffer
) {
3727 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
3728 if (!booterDataPtr
) {
3732 kextFileInfo
= (_BooterKextFileInfo
*) booterDataPtr
;
3733 if (!kextFileInfo
->infoDictPhysAddr
||
3734 !kextFileInfo
->infoDictLength
) {
3738 infoDictAddr
= (char *)
3739 ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
3740 if (!infoDictAddr
) {
3744 parsedXML
= OSUnserializeXML(infoDictAddr
);
3749 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
3755 OSDynamicCast(OSString
,
3756 theInfoDict
->getObject(kCFBundleIdentifierKey
));
3758 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3760 /* get copy of exclusion list dictionary */
3761 OSDictionary
* myTempDict
; // do not free
3763 myTempDict
= OSDynamicCast(
3765 theInfoDict
->getObject("OSKextExcludeList"));
3766 if ( NULL
== myTempDict
) {
3768 panic("Missing OSKextExcludeList dictionary\n");
3771 IORecursiveLockLock(sKextLock
);
3773 /* get rid of old exclusion list */
3774 if (sExcludeListByID
) {
3775 OSSafeReleaseNULL(sExcludeListByID
);
3777 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3778 IORecursiveLockUnlock(sKextLock
);
3783 } // while ( (deviceTreeName = ...) )
3785 OSSafeReleaseNULL(parsedXML
);
3789 /*********************************************************************
3790 * Create a dictionary of excluded kexts from the given prelink
3791 * info (kernelcache).
3792 *********************************************************************/
3795 OSKext::createExcludeListFromPrelinkInfo( OSArray
* theInfoArray
)
3797 OSDictionary
* myInfoDict
= NULL
; // do not release
3798 OSString
* myBundleID
; // do not release
3801 /* Find com.apple.driver.KextExcludeList. */
3802 for (i
= 0; i
< theInfoArray
->getCount(); i
++) {
3803 myInfoDict
= OSDynamicCast(OSDictionary
, theInfoArray
->getObject(i
));
3808 OSDynamicCast(OSString
,
3809 myInfoDict
->getObject(kCFBundleIdentifierKey
));
3811 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3812 // get copy of exclude list dictionary
3813 OSDictionary
* myTempDict
; // do not free
3814 myTempDict
= OSDynamicCast(OSDictionary
,
3815 myInfoDict
->getObject("OSKextExcludeList"));
3816 if ( NULL
== myTempDict
) {
3818 panic("Missing OSKextExcludeList dictionary\n");
3821 IORecursiveLockLock(sKextLock
);
3822 // get rid of old exclude list
3823 if (sExcludeListByID
) {
3824 OSSafeReleaseNULL(sExcludeListByID
);
3827 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3828 IORecursiveLockUnlock(sKextLock
);
3831 } // for (i = 0; i < theInfoArray->getCount()...
3837 #pragma mark Accessors
3839 /*********************************************************************
3840 *********************************************************************/
3842 OSKext::getIdentifier(void)
3847 /*********************************************************************
3848 * A kext must have a bundle identifier to even survive initialization;
3849 * this is guaranteed to exist past then.
3850 *********************************************************************/
3852 OSKext::getIdentifierCString(void)
3854 return bundleID
->getCStringNoCopy();
3857 /*********************************************************************
3858 *********************************************************************/
3860 OSKext::getVersion(void)
3865 /*********************************************************************
3866 *********************************************************************/
3868 OSKext::getCompatibleVersion(void)
3870 return compatibleVersion
;
3873 /*********************************************************************
3874 *********************************************************************/
3876 OSKext::isLibrary(void)
3878 return (getCompatibleVersion() > 0);
3881 /*********************************************************************
3882 *********************************************************************/
3884 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
)
3886 if ((compatibleVersion
> -1 && version
> -1) &&
3887 (compatibleVersion
<= version
&& aVersion
<= version
)) {
3893 /*********************************************************************
3894 *********************************************************************/
3896 OSKext::declaresExecutable(void)
3898 return (getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
);
3901 /*********************************************************************
3902 *********************************************************************/
3904 OSKext::getExecutable(void)
3906 OSData
* result
= NULL
;
3907 OSData
* extractedExecutable
= NULL
; // must release
3908 OSData
* mkextExecutableRef
= NULL
; // do not release
3910 result
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
));
3915 mkextExecutableRef
= OSDynamicCast(OSData
,
3916 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
));
3918 if (mkextExecutableRef
) {
3920 MkextEntryRef
* mkextEntryRef
= (MkextEntryRef
*)
3921 mkextExecutableRef
->getBytesNoCopy();
3922 uint32_t mkextVersion
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
);
3923 if (mkextVersion
== MKEXT_VERS_2
) {
3924 mkext2_file_entry
* fileinfo
=
3925 (mkext2_file_entry
*)mkextEntryRef
->fileinfo
;
3926 uint32_t compressedSize
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
);
3927 uint32_t fullSize
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
);
3928 extractedExecutable
= extractMkext2FileData(
3929 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable",
3930 compressedSize
, fullSize
);
3932 OSKextLog(this, kOSKextLogErrorLevel
|
3933 kOSKextLogArchiveFlag
,
3934 "Kext %s - unknown mkext version 0x%x for executable.",
3935 getIdentifierCString(), mkextVersion
);
3938 /* Regardless of success, remove the mkext executable,
3939 * and drop one reference on the mkext. (setExecutable() does not
3940 * replace, it removes, or panics if asked to replace.)
3942 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
3943 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
3945 if (extractedExecutable
&& extractedExecutable
->getLength()) {
3946 if (!setExecutable(extractedExecutable
)) {
3949 result
= extractedExecutable
;
3957 OSSafeReleaseNULL(extractedExecutable
);
3962 /*********************************************************************
3963 *********************************************************************/
3965 OSKext::isInterface(void)
3967 return flags
.interface
;
3970 /*********************************************************************
3971 *********************************************************************/
3973 OSKext::isKernel(void)
3975 return (this == sKernelKext
);
3978 /*********************************************************************
3979 *********************************************************************/
3981 OSKext::isKernelComponent(void)
3983 return flags
.kernelComponent
? true : false;
3986 /*********************************************************************
3987 *********************************************************************/
3989 OSKext::isExecutable(void)
3991 return (!isKernel() && !isInterface() && declaresExecutable());
3994 /*********************************************************************
3995 * We might want to check this recursively for all dependencies,
3996 * since a subtree of dependencies could get loaded before we hit
3997 * a dependency that isn't safe-boot-loadable.
3999 * xxx - Might want to return false if OSBundleEnableKextLogging or
4000 * OSBundleDebugLevel
4001 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4002 * the point except it's usually development drivers, which might
4003 * cause panics on startup, that have those properties). Heh; could
4004 * use a "kx" boot-arg!
4005 *********************************************************************/
4007 OSKext::isLoadableInSafeBoot(void)
4009 bool result
= false;
4010 OSString
* required
= NULL
; // do not release
4017 required
= OSDynamicCast(OSString
,
4018 getPropertyForHostArch(kOSBundleRequiredKey
));
4022 if (required
->isEqualTo(kOSBundleRequiredRoot
) ||
4023 required
->isEqualTo(kOSBundleRequiredLocalRoot
) ||
4024 required
->isEqualTo(kOSBundleRequiredNetworkRoot
) ||
4025 required
->isEqualTo(kOSBundleRequiredSafeBoot
) ||
4026 required
->isEqualTo(kOSBundleRequiredConsole
)) {
4035 /*********************************************************************
4036 *********************************************************************/
4038 OSKext::isPrelinked(void)
4040 return flags
.prelinked
? true : false;
4043 /*********************************************************************
4044 *********************************************************************/
4045 bool OSKext::isLoaded(void)
4047 return flags
.loaded
? true : false;
4050 /*********************************************************************
4051 *********************************************************************/
4053 OSKext::isStarted(void)
4055 return flags
.started
? true : false;
4058 /*********************************************************************
4059 *********************************************************************/
4061 OSKext::isCPPInitialized(void)
4063 return flags
.CPPInitialized
;
4066 /*********************************************************************
4067 *********************************************************************/
4069 OSKext::setCPPInitialized(bool initialized
)
4071 flags
.CPPInitialized
= initialized
;
4074 /*********************************************************************
4075 *********************************************************************/
4077 OSKext::getLoadTag(void)
4082 /*********************************************************************
4083 *********************************************************************/
4084 void OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
)
4086 if (linkedExecutable
) {
4087 *loadSize
= linkedExecutable
->getLength();
4089 /* If we have a kmod_info struct, calculated the wired size
4090 * from that. Otherwise it's the full load size.
4093 *wiredSize
= *loadSize
- kmod_info
->hdr_size
;
4095 *wiredSize
= *loadSize
;
4104 /*********************************************************************
4105 *********************************************************************/
4107 OSKext::copyUUID(void)
4109 OSData
* result
= NULL
;
4110 OSData
* theExecutable
= NULL
; // do not release
4111 const kernel_mach_header_t
* header
= NULL
;
4112 const struct load_command
* load_cmd
= NULL
;
4113 const struct uuid_command
* uuid_cmd
= NULL
;
4116 /* An interface kext doesn't have a linked executable with an LC_UUID,
4117 * we create one when it's linked.
4119 if (interfaceUUID
) {
4120 result
= interfaceUUID
;
4125 /* For real kexts, try to get the UUID from the linked executable,
4126 * or if is hasn't been linked yet, the unrelocated executable.
4128 theExecutable
= linkedExecutable
;
4129 if (!theExecutable
) {
4130 theExecutable
= getExecutable();
4132 if (!theExecutable
) {
4136 header
= (const kernel_mach_header_t
*)theExecutable
->getBytesNoCopy();
4137 load_cmd
= (const struct load_command
*)&header
[1];
4139 if (header
->magic
!= MH_MAGIC_KERNEL
) {
4141 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4142 "%s: bad header %p",
4148 for (i
= 0; i
< header
->ncmds
; i
++) {
4149 if (load_cmd
->cmd
== LC_UUID
) {
4150 uuid_cmd
= (struct uuid_command
*)load_cmd
;
4151 result
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
));
4154 load_cmd
= (struct load_command
*)((caddr_t
)load_cmd
+ load_cmd
->cmdsize
);
4161 /*********************************************************************
4162 *********************************************************************/
4163 #if defined (__arm__)
4164 #include <arm/arch.h>
4167 #if defined (__x86_64__)
4168 #define ARCHNAME "x86_64"
4169 #elif defined (__arm64__)
4170 #define ARCHNAME "arm64"
4171 #elif defined (__arm__)
4173 #if defined (__ARM_ARCH_7S__)
4174 #define ARCHNAME "armv7s"
4175 #elif defined (__ARM_ARCH_7F__)
4176 #define ARCHNAME "armv7f"
4177 #elif defined (__ARM_ARCH_7K__)
4178 #define ARCHNAME "armv7k"
4179 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
4180 #define ARCHNAME "armv7"
4181 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
4182 #define ARCHNAME "armv6"
4185 #elif defined (__arm64__)
4186 #define ARCHNAME "arm64"
4188 #error architecture not supported
4191 #define ARCH_SEPARATOR_CHAR '_'
4193 static char * makeHostArchKey(const char * key
, uint32_t * keySizeOut
)
4195 char * result
= NULL
;
4196 uint32_t keyLength
= strlen(key
);
4199 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4201 keySize
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
);
4202 result
= (char *)kalloc_tag(keySize
, VM_KERN_MEMORY_OSKEXT
);
4206 strlcpy(result
, key
, keySize
);
4207 result
[keyLength
++] = ARCH_SEPARATOR_CHAR
;
4208 result
[keyLength
] = '\0';
4209 strlcat(result
, ARCHNAME
, keySize
);
4210 *keySizeOut
= keySize
;
4216 /*********************************************************************
4217 *********************************************************************/
4219 OSKext::getPropertyForHostArch(const char * key
)
4221 OSObject
* result
= NULL
; // do not release
4222 uint32_t hostArchKeySize
= 0;
4223 char * hostArchKey
= NULL
; // must kfree
4225 if (!key
|| !infoDict
) {
4229 /* Some properties are not allowed to be arch-variant:
4230 * - Any CFBundle... property.
4231 * - OSBundleIsInterface.
4232 * - OSKernelResource.
4234 if (STRING_HAS_PREFIX(key
, "OS") ||
4235 STRING_HAS_PREFIX(key
, "IO")) {
4237 hostArchKey
= makeHostArchKey(key
, &hostArchKeySize
);
4239 OSKextLog(/* kext (this isn't about a kext) */ NULL
,
4240 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4241 "Allocation failure.");
4244 result
= infoDict
->getObject(hostArchKey
);
4248 result
= infoDict
->getObject(key
);
4252 if (hostArchKey
) kfree(hostArchKey
, hostArchKeySize
);
4257 #pragma mark Load/Start/Stop/Unload
4260 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4262 /*********************************************************************
4263 * sExcludeListByID is a dictionary with keys / values of:
4264 * key = bundleID string of kext we will not allow to load
4265 * value = version string(s) of the kext that is to be denied loading.
4266 * The version strings can be comma delimited. For example if kext
4267 * com.foocompany.fookext has two versions that we want to deny
4268 * loading then the version strings might look like:
4270 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4271 * not load the kext.
4273 * Value may also be in the form of "LE 2.0.0" (version numbers
4274 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4275 * number less than 2.0.0 will not load)
4277 * NOTE - we cannot use the characters "<=" or "<" because we have code
4278 * that serializes plists and treats '<' as a special character.
4279 *********************************************************************/
4281 OSKext::isInExcludeList(void)
4283 OSString
* versionString
= NULL
; // do not release
4284 char * versionCString
= NULL
; // do not free
4286 boolean_t wantLessThan
= false;
4287 boolean_t wantLessThanEqualTo
= false;
4290 if (!sExcludeListByID
) {
4293 /* look up by bundleID in our exclude list and if found get version
4294 * string (or strings) that we will not allow to load
4296 versionString
= OSDynamicCast(OSString
, sExcludeListByID
->getObject(bundleID
));
4297 if (versionString
== NULL
|| versionString
->getLength() > (sizeof(myBuffer
) - 1)) {
4301 /* parse version strings */
4302 versionCString
= (char *) versionString
->getCStringNoCopy();
4304 /* look for "LT" or "LE" form of version string, must be in first two
4307 if (*versionCString
== 'L' && *(versionCString
+ 1) == 'T') {
4308 wantLessThan
= true;
4311 else if (*versionCString
== 'L' && *(versionCString
+ 1) == 'E') {
4312 wantLessThanEqualTo
= true;
4316 for (i
= 0; *versionCString
!= 0x00; versionCString
++) {
4317 /* skip whitespace */
4318 if (isWhiteSpace(*versionCString
)) {
4322 /* peek ahead for version string separator or null terminator */
4323 if (*(versionCString
+ 1) == ',' || *(versionCString
+ 1) == 0x00) {
4325 /* OK, we have a version string */
4326 myBuffer
[i
++] = *versionCString
;
4329 OSKextVersion excludeVers
;
4330 excludeVers
= OSKextParseVersionString(myBuffer
);
4332 if (wantLessThanEqualTo
) {
4333 if (version
<= excludeVers
) {
4337 else if (wantLessThan
) {
4338 if (version
< excludeVers
) {
4342 else if ( version
== excludeVers
) {
4346 /* reset for the next (if any) version string */
4348 wantLessThan
= false;
4349 wantLessThanEqualTo
= false;
4352 /* save valid version character */
4353 myBuffer
[i
++] = *versionCString
;
4355 /* make sure bogus version string doesn't overrun local buffer */
4356 if ( i
>= sizeof(myBuffer
) ) {
4365 /*********************************************************************
4366 *********************************************************************/
4369 OSKext::loadKextWithIdentifier(
4370 const char * kextIdentifierCString
,
4371 Boolean allowDeferFlag
,
4372 Boolean delayAutounloadFlag
,
4373 OSKextExcludeLevel startOpt
,
4374 OSKextExcludeLevel startMatchingOpt
,
4375 OSArray
* personalityNames
)
4377 OSReturn result
= kOSReturnError
;
4378 OSString
* kextIdentifier
= NULL
; // must release
4380 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
4381 if (!kextIdentifier
) {
4382 result
= kOSKextReturnNoMemory
;
4385 result
= OSKext::loadKextWithIdentifier(kextIdentifier
,
4386 allowDeferFlag
, delayAutounloadFlag
,
4387 startOpt
, startMatchingOpt
, personalityNames
);
4390 OSSafeReleaseNULL(kextIdentifier
);
4394 /*********************************************************************
4395 *********************************************************************/
4397 OSKext::loadKextWithIdentifier(
4398 OSString
* kextIdentifier
,
4399 Boolean allowDeferFlag
,
4400 Boolean delayAutounloadFlag
,
4401 OSKextExcludeLevel startOpt
,
4402 OSKextExcludeLevel startMatchingOpt
,
4403 OSArray
* personalityNames
)
4405 OSReturn result
= kOSReturnError
;
4406 OSReturn pingResult
= kOSReturnError
;
4407 OSKext
* theKext
= NULL
; // do not release
4408 OSDictionary
* loadRequest
= NULL
; // must release
4409 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4411 IORecursiveLockLock(sKextLock
);
4413 if (!kextIdentifier
) {
4414 result
= kOSKextReturnInvalidArgument
;
4418 OSKext::recordIdentifierRequest(kextIdentifier
);
4420 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
4422 if (!allowDeferFlag
) {
4423 OSKextLog(/* kext */ NULL
,
4424 kOSKextLogErrorLevel
|
4426 "Can't load kext %s - not found.",
4427 kextIdentifier
->getCStringNoCopy());
4431 if (!sKernelRequestsEnabled
) {
4433 kOSKextLogErrorLevel
|
4435 "Can't load kext %s - requests to user space are disabled.",
4436 kextIdentifier
->getCStringNoCopy());
4437 result
= kOSKextReturnDisabled
;
4441 /* Create a new request unless one is already sitting
4442 * in sKernelRequests for this bundle identifier
4444 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4445 if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4446 result
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
,
4448 if (result
!= kOSReturnSuccess
) {
4451 if (!_OSKextSetRequestArgument(loadRequest
,
4452 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
4454 result
= kOSKextReturnNoMemory
;
4457 if (!sKernelRequests
->setObject(loadRequest
)) {
4458 result
= kOSKextReturnNoMemory
;
4462 if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4463 result
= kOSKextReturnNoMemory
;
4468 kOSKextLogDebugLevel
|
4470 "Kext %s not found; queued load request to user space.",
4471 kextIdentifier
->getCStringNoCopy());
4474 pingResult
= OSKext::pingKextd();
4475 if (pingResult
== kOSKextReturnDisabled
) {
4476 OSKextLog(/* kext */ NULL
,
4477 ((sPrelinkBoot
) ? kOSKextLogDebugLevel
: kOSKextLogErrorLevel
) |
4479 "Kext %s might not load - kextd is currently unavailable.",
4480 kextIdentifier
->getCStringNoCopy());
4483 result
= kOSKextReturnDeferred
;
4487 result
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
);
4489 if (result
!= kOSReturnSuccess
) {
4491 kOSKextLogErrorLevel
|
4493 "Failed to load kext %s (error 0x%x).",
4494 kextIdentifier
->getCStringNoCopy(), (int)result
);
4496 OSKext::removeKext(theKext
,
4497 /* terminateService/removePersonalities */ true);
4501 if (delayAutounloadFlag
) {
4503 kOSKextLogProgressLevel
|
4504 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4505 "Setting delayed autounload for %s.",
4506 kextIdentifier
->getCStringNoCopy());
4507 theKext
->flags
.delayAutounload
= 1;
4511 OSSafeReleaseNULL(loadRequest
);
4512 OSSafeReleaseNULL(kextIdentifierSymbol
);
4514 IORecursiveLockUnlock(sKextLock
);
4519 /*********************************************************************
4520 *********************************************************************/
4523 OSKext::recordIdentifierRequest(
4524 OSString
* kextIdentifier
)
4526 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4529 if (!sAllKextLoadIdentifiers
|| !kextIdentifier
) {
4533 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4534 if (!kextIdentifierSymbol
) {
4535 // xxx - this is really a basic alloc failure
4540 IORecursiveLockLock(sKextLock
);
4541 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4542 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4545 // xxx - need to find a way to associate this whole func w/the kext
4546 OSKextLog(/* kext */ NULL
,
4547 // xxx - check level
4548 kOSKextLogStepLevel
|
4549 kOSKextLogArchiveFlag
,
4550 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4551 kextIdentifier
->getCStringNoCopy());
4554 IORecursiveLockUnlock(sKextLock
);
4559 OSKextLog(/* kext */ NULL
,
4560 kOSKextLogErrorLevel
|
4561 kOSKextLogArchiveFlag
,
4562 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4563 kextIdentifier
->getCStringNoCopy());
4565 OSSafeReleaseNULL(kextIdentifierSymbol
);
4569 /*********************************************************************
4570 *********************************************************************/
4573 OSKextExcludeLevel startOpt
,
4574 OSKextExcludeLevel startMatchingOpt
,
4575 OSArray
* personalityNames
)
4577 OSReturn result
= kOSReturnError
;
4578 kern_return_t kxldResult
;
4579 OSKextExcludeLevel dependenciesStartOpt
= startOpt
;
4580 OSKextExcludeLevel dependenciesStartMatchingOpt
= startMatchingOpt
;
4581 unsigned int i
, count
;
4582 Boolean alreadyLoaded
= false;
4583 OSKext
* lastLoadedKext
= NULL
;
4585 if (isInExcludeList()) {
4587 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
|
4589 "Kext %s is in exclude list, not loadable",
4590 getIdentifierCString());
4592 result
= kOSKextReturnNotLoadable
;
4597 alreadyLoaded
= true;
4598 result
= kOSReturnSuccess
;
4601 kOSKextLogDebugLevel
|
4602 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4603 "Kext %s is already loaded.",
4604 getIdentifierCString());
4609 if (current_task() != kernel_task
) {
4610 int macCheckResult
= 0;
4611 kauth_cred_t cred
= NULL
;
4613 cred
= kauth_cred_get_with_ref();
4614 macCheckResult
= mac_kext_check_load(cred
, getIdentifierCString());
4615 kauth_cred_unref(&cred
);
4617 if (macCheckResult
!= 0) {
4618 result
= kOSReturnError
;
4620 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4621 "Failed to load kext %s (MAC policy error 0x%x).",
4622 getIdentifierCString(), macCheckResult
);
4628 if (!sLoadEnabled
) {
4630 kOSKextLogErrorLevel
|
4632 "Kext loading is disabled (attempt to load kext %s).",
4633 getIdentifierCString());
4634 result
= kOSKextReturnDisabled
;
4638 /* If we've pushed the next available load tag to the invalid value,
4639 * we can't load any more kexts.
4641 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4643 kOSKextLogErrorLevel
|
4645 "Can't load kext %s - no more load tags to assign.",
4646 getIdentifierCString());
4647 result
= kOSKextReturnNoResources
;
4651 /* This is a bit of a hack, because we shouldn't be handling
4652 * personalities within the load function.
4654 if (!declaresExecutable()) {
4655 result
= kOSReturnSuccess
;
4659 /* Are we in safe boot?
4661 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4663 kOSKextLogErrorLevel
|
4665 "Can't load kext %s - not loadable during safe boot.",
4666 getIdentifierCString());
4667 result
= kOSKextReturnBootLevel
;
4672 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4674 getIdentifierCString());
4676 if (!sKxldContext
) {
4677 kxldResult
= kxld_create_context(&sKxldContext
, &kern_allocate
,
4678 &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,
4679 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
4682 kOSKextLogErrorLevel
|
4683 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4684 "Can't load kext %s - failed to create link context.",
4685 getIdentifierCString());
4686 result
= kOSKextReturnNoMemory
;
4691 /* We only need to resolve dependencies once for the whole graph, but
4692 * resolveDependencies will just return if there's no work to do, so it's
4693 * safe to call it more than once.
4695 if (!resolveDependencies()) {
4696 // xxx - check resolveDependencies() for log msg
4698 kOSKextLogErrorLevel
|
4699 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4700 "Can't load kext %s - failed to resolve library dependencies.",
4701 getIdentifierCString());
4702 result
= kOSKextReturnDependencies
;
4706 /* If we are excluding just the kext being loaded now (and not its
4707 * dependencies), drop the exclusion level to none so dependencies
4708 * start and/or add their personalities.
4710 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4711 dependenciesStartOpt
= kOSKextExcludeNone
;
4714 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4715 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4718 /* Load the dependencies, recursively.
4720 count
= getNumDependencies();
4721 for (i
= 0; i
< count
; i
++) {
4722 OSKext
* dependency
= OSDynamicCast(OSKext
,
4723 dependencies
->getObject(i
));
4724 if (dependency
== NULL
) {
4726 kOSKextLogErrorLevel
|
4727 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4728 "Internal error loading kext %s; dependency disappeared.",
4729 getIdentifierCString());
4730 result
= kOSKextReturnInternalError
;
4734 /* Dependencies must be started accorting to the opt,
4735 * but not given the personality names of the main kext.
4737 result
= dependency
->load(dependenciesStartOpt
,
4738 dependenciesStartMatchingOpt
,
4739 /* personalityNames */ NULL
);
4740 if (result
!= KERN_SUCCESS
) {
4742 kOSKextLogErrorLevel
|
4743 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4744 "Dependency %s of kext %s failed to load.",
4745 dependency
->getIdentifierCString(),
4746 getIdentifierCString());
4748 OSKext::removeKext(dependency
,
4749 /* terminateService/removePersonalities */ true);
4750 result
= kOSKextReturnDependencyLoadError
;
4756 result
= loadExecutable();
4757 if (result
!= KERN_SUCCESS
) {
4761 pendingPgoHead
.next
= &pendingPgoHead
;
4762 pendingPgoHead
.prev
= &pendingPgoHead
;
4764 uuid_generate(instance_uuid
);
4765 account
= IONew(OSKextAccount
, 1);
4767 result
= KERN_MEMORY_ERROR
;
4770 bzero(account
, sizeof(*account
));
4771 account
->loadTag
= kmod_info
->id
;
4772 account
->site
.refcount
= 0;
4773 account
->site
.flags
= VM_TAG_KMOD
;
4774 account
->kext
= this;
4776 flags
.loaded
= true;
4778 /* Add the kext to the list of loaded kexts and update the kmod_info
4779 * struct to point to that of the last loaded kext (which is the way
4780 * it's always been done, though I'd rather do them in order now).
4782 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
4783 sLoadedKexts
->setObject(this);
4785 /* Keep the kernel itself out of the kmod list.
4787 if (lastLoadedKext
->isKernel()) {
4788 lastLoadedKext
= NULL
;
4791 if (lastLoadedKext
) {
4792 kmod_info
->next
= lastLoadedKext
->kmod_info
;
4795 notifyKextLoadObservers(this, kmod_info
);
4797 /* Make the global kmod list point at the just-loaded kext. Note that the
4798 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4799 * although we do report it in kextstat these days by using the newer
4800 * OSArray of loaded kexts, which does contain it.
4802 * (The OSKext object representing the kernel doesn't even have a kmod_info
4803 * struct, though I suppose we could stick a pointer to it from the
4804 * static struct in OSRuntime.cpp.)
4808 /* Save the list of loaded kexts in case we panic.
4810 OSKext::saveLoadedKextPanicList();
4812 if (isExecutable()) {
4813 OSKext::updateLoadedKextSummaries();
4814 savePanicString(/* isLoading */ true);
4817 registerWithDTrace();
4819 jettisonLinkeditSegment();
4820 #endif /* CONFIG_DTRACE */
4822 #if !VM_MAPPED_KEXTS
4823 /* If there is a page (or more) worth of padding after the end
4824 * of the last data section but before the end of the data segment
4825 * then free it in the same manner the LinkeditSegment is freed
4827 jettisonDATASegmentPadding();
4832 if (isExecutable() && !flags
.started
) {
4833 if (startOpt
== kOSKextExcludeNone
) {
4835 if (result
!= kOSReturnSuccess
) {
4837 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4838 "Kext %s start failed (result 0x%x).",
4839 getIdentifierCString(), result
);
4840 result
= kOSKextReturnStartStopError
;
4845 /* If not excluding matching, send the personalities to the kernel.
4846 * This never affects the result of the load operation.
4847 * This is a bit of a hack, because we shouldn't be handling
4848 * personalities within the load function.
4850 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
4851 result
= sendPersonalitiesToCatalog(true, personalityNames
);
4856 /* More hack! If the kext doesn't declare an executable, even if we
4857 * "loaded" it, we have to remove any personalities naming it, or we'll
4858 * never see the registry go quiet. Errors here do not count for the
4859 * load operation itself.
4861 * Note that in every other regard it's perfectly ok for a kext to
4862 * not declare an executable and serve only as a package for personalities
4863 * naming another kext, so we do have to allow such kexts to be "loaded"
4864 * so that those other personalities get added & matched.
4866 if (!declaresExecutable()) {
4868 kOSKextLogStepLevel
| kOSKextLogLoadFlag
,
4869 "Kext %s has no executable; removing any personalities naming it.",
4870 getIdentifierCString());
4871 removePersonalitiesFromCatalog();
4874 if (result
!= kOSReturnSuccess
) {
4876 kOSKextLogErrorLevel
|
4878 "Kext %s failed to load (0x%x).",
4879 getIdentifierCString(), (int)result
);
4880 } else if (!alreadyLoaded
) {
4882 kOSKextLogProgressLevel
|
4885 getIdentifierCString());
4887 queueKextNotification(kKextRequestPredicateLoadNotification
,
4888 OSDynamicCast(OSString
, bundleID
));
4893 /*********************************************************************
4895 *********************************************************************/
4896 static char * strdup(const char * string
)
4898 char * result
= NULL
;
4905 size
= 1 + strlen(string
);
4906 result
= (char *)kalloc_tag(size
, VM_KERN_MEMORY_OSKEXT
);
4911 memcpy(result
, string
, size
);
4917 /*********************************************************************
4919 *********************************************************************/
4922 OSKext::lookupSection(const char *segname
, const char *secname
)
4924 kernel_section_t
* found_section
= NULL
;
4925 kernel_mach_header_t
* mh
= NULL
;
4926 kernel_segment_command_t
* seg
= NULL
;
4927 kernel_section_t
* sec
= NULL
;
4929 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4931 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4933 if (0 != strcmp(seg
->segname
, segname
)) {
4937 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4939 if (0 == strcmp(sec
->sectname
, secname
)) {
4940 found_section
= sec
;
4947 return found_section
;
4950 /*********************************************************************
4952 *********************************************************************/
4955 OSKext::slidePrelinkedExecutable(bool doCoalesedSlides
)
4957 OSReturn result
= kOSKextReturnBadData
;
4958 kernel_mach_header_t
* mh
= NULL
;
4959 kernel_segment_command_t
* seg
= NULL
;
4960 kernel_segment_command_t
* linkeditSeg
= NULL
;
4961 kernel_section_t
* sec
= NULL
;
4962 char * linkeditBase
= NULL
;
4963 bool haveLinkeditBase
= false;
4964 char * relocBase
= NULL
;
4965 bool haveRelocBase
= false;
4966 struct dysymtab_command
* dysymtab
= NULL
;
4967 struct linkedit_data_command
* segmentSplitInfo
= NULL
;
4968 struct symtab_command
* symtab
= NULL
;
4969 kernel_nlist_t
* sym
= NULL
;
4970 struct relocation_info
* reloc
= NULL
;
4973 vm_offset_t new_kextsize
;
4975 if (linkedExecutable
== NULL
|| vm_kernel_slide
== 0) {
4976 result
= kOSReturnSuccess
;
4980 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4981 segmentSplitInfo
= (struct linkedit_data_command
*) getcommandfromheader(mh
, LC_SEGMENT_SPLIT_INFO
);
4983 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4987 seg
->vmaddr
+= vm_kernel_slide
;
4989 #if KASLR_KEXT_DEBUG
4990 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
4992 (unsigned long)VM_KERNEL_UNSLIDE(seg
->vmaddr
),
4993 (unsigned long)seg
->vmaddr
);
4996 if (!haveRelocBase
) {
4997 relocBase
= (char *) seg
->vmaddr
;
4998 haveRelocBase
= true;
5000 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
5001 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
5002 haveLinkeditBase
= true;
5005 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
5006 sec
->addr
+= vm_kernel_slide
;
5008 #if KASLR_KEXT_DEBUG
5009 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
5011 (unsigned long)VM_KERNEL_UNSLIDE(sec
->addr
),
5012 (unsigned long)sec
->addr
);
5017 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
5019 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
5021 if (symtab
!= NULL
&& doCoalesedSlides
== false) {
5022 /* Some pseudo-kexts have symbol tables without segments.
5024 if (symtab
->nsyms
> 0 && haveLinkeditBase
) {
5025 sym
= (kernel_nlist_t
*) (linkeditBase
+ symtab
->symoff
);
5026 for (i
= 0; i
< symtab
->nsyms
; i
++) {
5027 if (sym
[i
].n_type
& N_STAB
) {
5030 sym
[i
].n_value
+= vm_kernel_slide
;
5032 #if KASLR_KEXT_DEBUG
5033 #define MAX_SYMS_TO_LOG 5
5034 if ( i
< MAX_SYMS_TO_LOG
) {
5035 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
5036 (unsigned long)VM_KERNEL_UNSLIDE(sym
[i
].n_value
),
5037 (unsigned long)sym
[i
].n_value
);
5044 if (dysymtab
!= NULL
&& doCoalesedSlides
== false) {
5045 if (dysymtab
->nextrel
> 0) {
5047 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5049 "Sliding kext %s: External relocations found.",
5050 getIdentifierCString());
5054 if (dysymtab
->nlocrel
> 0) {
5055 if (!haveLinkeditBase
) {
5057 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5059 "Sliding kext %s: No linkedit segment.",
5060 getIdentifierCString());
5064 if (!haveRelocBase
) {
5066 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5069 "Sliding kext %s: No writable segments.",
5071 "Sliding kext %s: No segments.",
5073 getIdentifierCString());
5077 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
5078 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
5080 for (i
= 0; i
< dysymtab
->nlocrel
; i
++) {
5081 if ( reloc
[i
].r_extern
!= 0
5082 || reloc
[i
].r_type
!= 0
5083 || reloc
[i
].r_length
!= (sizeof(void *) == 8 ? 3 : 2)
5086 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5088 "Sliding kext %s: Unexpected relocation found.",
5089 getIdentifierCString());
5092 if (reloc
[i
].r_pcrel
!= 0) {
5095 *((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)) += vm_kernel_slide
;
5097 #if KASLR_KEXT_DEBUG
5098 #define MAX_DYSYMS_TO_LOG 5
5099 if ( i
< MAX_DYSYMS_TO_LOG
) {
5100 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
5101 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
))),
5102 (unsigned long)*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)));
5107 /* We should free these relocations, not just delete the reference to them.
5108 * <rdar://problem/10535549> Free relocations from PIE kexts.
5110 * For now, we do not free LINKEDIT for kexts with split segments.
5112 new_kextsize
= round_page(kmod_info
->size
- reloc_size
);
5113 if (((kmod_info
->size
- new_kextsize
) > PAGE_SIZE
) && (!segmentSplitInfo
)) {
5114 vm_offset_t endofkext
= kmod_info
->address
+ kmod_info
->size
;
5115 vm_offset_t new_endofkext
= kmod_info
->address
+ new_kextsize
;
5116 vm_offset_t endofrelocInfo
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
);
5117 int bytes_remaining
= endofkext
- endofrelocInfo
;
5118 OSData
* new_osdata
= NULL
;
5120 /* fix up symbol offsets if they are after the dsymtab local relocs */
5122 if (dysymtab
->locreloff
< symtab
->symoff
){
5123 symtab
->symoff
-= reloc_size
;
5125 if (dysymtab
->locreloff
< symtab
->stroff
) {
5126 symtab
->stroff
-= reloc_size
;
5129 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
5130 dysymtab
->extreloff
-= reloc_size
;
5133 /* move data behind reloc info down to new offset */
5134 if (endofrelocInfo
< endofkext
) {
5135 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
5138 /* Create a new OSData for the smaller kext object and reflect
5139 * new linkedit segment size.
5141 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
5142 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
5144 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
5146 /* Fix up kmod info and linkedExecutable.
5148 kmod_info
->size
= new_kextsize
;
5150 new_osdata
->setDeallocFunction(osdata_kext_free
);
5152 new_osdata
->setDeallocFunction(osdata_phys_free
);
5154 linkedExecutable
->setDeallocFunction(NULL
);
5155 linkedExecutable
->release();
5156 linkedExecutable
= new_osdata
;
5159 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
5161 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
5165 dysymtab
->nlocrel
= 0;
5166 dysymtab
->locreloff
= 0;
5170 result
= kOSReturnSuccess
;
5175 /*********************************************************************
5176 * called only by load()
5177 *********************************************************************/
5179 OSKext::loadExecutable()
5181 OSReturn result
= kOSReturnError
;
5182 kern_return_t kxldResult
;
5183 KXLDDependency
* kxlddeps
= NULL
; // must kfree
5184 uint32_t num_kxlddeps
= 0;
5185 OSArray
* linkDependencies
= NULL
; // must release
5186 uint32_t numDirectDependencies
= 0;
5187 uint32_t num_kmod_refs
= 0;
5188 struct mach_header
** kxldHeaderPtr
= NULL
; // do not free
5189 struct mach_header
* kxld_header
= NULL
; // xxx - need to free here?
5190 OSData
* theExecutable
= NULL
; // do not release
5191 OSString
* versString
= NULL
; // do not release
5192 const char * versCString
= NULL
; // do not free
5193 const char * string
= NULL
; // do not free
5196 /* We need the version string for a variety of bits below.
5198 versString
= OSDynamicCast(OSString
,
5199 getPropertyForHostArch(kCFBundleVersionKey
));
5203 versCString
= versString
->getCStringNoCopy();
5205 if (isKernelComponent()) {
5206 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
5208 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
5210 kOSKextLogErrorLevel
|
5212 "Kernel component %s has incorrect version %s; "
5214 getIdentifierCString(),
5215 versCString
, KERNEL6_VERSION
);
5216 result
= kOSKextReturnInternalError
;
5218 } else if (strcmp(versCString
, osrelease
)) {
5220 kOSKextLogErrorLevel
|
5222 "Kernel component %s has incorrect version %s; "
5224 getIdentifierCString(),
5225 versCString
, osrelease
);
5226 result
= kOSKextReturnInternalError
;
5232 if (isPrelinked()) {
5236 /* <rdar://problem/21444003> all callers must be entitled */
5237 if (FALSE
== IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management")) {
5239 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5240 "Not entitled to link kext '%s'",
5241 getIdentifierCString());
5242 result
= kOSKextReturnNotPrivileged
;
5246 theExecutable
= getExecutable();
5247 if (!theExecutable
) {
5248 if (declaresExecutable()) {
5250 kOSKextLogErrorLevel
|
5252 "Can't load kext %s - executable is missing.",
5253 getIdentifierCString());
5254 result
= kOSKextReturnValidation
;
5260 if (isInterface()) {
5261 OSData
*executableCopy
= OSData::withData(theExecutable
);
5262 setLinkedExecutable(executableCopy
);
5263 executableCopy
->release();
5267 numDirectDependencies
= getNumDependencies();
5269 if (flags
.hasBleedthrough
) {
5270 linkDependencies
= dependencies
;
5271 linkDependencies
->retain();
5273 linkDependencies
= OSArray::withArray(dependencies
);
5274 if (!linkDependencies
) {
5276 kOSKextLogErrorLevel
|
5277 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5278 "Can't allocate link dependencies to load kext %s.",
5279 getIdentifierCString());
5283 for (i
= 0; i
< numDirectDependencies
; ++i
) {
5284 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
5285 dependencies
->getObject(i
));
5286 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
5290 num_kxlddeps
= linkDependencies
->getCount();
5291 if (!num_kxlddeps
) {
5293 kOSKextLogErrorLevel
|
5294 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
5295 "Can't load kext %s - it has no library dependencies.",
5296 getIdentifierCString());
5300 kxlddeps
= (KXLDDependency
*)kalloc_tag(num_kxlddeps
* sizeof(*kxlddeps
), VM_KERN_MEMORY_OSKEXT
);
5303 kOSKextLogErrorLevel
|
5304 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5305 "Can't allocate link context to load kext %s.",
5306 getIdentifierCString());
5309 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
5311 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5312 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
5314 if (dependency
->isInterface()) {
5315 OSKext
*interfaceTargetKext
= NULL
;
5316 OSData
* interfaceTarget
= NULL
;
5318 if (dependency
->isKernelComponent()) {
5319 interfaceTargetKext
= sKernelKext
;
5320 interfaceTarget
= sKernelKext
->linkedExecutable
;
5322 interfaceTargetKext
= OSDynamicCast(OSKext
,
5323 dependency
->dependencies
->getObject(0));
5325 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
5328 if (!interfaceTarget
) {
5333 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5334 * it will be useful to have them in the debugger.
5335 * strdup() failing isn't critical right here so we don't check that.
5337 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
5338 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
5339 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
5341 kxlddeps
[i
].interface
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5342 kxlddeps
[i
].interface_size
= dependency
->linkedExecutable
->getLength();
5343 kxlddeps
[i
].interface_name
= strdup(dependency
->getIdentifierCString());
5345 kxlddeps
[i
].kext
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5346 kxlddeps
[i
].kext_size
= dependency
->linkedExecutable
->getLength();
5347 kxlddeps
[i
].kext_name
= strdup(dependency
->getIdentifierCString());
5350 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
5353 kxldHeaderPtr
= &kxld_header
;
5357 kOSKextLogExplicitLevel
|
5358 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5359 "Kext %s - calling kxld_link_file:\n"
5360 " kxld_context: %p\n"
5361 " executable: %p executable_length: %d\n"
5363 " kxld_dependencies: %p num_dependencies: %d\n"
5364 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5365 getIdentifierCString(), sKxldContext
,
5366 theExecutable
->getBytesNoCopy(), theExecutable
->getLength(),
5367 this, kxlddeps
, num_kxlddeps
,
5368 kxldHeaderPtr
, &kmod_info
);
5371 /* After this call, the linkedExecutable instance variable
5374 kxldResult
= kxld_link_file(sKxldContext
,
5375 (u_char
*)theExecutable
->getBytesNoCopy(),
5376 theExecutable
->getLength(),
5377 getIdentifierCString(), this, kxlddeps
, num_kxlddeps
,
5378 (u_char
**)kxldHeaderPtr
, (kxld_addr_t
*)&kmod_info
);
5380 if (kxldResult
!= KERN_SUCCESS
) {
5381 // xxx - add kxldResult here?
5383 kOSKextLogErrorLevel
|
5385 "Can't load kext %s - link failed.",
5386 getIdentifierCString());
5387 result
= kOSKextReturnLinkError
;
5391 /* We've written data & instructions into kernel memory, so flush the data
5392 * cache and invalidate the instruction cache.
5393 * I/D caches are coherent on x86
5395 #if !defined(__i386__) && !defined(__x86_64__)
5396 flush_dcache(kmod_info
->address
, kmod_info
->size
, false);
5397 invalidate_icache(kmod_info
->address
, kmod_info
->size
, false);
5401 if (isInterface()) {
5403 /* Whip up a fake kmod_info entry for the interface kext.
5405 kmod_info
= (kmod_info_t
*)kalloc_tag(sizeof(kmod_info_t
), VM_KERN_MEMORY_OSKEXT
);
5407 result
= KERN_MEMORY_ERROR
;
5411 /* A pseudokext has almost nothing in its kmod_info struct.
5413 bzero(kmod_info
, sizeof(kmod_info_t
));
5415 kmod_info
->info_version
= KMOD_INFO_VERSION
;
5417 /* An interface kext doesn't have a linkedExecutable, so save a
5418 * copy of the UUID out of the original executable via copyUUID()
5419 * while we still have the original executable.
5421 interfaceUUID
= copyUUID();
5424 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5425 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5427 /* Stamp the bundle ID and version from the OSKext over anything
5428 * resident inside the kmod_info.
5430 string
= getIdentifierCString();
5431 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5433 string
= versCString
;
5434 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5436 /* Add the dependencies' kmod_info structs as kmod_references.
5438 num_kmod_refs
= getNumDependencies();
5439 if (num_kmod_refs
) {
5440 kmod_info
->reference_list
= (kmod_reference_t
*)kalloc_tag(
5441 num_kmod_refs
* sizeof(kmod_reference_t
), VM_KERN_MEMORY_OSKEXT
);
5442 if (!kmod_info
->reference_list
) {
5443 result
= KERN_MEMORY_ERROR
;
5446 bzero(kmod_info
->reference_list
,
5447 num_kmod_refs
* sizeof(kmod_reference_t
));
5448 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5449 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5450 OSKext
* refKext
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
));
5451 ref
->info
= refKext
->kmod_info
;
5452 ref
->info
->reference_count
++;
5454 if (refIndex
+ 1 < num_kmod_refs
) {
5455 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5460 if (!isInterface() && linkedExecutable
) {
5462 kOSKextLogProgressLevel
|
5464 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5466 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5467 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5468 (unsigned)kmod_info
->id
);
5471 /* if prelinked, VM protections are already set */
5472 result
= setVMAttributes(!isPrelinked(), true);
5473 if (result
!= KERN_SUCCESS
) {
5478 kasan_load_kext((vm_offset_t
)linkedExecutable
->getBytesNoCopy(),
5479 linkedExecutable
->getLength(), getIdentifierCString());
5481 if (lookupSection(KASAN_GLOBAL_SEGNAME
, KASAN_GLOBAL_SECTNAME
)) {
5483 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5484 "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
5485 getIdentifierCString()
5487 result
= KERN_FAILURE
;
5492 result
= kOSReturnSuccess
;
5495 OSSafeReleaseNULL(linkDependencies
);
5497 /* Clear up locally allocated dependency info.
5499 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5502 if (kxlddeps
[i
].kext_name
) {
5503 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5504 kfree(kxlddeps
[i
].kext_name
, size
);
5506 if (kxlddeps
[i
].interface_name
) {
5507 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5508 kfree(kxlddeps
[i
].interface_name
, size
);
5511 if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5513 /* We no longer need the unrelocated executable (which the linker
5514 * has altered anyhow).
5516 setExecutable(NULL
);
5518 if (result
!= kOSReturnSuccess
) {
5520 kOSKextLogErrorLevel
|
5522 "Failed to load executable for kext %s.",
5523 getIdentifierCString());
5525 if (kmod_info
&& kmod_info
->reference_list
) {
5526 kfree(kmod_info
->reference_list
,
5527 num_kmod_refs
* sizeof(kmod_reference_t
));
5529 if (isInterface()) {
5530 kfree(kmod_info
, sizeof(kmod_info_t
));
5533 if (linkedExecutable
) {
5534 linkedExecutable
->release();
5535 linkedExecutable
= NULL
;
5542 /*********************************************************************
5543 * The linkedit segment is used by the kext linker for dependency
5544 * resolution, and by dtrace for probe initialization. We can free it
5545 * for non-library kexts, since no kexts depend on non-library kexts
5546 * by definition, once dtrace has been initialized.
5547 *********************************************************************/
5549 OSKext::jettisonLinkeditSegment(void)
5551 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5552 kernel_segment_command_t
* linkedit
= NULL
;
5554 vm_size_t linkeditsize
, kextsize
;
5555 OSData
* data
= NULL
;
5558 /* We can free symbol tables for all embedded kexts because we don't
5559 * support runtime kext linking.
5561 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5563 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5568 /* Find the linkedit segment. If it's not the last segment, then freeing
5569 * it will fragment the kext into multiple VM regions, which OSKext is not
5570 * designed to handle, so we'll have to skip it.
5572 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5577 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5578 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
))
5583 /* Create a new OSData for the smaller kext object.
5585 linkeditsize
= round_page(linkedit
->vmsize
);
5586 kextsize
= kmod_info
->size
- linkeditsize
;
5587 start
= linkedit
->vmaddr
;
5589 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5594 /* Fix the kmod info and linkedExecutable.
5596 kmod_info
->size
= kextsize
;
5599 data
->setDeallocFunction(osdata_kext_free
);
5601 data
->setDeallocFunction(osdata_phys_free
);
5603 linkedExecutable
->setDeallocFunction(NULL
);
5604 linkedExecutable
->release();
5605 linkedExecutable
= data
;
5606 flags
.jettisonLinkeditSeg
= 1;
5608 /* Free the linkedit segment.
5611 kext_free(start
, linkeditsize
);
5613 ml_static_mfree(start
, linkeditsize
);
5620 /*********************************************************************
5621 * If there are whole pages that are unused betweem the last section
5622 * of the DATA segment and the end of the DATA segment then we can free
5624 *********************************************************************/
5626 OSKext::jettisonDATASegmentPadding(void)
5628 kernel_mach_header_t
* mh
;
5629 kernel_segment_command_t
* dataSeg
;
5630 kernel_section_t
* sec
, * lastSec
;
5631 vm_offset_t dataSegEnd
, lastSecEnd
;
5634 mh
= (kernel_mach_header_t
*)kmod_info
->address
;
5636 dataSeg
= getsegbynamefromheader(mh
, SEG_DATA
);
5637 if (dataSeg
== NULL
) {
5642 sec
= firstsect(dataSeg
);
5643 while (sec
!= NULL
) {
5645 sec
= nextsect(dataSeg
, sec
);
5648 if (lastSec
== NULL
) {
5652 if ((dataSeg
->vmaddr
!= round_page(dataSeg
->vmaddr
)) ||
5653 (dataSeg
->vmsize
!= round_page(dataSeg
->vmsize
))) {
5657 dataSegEnd
= dataSeg
->vmaddr
+ dataSeg
->vmsize
;
5658 lastSecEnd
= round_page(lastSec
->addr
+ lastSec
->size
);
5660 if (dataSegEnd
<= lastSecEnd
) {
5664 padSize
= dataSegEnd
- lastSecEnd
;
5666 if (padSize
>= PAGE_SIZE
) {
5668 kext_free(lastSecEnd
, padSize
);
5670 ml_static_mfree(lastSecEnd
, padSize
);
5675 /*********************************************************************
5676 *********************************************************************/
5678 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5680 if (linkedExecutable
) {
5681 panic("Attempt to set linked executable on kext "
5682 "that already has one (%s).\n",
5683 getIdentifierCString());
5685 linkedExecutable
= anExecutable
;
5686 linkedExecutable
->retain();
5691 /*********************************************************************
5692 * Go through all loaded kexts and tell them to register with dtrace.
5693 * The instance method only registers if necessary.
5694 *********************************************************************/
5697 OSKext::registerKextsWithDTrace(void)
5699 uint32_t count
= sLoadedKexts
->getCount();
5702 IORecursiveLockLock(sKextLock
);
5704 for (i
= 0; i
< count
; i
++) {
5705 OSKext
* thisKext
= NULL
; // do not release
5707 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5708 if (!thisKext
|| !thisKext
->isExecutable()) {
5712 thisKext
->registerWithDTrace();
5715 IORecursiveLockUnlock(sKextLock
);
5721 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5722 extern int (*dtrace_modunload
)(struct kmod_info
*);
5725 /*********************************************************************
5726 *********************************************************************/
5728 OSKext::registerWithDTrace(void)
5730 /* Register kext with dtrace. A dtrace_modload failure should not
5731 * prevent a kext from loading, so we ignore the return code.
5733 if (!flags
.dtraceInitialized
&& (dtrace_modload
!= NULL
)) {
5734 uint32_t modflag
= 0;
5735 OSObject
* forceInit
= getPropertyForHostArch("OSBundleForceDTraceInit");
5736 if (forceInit
== kOSBooleanTrue
) {
5737 modflag
|= KMOD_DTRACE_FORCE_INIT
;
5740 (void)(*dtrace_modload
)(kmod_info
, modflag
);
5741 flags
.dtraceInitialized
= true;
5742 jettisonLinkeditSegment();
5746 /*********************************************************************
5747 *********************************************************************/
5749 OSKext::unregisterWithDTrace(void)
5751 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5752 * prevent a kext from loading, so we ignore the return code.
5754 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
5755 (void)(*dtrace_modunload
)(kmod_info
);
5756 flags
.dtraceInitialized
= false;
5760 #endif /* CONFIG_DTRACE */
5763 /*********************************************************************
5764 * called only by loadExecutable()
5765 *********************************************************************/
5766 #if !VM_MAPPED_KEXTS
5767 #if defined(__arm__) || defined(__arm64__)
5768 static inline kern_return_t
5771 vm_map_offset_t start
,
5772 vm_map_offset_t end
,
5777 assert(map
== kernel_map
); // we can handle KEXTs arising from the PRELINK segment and no others
5778 assert(start
<= end
);
5780 return KERN_SUCCESS
; // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
5782 return KERN_SUCCESS
; // Punt set_max, as there's no mechanism to record that state
5784 return ml_static_protect(start
, end
- start
, new_prot
);
5787 static inline kern_return_t
5790 vm_map_offset_t start
,
5791 vm_map_offset_t end
,
5792 vm_prot_t access_type
,
5793 boolean_t user_wire
)
5795 #pragma unused(map,start,end,access_type,user_wire)
5796 return KERN_SUCCESS
; // No-op as PRELINK kexts are cemented into physical memory at boot
5799 #error Unrecognized architecture
5802 static inline kern_return_t
5805 vm_map_offset_t start
,
5806 vm_map_offset_t end
,
5810 if (start
== end
) { // 10538581
5811 return(KERN_SUCCESS
);
5813 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
5816 static inline kern_return_t
5819 vm_map_offset_t start
,
5820 vm_map_offset_t end
,
5821 vm_prot_t access_type
,
5822 boolean_t user_wire
)
5824 return vm_map_wire_kernel(map
, start
, end
, access_type
, VM_KERN_MEMORY_KEXT
, user_wire
);
5829 OSKext::setVMAttributes(bool protect
, bool wire
)
5831 vm_map_t kext_map
= NULL
;
5832 kernel_segment_command_t
* seg
= NULL
;
5833 vm_map_offset_t start
= 0;
5834 vm_map_offset_t end
= 0;
5835 OSReturn result
= kOSReturnError
;
5837 if (isInterface() || !declaresExecutable()) {
5838 result
= kOSReturnSuccess
;
5842 /* Get the kext's vm map */
5843 kext_map
= kext_get_vm_map(kmod_info
);
5845 result
= KERN_MEMORY_ERROR
;
5849 #if !VM_MAPPED_KEXTS
5850 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
5851 /* This is a split kext in a prelinked kernelcache; we'll let the
5852 * platform code take care of protecting it. It is already wired.
5854 /* TODO: Should this still allow protections for the first segment
5855 * to go through, in the event that we have a mix of split and
5858 result
= KERN_SUCCESS
;
5863 /* Protect the headers as read-only; they do not need to be wired */
5864 result
= (protect
) ? OSKext_protect(kext_map
, kmod_info
->address
,
5865 kmod_info
->address
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
)
5867 if (result
!= KERN_SUCCESS
) {
5871 /* Set the VM protections and wire down each of the segments */
5872 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5876 /* We build all ARM kexts, so we can ensure they are aligned */
5877 assert((seg
->vmaddr
& PAGE_MASK
) == 0);
5878 assert((seg
->vmsize
& PAGE_MASK
) == 0);
5881 start
= round_page(seg
->vmaddr
);
5882 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
5885 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
5886 if (result
!= KERN_SUCCESS
) {
5888 kOSKextLogErrorLevel
|
5890 "Kext %s failed to set maximum VM protections "
5891 "for segment %s - 0x%x.",
5892 getIdentifierCString(), seg
->segname
, (int)result
);
5896 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5897 if (result
!= KERN_SUCCESS
) {
5899 kOSKextLogErrorLevel
|
5901 "Kext %s failed to set initial VM protections "
5902 "for segment %s - 0x%x.",
5903 getIdentifierCString(), seg
->segname
, (int)result
);
5908 if (segmentShouldBeWired(seg
) && wire
) {
5909 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5910 if (result
!= KERN_SUCCESS
) {
5915 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5922 /*********************************************************************
5923 *********************************************************************/
5925 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
5927 return (sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
)));
5930 /*********************************************************************
5931 *********************************************************************/
5933 OSKext::validateKextMapping(bool startFlag
)
5935 OSReturn result
= kOSReturnError
;
5936 const char * whichOp
= startFlag
? "start" : "stop";
5937 kern_return_t kern_result
= 0;
5938 vm_map_t kext_map
= NULL
;
5939 kernel_segment_command_t
* seg
= NULL
;
5940 mach_vm_address_t address
= 0;
5941 mach_vm_size_t size
= 0;
5943 mach_msg_type_number_t count
;
5944 vm_region_submap_short_info_data_64_t info
;
5946 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
5947 bzero(&info
, sizeof(info
));
5949 // xxx - do we need a distinct OSReturn value for these or is "bad data"
5950 // xxx - sufficient?
5952 /* Verify that the kmod_info and start/stop pointers are non-NULL.
5956 kOSKextLogErrorLevel
|
5958 "Kext %s - NULL kmod_info pointer.",
5959 getIdentifierCString());
5960 result
= kOSKextReturnBadData
;
5965 address
= (mach_vm_address_t
)kmod_info
->start
;
5967 address
= (mach_vm_address_t
)kmod_info
->stop
;
5972 kOSKextLogErrorLevel
|
5974 "Kext %s - NULL module %s pointer.",
5975 getIdentifierCString(), whichOp
);
5976 result
= kOSKextReturnBadData
;
5980 kext_map
= kext_get_vm_map(kmod_info
);
5981 depth
= (kernel_map
== kext_map
) ? 1 : 2;
5983 /* Verify that the start/stop function lies within the kext's address range.
5985 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
5986 /* This will likely be how we deal with split kexts; walk the segments to
5987 * check that the function lies inside one of the segments of this kext.
5989 for (seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5991 seg
= nextsegfromheader((kernel_mach_header_t
*)kmod_info
->address
, seg
)) {
5992 if ((address
>= seg
->vmaddr
) && address
< (seg
->vmaddr
+ seg
->vmsize
)) {
5999 kOSKextLogErrorLevel
|
6001 "Kext %s module %s pointer is outside of kext range "
6002 "(%s %p - kext starts at %p).",
6003 getIdentifierCString(),
6006 (void *)VM_KERNEL_UNSLIDE(address
),
6007 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
));
6008 result
= kOSKextReturnBadData
;
6014 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
6015 kmod_info
->address
+ kmod_info
->size
<= address
)
6018 kOSKextLogErrorLevel
|
6020 "Kext %s module %s pointer is outside of kext range "
6021 "(%s %p - kext at %p-%p).",
6022 getIdentifierCString(),
6025 (void *)VM_KERNEL_UNSLIDE(address
),
6026 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
),
6027 (void *)(VM_KERNEL_UNSLIDE(kmod_info
->address
) + kmod_info
->size
));
6028 result
= kOSKextReturnBadData
;
6033 /* Only do these checks before calling the start function;
6034 * If anything goes wrong with the mapping while the kext is running,
6035 * we'll likely have panicked well before any attempt to stop the kext.
6039 /* Verify that the start/stop function is executable.
6041 kern_result
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
,
6042 (vm_region_recurse_info_t
)&info
, &count
);
6043 if (kern_result
!= KERN_SUCCESS
) {
6045 kOSKextLogErrorLevel
|
6047 "Kext %s - bad %s pointer %p.",
6048 getIdentifierCString(),
6049 whichOp
, (void *)VM_KERNEL_UNSLIDE(address
));
6050 result
= kOSKextReturnBadData
;
6055 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
6057 kOSKextLogErrorLevel
|
6059 "Kext %s - memory region containing module %s function "
6060 "is not executable.",
6061 getIdentifierCString(), whichOp
);
6062 result
= kOSKextReturnBadData
;
6067 /* Verify that the kext's segments are backed by physical memory.
6069 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6071 if (!verifySegmentMapping(seg
)) {
6072 result
= kOSKextReturnBadData
;
6076 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6081 result
= kOSReturnSuccess
;
6086 /*********************************************************************
6087 *********************************************************************/
6089 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
6091 mach_vm_address_t address
= 0;
6093 if (!segmentShouldBeWired(seg
)) return true;
6095 for (address
= seg
->vmaddr
;
6096 address
< round_page(seg
->vmaddr
+ seg
->vmsize
);
6097 address
+= PAGE_SIZE
)
6099 if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) {
6101 kOSKextLogErrorLevel
|
6103 "Kext %s - page %p is not backed by physical memory.",
6104 getIdentifierCString(),
6113 /*********************************************************************
6114 *********************************************************************/
6116 OSKextLogKextInfo(OSKext
*aKext
, uint64_t address
, uint64_t size
, firehose_tracepoint_code_t code
)
6120 firehose_tracepoint_id_u trace_id
;
6121 struct firehose_trace_uuid_info_s uuid_info_s
;
6122 firehose_trace_uuid_info_t uuid_info
= &uuid_info_s
;
6123 size_t uuid_info_len
= sizeof(struct firehose_trace_uuid_info_s
);
6126 stamp
= firehose_tracepoint_time(firehose_activity_flags_default
);
6127 trace_id
.ftid_value
= FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata
, _firehose_tracepoint_type_metadata_kext
, (firehose_tracepoint_flags_t
)0, code
);
6129 uuid_data
= aKext
->copyUUID();
6131 memcpy(uuid_info
->ftui_uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_info
->ftui_uuid
));
6132 OSSafeReleaseNULL(uuid_data
);
6135 uuid_info
->ftui_size
= size
;
6136 uuid_info
->ftui_address
= VM_KERNEL_UNSLIDE(address
);
6138 firehose_trace_metadata(firehose_stream_metadata
, trace_id
, stamp
, uuid_info
, uuid_info_len
);
6142 /*********************************************************************
6143 *********************************************************************/
6145 OSKext::start(bool startDependenciesFlag
)
6147 OSReturn result
= kOSReturnError
;
6148 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
6149 unsigned int i
, count
;
6150 void * kmodStartData
= NULL
;
6152 if (isStarted() || isInterface() || isKernelComponent()) {
6153 result
= kOSReturnSuccess
;
6159 kOSKextLogErrorLevel
|
6161 "Attempt to start nonloaded kext %s.",
6162 getIdentifierCString());
6163 result
= kOSKextReturnInvalidArgument
;
6167 if (!sLoadEnabled
) {
6169 kOSKextLogErrorLevel
|
6171 "Kext loading is disabled (attempt to start kext %s).",
6172 getIdentifierCString());
6173 result
= kOSKextReturnDisabled
;
6177 result
= validateKextMapping(/* start? */ true);
6178 if (result
!= kOSReturnSuccess
) {
6182 startfunc
= kmod_info
->start
;
6184 count
= getNumDependencies();
6185 for (i
= 0; i
< count
; i
++) {
6186 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
6187 if (dependency
== NULL
) {
6189 kOSKextLogErrorLevel
|
6191 "Kext %s start - internal error, dependency disappeared.",
6192 getIdentifierCString());
6195 if (!dependency
->isStarted()) {
6196 if (startDependenciesFlag
) {
6197 OSReturn dependencyResult
=
6198 dependency
->start(startDependenciesFlag
);
6199 if (dependencyResult
!= KERN_SUCCESS
) {
6201 kOSKextLogErrorLevel
|
6203 "Kext %s start - dependency %s failed to start (error 0x%x).",
6204 getIdentifierCString(),
6205 dependency
->getIdentifierCString(),
6211 kOSKextLogErrorLevel
|
6213 "Not starting %s - dependency %s not started yet.",
6214 getIdentifierCString(),
6215 dependency
->getIdentifierCString());
6216 result
= kOSKextReturnStartStopError
; // xxx - make new return?
6223 kOSKextLogDetailLevel
|
6225 "Kext %s calling module start function.",
6226 getIdentifierCString());
6230 // Drop a log message so logd can grab the needed information to decode this kext
6231 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_load
);
6233 #if !CONFIG_STATIC_CPPINIT
6234 result
= OSRuntimeInitializeCPP(kmod_info
, NULL
);
6235 if (result
== KERN_SUCCESS
) {
6239 kmodStartData
= GetAppleTEXTHashForKext(this, this->infoDict
);
6242 if (kmodStartData
) {
6244 kOSKextLogErrorLevel
|
6245 kOSKextLogGeneralFlag
,
6246 "Kext %s calling module start function. kmodStartData %p. arch %s",
6247 getIdentifierCString(), kmodStartData
, ARCHNAME
);
6250 #endif // CONFIG_KEC_FIPS
6251 result
= startfunc(kmod_info
, kmodStartData
);
6253 #if !CONFIG_STATIC_CPPINIT
6254 if (result
!= KERN_SUCCESS
) {
6255 (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6262 /* On success overlap the setting of started/starting. On failure just
6265 if (result
== KERN_SUCCESS
) {
6268 // xxx - log start error from kernel?
6270 kOSKextLogProgressLevel
|
6272 "Kext %s is now started.",
6273 getIdentifierCString());
6275 invokeOrCancelRequestCallbacks(
6276 /* result not actually used */ kOSKextReturnStartStopError
,
6277 /* invokeFlag */ false);
6279 kOSKextLogProgressLevel
|
6281 "Kext %s did not start (return code 0x%x).",
6282 getIdentifierCString(), result
);
6289 /*********************************************************************
6290 *********************************************************************/
6292 bool OSKext::canUnloadKextWithIdentifier(
6293 OSString
* kextIdentifier
,
6294 bool checkClassesFlag
)
6296 bool result
= false;
6297 OSKext
* aKext
= NULL
; // do not release
6299 IORecursiveLockLock(sKextLock
);
6301 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
6304 goto finish
; // can't unload what's not loaded
6307 if (aKext
->isLoaded()) {
6308 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
6311 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
6319 IORecursiveLockUnlock(sKextLock
);
6323 /*********************************************************************
6324 *********************************************************************/
6328 OSReturn result
= kOSReturnError
;
6329 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
6331 if (!isStarted() || isInterface()) {
6332 result
= kOSReturnSuccess
;
6338 kOSKextLogErrorLevel
|
6340 "Attempt to stop nonloaded kext %s.",
6341 getIdentifierCString());
6342 result
= kOSKextReturnInvalidArgument
;
6346 /* Refuse to stop if we have clients or instances. It is up to
6347 * the caller to make sure those aren't true.
6349 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6351 kOSKextLogErrorLevel
|
6353 "Kext %s - C++ instances; can't stop.",
6354 getIdentifierCString());
6355 result
= kOSKextReturnInUse
;
6359 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6362 kOSKextLogErrorLevel
|
6364 "Kext %s - has references (linkage or tracking object); "
6366 getIdentifierCString());
6367 result
= kOSKextReturnInUse
;
6371 /* Note: If validateKextMapping fails on the stop & unload path,
6372 * we are in serious trouble and a kernel panic is likely whether
6373 * we stop & unload the kext or not.
6375 result
= validateKextMapping(/* start? */ false);
6376 if (result
!= kOSReturnSuccess
) {
6380 stopfunc
= kmod_info
->stop
;
6383 kOSKextLogDetailLevel
|
6385 "Kext %s calling module stop function.",
6386 getIdentifierCString());
6390 result
= stopfunc(kmod_info
, /* userData */ NULL
);
6391 #if !CONFIG_STATIC_CPPINIT
6392 if (result
== KERN_SUCCESS
) {
6393 result
= OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6399 if (result
== KERN_SUCCESS
) {
6403 kOSKextLogDetailLevel
|
6405 "Kext %s is now stopped and ready to unload.",
6406 getIdentifierCString());
6409 kOSKextLogErrorLevel
|
6411 "Kext %s did not stop (return code 0x%x).",
6412 getIdentifierCString(), result
);
6413 result
= kOSKextReturnStartStopError
;
6418 // Drop a log message so logd can update this kext's metadata
6419 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_unload
);
6423 /*********************************************************************
6424 *********************************************************************/
6426 OSKext::unload(void)
6428 OSReturn result
= kOSReturnError
;
6430 uint32_t num_kmod_refs
= 0;
6431 OSKextAccount
* freeAccount
;
6433 if (!sUnloadEnabled
) {
6435 kOSKextLogErrorLevel
|
6437 "Kext unloading is disabled (%s).",
6438 this->getIdentifierCString());
6440 result
= kOSKextReturnDisabled
;
6444 /* Refuse to unload if we have clients or instances. It is up to
6445 * the caller to make sure those aren't true.
6447 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6448 // xxx - Don't log under errors? this is more of an info thing
6450 kOSKextLogErrorLevel
|
6451 kOSKextLogKextBookkeepingFlag
,
6452 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6453 getIdentifierCString());
6454 result
= kOSKextReturnInUse
;
6459 result
= kOSReturnSuccess
;
6463 if (isKernelComponent()) {
6464 result
= kOSKextReturnInvalidArgument
;
6468 if (metaClasses
&& !OSMetaClass::removeClasses(metaClasses
)) {
6470 kOSKextLogErrorLevel
|
6471 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6472 "Can't unload kext %s; classes have instances:",
6473 getIdentifierCString());
6474 reportOSMetaClassInstances(kOSKextLogErrorLevel
|
6475 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
);
6476 result
= kOSKextReturnInUse
;
6480 /* Note that the kext is unloading before running any code that
6481 * might be in the kext (request callbacks, module stop function).
6482 * We will deny certain requests made against a kext in the process
6485 flags
.unloading
= 1;
6487 /* Update the string describing the last kext to unload in case we panic.
6489 savePanicString(/* isLoading */ false);
6493 if (result
!= KERN_SUCCESS
) {
6495 kOSKextLogErrorLevel
|
6497 "Kext %s can't unload - module stop returned 0x%x.",
6498 getIdentifierCString(), (unsigned)result
);
6499 result
= kOSKextReturnStartStopError
;
6505 kOSKextLogProgressLevel
|
6507 "Kext %s unloading.",
6508 getIdentifierCString());
6511 struct list_head
*p
;
6512 struct list_head
*prev
;
6513 struct list_head
*next
;
6514 for (p
= pendingPgoHead
.next
; p
!= &pendingPgoHead
; p
= next
) {
6515 OSKextGrabPgoStruct
*s
= container_of(p
, OSKextGrabPgoStruct
, list_head
);
6516 s
->err
= OSKextGrabPgoDataLocked(this, s
->metadata
, instance_uuid
, s
->pSize
, s
->pBuffer
, s
->bufferSize
);
6523 IORecursiveLockWakeup(sKextLock
, s
, false);
6528 /* Even if we don't call the stop function, we want to be sure we
6529 * have no OSMetaClass references before unloading the kext executable
6530 * from memory. OSMetaClasses may have pointers into the kext executable
6531 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6534 metaClasses
->flushCollection();
6537 /* Remove the kext from the list of loaded kexts, patch the gap
6538 * in the kmod_info_t linked list, and reset "kmod" to point to the
6539 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6541 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
6542 if (index
!= (unsigned int)-1) {
6544 sLoadedKexts
->removeObject(index
);
6546 OSKext
* nextKext
= OSDynamicCast(OSKext
,
6547 sLoadedKexts
->getObject(index
));
6551 OSKext
* gapKext
= OSDynamicCast(OSKext
,
6552 sLoadedKexts
->getObject(index
- 1));
6554 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
6556 } else /* index == 0 */ {
6557 nextKext
->kmod_info
->next
= NULL
;
6561 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
6562 if (lastKext
&& !lastKext
->isKernel()) {
6563 kmod
= lastKext
->kmod_info
;
6565 kmod
= NULL
; // clear the global kmod variable
6569 /* Clear out the kmod references that we're keeping for compatibility
6570 * with current panic backtrace code & kgmacros.
6571 * xxx - will want to update those bits sometime and remove this.
6573 num_kmod_refs
= getNumDependencies();
6574 if (num_kmod_refs
&& kmod_info
&& kmod_info
->reference_list
) {
6575 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
6576 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
6577 ref
->info
->reference_count
--;
6579 kfree(kmod_info
->reference_list
,
6580 num_kmod_refs
* sizeof(kmod_reference_t
));
6584 unregisterWithDTrace();
6585 #endif /* CONFIG_DTRACE */
6587 notifyKextUnloadObservers(this);
6590 IOSimpleLockLock(sKextAccountsLock
);
6591 account
->kext
= NULL
;
6592 if (account
->site
.tag
) account
->site
.flags
|= VM_TAG_UNLOAD
;
6593 else freeAccount
= account
;
6594 IOSimpleLockUnlock(sKextAccountsLock
);
6595 if (freeAccount
) IODelete(freeAccount
, OSKextAccount
, 1);
6597 /* Unwire and free the linked executable.
6599 if (linkedExecutable
) {
6601 kasan_unload_kext((vm_offset_t
)linkedExecutable
->getBytesNoCopy(), linkedExecutable
->getLength());
6605 if (!isInterface()) {
6606 kernel_segment_command_t
*seg
= NULL
;
6607 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6611 kOSKextLogErrorLevel
|
6613 "Failed to free kext %s; couldn't find the kext map.",
6614 getIdentifierCString());
6615 result
= kOSKextReturnInternalError
;
6620 kOSKextLogProgressLevel
|
6622 "Kext %s unwiring and unmapping linked executable.",
6623 getIdentifierCString());
6625 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6627 if (segmentShouldBeWired(seg
)) {
6628 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6629 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6630 if (result
!= KERN_SUCCESS
) {
6632 kOSKextLogErrorLevel
|
6634 "Failed to unwire kext %s.",
6635 getIdentifierCString());
6636 result
= kOSKextReturnInternalError
;
6641 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6645 OSSafeReleaseNULL(linkedExecutable
);
6648 /* An interface kext has a fake kmod_info that was allocated,
6649 * so we have to free it.
6651 if (isInterface()) {
6652 kfree(kmod_info
, sizeof(kmod_info_t
));
6657 flags
.loaded
= false;
6658 flushDependencies();
6660 /* save a copy of the bundle ID for us to check when deciding to
6661 * rebuild the kernel cache file. If a kext was already in the kernel
6662 * cache and unloaded then later loaded we do not need to rebuild the
6663 * kernel cache. 9055303
6665 if (isPrelinked()) {
6666 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6667 IORecursiveLockLock(sKextLock
);
6668 if (sUnloadedPrelinkedKexts
) {
6669 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6671 IORecursiveLockUnlock(sKextLock
);
6676 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6677 "Kext %s unloaded.", getIdentifierCString());
6679 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6680 OSDynamicCast(OSString
, bundleID
));
6683 OSKext::saveLoadedKextPanicList();
6684 OSKext::updateLoadedKextSummaries();
6686 flags
.unloading
= 0;
6690 /*********************************************************************
6691 * Assumes sKextLock is held.
6692 *********************************************************************/
6695 OSKext::queueKextNotification(
6696 const char * notificationName
,
6697 OSString
* kextIdentifier
)
6699 OSReturn result
= kOSReturnError
;
6700 OSDictionary
* loadRequest
= NULL
; // must release
6702 if (!kextIdentifier
) {
6703 result
= kOSKextReturnInvalidArgument
;
6707 /* Create a new request unless one is already sitting
6708 * in sKernelRequests for this bundle identifier
6710 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6711 if (result
!= kOSReturnSuccess
) {
6714 if (!_OSKextSetRequestArgument(loadRequest
,
6715 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6717 result
= kOSKextReturnNoMemory
;
6720 if (!sKernelRequests
->setObject(loadRequest
)) {
6721 result
= kOSKextReturnNoMemory
;
6725 /* We might want to only queue the notification if kextd is active,
6726 * but that wouldn't work for embedded. Note that we don't care if
6727 * the ping immediately succeeds here so don't do anything with the
6728 * result of this call.
6730 OSKext::pingKextd();
6732 result
= kOSReturnSuccess
;
6735 OSSafeReleaseNULL(loadRequest
);
6740 /*********************************************************************
6741 *********************************************************************/
6743 _OSKextConsiderDestroyingLinkContext(
6744 __unused thread_call_param_t p0
,
6745 __unused thread_call_param_t p1
)
6747 /* Take multiple locks in the correct order.
6749 IORecursiveLockLock(sKextLock
);
6750 IORecursiveLockLock(sKextInnerLock
);
6752 /* The first time we destroy the kxldContext is in the first
6753 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6754 * before calling this function. Thereafter any call to this function
6755 * will actually destroy the context.
6757 if (sConsiderUnloadsCalled
&& sKxldContext
) {
6758 kxld_destroy_context(sKxldContext
);
6759 sKxldContext
= NULL
;
6762 /* Free the thread_call that was allocated to execute this function.
6764 if (sDestroyLinkContextThread
) {
6765 if (!thread_call_free(sDestroyLinkContextThread
)) {
6766 OSKextLog(/* kext */ NULL
,
6767 kOSKextLogErrorLevel
|
6768 kOSKextLogGeneralFlag
,
6769 "thread_call_free() failed for kext link context.");
6771 sDestroyLinkContextThread
= 0;
6774 IORecursiveLockUnlock(sKextInnerLock
);
6775 IORecursiveLockUnlock(sKextLock
);
6780 /*********************************************************************
6781 * Destroying the kxldContext requires checking variables under both
6782 * sKextInnerLock and sKextLock, so we do it on a separate thread
6783 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6784 * call relationship.
6786 * This function must be invoked with sKextInnerLock held.
6787 * Do not call any function that takes sKextLock here!
6788 *********************************************************************/
6791 OSKext::considerDestroyingLinkContext(void)
6793 IORecursiveLockLock(sKextInnerLock
);
6795 /* If we have already queued a thread to destroy the link context,
6796 * don't bother resetting; that thread will take care of it.
6798 if (sDestroyLinkContextThread
) {
6802 /* The function to be invoked in the thread will deallocate
6803 * this thread_call, so don't share it around.
6805 sDestroyLinkContextThread
= thread_call_allocate(
6806 &_OSKextConsiderDestroyingLinkContext
, 0);
6807 if (!sDestroyLinkContextThread
) {
6808 OSKextLog(/* kext */ NULL
,
6809 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
| kOSKextLogLinkFlag
,
6810 "Can't create thread to destroy kext link context.");
6814 thread_call_enter(sDestroyLinkContextThread
);
6817 IORecursiveLockUnlock(sKextInnerLock
);
6822 #pragma mark Autounload
6824 /*********************************************************************
6825 * This is a static method because the kext will be deallocated if it
6827 *********************************************************************/
6830 OSKext::autounloadKext(OSKext
* aKext
)
6832 OSReturn result
= kOSKextReturnInUse
;
6834 /* Check for external references to this kext (usu. dependents),
6835 * instances of defined classes (or classes derived from them),
6836 * outstanding requests.
6838 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
6839 !aKext
->flags
.autounloadEnabled
||
6840 aKext
->isKernelComponent()) {
6845 /* Skip a delay-autounload kext, once.
6847 if (aKext
->flags
.delayAutounload
) {
6849 kOSKextLogProgressLevel
|
6850 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6851 "Kext %s has delayed autounload set; skipping and clearing flag.",
6852 aKext
->getIdentifierCString());
6853 aKext
->flags
.delayAutounload
= 0;
6857 if (aKext
->hasOSMetaClassInstances() ||
6858 aKext
->countRequestCallbacks()) {
6862 result
= OSKext::removeKext(aKext
);
6868 /*********************************************************************
6869 *********************************************************************/
6871 _OSKextConsiderUnloads(
6872 __unused thread_call_param_t p0
,
6873 __unused thread_call_param_t p1
)
6875 bool didUnload
= false;
6876 unsigned int count
, i
;
6878 /* Take multiple locks in the correct order
6879 * (note also sKextSummaries lock further down).
6881 IORecursiveLockLock(sKextLock
);
6882 IORecursiveLockLock(sKextInnerLock
);
6884 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6886 /* If the system is powering down, don't try to unload anything.
6892 OSKextLog(/* kext */ NULL
,
6893 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6894 "Checking for unused kexts to autounload.");
6897 * Remove any request callbacks marked as stale,
6898 * and mark as stale any currently in flight.
6900 count
= sRequestCallbackRecords
->getCount();
6904 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
6905 sRequestCallbackRecords
->getObject(i
));
6906 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
6907 callbackRecord
->getObject(kKextRequestStaleKey
));
6909 if (stale
== kOSBooleanTrue
) {
6910 OSKext::invokeRequestCallback(callbackRecord
,
6911 kOSKextReturnTimeout
);
6913 callbackRecord
->setObject(kKextRequestStaleKey
,
6920 * Make multiple passes through the array of loaded kexts until
6921 * we don't unload any. This handles unwinding of dependency
6922 * chains. We have to go *backwards* through the array because
6923 * kexts are removed from it when unloaded, and we cannot make
6924 * a copy or we'll mess up the retain counts we rely on to
6925 * check whether a kext will unload. If only we could have
6926 * nonretaining collections like CF has....
6931 count
= sLoadedKexts
->getCount();
6935 OSKext
* thisKext
= OSDynamicCast(OSKext
,
6936 sLoadedKexts
->getObject(i
));
6937 didUnload
|= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
6940 } while (didUnload
);
6943 sConsiderUnloadsPending
= false;
6944 sConsiderUnloadsExecuted
= true;
6946 (void) OSKext::considerRebuildOfPrelinkedKernel();
6948 IORecursiveLockUnlock(sKextInnerLock
);
6949 IORecursiveLockUnlock(sKextLock
);
6954 /*********************************************************************
6955 * Do not call any function that takes sKextLock here!
6956 *********************************************************************/
6957 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
6961 IORecursiveLockLock(sKextInnerLock
);
6963 if (!sUnloadCallout
) {
6964 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, 0);
6967 /* we only reset delay value for unloading if we already have something
6968 * pending. rescheduleOnlyFlag should not start the count down.
6970 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
6974 thread_call_cancel(sUnloadCallout
);
6975 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
6976 clock_interval_to_deadline(sConsiderUnloadDelay
,
6977 1000 * 1000 * 1000, &when
);
6979 OSKextLog(/* kext */ NULL
,
6980 kOSKextLogProgressLevel
|
6982 "%scheduling %sscan for unused kexts in %lu seconds.",
6983 sConsiderUnloadsPending
? "Res" : "S",
6984 sConsiderUnloadsCalled
? "" : "initial ",
6985 (unsigned long)sConsiderUnloadDelay
);
6987 sConsiderUnloadsPending
= true;
6988 thread_call_enter_delayed(sUnloadCallout
, when
);
6992 /* The kxld context should be reused throughout boot. We mark the end of
6993 * period as the first time considerUnloads() is called, and we destroy
6994 * the first kxld context in that function. Afterwards, it will be
6995 * destroyed in flushNonloadedKexts.
6997 if (!sConsiderUnloadsCalled
) {
6998 sConsiderUnloadsCalled
= true;
6999 OSKext::considerDestroyingLinkContext();
7002 IORecursiveLockUnlock(sKextInnerLock
);
7006 /*********************************************************************
7007 * Do not call any function that takes sKextLock here!
7008 *********************************************************************/
7011 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
);
7012 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
)
7014 IORecursiveLockLock(sKextInnerLock
);
7016 /* If the system is going to sleep, cancel the reaper thread timer,
7017 * and note that we're in a sleep state in case it just fired but hasn't
7018 * taken the lock yet. If we are coming back from sleep, just
7019 * clear the sleep flag; IOService's normal operation will cause
7020 * unloads to be considered soon enough.
7022 if (messageType
== kIOMessageSystemWillSleep
) {
7023 if (sUnloadCallout
) {
7024 thread_call_cancel(sUnloadCallout
);
7026 sSystemSleep
= true;
7027 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
7028 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
7029 sSystemSleep
= false;
7030 clock_get_uptime(&sLastWakeTime
);
7032 IORecursiveLockUnlock(sKextInnerLock
);
7034 return kIOReturnSuccess
;
7041 #pragma mark Prelinked Kernel
7043 /*********************************************************************
7044 * Do not access sConsiderUnloads... variables other than
7045 * sConsiderUnloadsExecuted in this function. They are guarded by a
7047 *********************************************************************/
7050 OSKext::considerRebuildOfPrelinkedKernel(void)
7052 static bool requestedPrelink
= false;
7053 OSReturn checkResult
= kOSReturnError
;
7054 OSDictionary
* prelinkRequest
= NULL
; // must release
7055 OSCollectionIterator
* kextIterator
= NULL
; // must release
7056 const OSSymbol
* thisID
= NULL
; // do not release
7057 bool doRebuild
= false;
7058 AbsoluteTime my_abstime
;
7062 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
7063 if (requestedPrelink
|| !sPrelinkBoot
) {
7067 /* no direct return from this point */
7068 IORecursiveLockLock(sKextLock
);
7070 /* We need to wait for kextd to get up and running with unloads already done
7071 * and any new startup kexts loaded.
7073 if (!sConsiderUnloadsExecuted
||
7074 !sDeferredLoadSucceeded
) {
7078 /* we really only care about boot / system start up related kexts so bail
7079 * if we're here after REBUILD_MAX_TIME.
7081 if (!_OSKextInPrelinkRebuildWindow()) {
7082 OSKextLog(/* kext */ NULL
,
7083 kOSKextLogArchiveFlag
,
7084 "%s prebuild rebuild has expired",
7086 requestedPrelink
= true;
7090 /* we do not want to trigger a rebuild if we get here too close to waking
7091 * up. (see radar 10233768)
7093 IORecursiveLockLock(sKextInnerLock
);
7095 clock_get_uptime(&my_abstime
);
7096 delta_secs
= MINIMUM_WAKEUP_SECONDS
+ 1;
7097 if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) {
7098 SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
);
7099 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
7100 delta_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
7102 IORecursiveLockUnlock(sKextInnerLock
);
7104 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
7105 /* too close to time of last wake from sleep */
7108 requestedPrelink
= true;
7110 /* Now it's time to see if we have a reason to rebuild. We may have done
7111 * some loads and unloads but the kernel cache didn't actually change.
7112 * We will rebuild if any kext is not marked prelinked AND is not in our
7113 * list of prelinked kexts that got unloaded. (see radar 9055303)
7115 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
7116 if (!kextIterator
) {
7120 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
7121 OSKext
* thisKext
; // do not release
7123 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
7124 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
7128 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
7131 /* kext is loaded and was not in current kernel cache so let's rebuild
7134 OSKextLog(/* kext */ NULL
,
7135 kOSKextLogArchiveFlag
,
7136 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
7137 thisKext
->bundleID
->getCStringNoCopy());
7140 sUnloadedPrelinkedKexts
->flushCollection();
7146 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
7148 if (checkResult
!= kOSReturnSuccess
) {
7152 if (!sKernelRequests
->setObject(prelinkRequest
)) {
7156 OSKext::pingKextd();
7159 IORecursiveLockUnlock(sKextLock
);
7160 OSSafeReleaseNULL(prelinkRequest
);
7161 OSSafeReleaseNULL(kextIterator
);
7167 #pragma mark Dependencies
7169 /*********************************************************************
7170 *********************************************************************/
7172 OSKext::resolveDependencies(
7173 OSArray
* loopStack
)
7175 bool result
= false;
7176 OSArray
* localLoopStack
= NULL
; // must release
7177 bool addedToLoopStack
= false;
7178 OSDictionary
* libraries
= NULL
; // do not release
7179 OSCollectionIterator
* libraryIterator
= NULL
; // must release
7180 OSString
* libraryID
= NULL
; // do not release
7181 OSString
* infoString
= NULL
; // do not release
7182 OSString
* readableString
= NULL
; // do not release
7183 OSKext
* libraryKext
= NULL
; // do not release
7184 bool hasRawKernelDependency
= false;
7185 bool hasKernelDependency
= false;
7186 bool hasKPIDependency
= false;
7187 bool hasPrivateKPIDependency
= false;
7190 /* A kernel component will automatically have this flag set,
7191 * and a loaded kext should also have it set (as should all its
7192 * loaded dependencies).
7194 if (flags
.hasAllDependencies
) {
7199 /* Check for loops in the dependency graph.
7202 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
7204 kOSKextLogErrorLevel
|
7205 kOSKextLogDependenciesFlag
,
7206 "Kext %s has a dependency loop; can't resolve dependencies.",
7207 getIdentifierCString());
7212 kOSKextLogStepLevel
|
7213 kOSKextLogDependenciesFlag
,
7214 "Kext %s resolving dependencies.",
7215 getIdentifierCString());
7217 loopStack
= OSArray::withCapacity(6); // any small capacity will do
7220 kOSKextLogErrorLevel
|
7221 kOSKextLogDependenciesFlag
,
7222 "Kext %s can't create bookkeeping stack to resolve dependencies.",
7223 getIdentifierCString());
7226 localLoopStack
= loopStack
;
7228 if (!loopStack
->setObject(this)) {
7230 kOSKextLogErrorLevel
|
7231 kOSKextLogDependenciesFlag
,
7232 "Kext %s - internal error resolving dependencies.",
7233 getIdentifierCString());
7236 addedToLoopStack
= true;
7238 /* Purge any existing kexts in the dependency list and start over.
7240 flushDependencies();
7243 kOSKextLogErrorLevel
|
7244 kOSKextLogDependenciesFlag
,
7245 "Kext %s - internal error resolving dependencies.",
7246 getIdentifierCString());
7249 libraries
= OSDynamicCast(OSDictionary
,
7250 getPropertyForHostArch(kOSBundleLibrariesKey
));
7251 if (libraries
== NULL
|| libraries
->getCount() == 0) {
7253 kOSKextLogErrorLevel
|
7254 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7255 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7256 getIdentifierCString(), kOSBundleLibrariesKey
);
7260 /* Make a new array to hold the dependencies (flush freed the old one).
7262 dependencies
= OSArray::withCapacity(libraries
->getCount());
7263 if (!dependencies
) {
7265 kOSKextLogErrorLevel
|
7266 kOSKextLogDependenciesFlag
,
7267 "Kext %s - can't allocate dependencies array.",
7268 getIdentifierCString());
7272 // xxx - compat: We used to add an implicit dependency on kernel 6.0
7273 // xxx - compat: if none were declared.
7275 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
7276 if (!libraryIterator
) {
7278 kOSKextLogErrorLevel
|
7279 kOSKextLogDependenciesFlag
,
7280 "Kext %s - can't allocate dependencies iterator.",
7281 getIdentifierCString());
7285 while ((libraryID
= OSDynamicCast(OSString
,
7286 libraryIterator
->getNextObject()))) {
7288 const char * library_id
= libraryID
->getCStringNoCopy();
7290 OSString
* libraryVersion
= OSDynamicCast(OSString
,
7291 libraries
->getObject(libraryID
));
7292 if (libraryVersion
== NULL
) {
7294 kOSKextLogErrorLevel
|
7295 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7296 "Kext %s - illegal type in OSBundleLibraries.",
7297 getIdentifierCString());
7301 OSKextVersion libraryVers
=
7302 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
7303 if (libraryVers
== -1) {
7305 kOSKextLogErrorLevel
|
7306 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7307 "Kext %s - invalid library version %s.",
7308 getIdentifierCString(),
7309 libraryVersion
->getCStringNoCopy());
7313 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
7314 if (libraryKext
== NULL
) {
7316 kOSKextLogErrorLevel
|
7317 kOSKextLogDependenciesFlag
,
7318 "Kext %s - library kext %s not found.",
7319 getIdentifierCString(), library_id
);
7323 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
7325 kOSKextLogErrorLevel
|
7326 kOSKextLogDependenciesFlag
,
7327 "Kext %s - library kext %s not compatible "
7328 "with requested version %s.",
7329 getIdentifierCString(), library_id
,
7330 libraryVersion
->getCStringNoCopy());
7334 /* If a nonprelinked library somehow got into the mix for a
7335 * prelinked kext, at any point in the chain, we must fail
7336 * because the prelinked relocs for the library will be all wrong.
7338 if (this->isPrelinked() &&
7339 libraryKext
->declaresExecutable() &&
7340 !libraryKext
->isPrelinked()) {
7343 kOSKextLogErrorLevel
|
7344 kOSKextLogDependenciesFlag
,
7345 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7346 getIdentifierCString(), library_id
,
7347 libraryVersion
->getCStringNoCopy());
7351 if (!libraryKext
->resolveDependencies(loopStack
)) {
7355 /* Add the library directly only if it has an executable to link.
7356 * Otherwise it's just used to collect other dependencies, so put
7357 * *its* dependencies on the list for this kext.
7359 // xxx - We are losing info here; would like to make fake entries or
7360 // xxx - keep these in the dependency graph for loaded kexts.
7361 // xxx - I really want to make kernel components not a special case!
7362 if (libraryKext
->declaresExecutable() ||
7363 libraryKext
->isInterface()) {
7365 if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) {
7366 dependencies
->setObject(libraryKext
);
7369 kOSKextLogDetailLevel
|
7370 kOSKextLogDependenciesFlag
,
7371 "Kext %s added dependency %s.",
7372 getIdentifierCString(),
7373 libraryKext
->getIdentifierCString());
7376 int numLibDependencies
= libraryKext
->getNumDependencies();
7377 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
7380 if (numLibDependencies
) {
7381 // xxx - this msg level should be 1 lower than the per-kext one
7383 kOSKextLogDetailLevel
|
7384 kOSKextLogDependenciesFlag
,
7385 "Kext %s pulling %d dependencies from codeless library %s.",
7386 getIdentifierCString(),
7388 libraryKext
->getIdentifierCString());
7390 for (index
= 0; index
< numLibDependencies
; index
++) {
7391 OSKext
* thisLibDependency
= OSDynamicCast(OSKext
,
7392 libraryDependencies
->getObject(index
));
7393 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) {
7394 dependencies
->setObject(thisLibDependency
);
7396 kOSKextLogDetailLevel
|
7397 kOSKextLogDependenciesFlag
,
7398 "Kext %s added dependency %s from codeless library %s.",
7399 getIdentifierCString(),
7400 thisLibDependency
->getIdentifierCString(),
7401 libraryKext
->getIdentifierCString());
7406 if ((strlen(library_id
) == strlen(KERNEL_LIB
)) &&
7407 0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) {
7409 hasRawKernelDependency
= true;
7410 } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) {
7411 hasKernelDependency
= true;
7412 } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) {
7413 hasKPIDependency
= true;
7414 if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) {
7415 hasPrivateKPIDependency
= true;
7420 if (hasRawKernelDependency
) {
7422 kOSKextLogErrorLevel
|
7423 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7424 "Error - kext %s declares a dependency on %s, which is not permitted.",
7425 getIdentifierCString(), KERNEL_LIB
);
7429 if (hasKernelDependency
) {
7431 kOSKextLogErrorLevel
|
7432 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7433 "Error - kext %s declares %s dependencies. "
7434 "Only %s* dependencies are supported for 64-bit kexts.",
7435 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7438 if (!hasKPIDependency
) {
7440 kOSKextLogWarningLevel
|
7441 kOSKextLogDependenciesFlag
,
7442 "Warning - kext %s declares no %s* dependencies. "
7443 "If it uses any KPIs, the link may fail with undefined symbols.",
7444 getIdentifierCString(), KPI_LIB_PREFIX
);
7446 #else /* __LP64__ */
7447 // xxx - will change to flatly disallow "kernel" dependencies at some point
7448 // xxx - is it invalid to do both "com.apple.kernel" and any
7449 // xxx - "com.apple.kernel.*"?
7451 if (hasKernelDependency
&& hasKPIDependency
) {
7453 kOSKextLogWarningLevel
|
7454 kOSKextLogDependenciesFlag
,
7455 "Warning - kext %s has immediate dependencies on both "
7456 "%s* and %s* components; use only one style.",
7457 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7460 if (!hasKernelDependency
&& !hasKPIDependency
) {
7461 // xxx - do we want to use validation flag for these too?
7463 kOSKextLogWarningLevel
|
7464 kOSKextLogDependenciesFlag
,
7465 "Warning - %s declares no kernel dependencies; using %s.",
7466 getIdentifierCString(), KERNEL6_LIB
);
7467 OSKext
* kernelKext
= OSDynamicCast(OSKext
,
7468 sKextsByID
->getObject(KERNEL6_LIB
));
7470 dependencies
->setObject(kernelKext
);
7473 kOSKextLogErrorLevel
|
7474 kOSKextLogDependenciesFlag
,
7475 "Error - Library %s not found for %s.",
7476 KERNEL6_LIB
, getIdentifierCString());
7480 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7481 * its indirect dependencies to simulate old-style linking. XXX - Should
7482 * check for duplicates.
7484 if (!hasKPIDependency
) {
7487 flags
.hasBleedthrough
= true;
7489 count
= getNumDependencies();
7491 /* We add to the dependencies array in this loop, but do not iterate
7492 * past its original count.
7494 for (i
= 0; i
< count
; i
++) {
7495 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
7496 dependencies
->getObject(i
));
7497 dependencyKext
->addBleedthroughDependencies(dependencies
);
7500 #endif /* __LP64__ */
7502 if (hasPrivateKPIDependency
) {
7503 bool hasApplePrefix
= false;
7504 bool infoCopyrightIsValid
= false;
7505 bool readableCopyrightIsValid
= false;
7507 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
7510 infoString
= OSDynamicCast(OSString
,
7511 getPropertyForHostArch("CFBundleGetInfoString"));
7513 infoCopyrightIsValid
=
7514 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
7517 readableString
= OSDynamicCast(OSString
,
7518 getPropertyForHostArch("NSHumanReadableCopyright"));
7519 if (readableString
) {
7520 readableCopyrightIsValid
=
7521 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
7524 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
7526 kOSKextLogErrorLevel
|
7527 kOSKextLogDependenciesFlag
,
7528 "Error - kext %s declares a dependency on %s. "
7529 "Only Apple kexts may declare a dependency on %s.",
7530 getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
);
7536 flags
.hasAllDependencies
= 1;
7540 if (addedToLoopStack
) {
7541 count
= loopStack
->getCount();
7542 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
7543 loopStack
->removeObject(count
- 1);
7546 kOSKextLogErrorLevel
|
7547 kOSKextLogDependenciesFlag
,
7548 "Kext %s - internal error resolving dependencies.",
7549 getIdentifierCString());
7553 if (result
&& localLoopStack
) {
7555 kOSKextLogStepLevel
|
7556 kOSKextLogDependenciesFlag
,
7557 "Kext %s successfully resolved dependencies.",
7558 getIdentifierCString());
7561 OSSafeReleaseNULL(localLoopStack
);
7562 OSSafeReleaseNULL(libraryIterator
);
7567 /*********************************************************************
7568 *********************************************************************/
7570 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
7572 bool result
= false;
7573 unsigned int dependencyIndex
, dependencyCount
;
7575 dependencyCount
= getNumDependencies();
7577 for (dependencyIndex
= 0;
7578 dependencyIndex
< dependencyCount
;
7579 dependencyIndex
++) {
7581 OSKext
* dependency
= OSDynamicCast(OSKext
,
7582 dependencies
->getObject(dependencyIndex
));
7585 kOSKextLogErrorLevel
|
7586 kOSKextLogDependenciesFlag
,
7587 "Kext %s - internal error propagating compatibility dependencies.",
7588 getIdentifierCString());
7591 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7592 anArray
->setObject(dependency
);
7594 dependency
->addBleedthroughDependencies(anArray
);
7603 /*********************************************************************
7604 *********************************************************************/
7606 OSKext::flushDependencies(bool forceFlag
)
7608 bool result
= false;
7610 /* Only clear the dependencies if the kext isn't loaded;
7611 * we need the info for loaded kexts to track references.
7613 if (!isLoaded() || forceFlag
) {
7615 // xxx - check level
7617 kOSKextLogProgressLevel
|
7618 kOSKextLogDependenciesFlag
,
7619 "Kext %s flushing dependencies.",
7620 getIdentifierCString());
7621 OSSafeReleaseNULL(dependencies
);
7624 if (!isKernelComponent()) {
7625 flags
.hasAllDependencies
= 0;
7633 /*********************************************************************
7634 *********************************************************************/
7636 OSKext::getNumDependencies(void)
7638 if (!dependencies
) {
7641 return dependencies
->getCount();
7644 /*********************************************************************
7645 *********************************************************************/
7647 OSKext::getDependencies(void)
7649 return dependencies
;
7653 #pragma mark OSMetaClass Support
7655 /*********************************************************************
7656 *********************************************************************/
7659 OSMetaClass
* aClass
,
7660 uint32_t numClasses
)
7662 OSReturn result
= kOSMetaClassNoInsKModSet
;
7665 metaClasses
= OSSet::withCapacity(numClasses
);
7671 if (metaClasses
->containsObject(aClass
)) {
7673 kOSKextLogWarningLevel
|
7675 "Notice - kext %s has already registered class %s.",
7676 getIdentifierCString(),
7677 aClass
->getClassName());
7678 result
= kOSReturnSuccess
;
7682 if (!metaClasses
->setObject(aClass
)) {
7686 kOSKextLogDetailLevel
|
7688 "Kext %s registered class %s.",
7689 getIdentifierCString(),
7690 aClass
->getClassName());
7693 if (!flags
.autounloadEnabled
) {
7694 const OSMetaClass
* metaScan
= NULL
; // do not release
7696 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7697 if (metaScan
== OSTypeID(IOService
)) {
7700 kOSKextLogProgressLevel
|
7702 "Kext %s has IOService subclass %s; enabling autounload.",
7703 getIdentifierCString(),
7704 aClass
->getClassName());
7706 flags
.autounloadEnabled
= 1;
7712 notifyAddClassObservers(this, aClass
, flags
);
7714 result
= kOSReturnSuccess
;
7717 if (result
!= kOSReturnSuccess
) {
7719 kOSKextLogErrorLevel
|
7721 "Kext %s failed to register class %s.",
7722 getIdentifierCString(),
7723 aClass
->getClassName());
7729 /*********************************************************************
7730 *********************************************************************/
7732 OSKext::removeClass(
7733 OSMetaClass
* aClass
)
7735 OSReturn result
= kOSMetaClassNoKModSet
;
7741 if (!metaClasses
->containsObject(aClass
)) {
7743 kOSKextLogWarningLevel
|
7745 "Notice - kext %s asked to unregister unknown class %s.",
7746 getIdentifierCString(),
7747 aClass
->getClassName());
7748 result
= kOSReturnSuccess
;
7753 kOSKextLogDetailLevel
|
7755 "Kext %s unregistering class %s.",
7756 getIdentifierCString(),
7757 aClass
->getClassName());
7759 metaClasses
->removeObject(aClass
);
7761 notifyRemoveClassObservers(this, aClass
, flags
);
7763 result
= kOSReturnSuccess
;
7766 if (result
!= kOSReturnSuccess
) {
7768 kOSKextLogErrorLevel
|
7770 "Failed to unregister kext %s class %s.",
7771 getIdentifierCString(),
7772 aClass
->getClassName());
7777 /*********************************************************************
7778 *********************************************************************/
7780 OSKext::getMetaClasses(void)
7785 /*********************************************************************
7786 *********************************************************************/
7788 OSKext::hasOSMetaClassInstances(void)
7790 bool result
= false;
7791 OSCollectionIterator
* classIterator
= NULL
; // must release
7792 OSMetaClass
* checkClass
= NULL
; // do not release
7798 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7799 if (!classIterator
) {
7800 // xxx - log alloc failure?
7803 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7804 if (checkClass
->getInstanceCount()) {
7812 OSSafeReleaseNULL(classIterator
);
7816 /*********************************************************************
7817 *********************************************************************/
7820 OSKext::reportOSMetaClassInstances(
7821 const char * kextIdentifier
,
7822 OSKextLogSpec msgLogSpec
)
7824 OSKext
* theKext
= NULL
; // must release
7826 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
7831 theKext
->reportOSMetaClassInstances(msgLogSpec
);
7833 OSSafeReleaseNULL(theKext
);
7837 /*********************************************************************
7838 *********************************************************************/
7840 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
7842 OSCollectionIterator
* classIterator
= NULL
; // must release
7843 OSMetaClass
* checkClass
= NULL
; // do not release
7849 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7850 if (!classIterator
) {
7853 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7854 if (checkClass
->getInstanceCount()) {
7857 " Kext %s class %s has %d instance%s.",
7858 getIdentifierCString(),
7859 checkClass
->getClassName(),
7860 checkClass
->getInstanceCount(),
7861 checkClass
->getInstanceCount() == 1 ? "" : "s");
7866 OSSafeReleaseNULL(classIterator
);
7871 #pragma mark User-Space Requests
7873 /*********************************************************************
7874 * XXX - this function is a big ugly mess
7875 *********************************************************************/
7878 OSKext::handleRequest(
7879 host_priv_t hostPriv
,
7880 OSKextLogSpec clientLogFilter
,
7881 char * requestBuffer
,
7882 uint32_t requestLength
,
7883 char ** responseOut
,
7884 uint32_t * responseLengthOut
,
7886 uint32_t * logInfoLengthOut
)
7888 OSReturn result
= kOSReturnError
;
7889 kern_return_t kmem_result
= KERN_FAILURE
;
7891 char * response
= NULL
; // returned by reference
7892 uint32_t responseLength
= 0;
7894 OSObject
* parsedXML
= NULL
; // must release
7895 OSDictionary
* requestDict
= NULL
; // do not release
7896 OSString
* errorString
= NULL
; // must release
7898 OSObject
* responseObject
= NULL
; // must release
7900 OSSerialize
* serializer
= NULL
; // must release
7902 OSArray
* logInfoArray
= NULL
; // must release
7904 OSString
* predicate
= NULL
; // do not release
7905 OSString
* kextIdentifier
= NULL
; // do not release
7906 OSArray
* kextIdentifiers
= NULL
; // do not release
7907 OSKext
* theKext
= NULL
; // do not release
7908 OSBoolean
* boolArg
= NULL
; // do not release
7910 IORecursiveLockLock(sKextLock
);
7913 *responseOut
= NULL
;
7914 *responseLengthOut
= 0;
7918 *logInfoLengthOut
= 0;
7921 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
7923 /* XML must be nul-terminated.
7925 if (requestBuffer
[requestLength
- 1] != '\0') {
7926 OSKextLog(/* kext */ NULL
,
7927 kOSKextLogErrorLevel
|
7929 "Invalid request from user space (not nul-terminated).");
7930 result
= kOSKextReturnBadData
;
7933 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
7935 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
7938 const char * errorCString
= "(unknown error)";
7940 if (errorString
&& errorString
->getCStringNoCopy()) {
7941 errorCString
= errorString
->getCStringNoCopy();
7942 } else if (parsedXML
) {
7943 errorCString
= "not a dictionary";
7945 OSKextLog(/* kext */ NULL
,
7946 kOSKextLogErrorLevel
|
7948 "Error unserializing request from user space: %s.",
7950 result
= kOSKextReturnSerialization
;
7954 predicate
= _OSKextGetRequestPredicate(requestDict
);
7956 OSKextLog(/* kext */ NULL
,
7957 kOSKextLogErrorLevel
|
7959 "Recieved kext request from user space with no predicate.");
7960 result
= kOSKextReturnInvalidArgument
;
7964 OSKextLog(/* kext */ NULL
,
7965 kOSKextLogDebugLevel
|
7967 "Received '%s' request from user space.",
7968 predicate
->getCStringNoCopy());
7970 result
= kOSKextReturnNotPrivileged
;
7971 if (hostPriv
== HOST_PRIV_NULL
) {
7972 /* must be root to use these kext requests */
7973 if (predicate
->isEqualTo(kKextRequestPredicateUnload
) ||
7974 predicate
->isEqualTo(kKextRequestPredicateStart
) ||
7975 predicate
->isEqualTo(kKextRequestPredicateStop
) ||
7976 predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
) ||
7977 predicate
->isEqualTo(kKextRequestPredicateSendResource
) ) {
7978 OSKextLog(/* kext */ NULL
,
7979 kOSKextLogErrorLevel
|
7981 "Access Failure - must be root user.");
7986 /* Get common args in anticipation of use.
7988 kextIdentifier
= OSDynamicCast(OSString
, _OSKextGetRequestArgument(
7989 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7990 kextIdentifiers
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument(
7991 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7992 if (kextIdentifier
) {
7993 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
7995 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
7996 requestDict
, kKextRequestArgumentValueKey
));
7998 result
= kOSKextReturnInvalidArgument
;
8000 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
8001 if (!kextIdentifier
) {
8002 OSKextLog(/* kext */ NULL
,
8003 kOSKextLogErrorLevel
|
8005 "Invalid arguments to kext start request.");
8006 } else if (!theKext
) {
8007 OSKextLog(/* kext */ NULL
,
8008 kOSKextLogErrorLevel
|
8010 "Kext %s not found for start request.",
8011 kextIdentifier
->getCStringNoCopy());
8012 result
= kOSKextReturnNotFound
;
8014 result
= theKext
->start();
8017 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
8018 if (!kextIdentifier
) {
8019 OSKextLog(/* kext */ NULL
,
8020 kOSKextLogErrorLevel
|
8022 "Invalid arguments to kext stop request.");
8023 } else if (!theKext
) {
8024 OSKextLog(/* kext */ NULL
,
8025 kOSKextLogErrorLevel
|
8027 "Kext %s not found for stop request.",
8028 kextIdentifier
->getCStringNoCopy());
8029 result
= kOSKextReturnNotFound
;
8031 result
= theKext
->stop();
8034 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
8035 if (!kextIdentifier
) {
8036 OSKextLog(/* kext */ NULL
,
8037 kOSKextLogErrorLevel
|
8039 "Invalid arguments to kext unload request.");
8040 } else if (!theKext
) {
8041 OSKextLog(/* kext */ NULL
,
8042 kOSKextLogErrorLevel
|
8044 "Kext %s not found for unload request.",
8045 kextIdentifier
->getCStringNoCopy());
8046 result
= kOSKextReturnNotFound
;
8048 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
8049 _OSKextGetRequestArgument(requestDict
,
8050 kKextRequestArgumentTerminateIOServicesKey
));
8051 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
8054 } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
8055 result
= OSKext::dispatchResource(requestDict
);
8057 } else if (predicate
->isEqualTo(kKextRequestPredicateGetUUIDByAddress
)) {
8059 OSNumber
*lookupNum
= NULL
;
8060 lookupNum
= OSDynamicCast(OSNumber
,
8061 _OSKextGetRequestArgument(requestDict
,
8062 kKextRequestArgumentLookupAddressKey
));
8064 responseObject
= OSKext::copyKextUUIDForAddress(lookupNum
);
8065 if (responseObject
) {
8066 result
= kOSReturnSuccess
;
8071 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
) ||
8072 predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
8073 OSBoolean
* delayAutounloadBool
= NULL
;
8074 OSObject
* infoKeysRaw
= NULL
;
8075 OSArray
* infoKeys
= NULL
;
8076 uint32_t infoKeysCount
= 0;
8078 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
8079 _OSKextGetRequestArgument(requestDict
,
8080 kKextRequestArgumentDelayAutounloadKey
));
8082 /* If asked to delay autounload, reset the timer if it's currently set.
8083 * (That is, don't schedule an unload if one isn't already pending.
8085 if (delayAutounloadBool
== kOSBooleanTrue
) {
8086 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8089 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
8090 kKextRequestArgumentInfoKeysKey
);
8091 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
8092 if (infoKeysRaw
&& !infoKeys
) {
8093 OSKextLog(/* kext */ NULL
,
8094 kOSKextLogErrorLevel
|
8096 "Invalid arguments to kext info request.");
8101 infoKeysCount
= infoKeys
->getCount();
8102 for (uint32_t i
= 0; i
< infoKeysCount
; i
++) {
8103 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) {
8104 OSKextLog(/* kext */ NULL
,
8105 kOSKextLogErrorLevel
|
8107 "Invalid arguments to kext info request.");
8113 if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
8114 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
8116 else if (predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
8117 responseObject
= OSKext::copyLoadedKextInfoByUUID(kextIdentifiers
, infoKeys
);
8119 if (!responseObject
) {
8120 result
= kOSKextReturnInternalError
;
8122 OSKextLog(/* kext */ NULL
,
8123 kOSKextLogDebugLevel
|
8125 "Returning loaded kext info.");
8126 result
= kOSReturnSuccess
;
8128 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) {
8130 /* Hand the current sKernelRequests array to the caller
8131 * (who must release it), and make a new one.
8133 responseObject
= sKernelRequests
;
8134 sKernelRequests
= OSArray::withCapacity(0);
8135 sPostedKextLoadIdentifiers
->flushCollection();
8136 OSKextLog(/* kext */ NULL
,
8137 kOSKextLogDebugLevel
|
8139 "Returning kernel requests.");
8140 result
= kOSReturnSuccess
;
8142 } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) {
8144 /* Return the set of all requested bundle identifiers */
8145 responseObject
= sAllKextLoadIdentifiers
;
8146 responseObject
->retain();
8147 OSKextLog(/* kext */ NULL
,
8148 kOSKextLogDebugLevel
|
8150 "Returning load requests.");
8151 result
= kOSReturnSuccess
;
8154 OSKextLog(/* kext */ NULL
,
8155 kOSKextLogDebugLevel
|
8157 "Received '%s' invalid request from user space.",
8158 predicate
->getCStringNoCopy());
8163 * Now we have handle the request, or not. Gather up the response & logging
8164 * info to ship to user space.
8167 /* Note: Nothing in OSKext is supposed to retain requestDict,
8168 * but you never know....
8170 if (requestDict
->getRetainCount() > 1) {
8171 OSKextLog(/* kext */ NULL
,
8172 kOSKextLogWarningLevel
|
8174 "Request from user space still retained by a kext; "
8175 "probable memory leak.");
8178 if (responseOut
&& responseObject
) {
8179 serializer
= OSSerialize::withCapacity(0);
8181 result
= kOSKextReturnNoMemory
;
8185 if (!responseObject
->serialize(serializer
)) {
8186 OSKextLog(/* kext */ NULL
,
8187 kOSKextLogGeneralFlag
| kOSKextLogErrorLevel
,
8188 "Failed to serialize response to request from user space.");
8189 result
= kOSKextReturnSerialization
;
8193 response
= (char *)serializer
->text();
8194 responseLength
= serializer
->getLength();
8197 if (responseOut
&& response
) {
8200 /* This kmem_alloc sets the return value of the function.
8202 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
,
8203 round_page(responseLength
), VM_KERN_MEMORY_OSKEXT
);
8204 if (kmem_result
!= KERN_SUCCESS
) {
8205 OSKextLog(/* kext */ NULL
,
8206 kOSKextLogErrorLevel
|
8208 "Failed to copy response to request from user space.");
8209 result
= kmem_result
;
8212 /* 11981737 - clear uninitialized data in last page */
8213 bzero((void *)(buffer
+ responseLength
),
8214 (round_page(responseLength
) - responseLength
));
8215 memcpy(buffer
, response
, responseLength
);
8216 *responseOut
= buffer
;
8217 *responseLengthOut
= responseLength
;
8223 /* Gather up the collected log messages for user space. Any messages
8224 * messages past this call will not make it up as log messages but
8225 * will be in the system log. Note that we ignore the return of the
8226 * serialize; it has no bearing on the operation at hand even if we
8227 * fail to get the log messages.
8229 logInfoArray
= OSKext::clearUserSpaceLogFilter();
8231 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
8232 (void)OSKext::serializeLogInfo(logInfoArray
,
8233 logInfoOut
, logInfoLengthOut
);
8236 IORecursiveLockUnlock(sKextLock
);
8238 OSSafeReleaseNULL(parsedXML
);
8239 OSSafeReleaseNULL(errorString
);
8240 OSSafeReleaseNULL(responseObject
);
8241 OSSafeReleaseNULL(serializer
);
8242 OSSafeReleaseNULL(logInfoArray
);
8248 // #include <InstrProfiling.h>
8251 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin
,
8252 const char *DataEnd
,
8253 const char *CountersBegin
,
8254 const char *CountersEnd
,
8255 const char *NamesBegin
,
8256 const char *NamesEnd
);
8257 int __llvm_profile_write_buffer_internal(char *Buffer
,
8258 const char *DataBegin
,
8259 const char *DataEnd
,
8260 const char *CountersBegin
,
8261 const char *CountersEnd
,
8262 const char *NamesBegin
,
8263 const char *NamesEnd
);
8268 void OSKextPgoMetadataPut(char *pBuffer
,
8271 uint32_t *num_pairs
,
8275 size_t strlen_key
= strlen(key
);
8276 size_t strlen_value
= strlen(value
);
8277 size_t len
= strlen(key
) + 1 + strlen(value
) + 1;
8278 char *pos
= pBuffer
+ *position
;
8280 if (pBuffer
&& bufferSize
&& *position
<= bufferSize
) {
8281 memcpy(pos
, key
, strlen_key
); pos
+= strlen_key
;
8283 memcpy(pos
, value
, strlen_value
); pos
+= strlen_value
;
8293 void OSKextPgoMetadataPutMax(size_t *position
, const char *key
, size_t value_max
)
8295 *position
+= strlen(key
) + 1 + value_max
+ 1;
8300 void OSKextPgoMetadataPutAll(OSKext
*kext
,
8301 uuid_t instance_uuid
,
8305 uint32_t *num_pairs
)
8307 _static_assert_1_arg(sizeof(clock_sec_t
) % 2 == 0);
8308 //log_10 2^16 ≈ 4.82
8309 const size_t max_secs_string_size
= 5 * sizeof(clock_sec_t
)/2;
8310 const size_t max_timestamp_string_size
= max_secs_string_size
+ 1 + 6;
8313 OSKextPgoMetadataPutMax(position
, "INSTANCE", 36);
8314 OSKextPgoMetadataPutMax(position
, "UUID", 36);
8315 OSKextPgoMetadataPutMax(position
, "TIMESTAMP", max_timestamp_string_size
);
8317 uuid_string_t instance_uuid_string
;
8318 uuid_unparse(instance_uuid
, instance_uuid_string
);
8319 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8320 "INSTANCE", instance_uuid_string
);
8324 uuid_string_t uuid_string
;
8325 uuid_data
= kext
->copyUUID();
8327 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
8328 OSSafeReleaseNULL(uuid_data
);
8329 uuid_unparse(uuid
, uuid_string
);
8330 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8331 "UUID", uuid_string
);
8336 clock_get_calendar_microtime(&secs
, &usecs
);
8337 assert(usecs
< 1000000);
8338 char timestamp
[max_timestamp_string_size
+ 1];
8339 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t
));
8340 snprintf(timestamp
, sizeof(timestamp
), "%lu.%06d", (unsigned long)secs
, (int)usecs
);
8341 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8342 "TIMESTAMP", timestamp
);
8345 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8346 "NAME", kext
->getIdentifierCString());
8348 char versionCString
[kOSKextVersionMaxLength
];
8349 OSKextVersionGetString(kext
->getVersion(), versionCString
, kOSKextVersionMaxLength
);
8350 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8351 "VERSION", versionCString
);
8356 size_t OSKextPgoMetadataSize(OSKext
*kext
)
8358 size_t position
= 0;
8359 uuid_t fakeuuid
= {};
8360 OSKextPgoMetadataPutAll(kext
, fakeuuid
, NULL
, &position
, 0, NULL
);
8364 int OSKextGrabPgoDataLocked(OSKext
*kext
,
8366 uuid_t instance_uuid
,
8369 uint64_t bufferSize
)
8373 kernel_section_t
*sect_prf_data
= NULL
;
8374 kernel_section_t
*sect_prf_name
= NULL
;
8375 kernel_section_t
*sect_prf_cnts
= NULL
;
8377 size_t metadata_size
= 0;
8379 sect_prf_data
= kext
->lookupSection("__DATA", "__llvm_prf_data");
8380 sect_prf_name
= kext
->lookupSection("__DATA", "__llvm_prf_name");
8381 sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8383 if (!sect_prf_data
|| !sect_prf_name
|| !sect_prf_cnts
) {
8388 size
= __llvm_profile_get_size_for_buffer_internal(
8389 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8390 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8391 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8394 metadata_size
= OSKextPgoMetadataSize(kext
);
8395 size
+= metadata_size
;
8396 size
+= sizeof(pgo_metadata_footer
);
8404 if (pBuffer
&& bufferSize
) {
8405 if (bufferSize
< size
) {
8410 err
= __llvm_profile_write_buffer_internal(
8412 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8413 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8414 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8422 char *end_of_buffer
= pBuffer
+ size
;
8423 struct pgo_metadata_footer
*footerp
= (struct pgo_metadata_footer
*) (end_of_buffer
- sizeof(struct pgo_metadata_footer
));
8424 char *metadata_buffer
= end_of_buffer
- (sizeof(struct pgo_metadata_footer
) + metadata_size
);
8426 size_t metadata_position
= 0;
8427 uint32_t num_pairs
= 0;
8428 OSKextPgoMetadataPutAll(kext
, instance_uuid
, metadata_buffer
, &metadata_position
, metadata_size
, &num_pairs
);
8429 while (metadata_position
< metadata_size
) {
8430 metadata_buffer
[metadata_position
++] = 0;
8433 struct pgo_metadata_footer footer
;
8434 footer
.magic
= htonl(0x6d657461);
8435 footer
.number_of_pairs
= htonl( num_pairs
);
8436 footer
.offset_to_pairs
= htonl( sizeof(struct pgo_metadata_footer
) + metadata_size
);
8437 memcpy(footerp
, &footer
, sizeof(footer
));
8448 OSKextGrabPgoData(uuid_t uuid
,
8451 uint64_t bufferSize
,
8452 int wait_for_unload
,
8456 OSKext
*kext
= NULL
;
8459 IORecursiveLockLock(sKextLock
);
8461 kext
= OSKext::lookupKextWithUUID(uuid
);
8467 if (wait_for_unload
) {
8468 OSKextGrabPgoStruct s
;
8470 s
.metadata
= metadata
;
8472 s
.pBuffer
= pBuffer
;
8473 s
.bufferSize
= bufferSize
;
8476 struct list_head
*prev
= &kext
->pendingPgoHead
;
8477 struct list_head
*next
= kext
->pendingPgoHead
.next
;
8479 s
.list_head
.prev
= prev
;
8480 s
.list_head
.next
= next
;
8482 prev
->next
= &s
.list_head
;
8483 next
->prev
= &s
.list_head
;
8488 IORecursiveLockSleep(sKextLock
, &s
, THREAD_ABORTSAFE
);
8490 prev
= s
.list_head
.prev
;
8491 next
= s
.list_head
.next
;
8499 err
= OSKextGrabPgoDataLocked(kext
, metadata
, kext
->instance_uuid
, pSize
, pBuffer
, bufferSize
);
8507 IORecursiveLockUnlock(sKextLock
);
8513 OSKextResetPgoCountersLock()
8515 IORecursiveLockLock(sKextLock
);
8519 OSKextResetPgoCountersUnlock()
8521 IORecursiveLockUnlock(sKextLock
);
8525 extern unsigned int not_in_kdp
;
8528 OSKextResetPgoCounters()
8530 assert(!not_in_kdp
);
8531 uint32_t count
= sLoadedKexts
->getCount();
8532 for (uint32_t i
= 0; i
< count
; i
++) {
8533 OSKext
*kext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8534 kernel_section_t
*sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8535 if (!sect_prf_cnts
) {
8538 memset((void*)sect_prf_cnts
->addr
, 0, sect_prf_cnts
->size
);
8543 OSKext::copyLoadedKextInfoByUUID(
8544 OSArray
* kextIdentifiers
,
8547 OSDictionary
* result
= NULL
;
8548 OSDictionary
* kextInfo
= NULL
; // must release
8550 uint32_t idCount
= 0;
8551 uint32_t idIndex
= 0;
8553 IORecursiveLockLock(sKextLock
);
8556 /* Is the calling process allowed to query kext info? */
8557 if (current_task() != kernel_task
) {
8558 int macCheckResult
= 0;
8559 kauth_cred_t cred
= NULL
;
8561 cred
= kauth_cred_get_with_ref();
8562 macCheckResult
= mac_kext_check_query(cred
);
8563 kauth_cred_unref(&cred
);
8565 if (macCheckResult
!= 0) {
8566 OSKextLog(/* kext */ NULL
,
8567 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8568 "Failed to query kext info (MAC policy error 0x%x).",
8575 /* Empty list of UUIDs is equivalent to no list (get all).
8577 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8578 kextIdentifiers
= NULL
;
8579 } else if (kextIdentifiers
) {
8580 idCount
= kextIdentifiers
->getCount();
8585 if (infoKeys
&& !infoKeys
->getCount()) {
8589 count
= sLoadedKexts
->getCount();
8590 result
= OSDictionary::withCapacity(count
);
8595 for (i
= 0; i
< count
; i
++) {
8596 OSKext
*thisKext
= NULL
; // do not release
8597 Boolean includeThis
= true;
8598 uuid_t thisKextUUID
;
8600 uuid_string_t uuid_key
;
8603 kextInfo
->release();
8607 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8612 uuid_data
= thisKext
->copyUUID();
8617 memcpy(&thisKextUUID
, uuid_data
->getBytesNoCopy(), sizeof(thisKextUUID
));
8618 OSSafeReleaseNULL(uuid_data
);
8620 uuid_unparse(thisKextUUID
, uuid_key
);
8622 /* Skip current kext if we have a list of UUIDs and
8623 * it isn't in the list.
8625 if (kextIdentifiers
) {
8626 includeThis
= false;
8628 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8629 const OSString
* wantedUUID
= OSDynamicCast(OSString
,
8630 kextIdentifiers
->getObject(idIndex
));
8633 uuid_parse(wantedUUID
->getCStringNoCopy(), uuid
);
8635 if (0 == uuid_compare(uuid
, thisKextUUID
)) {
8647 kextInfo
= thisKext
->copyInfo(infoKeys
);
8649 result
->setObject(uuid_key
, kextInfo
);
8654 IORecursiveLockUnlock(sKextLock
);
8656 if (kextInfo
) kextInfo
->release();
8661 /*********************************************************************
8662 *********************************************************************/
8665 OSKext::copyLoadedKextInfo(
8666 OSArray
* kextIdentifiers
,
8669 OSDictionary
* result
= NULL
;
8670 OSDictionary
* kextInfo
= NULL
; // must release
8672 uint32_t idCount
= 0;
8673 uint32_t idIndex
= 0;
8675 IORecursiveLockLock(sKextLock
);
8678 /* Is the calling process allowed to query kext info? */
8679 if (current_task() != kernel_task
) {
8680 int macCheckResult
= 0;
8681 kauth_cred_t cred
= NULL
;
8683 cred
= kauth_cred_get_with_ref();
8684 macCheckResult
= mac_kext_check_query(cred
);
8685 kauth_cred_unref(&cred
);
8687 if (macCheckResult
!= 0) {
8688 OSKextLog(/* kext */ NULL
,
8689 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8690 "Failed to query kext info (MAC policy error 0x%x).",
8697 /* Empty list of bundle ids is equivalent to no list (get all).
8699 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8700 kextIdentifiers
= NULL
;
8701 } else if (kextIdentifiers
) {
8702 idCount
= kextIdentifiers
->getCount();
8707 if (infoKeys
&& !infoKeys
->getCount()) {
8711 count
= sLoadedKexts
->getCount();
8712 result
= OSDictionary::withCapacity(count
);
8718 OSKextLog(/* kext */ NULL
,
8719 kOSKextLogErrorLevel
|
8720 kOSKextLogGeneralFlag
,
8721 "kaslr: vm_kernel_slide 0x%lx \n",
8723 OSKextLog(/* kext */ NULL
,
8724 kOSKextLogErrorLevel
|
8725 kOSKextLogGeneralFlag
,
8726 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
8727 vm_kernel_stext
, vm_kernel_etext
);
8728 OSKextLog(/* kext */ NULL
,
8729 kOSKextLogErrorLevel
|
8730 kOSKextLogGeneralFlag
,
8731 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
8732 vm_kernel_base
, vm_kernel_top
);
8733 OSKextLog(/* kext */ NULL
,
8734 kOSKextLogErrorLevel
|
8735 kOSKextLogGeneralFlag
,
8736 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
8737 vm_kext_base
, vm_kext_top
);
8738 OSKextLog(/* kext */ NULL
,
8739 kOSKextLogErrorLevel
|
8740 kOSKextLogGeneralFlag
,
8741 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
8742 vm_prelink_stext
, vm_prelink_etext
);
8743 OSKextLog(/* kext */ NULL
,
8744 kOSKextLogErrorLevel
|
8745 kOSKextLogGeneralFlag
,
8746 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
8747 vm_prelink_sinfo
, vm_prelink_einfo
);
8748 OSKextLog(/* kext */ NULL
,
8749 kOSKextLogErrorLevel
|
8750 kOSKextLogGeneralFlag
,
8751 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
8752 vm_slinkedit
, vm_elinkedit
);
8755 for (i
= 0; i
< count
; i
++) {
8756 OSKext
* thisKext
= NULL
; // do not release
8757 Boolean includeThis
= true;
8760 kextInfo
->release();
8763 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8768 /* Skip current kext if we have a list of bundle IDs and
8769 * it isn't in the list.
8771 if (kextIdentifiers
) {
8772 const OSString
* thisKextID
= thisKext
->getIdentifier();
8774 includeThis
= false;
8776 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8777 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
8778 kextIdentifiers
->getObject(idIndex
));
8779 if (thisKextID
->isEqualTo(thisRequestID
)) {
8790 kextInfo
= thisKext
->copyInfo(infoKeys
);
8792 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
8797 IORecursiveLockUnlock(sKextLock
);
8799 if (kextInfo
) kextInfo
->release();
8804 /*********************************************************************
8805 * Any info that needs to do allocations must goto finish on alloc
8806 * failure. Info that is just a lookup should just not set the object
8807 * if the info does not exist.
8808 *********************************************************************/
8809 #define _OSKextLoadInfoDictCapacity (12)
8812 OSKext::copyInfo(OSArray
* infoKeys
)
8814 OSDictionary
* result
= NULL
;
8815 bool success
= false;
8816 OSData
* headerData
= NULL
; // must release
8817 OSData
* logData
= NULL
; // must release
8818 OSNumber
* cpuTypeNumber
= NULL
; // must release
8819 OSNumber
* cpuSubtypeNumber
= NULL
; // must release
8820 OSString
* versionString
= NULL
; // do not release
8821 uint32_t executablePathCStringSize
= 0;
8822 char * executablePathCString
= NULL
; // must release
8823 OSString
* executablePathString
= NULL
; // must release
8824 OSData
* uuid
= NULL
; // must release
8825 OSNumber
* scratchNumber
= NULL
; // must release
8826 OSArray
* dependencyLoadTags
= NULL
; // must release
8827 OSCollectionIterator
* metaClassIterator
= NULL
; // must release
8828 OSArray
* metaClassInfo
= NULL
; // must release
8829 OSDictionary
* metaClassDict
= NULL
; // must release
8830 OSMetaClass
* thisMetaClass
= NULL
; // do not release
8831 OSString
* metaClassName
= NULL
; // must release
8832 OSString
* superclassName
= NULL
; // must release
8835 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
8841 /* Empty keys means no keys, but NULL is quicker to check.
8843 if (infoKeys
&& !infoKeys
->getCount()) {
8847 /* Headers, CPU type, and CPU subtype.
8850 _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) ||
8851 _OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
) ||
8852 _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) ||
8853 _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
))
8856 if (linkedExecutable
&& !isInterface()) {
8858 kernel_mach_header_t
*kext_mach_hdr
= (kernel_mach_header_t
*)
8859 linkedExecutable
->getBytesNoCopy();
8862 // do not return macho header info on shipping iOS - 19095897
8863 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) {
8864 kernel_mach_header_t
* temp_kext_mach_hdr
;
8865 struct load_command
* lcp
;
8867 headerData
= OSData::withBytes(kext_mach_hdr
,
8868 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
8873 // unslide any vmaddrs we return to userspace - 10726716
8874 temp_kext_mach_hdr
= (kernel_mach_header_t
*)
8875 headerData
->getBytesNoCopy();
8876 if (temp_kext_mach_hdr
== NULL
) {
8880 lcp
= (struct load_command
*) (temp_kext_mach_hdr
+ 1);
8881 for (i
= 0; i
< temp_kext_mach_hdr
->ncmds
; i
++) {
8882 if (lcp
->cmd
== LC_SEGMENT_KERNEL
) {
8883 kernel_segment_command_t
* segp
;
8884 kernel_section_t
* secp
;
8886 segp
= (kernel_segment_command_t
*) lcp
;
8887 // 10543468 - if we jettisoned __LINKEDIT clear size info
8888 if (flags
.jettisonLinkeditSeg
) {
8889 if (strncmp(segp
->segname
, SEG_LINKEDIT
, sizeof(segp
->segname
)) == 0) {
8897 OSKextLog(/* kext */ NULL
,
8898 kOSKextLogErrorLevel
|
8899 kOSKextLogGeneralFlag
,
8900 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
8901 __FUNCTION__
, segp
->segname
, segp
->vmaddr
,
8902 VM_KERNEL_UNSLIDE(segp
->vmaddr
),
8903 segp
->vmsize
, segp
->nsects
);
8904 if ( (VM_KERNEL_IS_SLID(segp
->vmaddr
) == false) &&
8905 (VM_KERNEL_IS_KEXT(segp
->vmaddr
) == false) &&
8906 (VM_KERNEL_IS_PRELINKTEXT(segp
->vmaddr
) == false) &&
8907 (VM_KERNEL_IS_PRELINKINFO(segp
->vmaddr
) == false) &&
8908 (VM_KERNEL_IS_KEXT_LINKEDIT(segp
->vmaddr
) == false) ) {
8909 OSKextLog(/* kext */ NULL
,
8910 kOSKextLogErrorLevel
|
8911 kOSKextLogGeneralFlag
,
8912 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
8913 __FUNCTION__
, segp
->vmaddr
, vm_kext_base
, vm_kext_top
);
8916 segp
->vmaddr
= VM_KERNEL_UNSLIDE(segp
->vmaddr
);
8918 for (secp
= firstsect(segp
); secp
!= NULL
; secp
= nextsect(segp
, secp
)) {
8919 secp
->addr
= VM_KERNEL_UNSLIDE(secp
->addr
);
8922 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
8924 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
8926 #endif // SECURE_KERNEL
8928 if (_OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
)) {
8929 osLogDataHeaderRef
*header
;
8930 char headerBytes
[offsetof(osLogDataHeaderRef
, sections
) + NUM_OS_LOG_SECTIONS
* sizeof(header
->sections
[0])];
8932 void *os_log_data
= NULL
;
8933 void *cstring_data
= NULL
;
8934 unsigned long os_log_size
= 0;
8935 unsigned long cstring_size
= 0;
8936 uint32_t os_log_offset
= 0;
8937 uint32_t cstring_offset
= 0;
8940 os_log_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__os_log", &os_log_size
);
8941 os_log_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__os_log");
8942 cstring_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__cstring", &cstring_size
);
8943 cstring_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__cstring");
8945 header
= (osLogDataHeaderRef
*) headerBytes
;
8946 header
->version
= OS_LOG_HDR_VERSION
;
8947 header
->sect_count
= NUM_OS_LOG_SECTIONS
;
8948 header
->sections
[OS_LOG_SECT_IDX
].sect_offset
= os_log_offset
;
8949 header
->sections
[OS_LOG_SECT_IDX
].sect_size
= (uint32_t) os_log_size
;
8950 header
->sections
[CSTRING_SECT_IDX
].sect_offset
= cstring_offset
;
8951 header
->sections
[CSTRING_SECT_IDX
].sect_size
= (uint32_t) cstring_size
;
8954 logData
= OSData::withBytes(header
, (u_int
) (sizeof(osLogDataHeaderRef
)));
8958 res
= logData
->appendBytes(&(header
->sections
[0]), (u_int
)(header
->sect_count
* sizeof(header
->sections
[0])));
8963 res
= logData
->appendBytes(os_log_data
, (u_int
)header
->sections
[OS_LOG_SECT_IDX
].sect_size
);
8969 res
= logData
->appendBytes(cstring_data
, (u_int
)header
->sections
[CSTRING_SECT_IDX
].sect_size
);
8974 result
->setObject(kOSBundleLogStringsKey
, logData
);
8977 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) {
8978 cpuTypeNumber
= OSNumber::withNumber(
8979 (uint64_t) kext_mach_hdr
->cputype
,
8980 8 * sizeof(kext_mach_hdr
->cputype
));
8981 if (!cpuTypeNumber
) {
8984 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
8987 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
8988 cpuSubtypeNumber
= OSNumber::withNumber(
8989 (uint64_t) kext_mach_hdr
->cpusubtype
,
8990 8 * sizeof(kext_mach_hdr
->cpusubtype
));
8991 if (!cpuSubtypeNumber
) {
8994 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
8999 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
9001 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
9005 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
9006 versionString
= OSDynamicCast(OSString
,
9007 getPropertyForHostArch(kCFBundleVersionKey
));
9008 if (versionString
) {
9009 result
->setObject(kCFBundleVersionKey
, versionString
);
9013 /* OSBundleCompatibleVersion.
9015 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
9016 versionString
= OSDynamicCast(OSString
,
9017 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
9018 if (versionString
) {
9019 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
9025 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
9027 result
->setObject(kOSBundlePathKey
, path
);
9032 /* OSBundleExecutablePath.
9034 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
9035 if (path
&& executableRelPath
) {
9037 uint32_t pathLength
= path
->getLength(); // gets incremented below
9039 // +1 for slash, +1 for \0
9040 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
9042 executablePathCString
= (char *)kalloc_tag((executablePathCStringSize
) *
9043 sizeof(char), VM_KERN_MEMORY_OSKEXT
); // +1 for \0
9044 if (!executablePathCString
) {
9047 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
9048 executablePathCStringSize
);
9049 executablePathCString
[pathLength
++] = '/';
9050 executablePathCString
[pathLength
++] = '\0';
9051 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
9052 executablePathCStringSize
);
9054 executablePathString
= OSString::withCString(executablePathCString
);
9056 if (!executablePathString
) {
9060 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
9064 /* UUID, if the kext has one.
9066 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
9069 result
->setObject(kOSBundleUUIDKey
, uuid
);
9074 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
9076 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSKernelResourceKey
)) {
9077 result
->setObject(kOSKernelResourceKey
,
9078 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
9081 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
9082 result
->setObject(kOSBundleIsInterfaceKey
,
9083 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
9086 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
9087 result
->setObject(kOSBundlePrelinkedKey
,
9088 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
9091 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
9092 result
->setObject(kOSBundleStartedKey
,
9093 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
9098 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
9099 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
9100 /* numBits */ 8 * sizeof(loadTag
));
9101 if (!scratchNumber
) {
9104 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
9105 OSSafeReleaseNULL(scratchNumber
);
9108 /* LoadAddress, LoadSize.
9111 _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) ||
9112 _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) ||
9113 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
) ||
9114 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
) ||
9115 _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
))
9117 if (isInterface() || linkedExecutable
) {
9118 /* These go to userspace via serialization, so we don't want any doubts
9121 uint64_t loadAddress
= 0;
9122 uint32_t loadSize
= 0;
9123 uint32_t wiredSize
= 0;
9124 uint64_t execLoadAddress
= 0;
9125 uint32_t execLoadSize
= 0;
9127 /* Interfaces always report 0 load address & size.
9128 * Just the way they roll.
9130 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
9131 * xxx - shouldn't have one!
9133 if (linkedExecutable
/* && !isInterface() */) {
9134 kernel_mach_header_t
*mh
= NULL
;
9135 kernel_segment_command_t
*seg
= NULL
;
9137 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
9138 mh
= (kernel_mach_header_t
*)loadAddress
;
9139 loadAddress
= VM_KERNEL_UNSLIDE(loadAddress
);
9140 loadSize
= linkedExecutable
->getLength();
9142 /* Walk through the kext, looking for the first executable
9143 * segment in case we were asked for its size/address.
9145 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
9146 if (seg
->initprot
& VM_PROT_EXECUTE
) {
9147 execLoadAddress
= VM_KERNEL_UNSLIDE(seg
->vmaddr
);
9148 execLoadSize
= seg
->vmsize
;
9153 /* If we have a kmod_info struct, calculated the wired size
9154 * from that. Otherwise it's the full load size.
9157 wiredSize
= loadSize
- kmod_info
->hdr_size
;
9159 wiredSize
= loadSize
;
9163 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
9164 scratchNumber
= OSNumber::withNumber(
9165 (unsigned long long)(loadAddress
),
9166 /* numBits */ 8 * sizeof(loadAddress
));
9167 if (!scratchNumber
) {
9170 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
9171 OSSafeReleaseNULL(scratchNumber
);
9173 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
)) {
9174 scratchNumber
= OSNumber::withNumber(
9175 (unsigned long long)(execLoadAddress
),
9176 /* numBits */ 8 * sizeof(execLoadAddress
));
9177 if (!scratchNumber
) {
9180 result
->setObject(kOSBundleExecLoadAddressKey
, scratchNumber
);
9181 OSSafeReleaseNULL(scratchNumber
);
9183 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
9184 scratchNumber
= OSNumber::withNumber(
9185 (unsigned long long)(loadSize
),
9186 /* numBits */ 8 * sizeof(loadSize
));
9187 if (!scratchNumber
) {
9190 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
9191 OSSafeReleaseNULL(scratchNumber
);
9193 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
)) {
9194 scratchNumber
= OSNumber::withNumber(
9195 (unsigned long long)(execLoadSize
),
9196 /* numBits */ 8 * sizeof(execLoadSize
));
9197 if (!scratchNumber
) {
9200 result
->setObject(kOSBundleExecLoadSizeKey
, scratchNumber
);
9201 OSSafeReleaseNULL(scratchNumber
);
9203 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
9204 scratchNumber
= OSNumber::withNumber(
9205 (unsigned long long)(wiredSize
),
9206 /* numBits */ 8 * sizeof(wiredSize
));
9207 if (!scratchNumber
) {
9210 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
9211 OSSafeReleaseNULL(scratchNumber
);
9216 /* OSBundleDependencies. In descending order for
9217 * easy compatibility with kextstat(8).
9219 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
9220 if ((count
= getNumDependencies())) {
9221 dependencyLoadTags
= OSArray::withCapacity(count
);
9222 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
9226 OSKext
* dependency
= OSDynamicCast(OSKext
,
9227 dependencies
->getObject(i
));
9229 OSSafeReleaseNULL(scratchNumber
);
9234 scratchNumber
= OSNumber::withNumber(
9235 (unsigned long long)dependency
->getLoadTag(),
9236 /* numBits*/ 8 * sizeof(loadTag
));
9237 if (!scratchNumber
) {
9240 dependencyLoadTags
->setObject(scratchNumber
);
9245 OSSafeReleaseNULL(scratchNumber
);
9247 /* OSBundleMetaClasses.
9249 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) {
9250 if (metaClasses
&& metaClasses
->getCount()) {
9251 metaClassIterator
= OSCollectionIterator::withCollection(metaClasses
);
9252 metaClassInfo
= OSArray::withCapacity(metaClasses
->getCount());
9253 if (!metaClassIterator
|| !metaClassInfo
) {
9256 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
9258 while ( (thisMetaClass
= OSDynamicCast(OSMetaClass
,
9259 metaClassIterator
->getNextObject())) ) {
9261 OSSafeReleaseNULL(metaClassDict
);
9262 OSSafeReleaseNULL(scratchNumber
);
9263 OSSafeReleaseNULL(metaClassName
);
9264 OSSafeReleaseNULL(superclassName
);
9266 metaClassDict
= OSDictionary::withCapacity(3);
9267 if (!metaClassDict
) {
9271 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
9272 if (thisMetaClass
->getSuperClass()) {
9273 superclassName
= OSString::withCString(
9274 thisMetaClass
->getSuperClass()->getClassName());
9276 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
9277 8 * sizeof(unsigned int));
9279 /* Bail if any of the essentials is missing. The root class lacks a superclass,
9282 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
9286 metaClassInfo
->setObject(metaClassDict
);
9287 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
9288 if (superclassName
) {
9289 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
9291 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
9296 /* OSBundleRetainCount.
9298 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
9299 OSSafeReleaseNULL(scratchNumber
);
9301 int kextRetainCount
= getRetainCount() - 1;
9305 scratchNumber
= OSNumber::withNumber(
9306 (int)kextRetainCount
,
9307 /* numBits*/ 8 * sizeof(int));
9308 if (scratchNumber
) {
9309 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
9317 OSSafeReleaseNULL(headerData
);
9318 OSSafeReleaseNULL(logData
);
9319 OSSafeReleaseNULL(cpuTypeNumber
);
9320 OSSafeReleaseNULL(cpuSubtypeNumber
);
9321 OSSafeReleaseNULL(executablePathString
);
9322 if (executablePathCString
) kfree(executablePathCString
, executablePathCStringSize
);
9323 OSSafeReleaseNULL(uuid
);
9324 OSSafeReleaseNULL(scratchNumber
);
9325 OSSafeReleaseNULL(dependencyLoadTags
);
9326 OSSafeReleaseNULL(metaClassIterator
);
9327 OSSafeReleaseNULL(metaClassInfo
);
9328 OSSafeReleaseNULL(metaClassDict
);
9329 OSSafeReleaseNULL(metaClassName
);
9330 OSSafeReleaseNULL(superclassName
);
9332 OSSafeReleaseNULL(result
);
9337 /*********************************************************************
9338 *********************************************************************/
9341 OSKext::requestResource(
9342 const char * kextIdentifierCString
,
9343 const char * resourceNameCString
,
9344 OSKextRequestResourceCallback callback
,
9346 OSKextRequestTag
* requestTagOut
)
9348 OSReturn result
= kOSReturnError
;
9349 OSKext
* callbackKext
= NULL
; // must release (looked up)
9351 OSKextRequestTag requestTag
= -1;
9352 OSNumber
* requestTagNum
= NULL
; // must release
9354 OSDictionary
* requestDict
= NULL
; // must release
9355 OSString
* kextIdentifier
= NULL
; // must release
9356 OSString
* resourceName
= NULL
; // must release
9358 OSDictionary
* callbackRecord
= NULL
; // must release
9359 OSData
* callbackWrapper
= NULL
; // must release
9361 OSData
* contextWrapper
= NULL
; // must release
9363 IORecursiveLockLock(sKextLock
);
9365 if (requestTagOut
) {
9366 *requestTagOut
= kOSKextRequestTagInvalid
;
9369 /* If requests to user space are disabled, don't go any further */
9370 if (!sKernelRequestsEnabled
) {
9371 OSKextLog(/* kext */ NULL
,
9372 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9373 "Can't request resource %s for %s - requests to user space are disabled.",
9374 resourceNameCString
,
9375 kextIdentifierCString
);
9376 result
= kOSKextReturnDisabled
;
9380 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
9381 result
= kOSKextReturnInvalidArgument
;
9385 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9386 if (!callbackKext
) {
9387 OSKextLog(/* kext */ NULL
,
9388 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9389 "Resource request has bad callback address.");
9390 result
= kOSKextReturnInvalidArgument
;
9393 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9394 OSKextLog(/* kext */ NULL
,
9395 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9396 "Resource request callback is in a kext that is not started.");
9397 result
= kOSKextReturnInvalidArgument
;
9401 /* Do not allow any new requests to be made on a kext that is unloading.
9403 if (callbackKext
->flags
.stopping
) {
9404 result
= kOSKextReturnStopping
;
9408 /* If we're wrapped the next available request tag around to the negative
9409 * numbers, we can't service any more requests.
9411 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
9412 OSKextLog(/* kext */ NULL
,
9413 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9414 "No more request tags available; restart required.");
9415 result
= kOSKextReturnNoResources
;
9418 requestTag
= sNextRequestTag
++;
9420 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
9422 if (result
!= kOSReturnSuccess
) {
9426 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
9427 resourceName
= OSString::withCString(resourceNameCString
);
9428 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9429 8 * sizeof(requestTag
));
9430 if (!kextIdentifier
||
9433 !_OSKextSetRequestArgument(requestDict
,
9434 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
9435 !_OSKextSetRequestArgument(requestDict
,
9436 kKextRequestArgumentNameKey
, resourceName
) ||
9437 !_OSKextSetRequestArgument(requestDict
,
9438 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
9440 result
= kOSKextReturnNoMemory
;
9444 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
9445 if (!callbackRecord
) {
9446 result
= kOSKextReturnNoMemory
;
9449 // we validate callback address at call time
9450 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
9452 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
9454 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9455 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
9457 result
= kOSKextReturnNoMemory
;
9462 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9463 kKextRequestArgumentContextKey
, contextWrapper
)) {
9465 result
= kOSKextReturnNoMemory
;
9470 /* Only post the requests after all the other potential failure points
9473 if (!sKernelRequests
->setObject(requestDict
) ||
9474 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
9476 result
= kOSKextReturnNoMemory
;
9480 OSKext::pingKextd();
9482 result
= kOSReturnSuccess
;
9483 if (requestTagOut
) {
9484 *requestTagOut
= requestTag
;
9489 /* If we didn't succeed, yank the request & callback
9490 * from their holding arrays.
9492 if (result
!= kOSReturnSuccess
) {
9495 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
9496 if (index
!= (unsigned int)-1) {
9497 sKernelRequests
->removeObject(index
);
9499 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
9500 if (index
!= (unsigned int)-1) {
9501 sRequestCallbackRecords
->removeObject(index
);
9505 OSKext::considerUnloads(/* rescheduleOnly? */ true);
9507 IORecursiveLockUnlock(sKextLock
);
9509 if (callbackKext
) callbackKext
->release();
9510 if (requestTagNum
) requestTagNum
->release();
9512 if (requestDict
) requestDict
->release();
9513 if (kextIdentifier
) kextIdentifier
->release();
9514 if (resourceName
) resourceName
->release();
9516 if (callbackRecord
) callbackRecord
->release();
9517 if (callbackWrapper
) callbackWrapper
->release();
9518 if (contextWrapper
) contextWrapper
->release();
9523 /*********************************************************************
9524 * Assumes sKextLock is held.
9525 *********************************************************************/
9528 OSKext::dequeueCallbackForRequestTag(
9529 OSKextRequestTag requestTag
,
9530 OSDictionary
** callbackRecordOut
)
9532 OSReturn result
= kOSReturnError
;
9533 OSNumber
* requestTagNum
= NULL
; // must release
9535 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9536 8 * sizeof(requestTag
));
9537 if (!requestTagNum
) {
9541 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
9545 OSSafeReleaseNULL(requestTagNum
);
9550 /*********************************************************************
9551 * Assumes sKextLock is held.
9552 *********************************************************************/
9555 OSKext::dequeueCallbackForRequestTag(
9556 OSNumber
* requestTagNum
,
9557 OSDictionary
** callbackRecordOut
)
9559 OSReturn result
= kOSKextReturnInvalidArgument
;
9560 OSDictionary
* callbackRecord
= NULL
; // retain if matched!
9561 OSNumber
* callbackTagNum
= NULL
; // do not release
9562 unsigned int count
, i
;
9564 result
= kOSReturnError
;
9565 count
= sRequestCallbackRecords
->getCount();
9566 for (i
= 0; i
< count
; i
++) {
9567 callbackRecord
= OSDynamicCast(OSDictionary
,
9568 sRequestCallbackRecords
->getObject(i
));
9569 if (!callbackRecord
) {
9573 /* If we don't find a tag, we basically have a leak here. Maybe
9574 * we should just remove it.
9576 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
9577 callbackRecord
, kKextRequestArgumentRequestTagKey
));
9578 if (!callbackTagNum
) {
9582 /* We could be even more paranoid and check that all the incoming
9583 * args match what's in the callback record.
9585 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
9586 if (callbackRecordOut
) {
9587 *callbackRecordOut
= callbackRecord
;
9588 callbackRecord
->retain();
9590 sRequestCallbackRecords
->removeObject(i
);
9591 result
= kOSReturnSuccess
;
9595 result
= kOSKextReturnNotFound
;
9602 /*********************************************************************
9603 * Busy timeout triage
9604 *********************************************************************/
9607 OSKext::isWaitingKextd(void)
9609 return sRequestCallbackRecords
&& sRequestCallbackRecords
->getCount();
9612 /*********************************************************************
9613 * Assumes sKextLock is held.
9614 *********************************************************************/
9617 OSKext::dispatchResource(OSDictionary
* requestDict
)
9619 OSReturn result
= kOSReturnError
;
9620 OSDictionary
* callbackRecord
= NULL
; // must release
9621 OSNumber
* requestTag
= NULL
; // do not release
9622 OSNumber
* requestResult
= NULL
; // do not release
9623 OSData
* dataObj
= NULL
; // do not release
9624 uint32_t dataLength
= 0;
9625 const void * dataPtr
= NULL
; // do not free
9626 OSData
* callbackWrapper
= NULL
; // do not release
9627 OSKextRequestResourceCallback callback
= NULL
;
9628 OSData
* contextWrapper
= NULL
; // do not release
9629 void * context
= NULL
; // do not free
9630 OSKext
* callbackKext
= NULL
; // must release (looked up)
9632 /* Get the args from the request. Right now we need the tag
9633 * to look up the callback record, and the result for invoking the callback.
9635 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9636 kKextRequestArgumentRequestTagKey
));
9637 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9638 kKextRequestArgumentResultKey
));
9639 if (!requestTag
|| !requestResult
) {
9640 result
= kOSKextReturnInvalidArgument
;
9644 /* Look for a callback record matching this request's tag.
9646 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
9647 if (result
!= kOSReturnSuccess
) {
9652 * Get the context pointer of the callback record (if there is one).
9654 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
9655 kKextRequestArgumentContextKey
));
9656 context
= _OSKextExtractPointer(contextWrapper
);
9657 if (contextWrapper
&& !context
) {
9661 callbackWrapper
= OSDynamicCast(OSData
,
9662 _OSKextGetRequestArgument(callbackRecord
,
9663 kKextRequestArgumentCallbackKey
));
9664 callback
= (OSKextRequestResourceCallback
)
9665 _OSKextExtractPointer(callbackWrapper
);
9670 /* Check for a data obj. We might not have one and that's ok, that means
9671 * we didn't find the requested resource, and we still have to tell the
9672 * caller that via the callback.
9674 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
9675 kKextRequestArgumentValueKey
));
9677 dataPtr
= dataObj
->getBytesNoCopy();
9678 dataLength
= dataObj
->getLength();
9681 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9682 if (!callbackKext
) {
9683 OSKextLog(/* kext */ NULL
,
9684 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9685 "Can't invoke callback for resource request; ");
9688 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9689 OSKextLog(/* kext */ NULL
,
9690 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9691 "Can't invoke kext resource callback; ");
9695 (void)callback(requestTag
->unsigned32BitValue(),
9696 (OSReturn
)requestResult
->unsigned32BitValue(),
9697 dataPtr
, dataLength
, context
);
9699 result
= kOSReturnSuccess
;
9702 if (callbackKext
) callbackKext
->release();
9703 if (callbackRecord
) callbackRecord
->release();
9708 /*********************************************************************
9709 *********************************************************************/
9712 OSKext::invokeRequestCallback(
9713 OSDictionary
* callbackRecord
,
9714 OSReturn callbackResult
)
9716 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
9717 OSNumber
* resultNum
= NULL
; // must release
9723 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
9724 8 * sizeof(callbackResult
));
9729 /* Insert the result into the callback record and dispatch it as if it
9730 * were the reply coming down from user space.
9732 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
9735 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
9736 /* This removes the pending callback record.
9738 OSKext::dispatchResource(callbackRecord
);
9742 if (resultNum
) resultNum
->release();
9746 /*********************************************************************
9747 * Assumes sKextLock is held.
9748 *********************************************************************/
9751 OSKext::cancelRequest(
9752 OSKextRequestTag requestTag
,
9755 OSReturn result
= kOSKextReturnNoMemory
;
9756 OSDictionary
* callbackRecord
= NULL
; // must release
9757 OSData
* contextWrapper
= NULL
; // do not release
9759 IORecursiveLockLock(sKextLock
);
9760 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
9762 IORecursiveLockUnlock(sKextLock
);
9764 if (result
== kOSReturnSuccess
&& contextOut
) {
9765 contextWrapper
= OSDynamicCast(OSData
,
9766 _OSKextGetRequestArgument(callbackRecord
,
9767 kKextRequestArgumentContextKey
));
9768 *contextOut
= _OSKextExtractPointer(contextWrapper
);
9771 if (callbackRecord
) callbackRecord
->release();
9776 /*********************************************************************
9777 * Assumes sKextLock is held.
9778 *********************************************************************/
9780 OSKext::invokeOrCancelRequestCallbacks(
9781 OSReturn callbackResult
,
9784 unsigned int count
, i
;
9786 count
= sRequestCallbackRecords
->getCount();
9793 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9794 sRequestCallbackRecords
->getObject(i
));
9799 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9800 _OSKextGetRequestArgument(request
,
9801 kKextRequestArgumentCallbackKey
));
9803 if (!callbackWrapper
) {
9804 sRequestCallbackRecords
->removeObject(i
);
9808 vm_address_t callbackAddress
= (vm_address_t
)
9809 _OSKextExtractPointer(callbackWrapper
);
9811 if ((kmod_info
->address
<= callbackAddress
) &&
9812 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9815 /* This removes the callback record.
9817 invokeRequestCallback(request
, callbackResult
);
9819 sRequestCallbackRecords
->removeObject(i
);
9828 /*********************************************************************
9829 * Assumes sKextLock is held.
9830 *********************************************************************/
9832 OSKext::countRequestCallbacks(void)
9834 uint32_t result
= 0;
9835 unsigned int count
, i
;
9837 count
= sRequestCallbackRecords
->getCount();
9844 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9845 sRequestCallbackRecords
->getObject(i
));
9850 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9851 _OSKextGetRequestArgument(request
,
9852 kKextRequestArgumentCallbackKey
));
9854 if (!callbackWrapper
) {
9858 vm_address_t callbackAddress
= (vm_address_t
)
9859 _OSKextExtractPointer(callbackWrapper
);
9861 if ((kmod_info
->address
<= callbackAddress
) &&
9862 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9872 /*********************************************************************
9873 *********************************************************************/
9874 static OSReturn
_OSKextCreateRequest(
9875 const char * predicate
,
9876 OSDictionary
** requestP
)
9878 OSReturn result
= kOSKextReturnNoMemory
;
9879 OSDictionary
* request
= NULL
; // must release on error
9881 request
= OSDictionary::withCapacity(2);
9885 result
= _OSDictionarySetCStringValue(request
,
9886 kKextRequestPredicateKey
, predicate
);
9887 if (result
!= kOSReturnSuccess
) {
9890 result
= kOSReturnSuccess
;
9893 if (result
!= kOSReturnSuccess
) {
9894 if (request
) request
->release();
9896 *requestP
= request
;
9902 /*********************************************************************
9903 *********************************************************************/
9904 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
9906 return OSDynamicCast(OSString
,
9907 requestDict
->getObject(kKextRequestPredicateKey
));
9910 /*********************************************************************
9911 *********************************************************************/
9912 static OSObject
* _OSKextGetRequestArgument(
9913 OSDictionary
* requestDict
,
9914 const char * argName
)
9916 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9917 requestDict
->getObject(kKextRequestArgumentsKey
));
9919 return args
->getObject(argName
);
9924 /*********************************************************************
9925 *********************************************************************/
9926 static bool _OSKextSetRequestArgument(
9927 OSDictionary
* requestDict
,
9928 const char * argName
,
9931 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9932 requestDict
->getObject(kKextRequestArgumentsKey
));
9934 args
= OSDictionary::withCapacity(2);
9938 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
9942 return args
->setObject(argName
, value
);
9948 /*********************************************************************
9949 *********************************************************************/
9950 static void * _OSKextExtractPointer(OSData
* wrapper
)
9952 void * result
= NULL
;
9953 const void * resultPtr
= NULL
;
9958 resultPtr
= wrapper
->getBytesNoCopy();
9959 result
= *(void **)resultPtr
;
9964 /*********************************************************************
9965 *********************************************************************/
9966 static OSReturn
_OSDictionarySetCStringValue(
9967 OSDictionary
* dict
,
9969 const char * cValue
)
9971 OSReturn result
= kOSKextReturnNoMemory
;
9972 const OSSymbol
* key
= NULL
; // must release
9973 OSString
* value
= NULL
; // must release
9975 key
= OSSymbol::withCString(cKey
);
9976 value
= OSString::withCString(cValue
);
9977 if (!key
|| !value
) {
9980 if (dict
->setObject(key
, value
)) {
9981 result
= kOSReturnSuccess
;
9985 if (key
) key
->release();
9986 if (value
) value
->release();
9991 /*********************************************************************
9992 *********************************************************************/
9993 static bool _OSArrayContainsCString(
9995 const char * cString
)
9997 bool result
= false;
9998 const OSSymbol
* symbol
= NULL
;
10001 if (!array
|| !cString
) {
10005 symbol
= OSSymbol::withCStringNoCopy(cString
);
10010 count
= array
->getCount();
10011 for (i
= 0; i
< count
; i
++) {
10012 OSObject
* thisObject
= array
->getObject(i
);
10013 if (symbol
->isEqualTo(thisObject
)) {
10020 if (symbol
) symbol
->release();
10024 /*********************************************************************
10025 * We really only care about boot / system start up related kexts.
10026 * We return true if we're less than REBUILD_MAX_TIME since start up,
10027 * otherwise return false.
10028 *********************************************************************/
10029 bool _OSKextInPrelinkRebuildWindow(void)
10031 static bool outside_the_window
= false;
10032 AbsoluteTime my_abstime
;
10036 if (outside_the_window
) {
10039 clock_get_uptime(&my_abstime
);
10040 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
10041 my_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
10042 if (my_secs
> REBUILD_MAX_TIME
) {
10043 outside_the_window
= true;
10049 /*********************************************************************
10050 *********************************************************************/
10051 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
10053 int unLoadedCount
, i
;
10054 bool result
= false;
10056 IORecursiveLockLock(sKextLock
);
10058 if (sUnloadedPrelinkedKexts
== NULL
) {
10061 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
10062 if (unLoadedCount
== 0) {
10066 for (i
= 0; i
< unLoadedCount
; i
++) {
10067 const OSSymbol
* myBundleID
; // do not release
10069 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
10070 if (!myBundleID
) continue;
10071 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
10077 IORecursiveLockUnlock(sKextLock
);
10082 #pragma mark Personalities (IOKit Drivers)
10084 /*********************************************************************
10085 *********************************************************************/
10088 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
10090 OSArray
* result
= NULL
; // returned
10091 OSCollectionIterator
* kextIterator
= NULL
; // must release
10092 OSArray
* personalities
= NULL
; // must release
10093 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
10095 OSString
* kextID
= NULL
; // do not release
10096 OSKext
* theKext
= NULL
; // do not release
10098 IORecursiveLockLock(sKextLock
);
10100 /* Let's conservatively guess that any given kext has around 3
10101 * personalities for now.
10103 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
10108 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
10109 if (!kextIterator
) {
10113 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
10114 if (personalitiesIterator
) {
10115 personalitiesIterator
->release();
10116 personalitiesIterator
= NULL
;
10118 if (personalities
) {
10119 personalities
->release();
10120 personalities
= NULL
;
10123 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
10124 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
10125 personalities
= theKext
->copyPersonalitiesArray();
10126 if (!personalities
) {
10129 result
->merge(personalities
);
10131 // xxx - check for better place to put this log msg
10133 kOSKextLogWarningLevel
|
10134 kOSKextLogLoadFlag
,
10135 "Kext %s is not loadable during safe boot; "
10136 "omitting its personalities.",
10137 theKext
->getIdentifierCString());
10143 IORecursiveLockUnlock(sKextLock
);
10145 if (kextIterator
) kextIterator
->release();
10146 if (personalitiesIterator
) personalitiesIterator
->release();
10147 if (personalities
) personalities
->release();
10152 /*********************************************************************
10153 *********************************************************************/
10156 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
10158 int numPersonalities
= 0;
10160 OSKextLog(/* kext */ NULL
,
10161 kOSKextLogStepLevel
|
10162 kOSKextLogLoadFlag
,
10163 "Sending all eligible registered kexts' personalities "
10164 "to the IOCatalogue %s.",
10165 startMatching
? "and starting matching" : "but not starting matching");
10167 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
10168 /* filterSafeBootFlag */ true);
10170 if (personalities
) {
10171 gIOCatalogue
->addDrivers(personalities
, startMatching
);
10172 numPersonalities
= personalities
->getCount();
10173 personalities
->release();
10176 OSKextLog(/* kext */ NULL
,
10177 kOSKextLogStepLevel
|
10178 kOSKextLogLoadFlag
,
10179 "%d kext personalit%s sent to the IOCatalogue; %s.",
10180 numPersonalities
, numPersonalities
> 0 ? "ies" : "y",
10181 startMatching
? "matching started" : "matching not started");
10185 /*********************************************************************
10186 * Do not make a deep copy, just convert the IOKitPersonalities dict
10187 * to an array for sending to the IOCatalogue.
10188 *********************************************************************/
10190 OSKext::copyPersonalitiesArray(void)
10192 OSArray
* result
= NULL
;
10193 OSDictionary
* personalities
= NULL
; // do not release
10194 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
10196 OSString
* personalityName
= NULL
; // do not release
10197 OSString
* personalityBundleIdentifier
= NULL
; // do not release
10199 personalities
= OSDynamicCast(OSDictionary
,
10200 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10201 if (!personalities
) {
10205 result
= OSArray::withCapacity(personalities
->getCount());
10210 personalitiesIterator
=
10211 OSCollectionIterator::withCollection(personalities
);
10212 if (!personalitiesIterator
) {
10215 while ((personalityName
= OSDynamicCast(OSString
,
10216 personalitiesIterator
->getNextObject()))) {
10218 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10219 personalities
->getObject(personalityName
));
10222 * If the personality doesn't have a CFBundleIdentifier, or if it
10223 * differs from the kext's, insert the kext's ID so we can find it.
10224 * The publisher ID is used to remove personalities from bundles
10227 personalityBundleIdentifier
= OSDynamicCast(OSString
,
10228 personality
->getObject(kCFBundleIdentifierKey
));
10230 if (!personalityBundleIdentifier
) {
10231 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
10232 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
10233 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
10236 result
->setObject(personality
);
10240 if (personalitiesIterator
) personalitiesIterator
->release();
10245 /*********************************************************************
10246 Might want to change this to a bool return?
10247 *********************************************************************/
10249 OSKext::sendPersonalitiesToCatalog(
10250 bool startMatching
,
10251 OSArray
* personalityNames
)
10253 OSReturn result
= kOSReturnSuccess
;
10254 OSArray
* personalitiesToSend
= NULL
; // must release
10255 OSDictionary
* kextPersonalities
= NULL
; // do not release
10258 if (!sLoadEnabled
) {
10260 kOSKextLogErrorLevel
|
10261 kOSKextLogLoadFlag
,
10262 "Kext loading is disabled (attempt to start matching for kext %s).",
10263 getIdentifierCString());
10264 result
= kOSKextReturnDisabled
;
10268 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
10270 kOSKextLogErrorLevel
|
10271 kOSKextLogLoadFlag
,
10272 "Kext %s is not loadable during safe boot; "
10273 "not sending personalities to the IOCatalogue.",
10274 getIdentifierCString());
10275 result
= kOSKextReturnNotLoadable
;
10279 if (!personalityNames
|| !personalityNames
->getCount()) {
10280 personalitiesToSend
= copyPersonalitiesArray();
10282 kextPersonalities
= OSDynamicCast(OSDictionary
,
10283 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10284 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
10288 personalitiesToSend
= OSArray::withCapacity(0);
10289 if (!personalitiesToSend
) {
10290 result
= kOSKextReturnNoMemory
;
10293 count
= personalityNames
->getCount();
10294 for (i
= 0; i
< count
; i
++) {
10295 OSString
* name
= OSDynamicCast(OSString
,
10296 personalityNames
->getObject(i
));
10300 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10301 kextPersonalities
->getObject(name
));
10303 personalitiesToSend
->setObject(personality
);
10307 if (personalitiesToSend
) {
10308 unsigned numPersonalities
= personalitiesToSend
->getCount();
10310 kOSKextLogStepLevel
|
10311 kOSKextLogLoadFlag
,
10312 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
10313 getIdentifierCString(),
10315 numPersonalities
> 1 ? "ies" : "y",
10316 startMatching
? " and starting matching" : " but not starting matching");
10317 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
10320 if (personalitiesToSend
) {
10321 personalitiesToSend
->release();
10326 /*********************************************************************
10327 * xxx - We should allow removing the kext's declared personalities,
10328 * xxx - even with other bundle identifiers.
10329 *********************************************************************/
10331 OSKext::removePersonalitiesFromCatalog(void)
10333 OSDictionary
* personality
= NULL
; // do not release
10335 personality
= OSDictionary::withCapacity(1);
10336 if (!personality
) {
10339 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
10342 kOSKextLogStepLevel
|
10343 kOSKextLogLoadFlag
,
10344 "Kext %s removing all personalities naming it from the IOCatalogue.",
10345 getIdentifierCString());
10347 /* Have the IOCatalog remove all personalities matching this kext's
10348 * bundle ID and trigger matching anew.
10350 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
10353 if (personality
) personality
->release();
10360 #pragma mark Logging
10362 /*********************************************************************
10363 * Do not call any function that takes sKextLock here!
10364 *********************************************************************/
10367 OSKext::setUserSpaceLogFilter(
10368 OSKextLogSpec newUserLogFilter
,
10371 OSKextLogSpec result
;
10372 bool allocError
= false;
10374 /* Do not call any function that takes sKextLoggingLock during
10375 * this critical block. That means do logging after.
10377 IOLockLock(sKextLoggingLock
);
10379 result
= sUserSpaceKextLogFilter
;
10380 sUserSpaceKextLogFilter
= newUserLogFilter
;
10382 if (newUserLogFilter
&& captureFlag
&&
10383 !sUserSpaceLogSpecArray
&& !sUserSpaceLogMessageArray
) {
10385 // xxx - do some measurements for a good initial capacity?
10386 sUserSpaceLogSpecArray
= OSArray::withCapacity(0);
10387 sUserSpaceLogMessageArray
= OSArray::withCapacity(0);
10389 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
10390 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10391 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10396 IOLockUnlock(sKextLoggingLock
);
10398 /* If the config flag itself is changing, log the state change
10399 * going both ways, before setting up the user-space log arrays,
10400 * so that this is only logged in the kernel.
10402 if (result
!= newUserLogFilter
) {
10403 OSKextLog(/* kext */ NULL
,
10404 kOSKextLogDebugLevel
|
10405 kOSKextLogGeneralFlag
,
10406 "User-space log flags changed from 0x%x to 0x%x.",
10407 result
, newUserLogFilter
);
10410 OSKextLog(/* kext */ NULL
,
10411 kOSKextLogErrorLevel
|
10412 kOSKextLogGeneralFlag
,
10413 "Failed to allocate user-space log message arrays.");
10419 /*********************************************************************
10420 * Do not call any function that takes sKextLock here!
10421 *********************************************************************/
10424 OSKext::clearUserSpaceLogFilter(void)
10426 OSArray
* result
= NULL
;
10427 OSKextLogSpec oldLogFilter
;
10428 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
10430 /* Do not call any function that takes sKextLoggingLock during
10431 * this critical block. That means do logging after.
10433 IOLockLock(sKextLoggingLock
);
10435 result
= OSArray::withCapacity(2);
10437 result
->setObject(sUserSpaceLogSpecArray
);
10438 result
->setObject(sUserSpaceLogMessageArray
);
10440 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10441 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10443 oldLogFilter
= sUserSpaceKextLogFilter
;
10444 sUserSpaceKextLogFilter
= newLogFilter
;
10446 IOLockUnlock(sKextLoggingLock
);
10448 /* If the config flag itself is changing, log the state change
10449 * going both ways, after tearing down the user-space log
10450 * arrays, so this is only logged within the kernel.
10452 if (oldLogFilter
!= newLogFilter
) {
10453 OSKextLog(/* kext */ NULL
,
10454 kOSKextLogDebugLevel
|
10455 kOSKextLogGeneralFlag
,
10456 "User-space log flags changed from 0x%x to 0x%x.",
10457 oldLogFilter
, newLogFilter
);
10464 /*********************************************************************
10465 * Do not call any function that takes sKextLock here!
10466 *********************************************************************/
10469 OSKext::getUserSpaceLogFilter(void)
10471 OSKextLogSpec result
;
10473 IOLockLock(sKextLoggingLock
);
10474 result
= sUserSpaceKextLogFilter
;
10475 IOLockUnlock(sKextLoggingLock
);
10480 /*********************************************************************
10481 * This function is called by OSMetaClass during kernel C++ setup.
10482 * Be careful what you access here; assume only OSKext::initialize()
10485 * Do not call any function that takes sKextLock here!
10486 *********************************************************************/
10487 #define VTRESET "\033[0m"
10489 #define VTBOLD "\033[1m"
10490 #define VTUNDER "\033[4m"
10492 #define VTRED "\033[31m"
10493 #define VTGREEN "\033[32m"
10494 #define VTYELLOW "\033[33m"
10495 #define VTBLUE "\033[34m"
10496 #define VTMAGENTA "\033[35m"
10497 #define VTCYAN "\033[36m"
10499 inline const char * colorForFlags(OSKextLogSpec flags
)
10501 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
10503 switch (logLevel
) {
10504 case kOSKextLogErrorLevel
:
10505 return VTRED VTBOLD
;
10506 case kOSKextLogWarningLevel
:
10508 case kOSKextLogBasicLevel
:
10509 return VTYELLOW VTUNDER
;
10510 case kOSKextLogProgressLevel
:
10512 case kOSKextLogStepLevel
:
10514 case kOSKextLogDetailLevel
:
10516 case kOSKextLogDebugLevel
:
10519 return ""; // white
10523 inline bool logSpecMatch(
10524 OSKextLogSpec msgLogSpec
,
10525 OSKextLogSpec logFilter
)
10527 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
10528 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
10529 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
10531 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
10532 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
10533 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
10535 /* Explicit messages always get logged.
10537 if (msgLevel
== kOSKextLogExplicitLevel
) {
10541 /* Warnings and errors are logged regardless of the flags.
10543 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
10547 /* A verbose message that isn't for a logging-enabled kext and isn't global
10548 * does *not* get logged.
10550 if (!msgKextGlobal
&& !filterKextGlobal
) {
10554 /* Warnings and errors are logged regardless of the flags.
10555 * All other messages must fit the flags and
10556 * have a level at or below the filter.
10559 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
10570 OSKextLogSpec msgLogSpec
,
10571 const char * format
, ...)
10575 va_start(argList
, format
);
10576 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
10583 OSKextLogSpec msgLogSpec
,
10584 const char * format
,
10585 va_list srcArgList
)
10587 extern int disableConsoleOutput
;
10589 bool logForKernel
= false;
10590 bool logForUser
= false;
10592 char stackBuffer
[120];
10593 uint32_t length
= 0;
10594 char * allocBuffer
= NULL
; // must kfree
10595 OSNumber
* logSpecNum
= NULL
; // must release
10596 OSString
* logString
= NULL
; // must release
10597 char * buffer
= stackBuffer
; // do not free
10599 IOLockLock(sKextLoggingLock
);
10601 /* Set the kext/global bit in the message spec if we have no
10602 * kext or if the kext requests logging.
10604 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
10605 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
10608 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
10609 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10610 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
10613 if (! (logForKernel
|| logForUser
) ) {
10617 /* No goto from here until past va_end()!
10619 va_copy(argList
, srcArgList
);
10620 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
10623 if (length
+ 1 >= sizeof(stackBuffer
)) {
10624 allocBuffer
= (char *)kalloc_tag((length
+ 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT
);
10625 if (!allocBuffer
) {
10629 /* No goto from here until past va_end()!
10631 va_copy(argList
, srcArgList
);
10632 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
10635 buffer
= allocBuffer
;
10638 /* If user space wants the log message, queue it up.
10640 if (logForUser
&& sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10641 logSpecNum
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
));
10642 logString
= OSString::withCString(buffer
);
10643 if (logSpecNum
&& logString
) {
10644 sUserSpaceLogSpecArray
->setObject(logSpecNum
);
10645 sUserSpaceLogMessageArray
->setObject(logString
);
10649 /* Always log messages from the kernel according to the kernel's
10652 if (logForKernel
) {
10654 /* If we are in console mode and have a custom log filter,
10655 * colorize the log message.
10657 if (!disableConsoleOutput
&& sBootArgLogFilterFound
) {
10658 const char * color
= ""; // do not free
10659 color
= colorForFlags(msgLogSpec
);
10660 printf("%s%s%s\n", colorForFlags(msgLogSpec
),
10661 buffer
, color
[0] ? VTRESET
: "");
10663 printf("%s\n", buffer
);
10668 IOLockUnlock(sKextLoggingLock
);
10671 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
10673 OSSafeReleaseNULL(logString
);
10674 OSSafeReleaseNULL(logSpecNum
);
10678 #if KASLR_IOREG_DEBUG
10680 #define IOLOG_INDENT( the_indention ) \
10683 for ( i = 0; i < (the_indention); i++ ) { \
10688 extern vm_offset_t vm_kernel_stext
;
10689 extern vm_offset_t vm_kernel_etext
;
10690 extern mach_vm_offset_t kext_alloc_base
;
10691 extern mach_vm_offset_t kext_alloc_max
;
10693 bool ScanForAddrInObject(OSObject
* theObject
,
10696 bool ScanForAddrInObject(OSObject
* theObject
,
10699 const OSMetaClass
* myTypeID
;
10700 OSCollectionIterator
* myIter
;
10702 OSObject
* myValue
;
10703 bool myResult
= false;
10705 if ( theObject
== NULL
) {
10706 IOLog("%s: theObject is NULL \n",
10711 myTypeID
= OSTypeIDInst(theObject
);
10713 if ( myTypeID
== OSTypeID(OSDictionary
) ) {
10714 OSDictionary
* myDictionary
;
10716 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
10717 myIter
= OSCollectionIterator::withCollection( myDictionary
);
10718 if ( myIter
== NULL
)
10722 while ( (myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject())) ) {
10725 myValue
= myDictionary
->getObject(myKey
);
10726 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10727 if (myTempResult
) {
10728 // if we ever get a true result return true
10730 IOLOG_INDENT(indent
);
10731 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
10736 else if ( myTypeID
== OSTypeID(OSArray
) ) {
10739 myArray
= OSDynamicCast(OSArray
, theObject
);
10740 myIter
= OSCollectionIterator::withCollection(myArray
);
10741 if ( myIter
== NULL
)
10745 while ( (myValue
= myIter
->getNextObject()) ) {
10747 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10748 if (myTempResult
) {
10749 // if we ever get a true result return true
10751 IOLOG_INDENT(indent
);
10752 IOLog("OSArray: \n");
10757 else if ( myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
) ) {
10759 // should we look for addresses in strings?
10761 else if ( myTypeID
== OSTypeID(OSData
) ) {
10764 unsigned int myLen
;
10765 OSData
* myDataObj
;
10767 myDataObj
= OSDynamicCast(OSData
, theObject
);
10768 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
10769 myLen
= myDataObj
->getLength();
10771 if (myPtrPtr
&& myLen
&& myLen
> 7) {
10773 int myPtrCount
= (myLen
/ sizeof(void *));
10775 for (i
= 0; i
< myPtrCount
; i
++) {
10776 UInt64 numberValue
= (UInt64
) *(myPtrPtr
);
10778 if ( kext_alloc_max
!= 0 &&
10779 numberValue
>= kext_alloc_base
&&
10780 numberValue
< kext_alloc_max
) {
10782 OSKext
* myKext
= NULL
; // must release (looked up)
10783 // IOLog("found OSData %p in kext map %p to %p \n",
10785 // (void *) kext_alloc_base,
10786 // (void *) kext_alloc_max);
10788 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) *(myPtrPtr
) );
10790 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
10792 myKext
->getIdentifierCString());
10797 if ( vm_kernel_etext
!= 0 &&
10798 numberValue
>= vm_kernel_stext
&&
10799 numberValue
< vm_kernel_etext
) {
10800 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
10802 (void *) vm_kernel_stext
,
10803 (void *) vm_kernel_etext
);
10810 else if ( myTypeID
== OSTypeID(OSBoolean
) ) {
10812 // do nothing here...
10814 else if ( myTypeID
== OSTypeID(OSNumber
) ) {
10816 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
10818 UInt64 numberValue
= number
->unsigned64BitValue();
10820 if ( kext_alloc_max
!= 0 &&
10821 numberValue
>= kext_alloc_base
&&
10822 numberValue
< kext_alloc_max
) {
10824 OSKext
* myKext
= NULL
; // must release (looked up)
10825 IOLog("found OSNumber in kext map %p to %p \n",
10826 (void *) kext_alloc_base
,
10827 (void *) kext_alloc_max
);
10828 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10830 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) numberValue
);
10832 IOLog("found in kext \"%s\" \n",
10833 myKext
->getIdentifierCString());
10839 if ( vm_kernel_etext
!= 0 &&
10840 numberValue
>= vm_kernel_stext
&&
10841 numberValue
< vm_kernel_etext
) {
10842 IOLog("found OSNumber in kernel text segment %p to %p \n",
10843 (void *) vm_kernel_stext
,
10844 (void *) vm_kernel_etext
);
10845 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10851 const OSMetaClass
* myMetaClass
= NULL
;
10853 myMetaClass
= theObject
->getMetaClass();
10854 if ( myMetaClass
) {
10855 IOLog("class %s \n", myMetaClass
->getClassName() );
10858 IOLog("Unknown object \n" );
10865 #endif // KASLR_KEXT_DEBUG
10867 }; /* extern "C" */
10870 #pragma mark Backtrace Dump & kmod_get_info() support
10872 /*********************************************************************
10873 * This function must be safe to call in panic context.
10874 *********************************************************************/
10877 OSKext::printKextsInBacktrace(
10878 vm_offset_t
* addr
,
10880 int (* printf_func
)(const char *fmt
, ...),
10883 addr64_t summary_page
= 0;
10884 addr64_t last_summary_page
= 0;
10885 bool found_kmod
= false;
10888 if (kPrintKextsLock
& flags
) {
10889 if (!sKextSummariesLock
) return;
10890 IOLockLock(sKextSummariesLock
);
10893 if (!gLoadedKextSummaries
) {
10894 (*printf_func
)(" can't perform kext scan: no kext summary");
10898 summary_page
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
);
10899 last_summary_page
= round_page(summary_page
+ sLoadedKextSummariesAllocSize
);
10900 for (; summary_page
< last_summary_page
; summary_page
+= PAGE_SIZE
) {
10901 if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) {
10902 (*printf_func
)(" can't perform kext scan: "
10903 "missing kext summary page %p", summary_page
);
10908 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10909 OSKextLoadedKextSummary
* summary
;
10911 summary
= gLoadedKextSummaries
->summaries
+ i
;
10912 if (!summary
->address
) {
10916 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
10921 if (!(kPrintKextsTerse
& flags
)) {
10922 (*printf_func
)(" Kernel Extensions in backtrace:\n");
10927 printSummary(summary
, printf_func
, flags
);
10931 if (kPrintKextsLock
& flags
) {
10932 IOLockUnlock(sKextSummariesLock
);
10938 /*********************************************************************
10939 * This function must be safe to call in panic context.
10940 *********************************************************************/
10943 OSKext::summaryIsInBacktrace(
10944 OSKextLoadedKextSummary
* summary
,
10945 vm_offset_t
* addr
,
10950 for (i
= 0; i
< cnt
; i
++) {
10951 vm_offset_t kscan_addr
= addr
[i
];
10952 if ((kscan_addr
>= summary
->address
) &&
10953 (kscan_addr
< (summary
->address
+ summary
->size
)))
10963 * Get the kext summary object for the kext where 'addr' lies. Must be called with
10964 * sKextSummariesLock held.
10966 OSKextLoadedKextSummary
*
10967 OSKext::summaryForAddress(const uintptr_t addr
)
10969 for (unsigned i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10971 OSKextLoadedKextSummary
*summary
= &gLoadedKextSummaries
->summaries
[i
];
10972 if (!summary
->address
) {
10976 #if VM_MAPPED_KEXTS
10977 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not
10978 * support split kexts, but we also may unmap the kexts, which can
10979 * race with the above codepath (see OSKext::unload). As such,
10980 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
10982 if ((addr
>= summary
->address
) && (addr
< (summary
->address
+ summary
->size
))) {
10986 kernel_mach_header_t
*mh
= (kernel_mach_header_t
*)summary
->address
;
10987 kernel_segment_command_t
*seg
;
10989 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
10990 if ((addr
>= seg
->vmaddr
) && (addr
< (seg
->vmaddr
+ seg
->vmsize
))) {
10997 /* addr did not map to any kext */
11003 OSKext::kextForAddress(const void *addr
)
11005 void *image
= NULL
;
11007 if (((vm_offset_t
)(uintptr_t)addr
>= vm_kernel_stext
) &&
11008 ((vm_offset_t
)(uintptr_t)addr
< vm_kernel_etext
)) {
11009 return (void *)&_mh_execute_header
;
11012 if (!sKextSummariesLock
) {
11015 IOLockLock(sKextSummariesLock
);
11016 OSKextLoadedKextSummary
*summary
= OSKext::summaryForAddress((uintptr_t)addr
);
11018 image
= (void *)summary
->address
;
11020 IOLockUnlock(sKextSummariesLock
);
11025 /*********************************************************************
11026 * scan list of loaded kext summaries looking for a load address match and if
11027 * found return the UUID C string. If not found then set empty string.
11028 *********************************************************************/
11029 static void findSummaryUUID(
11031 uuid_string_t uuid
);
11033 static void findSummaryUUID(
11035 uuid_string_t uuid
)
11039 uuid
[0] = 0x00; // default to no UUID
11041 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
11042 OSKextLoadedKextSummary
* summary
;
11044 summary
= gLoadedKextSummaries
->summaries
+ i
;
11046 if (summary
->loadTag
== tag_ID
) {
11047 (void) uuid_unparse(summary
->uuid
, uuid
);
11054 /*********************************************************************
11055 * This function must be safe to call in panic context.
11056 *********************************************************************/
11057 void OSKext::printSummary(
11058 OSKextLoadedKextSummary
* summary
,
11059 int (* printf_func
)(const char *fmt
, ...),
11062 kmod_reference_t
* kmod_ref
= NULL
;
11063 uuid_string_t uuid
;
11064 char version
[kOSKextVersionMaxLength
];
11067 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
11068 strlcpy(version
, "unknown version", sizeof(version
));
11070 (void) uuid_unparse(summary
->uuid
, uuid
);
11072 if (kPrintKextsUnslide
& flags
) {
11073 tmpAddr
= VM_KERNEL_UNSLIDE(summary
->address
);
11076 tmpAddr
= summary
->address
;
11078 (*printf_func
)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
11079 (kPrintKextsTerse
& flags
) ? "" : " ",
11080 summary
->name
, version
, uuid
,
11081 tmpAddr
, tmpAddr
+ summary
->size
- 1);
11083 if (kPrintKextsTerse
& flags
) return;
11085 /* print dependency info */
11086 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
11088 kmod_ref
= kmod_ref
->next
) {
11089 kmod_info_t
* rinfo
;
11091 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) {
11092 (*printf_func
)(" kmod dependency scan stopped "
11093 "due to missing dependency page: %p\n",
11094 (kPrintKextsUnslide
& flags
) ? (void *)VM_KERNEL_UNSLIDE(kmod_ref
) : kmod_ref
);
11097 rinfo
= kmod_ref
->info
;
11099 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) {
11100 (*printf_func
)(" kmod dependency scan stopped "
11101 "due to missing kmod page: %p\n",
11102 (kPrintKextsUnslide
& flags
) ? (void *)VM_KERNEL_UNSLIDE(rinfo
) : rinfo
);
11106 if (!rinfo
->address
) {
11107 continue; // skip fake entries for built-ins
11110 /* locate UUID in gLoadedKextSummaries */
11111 findSummaryUUID(rinfo
->id
, uuid
);
11113 if (kPrintKextsUnslide
& flags
) {
11114 tmpAddr
= VM_KERNEL_UNSLIDE(rinfo
->address
);
11117 tmpAddr
= rinfo
->address
;
11119 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
11120 rinfo
->name
, rinfo
->version
, uuid
, tmpAddr
);
11126 /*******************************************************************************
11127 * substitute() looks at an input string (a pointer within a larger buffer)
11128 * for a match to a substring, and on match it writes the marker & substitution
11129 * character to an output string, updating the scan (from) and
11130 * output (to) indexes as appropriate.
11131 *******************************************************************************/
11132 static int substitute(
11133 const char * scan_string
,
11135 uint32_t * to_index
,
11136 uint32_t * from_index
,
11137 const char * substring
,
11139 char substitution
);
11141 /* string_out must be at least KMOD_MAX_NAME bytes.
11145 const char * scan_string
,
11147 uint32_t * to_index
,
11148 uint32_t * from_index
,
11149 const char * substring
,
11153 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
11155 /* On a substring match, append the marker (if there is one) and then
11156 * the substitution character, updating the output (to) index accordingly.
11157 * Then update the input (from) length by the length of the substring
11158 * that got replaced.
11160 if (!strncmp(scan_string
, substring
, substring_length
)) {
11162 string_out
[(*to_index
)++] = marker
;
11164 string_out
[(*to_index
)++] = substitution
;
11165 (*from_index
) += substring_length
;
11171 /*******************************************************************************
11172 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
11173 * KMOD_MAX_NAME characters and performs various substitutions of common
11174 * prefixes & substrings as defined by tables in kext_panic_report.h.
11175 *******************************************************************************/
11176 static void compactIdentifier(
11177 const char * identifier
,
11178 char * identifier_out
,
11179 char ** identifier_out_end
);
11183 const char * identifier
,
11184 char * identifier_out
,
11185 char ** identifier_out_end
)
11187 uint32_t from_index
, to_index
;
11188 uint32_t scan_from_index
= 0;
11189 uint32_t scan_to_index
= 0;
11190 subs_entry_t
* subs_entry
= NULL
;
11193 from_index
= to_index
= 0;
11194 identifier_out
[0] = '\0';
11196 /* Replace certain identifier prefixes with shorter @+character sequences.
11197 * Check the return value of substitute() so we only replace the prefix.
11199 for (subs_entry
= &kext_identifier_prefix_subs
[0];
11200 subs_entry
->substring
&& !did_sub
;
11203 did_sub
= substitute(identifier
, identifier_out
,
11204 &scan_to_index
, &scan_from_index
,
11205 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
11209 /* Now scan through the identifier looking for the common substrings
11210 * and replacing them with shorter !+character sequences via substitute().
11212 for (/* see above */;
11213 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
11216 const char * scan_string
= &identifier
[scan_from_index
];
11220 if (scan_from_index
) {
11221 for (subs_entry
= &kext_identifier_substring_subs
[0];
11222 subs_entry
->substring
&& !did_sub
;
11225 did_sub
= substitute(scan_string
, identifier_out
,
11226 &scan_to_index
, &scan_from_index
,
11227 subs_entry
->substring
, '!', subs_entry
->substitute
);
11231 /* If we didn't substitute, copy the input character to the output.
11234 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
11238 identifier_out
[scan_to_index
] = '\0';
11239 if (identifier_out_end
) {
11240 *identifier_out_end
= &identifier_out
[scan_to_index
];
11246 /*******************************************************************************
11247 * assemble_identifier_and_version() adds to a string buffer a compacted
11248 * bundle identifier followed by a version string.
11249 *******************************************************************************/
11251 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
11253 static int assemble_identifier_and_version(
11254 kmod_info_t
* kmod_info
,
11255 char * identPlusVers
,
11259 assemble_identifier_and_version(
11260 kmod_info_t
* kmod_info
,
11261 char * identPlusVers
,
11266 compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
);
11267 result
= strnlen(identPlusVers
, KMOD_MAX_NAME
- 1);
11268 identPlusVers
[result
++] = '\t'; // increment for real char
11269 identPlusVers
[result
] = '\0'; // don't increment for nul char
11270 result
= strlcat(identPlusVers
, kmod_info
->version
, bufSize
);
11271 if (result
>= bufSize
) {
11272 identPlusVers
[bufSize
- 1] = '\0';
11273 result
= bufSize
- 1;
11279 /*******************************************************************************
11280 * Assumes sKextLock is held.
11281 *******************************************************************************/
11284 OSKext::saveLoadedKextPanicListTyped(
11285 const char * prefix
,
11289 uint32_t list_size
)
11292 unsigned int count
, i
;
11294 count
= sLoadedKexts
->getCount();
11301 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
11302 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
11304 uint32_t identPlusVersLength
;
11306 char identPlusVers
[2*KMOD_MAX_NAME
];
11309 printf("OSKext::saveLoadedKextPanicListTyped - "
11310 "NULL kext in loaded kext list; continuing\n");
11315 printf("OSKext::saveLoadedKextPanicListTyped - "
11316 "Kext type cast failed in loaded kext list; continuing\n");
11320 /* Skip all built-in kexts.
11322 if (theKext
->isKernelComponent()) {
11326 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
11328 /* Filter for kmod name (bundle identifier).
11330 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
11331 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
11335 /* Filter for libraries (kexts that have a compatible version).
11337 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
11338 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
11344 !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) {
11346 printf("kext scan stopped due to missing kmod_info page: %p\n",
11351 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
11353 sizeof(identPlusVers
));
11354 if (!identPlusVersLength
) {
11355 printf("error saving loaded kext info\n");
11359 /* make sure everything fits and we null terminate.
11361 tempLen
= strlcat(paniclist
, identPlusVers
, list_size
);
11362 if (tempLen
>= list_size
) {
11363 // panic list is full, keep it and null terminate
11364 paniclist
[list_size
- 1] = 0x00;
11368 tempLen
= strlcat(paniclist
, "\n", list_size
);
11369 if (tempLen
>= list_size
) {
11370 // panic list is full, keep it and null terminate
11371 paniclist
[list_size
- 1] = 0x00;
11383 /*********************************************************************
11384 *********************************************************************/
11387 OSKext::saveLoadedKextPanicList(void)
11389 char * newlist
= NULL
;
11390 uint32_t newlist_size
= 0;
11392 newlist_size
= KEXT_PANICLIST_SIZE
;
11393 newlist
= (char *)kalloc_tag(newlist_size
, VM_KERN_MEMORY_OSKEXT
);
11396 OSKextLog(/* kext */ NULL
,
11397 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
11398 "Couldn't allocate kext panic log buffer.");
11404 // non-"com.apple." kexts
11405 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
11406 /* libs? */ -1, newlist
, newlist_size
) != 0) {
11410 // "com.apple." nonlibrary kexts
11411 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11412 /* libs? */ 0, newlist
, newlist_size
) != 0) {
11416 // "com.apple." library kexts
11417 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11418 /* libs? */ 1, newlist
, newlist_size
) != 0) {
11423 if (loaded_kext_paniclist
) {
11424 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
11426 loaded_kext_paniclist
= newlist
;
11428 loaded_kext_paniclist_size
= newlist_size
;
11432 kfree(newlist
, newlist_size
);
11437 /*********************************************************************
11438 * Assumes sKextLock is held.
11439 *********************************************************************/
11441 OSKext::savePanicString(bool isLoading
)
11446 return; // do not goto finish here b/c of lock
11449 len
= assemble_identifier_and_version( kmod_info
,
11450 (isLoading
) ? last_loaded_str_buf
: last_unloaded_str_buf
,
11451 (isLoading
) ? sizeof(last_loaded_str_buf
) : sizeof(last_unloaded_str_buf
) );
11453 printf("error saving unloaded kext info\n");
11458 last_loaded_strlen
= len
;
11459 last_loaded_address
= (void *)kmod_info
->address
;
11460 last_loaded_size
= kmod_info
->size
;
11461 clock_get_uptime(&last_loaded_timestamp
);
11463 last_unloaded_strlen
= len
;
11464 last_unloaded_address
= (void *)kmod_info
->address
;
11465 last_unloaded_size
= kmod_info
->size
;
11466 clock_get_uptime(&last_unloaded_timestamp
);
11473 /*********************************************************************
11474 *********************************************************************/
11477 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
11479 if (last_loaded_strlen
) {
11480 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
11481 AbsoluteTime_to_scalar(&last_loaded_timestamp
),
11482 last_loaded_strlen
, last_loaded_str_buf
,
11483 last_loaded_address
, last_loaded_size
);
11486 if (last_unloaded_strlen
) {
11487 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
11488 AbsoluteTime_to_scalar(&last_unloaded_timestamp
),
11489 last_unloaded_strlen
, last_unloaded_str_buf
,
11490 last_unloaded_address
, last_unloaded_size
);
11493 printf_func("loaded kexts:\n");
11494 if (loaded_kext_paniclist
&&
11495 pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) &&
11496 loaded_kext_paniclist
[0]) {
11498 printf_func("%.*s",
11499 strnlen(loaded_kext_paniclist
, loaded_kext_paniclist_size
),
11500 loaded_kext_paniclist
);
11502 printf_func("(none)\n");
11507 /*********************************************************************
11508 * Assumes sKextLock is held.
11509 *********************************************************************/
11512 OSKext::updateLoadedKextSummaries(void)
11514 kern_return_t result
= KERN_FAILURE
;
11515 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
11516 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
11518 vm_map_offset_t start
, end
;
11519 size_t summarySize
= 0;
11524 OSKextActiveAccount
* accountingList
;
11525 OSKextActiveAccount
* prevAccountingList
;
11526 uint32_t idx
, accountingListAlloc
, accountingListCount
, prevAccountingListCount
;
11528 prevAccountingList
= NULL
;
11529 prevAccountingListCount
= 0;
11531 #if DEVELOPMENT || DEBUG
11532 if (IORecursiveLockHaveLock(sKextLock
) == false) {
11533 panic("sKextLock must be held");
11537 IOLockLock(sKextSummariesLock
);
11539 count
= sLoadedKexts
->getCount();
11540 for (i
= 0, maxKexts
= 0; i
< count
; ++i
) {
11541 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11542 maxKexts
+= (aKext
&& aKext
->isExecutable());
11545 if (!maxKexts
) goto finish
;
11546 if (maxKexts
< kOSKextTypicalLoadCount
) maxKexts
= kOSKextTypicalLoadCount
;
11548 /* Calculate the size needed for the new summary headers.
11551 size
= sizeof(*gLoadedKextSummaries
);
11552 size
+= maxKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
11553 size
= round_page(size
);
11555 if (gLoadedKextSummaries
== NULL
|| sLoadedKextSummariesAllocSize
< size
) {
11556 if (gLoadedKextSummaries
) {
11557 kmem_free(kernel_map
, (vm_offset_t
)gLoadedKextSummaries
, sLoadedKextSummariesAllocSize
);
11558 gLoadedKextSummaries
= NULL
;
11559 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11560 sLoadedKextSummariesAllocSize
= 0;
11562 result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&summaryHeaderAlloc
, size
, VM_KERN_MEMORY_OSKEXT
);
11563 if (result
!= KERN_SUCCESS
) goto finish
;
11564 summaryHeader
= summaryHeaderAlloc
;
11565 summarySize
= size
;
11568 summaryHeader
= gLoadedKextSummaries
;
11569 summarySize
= sLoadedKextSummariesAllocSize
;
11571 start
= (vm_map_offset_t
) summaryHeader
;
11572 end
= start
+ summarySize
;
11573 result
= vm_map_protect(kernel_map
,
11578 if (result
!= KERN_SUCCESS
) goto finish
;
11581 /* Populate the summary header.
11584 bzero(summaryHeader
, summarySize
);
11585 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
11586 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
11588 /* Populate each kext summary.
11591 count
= sLoadedKexts
->getCount();
11592 accountingListAlloc
= 0;
11593 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11594 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11595 if (!aKext
|| !aKext
->isExecutable()) {
11599 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
11600 summaryHeader
->numSummaries
++;
11601 accountingListAlloc
++;
11604 accountingList
= IONew(typeof(accountingList
[0]), accountingListAlloc
);
11605 accountingListCount
= 0;
11606 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11607 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11608 if (!aKext
|| !aKext
->isExecutable()) {
11612 OSKextActiveAccount activeAccount
;
11613 aKext
->updateActiveAccount(&activeAccount
);
11614 // order by address
11615 for (idx
= 0; idx
< accountingListCount
; idx
++)
11617 if (activeAccount
.address
< accountingList
[idx
].address
) break;
11619 bcopy(&accountingList
[idx
], &accountingList
[idx
+ 1], (accountingListCount
- idx
) * sizeof(accountingList
[0]));
11620 accountingList
[idx
] = activeAccount
;
11621 accountingListCount
++;
11623 assert(accountingListCount
== accountingListAlloc
);
11624 /* Write protect the buffer and move it into place.
11627 start
= (vm_map_offset_t
) summaryHeader
;
11628 end
= start
+ summarySize
;
11630 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_READ
, FALSE
);
11631 if (result
!= KERN_SUCCESS
)
11634 gLoadedKextSummaries
= summaryHeader
;
11635 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11636 sLoadedKextSummariesAllocSize
= summarySize
;
11637 summaryHeaderAlloc
= NULL
;
11639 /* Call the magic breakpoint function through a static function pointer so
11640 * the compiler can't optimize the function away.
11642 if (sLoadedKextSummariesUpdated
) (*sLoadedKextSummariesUpdated
)();
11644 IOSimpleLockLock(sKextAccountsLock
);
11645 prevAccountingList
= sKextAccounts
;
11646 prevAccountingListCount
= sKextAccountsCount
;
11647 sKextAccounts
= accountingList
;
11648 sKextAccountsCount
= accountingListCount
;
11649 IOSimpleLockUnlock(sKextAccountsLock
);
11652 IOLockUnlock(sKextSummariesLock
);
11654 /* If we had to allocate a new buffer but failed to generate the summaries,
11657 if (summaryHeaderAlloc
) {
11658 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
11660 if (prevAccountingList
) {
11661 IODelete(prevAccountingList
, typeof(accountingList
[0]), prevAccountingListCount
);
11667 /*********************************************************************
11668 *********************************************************************/
11670 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
11674 strlcpy(summary
->name
, getIdentifierCString(),
11675 sizeof(summary
->name
));
11679 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
11680 OSSafeReleaseNULL(uuid
);
11683 summary
->address
= kmod_info
->address
;
11684 summary
->size
= kmod_info
->size
;
11685 summary
->version
= getVersion();
11686 summary
->loadTag
= kmod_info
->id
;
11687 summary
->flags
= 0;
11688 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
11693 /*********************************************************************
11694 *********************************************************************/
11697 OSKext::updateActiveAccount(OSKextActiveAccount
*accountp
)
11699 kernel_mach_header_t
*hdr
= NULL
;
11700 kernel_segment_command_t
*seg
= NULL
;
11702 hdr
= (kernel_mach_header_t
*)kmod_info
->address
;
11704 if (getcommandfromheader(hdr
, LC_SEGMENT_SPLIT_INFO
)) {
11705 /* If this kext supports split segments, use the first
11706 * executable segment as the range for instructions
11707 * (and thus for backtracing.
11709 for (seg
= firstsegfromheader(hdr
); seg
!= NULL
; seg
= nextsegfromheader(hdr
, seg
)) {
11710 if (seg
->initprot
& VM_PROT_EXECUTE
) {
11716 bzero(accountp
, sizeof(*accountp
));
11718 accountp
->address
= seg
->vmaddr
;
11719 if (accountp
->address
) {
11720 accountp
->address_end
= seg
->vmaddr
+ seg
->vmsize
;
11723 /* For non-split kexts and for kexts without executable
11724 * segments, just use the kmod_info range (as the kext
11725 * is either all in one range or should not show up in
11726 * instruction backtraces).
11728 accountp
->address
= kmod_info
->address
;
11729 if (accountp
->address
) {
11730 accountp
->address_end
= kmod_info
->address
+ kmod_info
->size
;
11733 accountp
->account
= this->account
;
11736 extern "C" const vm_allocation_site_t
*
11737 OSKextGetAllocationSiteForCaller(uintptr_t address
)
11739 OSKextActiveAccount
* active
;
11740 vm_allocation_site_t
* site
;
11741 vm_allocation_site_t
* releasesite
;
11746 IOSimpleLockLock(sKextAccountsLock
);
11747 site
= releasesite
= NULL
;
11749 // bsearch sKextAccounts list
11750 for (baseIdx
= 0, lim
= sKextAccountsCount
; lim
; lim
>>= 1)
11752 active
= &sKextAccounts
[baseIdx
+ (lim
>> 1)];
11753 if ((address
>= active
->address
) && (address
< active
->address_end
))
11755 site
= &active
->account
->site
;
11756 if (!site
->tag
) vm_tag_alloc_locked(site
, &releasesite
);
11759 else if (address
> active
->address
)
11762 baseIdx
+= (lim
>> 1) + 1;
11767 IOSimpleLockUnlock(sKextAccountsLock
);
11768 if (releasesite
) kern_allocation_name_release(releasesite
);
11773 extern "C" uint32_t
11774 OSKextGetKmodIDForSite(const vm_allocation_site_t
* site
, char * name
, vm_size_t namelen
)
11776 OSKextAccount
* account
= (typeof(account
)) site
;
11777 const char * kname
;
11781 if (account
->kext
) kname
= account
->kext
->getIdentifierCString();
11783 strlcpy(name
, kname
, namelen
);
11786 return (account
->loadTag
);
11790 OSKextFreeSite(vm_allocation_site_t
* site
)
11792 OSKextAccount
* freeAccount
= (typeof(freeAccount
)) site
;
11793 IODelete(freeAccount
, OSKextAccount
, 1);
11796 /*********************************************************************
11797 *********************************************************************/
11799 #if CONFIG_KEC_FIPS
11802 #pragma mark Kernel External Components for FIPS compliance
11805 /*********************************************************************
11806 * Kernel External Components for FIPS compliance (KEC_FIPS)
11807 *********************************************************************/
11809 GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
)
11811 AppleTEXTHash_t my_ath
= {2, 0, NULL
};
11812 AppleTEXTHash_t
* my_athp
= NULL
; // do not release
11813 OSData
* segmentHash
= NULL
; // do not release
11815 if (theKext
== NULL
|| theInfoDict
== NULL
) {
11819 // Get the part of the plist associate with kAppleTextHashesKey and let
11820 // the crypto library do further parsing (slice/architecture)
11821 segmentHash
= OSDynamicCast(OSData
, theInfoDict
->getObject(kAppleTextHashesKey
));
11822 // Support for ATH v1 while rolling out ATH v2 without revision locking submissions
11823 // Remove this when v2 PLIST are supported
11824 if (segmentHash
== NULL
) {
11825 // If this fails, we may be dealing with a v1 PLIST
11826 OSDictionary
* textHashDict
= NULL
; // do not release
11827 textHashDict
= OSDynamicCast(OSDictionary
, theInfoDict
->getObject(kAppleTextHashesKey
));
11828 if (textHashDict
== NULL
) {
11831 my_ath
.ath_version
=1;
11832 segmentHash
= OSDynamicCast(OSData
,textHashDict
->getObject(ARCHNAME
));
11833 } // end of v2 rollout
11835 if (segmentHash
== NULL
) {
11839 // KEC_FIPS type kexts never unload so we don't have to clean up our
11841 if (kmem_alloc(kernel_map
, (vm_offset_t
*) &my_athp
,
11842 sizeof(AppleTEXTHash_t
), VM_KERN_MEMORY_OSKEXT
) != KERN_SUCCESS
) {
11846 memcpy(my_athp
, &my_ath
, sizeof(my_ath
));
11847 my_athp
->ath_length
= segmentHash
->getLength();
11848 if (my_athp
->ath_length
> 0) {
11849 my_athp
->ath_hash
= (void *)segmentHash
->getBytesNoCopy();
11854 kOSKextLogErrorLevel
|
11855 kOSKextLogGeneralFlag
,
11856 "Kext %s ath_version %d ath_length %d ath_hash %p",
11857 theKext
->getIdentifierCString(),
11858 my_athp
->ath_version
,
11859 my_athp
->ath_length
,
11860 my_athp
->ath_hash
);
11863 return( (void *) my_athp
);
11866 #endif // CONFIG_KEC_FIPS
11868 #if CONFIG_IMAGEBOOT
11869 int OSKextGetUUIDForName(const char *name
, uuid_t uuid
)
11871 OSKext
*kext
= OSKext::lookupKextWithIdentifier(name
);
11876 OSData
*uuid_data
= kext
->copyUUID();
11878 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_t
));
11879 OSSafeReleaseNULL(uuid_data
);