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 OSKextVersion sExcludeListVersion
= 0;
270 static OSArray
* sLoadedKexts
= NULL
;
271 static OSArray
* sUnloadedPrelinkedKexts
= NULL
;
273 // Requests to kextd waiting to be picked up.
274 static OSArray
* sKernelRequests
= NULL
;
275 // Identifier of kext load requests in sKernelRequests
276 static OSSet
* sPostedKextLoadIdentifiers
= NULL
;
277 static OSArray
* sRequestCallbackRecords
= NULL
;
279 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
280 static OSSet
* sAllKextLoadIdentifiers
= NULL
;
281 static KXLDContext
* sKxldContext
= NULL
;
282 static uint32_t sNextLoadTag
= 0;
283 static uint32_t sNextRequestTag
= 0;
285 static bool sUserLoadsActive
= false;
286 static bool sKextdActive
= false;
287 static bool sDeferredLoadSucceeded
= false;
288 static bool sConsiderUnloadsExecuted
= false;
291 static bool sKernelRequestsEnabled
= false;
293 static bool sKernelRequestsEnabled
= true;
295 static bool sLoadEnabled
= true;
296 static bool sUnloadEnabled
= true;
298 /*********************************************************************
299 * Stuff for the OSKext representing the kernel itself.
301 static OSKext
* sKernelKext
= NULL
;
303 /* Set up a fake kmod_info struct for the kernel.
304 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
305 * before OSKext is initialized; that call only needs the name
306 * and address to be set correctly.
308 * We don't do much else with the kerne's kmod_info; we never
309 * put it into the kmod list, never adjust the reference count,
310 * and never have kernel components reference it.
311 * For that matter, we don't do much with kmod_info structs
312 * at all anymore! We just keep them filled in for gdb and
313 * binary compability.
315 kmod_info_t g_kernel_kmod_info
= {
317 /* info_version */ KMOD_INFO_VERSION
,
318 /* id */ 0, // loadTag: kernel is always 0
319 /* name */ kOSKextKernelIdentifier
, // bundle identifier
320 /* version */ "0", // filled in in OSKext::initialize()
321 /* reference_count */ -1, // never adjusted; kernel never unloads
322 /* reference_list */ NULL
,
324 /* size */ 0, // filled in in OSKext::initialize()
331 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
332 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
333 // misc_protos.h, db_low_trace.c, kgmacros
334 // 'kmod' is a holdover from the old kmod system, we can't rename it.
335 kmod_info_t
* kmod
= NULL
;
337 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
340 static char * loaded_kext_paniclist
= NULL
;
341 static uint32_t loaded_kext_paniclist_size
= 0;
343 AbsoluteTime last_loaded_timestamp
;
344 static char last_loaded_str_buf
[2*KMOD_MAX_NAME
];
345 static u_long last_loaded_strlen
= 0;
346 static void * last_loaded_address
= NULL
;
347 static u_long last_loaded_size
= 0;
349 AbsoluteTime last_unloaded_timestamp
;
350 static char last_unloaded_str_buf
[2*KMOD_MAX_NAME
];
351 static u_long last_unloaded_strlen
= 0;
352 static void * last_unloaded_address
= NULL
;
353 static u_long last_unloaded_size
= 0;
355 /*********************************************************************
356 * sKextInnerLock protects against cross-calls with IOService and
357 * IOCatalogue, and owns the variables declared immediately below.
359 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
361 * When both sKextLock and sKextInnerLock need to be taken,
362 * always lock sKextLock first and unlock it second. Never take both
363 * locks in an entry point to OSKext; if you need to do so, you must
364 * spawn an independent thread to avoid potential deadlocks for threads
365 * calling into OSKext.
367 static IORecursiveLock
* sKextInnerLock
= NULL
;
369 static bool sAutounloadEnabled
= true;
370 static bool sConsiderUnloadsCalled
= false;
371 static bool sConsiderUnloadsPending
= false;
373 static unsigned int sConsiderUnloadDelay
= 60; // seconds
374 static thread_call_t sUnloadCallout
= 0;
375 static thread_call_t sDestroyLinkContextThread
= 0; // one-shot, one-at-a-time thread
376 static bool sSystemSleep
= false; // true when system going to sleep
377 static AbsoluteTime sLastWakeTime
; // last time we woke up
379 /*********************************************************************
380 * Backtraces can be printed at various times so we need a tight lock
381 * on data used for that. sKextSummariesLock protects the variables
382 * declared immediately below.
384 * gLoadedKextSummaries is accessed by other modules, but only during
385 * a panic so the lock isn't needed then.
387 * gLoadedKextSummaries has the "used" attribute in order to ensure
388 * that it remains visible even when we are performing extremely
389 * aggressive optimizations, as it is needed to allow the debugger
390 * to automatically parse the list of loaded kexts.
392 static IOLock
* sKextSummariesLock
= NULL
;
393 extern "C" lck_spin_t vm_allocation_sites_lock
;
394 static IOSimpleLock
* sKextAccountsLock
= &vm_allocation_sites_lock
;
396 void (*sLoadedKextSummariesUpdated
)(void) = OSKextLoadedKextSummariesUpdated
;
397 OSKextLoadedKextSummaryHeader
* gLoadedKextSummaries
__attribute__((used
)) = NULL
;
398 uint64_t gLoadedKextSummariesTimestamp
__attribute__((used
)) = 0;
399 static size_t sLoadedKextSummariesAllocSize
= 0;
401 static OSKextActiveAccount
* sKextAccounts
;
402 static uint32_t sKextAccountsCount
;
405 /*********************************************************************
406 * sKextLoggingLock protects the logging variables declared immediately below.
408 static IOLock
* sKextLoggingLock
= NULL
;
410 static const OSKextLogSpec kDefaultKernelLogFilter
= kOSKextLogBasicLevel
|
411 kOSKextLogVerboseFlagsMask
;
412 static OSKextLogSpec sKernelLogFilter
= kDefaultKernelLogFilter
;
413 static bool sBootArgLogFilterFound
= false;
414 SYSCTL_UINT(_debug
, OID_AUTO
, kextlog
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &sKernelLogFilter
,
415 0, "kernel kext logging");
417 static OSKextLogSpec sUserSpaceKextLogFilter
= kOSKextLogSilentFilter
;
418 static OSArray
* sUserSpaceLogSpecArray
= NULL
;
419 static OSArray
* sUserSpaceLogMessageArray
= NULL
;
422 * End scope for sKextInnerLock-protected variables.
423 *********************************************************************/
426 /*********************************************************************
427 helper function used for collecting PGO data upon unload of a kext
430 static int OSKextGrabPgoDataLocked(OSKext
*kext
,
432 uuid_t instance_uuid
,
435 uint64_t bufferSize
);
437 /**********************************************************************/
442 #pragma mark OSData callbacks (need to move to OSData)
444 /*********************************************************************
445 * C functions used for callbacks.
446 *********************************************************************/
448 void osdata_kmem_free(void * ptr
, unsigned int length
) {
449 kmem_free(kernel_map
, (vm_address_t
)ptr
, length
);
453 void osdata_phys_free(void * ptr
, unsigned int length
) {
454 ml_static_mfree((vm_offset_t
)ptr
, length
);
458 void osdata_vm_deallocate(void * ptr
, unsigned int length
)
460 (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
);
464 void osdata_kext_free(void * ptr
, unsigned int length
)
466 (void)kext_free((vm_offset_t
)ptr
, length
);
472 #pragma mark KXLD Allocation Callback
474 /*********************************************************************
475 * KXLD Allocation Callback
476 *********************************************************************/
480 KXLDAllocateFlags
* flags
,
483 vm_address_t result
= 0; // returned
484 kern_return_t mach_result
= KERN_FAILURE
;
485 bool success
= false;
486 OSKext
* theKext
= (OSKext
*)user_data
;
487 u_long roundSize
= round_page(size
);
488 OSData
* linkBuffer
= NULL
; // must release
490 mach_result
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
);
491 if (mach_result
!= KERN_SUCCESS
) {
493 kOSKextLogErrorLevel
|
494 kOSKextLogGeneralFlag
,
495 "Can't allocate kernel memory to link %s.",
496 theKext
->getIdentifierCString());
500 /* Create an OSData wrapper for the allocated buffer.
502 linkBuffer
= OSData::withBytesNoCopy((void *)result
, roundSize
);
505 kOSKextLogErrorLevel
|
506 kOSKextLogGeneralFlag
,
507 "Can't allocate linked executable wrapper for %s.",
508 theKext
->getIdentifierCString());
511 linkBuffer
->setDeallocFunction(osdata_kext_free
);
513 kOSKextLogProgressLevel
|
514 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
515 "Allocated link buffer for kext %s at %p (%lu bytes).",
516 theKext
->getIdentifierCString(),
517 (void *)result
, (unsigned long)roundSize
);
519 theKext
->setLinkedExecutable(linkBuffer
);
521 *flags
= kKxldAllocateWritable
;
525 if (!success
&& result
) {
526 kext_free(result
, roundSize
);
530 OSSafeReleaseNULL(linkBuffer
);
532 return (kxld_addr_t
)result
;
535 /*********************************************************************
536 *********************************************************************/
539 KXLDLogSubsystem subsystem
,
545 OSKext
*theKext
= (OSKext
*) user_data
;
546 OSKextLogSpec logSpec
= 0;
549 case kKxldLogLinking
:
550 logSpec
|= kOSKextLogLinkFlag
;
552 case kKxldLogPatching
:
553 logSpec
|= kOSKextLogPatchFlag
;
558 case kKxldLogExplicit
:
559 logSpec
|= kOSKextLogExplicitLevel
;
562 logSpec
|= kOSKextLogErrorLevel
;
565 logSpec
|= kOSKextLogWarningLevel
;
568 logSpec
|= kOSKextLogProgressLevel
;
571 logSpec
|= kOSKextLogDetailLevel
;
574 logSpec
|= kOSKextLogDebugLevel
;
578 OSKextVLog(theKext
, logSpec
, format
, argList
);
582 #pragma mark IOStatistics defines
587 #define notifyKextLoadObservers(kext, kmod_info) \
589 IOStatistics::onKextLoad(kext, kmod_info); \
592 #define notifyKextUnloadObservers(kext) \
594 IOStatistics::onKextUnload(kext); \
597 #define notifyAddClassObservers(kext, addedClass, flags) \
599 IOStatistics::onClassAdded(kext, addedClass); \
602 #define notifyRemoveClassObservers(kext, removedClass, flags) \
604 IOStatistics::onClassRemoved(kext, removedClass); \
609 #define notifyKextLoadObservers(kext, kmod_info)
610 #define notifyKextUnloadObservers(kext)
611 #define notifyAddClassObservers(kext, addedClass, flags)
612 #define notifyRemoveClassObservers(kext, removedClass, flags)
614 #endif /* IOKITSTATS */
617 #pragma mark Module Config (Startup & Shutdown)
619 /*********************************************************************
620 * Module Config (Class Definition & Class Methods)
621 *********************************************************************/
622 #define super OSObject
623 OSDefineMetaClassAndStructors(OSKext
, OSObject
)
625 /*********************************************************************
626 *********************************************************************/
629 OSKext::initialize(void)
631 OSData
* kernelExecutable
= NULL
; // do not release
632 u_char
* kernelStart
= NULL
; // do not free
633 size_t kernelLength
= 0;
634 OSString
* scratchString
= NULL
; // must release
635 IORegistryEntry
* registryRoot
= NULL
; // do not release
636 OSNumber
* kernelCPUType
= NULL
; // must release
637 OSNumber
* kernelCPUSubtype
= NULL
; // must release
638 OSKextLogSpec bootLogFilter
= kOSKextLogSilentFilter
;
639 bool setResult
= false;
640 uint64_t * timestamp
= 0;
641 char bootArgBuffer
[16]; // for PE_parse_boot_argn w/strings
643 /* This must be the first thing allocated. Everything else grabs this lock.
645 sKextLock
= IORecursiveLockAlloc();
646 sKextInnerLock
= IORecursiveLockAlloc();
647 sKextSummariesLock
= IOLockAlloc();
648 sKextLoggingLock
= IOLockAlloc();
650 assert(sKextInnerLock
);
651 assert(sKextSummariesLock
);
652 assert(sKextLoggingLock
);
654 sKextsByID
= OSDictionary::withCapacity(kOSKextTypicalLoadCount
);
655 sLoadedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
);
656 sUnloadedPrelinkedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
/ 10);
657 sKernelRequests
= OSArray::withCapacity(0);
658 sPostedKextLoadIdentifiers
= OSSet::withCapacity(0);
659 sAllKextLoadIdentifiers
= OSSet::withCapacity(kOSKextTypicalLoadCount
);
660 sRequestCallbackRecords
= OSArray::withCapacity(0);
661 assert(sKextsByID
&& sLoadedKexts
&& sKernelRequests
&&
662 sPostedKextLoadIdentifiers
&& sAllKextLoadIdentifiers
&&
663 sRequestCallbackRecords
&& sUnloadedPrelinkedKexts
);
665 /* Read the log flag boot-args and set the log flags.
667 if (PE_parse_boot_argn("kextlog", &bootLogFilter
, sizeof(bootLogFilter
))) {
668 sBootArgLogFilterFound
= true;
669 sKernelLogFilter
= bootLogFilter
;
670 // log this if any flags are set
671 OSKextLog(/* kext */ NULL
,
672 kOSKextLogBasicLevel
|
674 "Kernel kext log filter 0x%x per kextlog boot arg.",
675 (unsigned)sKernelLogFilter
);
678 sSafeBoot
= PE_parse_boot_argn("-x", bootArgBuffer
,
679 sizeof(bootArgBuffer
)) ? true : false;
682 OSKextLog(/* kext */ NULL
,
683 kOSKextLogWarningLevel
|
684 kOSKextLogGeneralFlag
,
685 "SAFE BOOT DETECTED - "
686 "only valid OSBundleRequired kexts will be loaded.");
689 PE_parse_boot_argn("keepsyms", &sKeepSymbols
, sizeof(sKeepSymbols
));
690 #if KASAN_DYNAMIC_BLACKLIST
691 /* needed for function lookup */
695 /* Set up an OSKext instance to represent the kernel itself.
697 sKernelKext
= new OSKext
;
700 kernelStart
= (u_char
*)&_mh_execute_header
;
701 kernelLength
= getlastaddr() - (vm_offset_t
)kernelStart
;
702 kernelExecutable
= OSData::withBytesNoCopy(
703 kernelStart
, kernelLength
);
704 assert(kernelExecutable
);
707 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %llu (0x%016lx) \n",
708 (unsigned long)kernelStart
,
709 (unsigned long)getlastaddr(),
711 vm_kernel_slide
, vm_kernel_slide
);
714 sKernelKext
->loadTag
= sNextLoadTag
++; // the kernel is load tag 0
715 sKernelKext
->bundleID
= OSSymbol::withCString(kOSKextKernelIdentifier
);
717 sKernelKext
->version
= OSKextParseVersionString(osrelease
);
718 sKernelKext
->compatibleVersion
= sKernelKext
->version
;
719 sKernelKext
->linkedExecutable
= kernelExecutable
;
721 sKernelKext
->flags
.hasAllDependencies
= 1;
722 sKernelKext
->flags
.kernelComponent
= 1;
723 sKernelKext
->flags
.prelinked
= 0;
724 sKernelKext
->flags
.loaded
= 1;
725 sKernelKext
->flags
.started
= 1;
726 sKernelKext
->flags
.CPPInitialized
= 0;
727 sKernelKext
->flags
.jettisonLinkeditSeg
= 0;
729 sKernelKext
->kmod_info
= &g_kernel_kmod_info
;
730 strlcpy(g_kernel_kmod_info
.version
, osrelease
,
731 sizeof(g_kernel_kmod_info
.version
));
732 g_kernel_kmod_info
.size
= kernelLength
;
733 g_kernel_kmod_info
.id
= sKernelKext
->loadTag
;
735 /* Cons up an info dict, so we don't have to have special-case
738 sKernelKext
->infoDict
= OSDictionary::withCapacity(5);
739 assert(sKernelKext
->infoDict
);
740 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
,
741 sKernelKext
->bundleID
);
743 setResult
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
,
747 scratchString
= OSString::withCStringNoCopy(osrelease
);
748 assert(scratchString
);
749 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
,
752 OSSafeReleaseNULL(scratchString
);
754 scratchString
= OSString::withCStringNoCopy("mach_kernel");
755 assert(scratchString
);
756 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
,
759 OSSafeReleaseNULL(scratchString
);
761 /* Add the kernel kext to the bookkeeping dictionaries. Note that
762 * the kernel kext doesn't have a kmod_info struct. copyInfo()
763 * gathers info from other places anyhow.
765 setResult
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
);
767 setResult
= sLoadedKexts
->setObject(sKernelKext
);
769 sKernelKext
->release();
771 registryRoot
= IORegistryEntry::getRegistryRoot();
772 kernelCPUType
= OSNumber::withNumber(
773 (long long unsigned int)_mh_execute_header
.cputype
,
774 8 * sizeof(_mh_execute_header
.cputype
));
775 kernelCPUSubtype
= OSNumber::withNumber(
776 (long long unsigned int)_mh_execute_header
.cpusubtype
,
777 8 * sizeof(_mh_execute_header
.cpusubtype
));
778 assert(registryRoot
&& kernelCPUSubtype
&& kernelCPUType
);
780 registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
);
781 registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
);
783 OSSafeReleaseNULL(kernelCPUType
);
784 OSSafeReleaseNULL(kernelCPUSubtype
);
786 timestamp
= __OSAbsoluteTimePtr(&last_loaded_timestamp
);
788 timestamp
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
);
790 timestamp
= __OSAbsoluteTimePtr(&sLastWakeTime
);
793 OSKextLog(/* kext */ NULL
,
794 kOSKextLogProgressLevel
|
795 kOSKextLogGeneralFlag
,
796 "Kext system initialized.");
798 notifyKextLoadObservers(sKernelKext
, sKernelKext
->kmod_info
);
803 /*********************************************************************
804 * This could be in OSKextLib.cpp but we need to hold a lock
805 * while removing all the segments and sKextLock will do.
806 *********************************************************************/
809 OSKext::removeKextBootstrap(void)
811 OSReturn result
= kOSReturnError
;
813 static bool alreadyDone
= false;
815 const char * dt_kernel_header_name
= "Kernel-__HEADER";
816 const char * dt_kernel_symtab_name
= "Kernel-__SYMTAB";
817 kernel_mach_header_t
* dt_mach_header
= NULL
;
818 int dt_mach_header_size
= 0;
819 struct symtab_command
* dt_symtab
= NULL
;
820 int dt_symtab_size
= 0;
823 kernel_segment_command_t
* seg_to_remove
= NULL
;
825 #if __arm__ || __arm64__
826 const char * dt_segment_name
= NULL
;
827 void * segment_paddress
= NULL
;
828 int segment_size
= 0;
831 /* This must be the very first thing done by this function.
833 IORecursiveLockLock(sKextLock
);
835 /* If we already did this, it's a success.
838 result
= kOSReturnSuccess
;
842 OSKextLog(/* kext */ NULL
,
843 kOSKextLogProgressLevel
|
844 kOSKextLogGeneralFlag
,
845 "Jettisoning kext bootstrap segments.");
848 * Dispose of unnecessary stuff that the booter didn't need to load.
850 dt_result
= IODTGetLoaderInfo(dt_kernel_header_name
,
851 (void **)&dt_mach_header
, &dt_mach_header_size
);
852 if (dt_result
== 0 && dt_mach_header
) {
853 IODTFreeLoaderInfo(dt_kernel_header_name
, (void *)dt_mach_header
,
854 round_page_32(dt_mach_header_size
));
856 dt_result
= IODTGetLoaderInfo(dt_kernel_symtab_name
,
857 (void **)&dt_symtab
, &dt_symtab_size
);
858 if (dt_result
== 0 && dt_symtab
) {
859 IODTFreeLoaderInfo(dt_kernel_symtab_name
, (void *)dt_symtab
,
860 round_page_32(dt_symtab_size
));
864 * KLD bootstrap segment.
866 // xxx - should rename KLD segment
867 seg_to_remove
= getsegbyname("__KLD");
869 OSRuntimeUnloadCPPForSegment(seg_to_remove
);
872 #if __arm__ || __arm64__
873 #if !(defined(KERNEL_INTEGRITY_KTRR))
874 /* Free the memory that was set up by bootx.
876 dt_segment_name
= "Kernel-__KLD";
877 if (0 == IODTGetLoaderInfo(dt_segment_name
, &segment_paddress
, &segment_size
)) {
878 /* We cannot free this with KTRR enabled, as we cannot
879 * update the permissions on the KLD range this late
880 * in the boot process.
882 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
885 #endif /* !(defined(KERNEL_INTEGRITY_KTRR)) */
886 #elif __i386__ || __x86_64__
887 /* On x86, use the mapping data from the segment load command to
888 * unload KLD directly.
889 * This may invalidate any assumptions about "avail_start"
890 * defining the lower bound for valid physical addresses.
892 if (seg_to_remove
&& seg_to_remove
->vmaddr
&& seg_to_remove
->vmsize
) {
893 // 04/18/11 - gab: <rdar://problem/9236163>
894 // overwrite memory occupied by KLD segment with random data before
896 read_frandom((void *) seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
897 ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
903 seg_to_remove
= NULL
;
906 * Prelinked kernel's symtab (if there is one).
908 kernel_section_t
* sect
;
909 sect
= getsectbyname("__PRELINK", "__symtab");
910 if (sect
&& sect
->addr
&& sect
->size
) {
911 ml_static_mfree(sect
->addr
, sect
->size
);
914 seg_to_remove
= (kernel_segment_command_t
*)getsegbyname("__LINKEDIT");
916 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
917 * pageable, unless keepsyms is set. To do that, we have to copy it from
918 * its booter-allocated memory, free the booter memory, reallocate proper
919 * managed memory, then copy the segment back in.
922 #if (__arm__ || __arm64__)
923 #error CONFIG_KXLD not expected for this arch
926 kern_return_t mem_result
;
927 void *seg_copy
= NULL
;
928 void *seg_data
= NULL
;
929 vm_map_offset_t seg_offset
= 0;
930 vm_map_offset_t seg_copy_offset
= 0;
931 vm_map_size_t seg_length
= 0;
933 seg_data
= (void *) seg_to_remove
->vmaddr
;
934 seg_offset
= (vm_map_offset_t
) seg_to_remove
->vmaddr
;
935 seg_length
= (vm_map_size_t
) seg_to_remove
->vmsize
;
937 /* Allocate space for the LINKEDIT copy.
939 mem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*) &seg_copy
,
940 seg_length
, VM_KERN_MEMORY_KEXT
);
941 if (mem_result
!= KERN_SUCCESS
) {
942 OSKextLog(/* kext */ NULL
,
943 kOSKextLogErrorLevel
|
944 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
945 "Can't copy __LINKEDIT segment for VM reassign.");
948 seg_copy_offset
= (vm_map_offset_t
) seg_copy
;
952 memcpy(seg_copy
, seg_data
, seg_length
);
954 /* Dump the booter memory.
956 ml_static_mfree(seg_offset
, seg_length
);
958 /* Set up the VM region.
960 mem_result
= vm_map_enter_mem_object(
963 seg_length
, /* mask */ 0,
964 VM_FLAGS_FIXED
| VM_FLAGS_OVERWRITE
,
965 VM_MAP_KERNEL_FLAGS_NONE
,
968 (vm_object_offset_t
) 0,
970 /* cur_protection */ VM_PROT_READ
| VM_PROT_WRITE
,
971 /* max_protection */ VM_PROT_ALL
,
972 /* inheritance */ VM_INHERIT_DEFAULT
);
973 if ((mem_result
!= KERN_SUCCESS
) ||
974 (seg_offset
!= (vm_map_offset_t
) seg_data
))
976 OSKextLog(/* kext */ NULL
,
977 kOSKextLogErrorLevel
|
978 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
979 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
980 seg_data
, seg_length
, mem_result
);
986 memcpy(seg_data
, seg_copy
, seg_length
);
990 kmem_free(kernel_map
, seg_copy_offset
, seg_length
);
992 #else /* we are not CONFIG_KXLD */
993 #if !(__arm__ || __arm64__)
994 #error CONFIG_KXLD is expected for this arch
998 * Dump the LINKEDIT segment, unless keepsyms is set.
1000 if (!sKeepSymbols
) {
1001 dt_segment_name
= "Kernel-__LINKEDIT";
1002 if (0 == IODTGetLoaderInfo(dt_segment_name
,
1003 &segment_paddress
, &segment_size
)) {
1004 #ifdef SECURE_KERNEL
1005 vm_offset_t vmaddr
= ml_static_ptovirt((vm_offset_t
)segment_paddress
);
1006 bzero((void*)vmaddr
, segment_size
);
1008 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
1012 OSKextLog(/* kext */ NULL
,
1013 kOSKextLogBasicLevel
|
1014 kOSKextLogGeneralFlag
,
1015 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1017 #endif /* CONFIG_KXLD */
1019 seg_to_remove
= NULL
;
1022 result
= kOSReturnSuccess
;
1026 /* This must be the very last thing done before returning.
1028 IORecursiveLockUnlock(sKextLock
);
1033 /*********************************************************************
1034 *********************************************************************/
1036 OSKext::flushNonloadedKexts(
1037 Boolean flushPrelinkedKexts
)
1039 OSSet
* prelinkedKexts
= NULL
; // must release
1040 OSCollectionIterator
* kextIterator
= NULL
; // must release
1041 OSCollectionIterator
* prelinkIterator
= NULL
; // must release
1042 const OSSymbol
* thisID
= NULL
; // do not release
1043 OSKext
* thisKext
= NULL
; // do not release
1046 IORecursiveLockLock(sKextLock
);
1048 OSKextLog(/* kext */ NULL
,
1049 kOSKextLogProgressLevel
|
1050 kOSKextLogKextBookkeepingFlag
,
1051 "Flushing nonloaded kexts and other unused data.");
1053 OSKext::considerDestroyingLinkContext();
1055 /* If we aren't flushing unused prelinked kexts, we have to put them
1056 * aside while we flush everything else so make a container for them.
1058 if (!flushPrelinkedKexts
) {
1059 prelinkedKexts
= OSSet::withCapacity(0);
1060 if (!prelinkedKexts
) {
1065 /* Set aside prelinked kexts (in-use or not) and break
1066 * any lingering inter-kext references for nonloaded kexts
1067 * so they have min. retain counts.
1069 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1070 if (!kextIterator
) {
1074 while ((thisID
= OSDynamicCast(OSSymbol
,
1075 kextIterator
->getNextObject()))) {
1077 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1080 if (prelinkedKexts
&& thisKext
->isPrelinked()) {
1081 prelinkedKexts
->setObject(thisKext
);
1083 thisKext
->flushDependencies(/* forceIfLoaded */ false);
1087 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1089 sKextsByID
->flushCollection();
1091 /* Now put the loaded kexts back into the ID dictionary.
1093 count
= sLoadedKexts
->getCount();
1094 for (i
= 0; i
< count
; i
++) {
1095 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
1096 sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
);
1099 /* Finally, put back the prelinked kexts if we saved any.
1101 if (prelinkedKexts
) {
1102 prelinkIterator
= OSCollectionIterator::withCollection(prelinkedKexts
);
1103 if (!prelinkIterator
) {
1107 while ((thisKext
= OSDynamicCast(OSKext
,
1108 prelinkIterator
->getNextObject()))) {
1110 sKextsByID
->setObject(thisKext
->getIdentifierCString(),
1116 IORecursiveLockUnlock(sKextLock
);
1118 OSSafeReleaseNULL(prelinkedKexts
);
1119 OSSafeReleaseNULL(kextIterator
);
1120 OSSafeReleaseNULL(prelinkIterator
);
1125 /*********************************************************************
1126 *********************************************************************/
1129 OSKext::setKextdActive(Boolean active
)
1131 IORecursiveLockLock(sKextLock
);
1132 sKextdActive
= active
;
1133 if (sKernelRequests
->getCount()) {
1134 OSKext::pingKextd();
1136 IORecursiveLockUnlock(sKextLock
);
1141 /*********************************************************************
1142 * OSKextLib.cpp might need access to this someday but for now it's
1144 *********************************************************************/
1146 extern void ipc_port_release_send(ipc_port_t
);
1151 OSKext::pingKextd(void)
1153 OSReturn result
= kOSReturnError
;
1155 mach_port_t kextd_port
= IPC_PORT_NULL
;
1157 if (!sKextdActive
) {
1158 result
= kOSKextReturnDisabled
; // basically unavailable
1162 result
= host_get_kextd_port(host_priv_self(), &kextd_port
);
1163 if (result
!= KERN_SUCCESS
|| !IPC_PORT_VALID(kextd_port
)) {
1164 OSKextLog(/* kext */ NULL
,
1165 kOSKextLogErrorLevel
|
1167 "Can't get kextd port.");
1171 result
= kextd_ping(kextd_port
);
1172 if (result
!= KERN_SUCCESS
) {
1173 OSKextLog(/* kext */ NULL
,
1174 kOSKextLogErrorLevel
|
1176 "kextd ping failed (0x%x).", (int)result
);
1181 if (IPC_PORT_VALID(kextd_port
)) {
1182 ipc_port_release_send(kextd_port
);
1189 /*********************************************************************
1190 *********************************************************************/
1193 OSKext::setDeferredLoadSucceeded(Boolean succeeded
)
1195 IORecursiveLockLock(sKextLock
);
1196 sDeferredLoadSucceeded
= succeeded
;
1197 IORecursiveLockUnlock(sKextLock
);
1202 /*********************************************************************
1203 * Called from IOSystemShutdownNotification.
1204 *********************************************************************/
1207 OSKext::willShutdown(void)
1210 OSReturn checkResult
= kOSReturnError
;
1212 OSDictionary
* exitRequest
= NULL
; // must release
1214 IORecursiveLockLock(sKextLock
);
1216 OSKext::setLoadEnabled(false);
1217 OSKext::setUnloadEnabled(false);
1218 OSKext::setAutounloadsEnabled(false);
1219 OSKext::setKernelRequestsEnabled(false);
1222 OSKextLog(/* kext */ NULL
,
1223 kOSKextLogProgressLevel
|
1224 kOSKextLogGeneralFlag
,
1225 "System shutdown; requesting immediate kextd exit.");
1227 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
,
1229 if (checkResult
!= kOSReturnSuccess
) {
1232 if (!sKernelRequests
->setObject(exitRequest
)) {
1236 OSKext::pingKextd();
1241 IORecursiveLockUnlock(sKextLock
);
1243 OSSafeReleaseNULL(exitRequest
);
1247 /*********************************************************************
1248 *********************************************************************/
1251 OSKext::getLoadEnabled(void)
1255 IORecursiveLockLock(sKextLock
);
1256 result
= sLoadEnabled
;
1257 IORecursiveLockUnlock(sKextLock
);
1261 /*********************************************************************
1262 *********************************************************************/
1265 OSKext::setLoadEnabled(bool flag
)
1269 IORecursiveLockLock(sKextLock
);
1270 result
= sLoadEnabled
;
1271 sLoadEnabled
= (flag
? true : false);
1273 if (sLoadEnabled
!= result
) {
1274 OSKextLog(/* kext */ NULL
,
1275 kOSKextLogBasicLevel
|
1277 "Kext loading now %sabled.", sLoadEnabled
? "en" : "dis");
1280 IORecursiveLockUnlock(sKextLock
);
1285 /*********************************************************************
1286 *********************************************************************/
1289 OSKext::getUnloadEnabled(void)
1293 IORecursiveLockLock(sKextLock
);
1294 result
= sUnloadEnabled
;
1295 IORecursiveLockUnlock(sKextLock
);
1299 /*********************************************************************
1300 *********************************************************************/
1303 OSKext::setUnloadEnabled(bool flag
)
1307 IORecursiveLockLock(sKextLock
);
1308 result
= sUnloadEnabled
;
1309 sUnloadEnabled
= (flag
? true : false);
1310 IORecursiveLockUnlock(sKextLock
);
1312 if (sUnloadEnabled
!= result
) {
1313 OSKextLog(/* kext */ NULL
,
1314 kOSKextLogBasicLevel
|
1315 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1316 "Kext unloading now %sabled.", sUnloadEnabled
? "en" : "dis");
1322 /*********************************************************************
1323 * Do not call any function that takes sKextLock here!
1324 *********************************************************************/
1327 OSKext::getAutounloadEnabled(void)
1331 IORecursiveLockLock(sKextInnerLock
);
1332 result
= sAutounloadEnabled
? true : false;
1333 IORecursiveLockUnlock(sKextInnerLock
);
1337 /*********************************************************************
1338 * Do not call any function that takes sKextLock here!
1339 *********************************************************************/
1342 OSKext::setAutounloadsEnabled(bool flag
)
1346 IORecursiveLockLock(sKextInnerLock
);
1348 result
= sAutounloadEnabled
;
1349 sAutounloadEnabled
= (flag
? true : false);
1350 if (!sAutounloadEnabled
&& sUnloadCallout
) {
1351 thread_call_cancel(sUnloadCallout
);
1354 if (sAutounloadEnabled
!= result
) {
1355 OSKextLog(/* kext */ NULL
,
1356 kOSKextLogBasicLevel
|
1357 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1358 "Kext autounloading now %sabled.",
1359 sAutounloadEnabled
? "en" : "dis");
1362 IORecursiveLockUnlock(sKextInnerLock
);
1367 /*********************************************************************
1368 *********************************************************************/
1369 /* instance method operating on OSKext field */
1371 OSKext::setAutounloadEnabled(bool flag
)
1373 bool result
= flags
.autounloadEnabled
? true : false;
1374 flags
.autounloadEnabled
= flag
? 1 : 0;
1376 if (result
!= (flag
? true : false)) {
1378 kOSKextLogProgressLevel
|
1379 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
1380 "Autounloading for kext %s now %sabled.",
1381 getIdentifierCString(),
1382 flags
.autounloadEnabled
? "en" : "dis");
1387 /*********************************************************************
1388 *********************************************************************/
1391 OSKext::setKernelRequestsEnabled(bool flag
)
1395 IORecursiveLockLock(sKextLock
);
1396 result
= sKernelRequestsEnabled
;
1397 sKernelRequestsEnabled
= flag
? true : false;
1399 if (sKernelRequestsEnabled
!= result
) {
1400 OSKextLog(/* kext */ NULL
,
1401 kOSKextLogBasicLevel
|
1402 kOSKextLogGeneralFlag
,
1403 "Kernel requests now %sabled.",
1404 sKernelRequestsEnabled
? "en" : "dis");
1406 IORecursiveLockUnlock(sKextLock
);
1410 /*********************************************************************
1411 *********************************************************************/
1414 OSKext::getKernelRequestsEnabled(void)
1418 IORecursiveLockLock(sKextLock
);
1419 result
= sKernelRequestsEnabled
;
1420 IORecursiveLockUnlock(sKextLock
);
1425 #pragma mark Kext Life Cycle
1427 /*********************************************************************
1428 *********************************************************************/
1430 OSKext::withPrelinkedInfoDict(
1431 OSDictionary
* anInfoDict
,
1432 bool doCoalesedSlides
)
1434 OSKext
* newKext
= new OSKext
;
1436 if (newKext
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
, doCoalesedSlides
)) {
1444 /*********************************************************************
1445 *********************************************************************/
1447 OSKext::initWithPrelinkedInfoDict(
1448 OSDictionary
* anInfoDict
,
1449 bool doCoalesedSlides
)
1451 bool result
= false;
1452 OSString
* kextPath
= NULL
; // do not release
1453 OSNumber
* addressNum
= NULL
; // reused; do not release
1454 OSNumber
* lengthNum
= NULL
; // reused; do not release
1455 void * data
= NULL
; // do not free
1456 void * srcData
= NULL
; // do not free
1457 OSData
* prelinkedExecutable
= NULL
; // must release
1458 uint32_t length
= 0; // reused
1460 if (!super::init()) {
1464 /* Get the path. Don't look for an arch-specific path property.
1466 kextPath
= OSDynamicCast(OSString
,
1467 anInfoDict
->getObject(kPrelinkBundlePathKey
));
1469 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
1472 #if KASLR_KEXT_DEBUG
1473 IOLog("kaslr: doCoalesedSlides %d kext %s \n", doCoalesedSlides
, getIdentifierCString());
1476 /* Also get the executable's bundle-relative path if present.
1477 * Don't look for an arch-specific path property.
1479 executableRelPath
= OSDynamicCast(OSString
,
1480 anInfoDict
->getObject(kPrelinkExecutableRelativePathKey
));
1481 if (executableRelPath
) {
1482 executableRelPath
->retain();
1485 /* Don't need the paths to be in the info dictionary any more.
1487 anInfoDict
->removeObject(kPrelinkBundlePathKey
);
1488 anInfoDict
->removeObject(kPrelinkExecutableRelativePathKey
);
1490 /* Create an OSData wrapper around the linked executable.
1492 addressNum
= OSDynamicCast(OSNumber
,
1493 anInfoDict
->getObject(kPrelinkExecutableLoadKey
));
1495 lengthNum
= OSDynamicCast(OSNumber
,
1496 anInfoDict
->getObject(kPrelinkExecutableSizeKey
));
1499 kOSKextLogErrorLevel
|
1500 kOSKextLogArchiveFlag
,
1501 "Kext %s can't find prelinked kext executable size.",
1502 getIdentifierCString());
1506 data
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1507 length
= (uint32_t) (lengthNum
->unsigned32BitValue());
1509 #if KASLR_KEXT_DEBUG
1510 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1511 (unsigned long)VM_KERNEL_UNSLIDE(data
),
1512 (unsigned long)data
,
1516 anInfoDict
->removeObject(kPrelinkExecutableLoadKey
);
1517 anInfoDict
->removeObject(kPrelinkExecutableSizeKey
);
1519 /* If the kext's load address differs from its source address, allocate
1520 * space in the kext map at the load address and copy the kext over.
1522 addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
));
1524 srcData
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1526 #if KASLR_KEXT_DEBUG
1527 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1528 (unsigned long)VM_KERNEL_UNSLIDE(srcData
),
1529 (unsigned long)srcData
);
1532 if (data
!= srcData
) {
1534 kern_return_t alloc_result
;
1536 alloc_result
= kext_alloc((vm_offset_t
*)&data
, length
, /* fixed */ TRUE
);
1537 if (alloc_result
!= KERN_SUCCESS
) {
1539 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1540 "Failed to allocate space for prelinked kext %s.",
1541 getIdentifierCString());
1544 memcpy(data
, srcData
, length
);
1547 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1548 "Error: prelinked kext %s - source and load addresses "
1549 "differ on ILP32 architecture.",
1550 getIdentifierCString());
1552 #endif /* __LP64__ */
1555 anInfoDict
->removeObject(kPrelinkExecutableSourceKey
);
1558 prelinkedExecutable
= OSData::withBytesNoCopy(data
, length
);
1559 if (!prelinkedExecutable
) {
1561 kOSKextLogErrorLevel
|
1562 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
1563 "Kext %s failed to create executable wrapper.",
1564 getIdentifierCString());
1569 prelinkedExecutable
->setDeallocFunction(osdata_kext_free
);
1571 prelinkedExecutable
->setDeallocFunction(osdata_phys_free
);
1573 setLinkedExecutable(prelinkedExecutable
);
1574 addressNum
= OSDynamicCast(OSNumber
,
1575 anInfoDict
->getObject(kPrelinkKmodInfoKey
));
1578 kOSKextLogErrorLevel
|
1579 kOSKextLogArchiveFlag
,
1580 "Kext %s can't find prelinked kext kmod_info address.",
1581 getIdentifierCString());
1585 if (addressNum
->unsigned64BitValue() != 0) {
1586 kmod_info
= (kmod_info_t
*) (intptr_t) (addressNum
->unsigned64BitValue() + vm_kernel_slide
);
1587 kmod_info
->address
+= vm_kernel_slide
;
1588 #if KASLR_KEXT_DEBUG
1589 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1590 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
),
1591 (unsigned long)kmod_info
);
1592 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1593 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
1594 (unsigned long)kmod_info
->address
);
1598 anInfoDict
->removeObject(kPrelinkKmodInfoKey
);
1601 /* If the plist has a UUID for an interface, save that off.
1603 if (isInterface()) {
1604 interfaceUUID
= OSDynamicCast(OSData
,
1605 anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
));
1606 if (interfaceUUID
) {
1607 interfaceUUID
->retain();
1608 anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
);
1612 result
= slidePrelinkedExecutable(doCoalesedSlides
);
1613 if (result
!= kOSReturnSuccess
) {
1617 if (doCoalesedSlides
== false) {
1618 /* set VM protections now, wire later at kext load */
1619 result
= setVMAttributes(true, false);
1620 if (result
!= KERN_SUCCESS
) {
1625 flags
.prelinked
= true;
1627 /* If we created a kext from prelink info,
1628 * we must be booting from a prelinked kernel.
1630 sPrelinkBoot
= true;
1632 result
= registerIdentifier();
1635 OSSafeReleaseNULL(prelinkedExecutable
);
1640 /*********************************************************************
1641 *********************************************************************/
1643 void OSKext::setAllVMAttributes(void)
1645 OSCollectionIterator
* kextIterator
= NULL
; // must release
1646 const OSSymbol
* thisID
= NULL
; // do not release
1648 IORecursiveLockLock(sKextLock
);
1650 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1651 if (!kextIterator
) {
1655 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
1656 OSKext
* thisKext
; // do not release
1658 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1659 if (!thisKext
|| thisKext
->isInterface() || !thisKext
->declaresExecutable()) {
1663 /* set VM protections now, wire later at kext load */
1664 thisKext
->setVMAttributes(true, false);
1668 IORecursiveLockUnlock(sKextLock
);
1669 OSSafeReleaseNULL(kextIterator
);
1674 /*********************************************************************
1675 *********************************************************************/
1677 OSKext::withBooterData(
1678 OSString
* deviceTreeName
,
1679 OSData
* booterData
)
1681 OSKext
* newKext
= new OSKext
;
1683 if (newKext
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) {
1691 /*********************************************************************
1692 *********************************************************************/
1693 typedef struct _BooterKextFileInfo
{
1694 uint32_t infoDictPhysAddr
;
1695 uint32_t infoDictLength
;
1696 uint32_t executablePhysAddr
;
1697 uint32_t executableLength
;
1698 uint32_t bundlePathPhysAddr
;
1699 uint32_t bundlePathLength
;
1700 } _BooterKextFileInfo
;
1703 OSKext::initWithBooterData(
1704 OSString
* deviceTreeName
,
1705 OSData
* booterData
)
1707 bool result
= false;
1708 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not free
1709 char * infoDictAddr
= NULL
; // do not free
1710 void * executableAddr
= NULL
; // do not free
1711 char * bundlePathAddr
= NULL
; // do not free
1713 OSObject
* parsedXML
= NULL
; // must release
1714 OSDictionary
* theInfoDict
= NULL
; // do not release
1715 OSString
* kextPath
= NULL
; // must release
1716 OSString
* errorString
= NULL
; // must release
1717 OSData
* executable
= NULL
; // must release
1719 if (!super::init()) {
1723 kextFileInfo
= (_BooterKextFileInfo
*)booterData
->getBytesNoCopy();
1724 if (!kextFileInfo
) {
1726 kOSKextLogErrorLevel
|
1727 kOSKextLogGeneralFlag
,
1728 "No booter-provided data for kext device tree entry %s.",
1729 deviceTreeName
->getCStringNoCopy());
1733 /* The info plist must exist or we can't read the kext.
1735 if (!kextFileInfo
->infoDictPhysAddr
|| !kextFileInfo
->infoDictLength
) {
1737 kOSKextLogErrorLevel
|
1738 kOSKextLogGeneralFlag
,
1739 "No kext info dictionary for booter device tree entry %s.",
1740 deviceTreeName
->getCStringNoCopy());
1744 infoDictAddr
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
1745 if (!infoDictAddr
) {
1747 kOSKextLogErrorLevel
|
1748 kOSKextLogGeneralFlag
,
1749 "Can't translate physical address 0x%x of kext info dictionary "
1750 "for device tree entry %s.",
1751 (int)kextFileInfo
->infoDictPhysAddr
,
1752 deviceTreeName
->getCStringNoCopy());
1756 parsedXML
= OSUnserializeXML(infoDictAddr
, &errorString
);
1758 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
1761 const char * errorCString
= "(unknown error)";
1763 if (errorString
&& errorString
->getCStringNoCopy()) {
1764 errorCString
= errorString
->getCStringNoCopy();
1765 } else if (parsedXML
) {
1766 errorCString
= "not a dictionary";
1769 kOSKextLogErrorLevel
|
1770 kOSKextLogGeneralFlag
,
1771 "Error unserializing info dictionary for device tree entry %s: %s.",
1772 deviceTreeName
->getCStringNoCopy(), errorCString
);
1776 /* A bundle path is not mandatory.
1778 if (kextFileInfo
->bundlePathPhysAddr
&& kextFileInfo
->bundlePathLength
) {
1779 bundlePathAddr
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
);
1780 if (!bundlePathAddr
) {
1782 kOSKextLogErrorLevel
|
1783 kOSKextLogGeneralFlag
,
1784 "Can't translate physical address 0x%x of kext bundle path "
1785 "for device tree entry %s.",
1786 (int)kextFileInfo
->bundlePathPhysAddr
,
1787 deviceTreeName
->getCStringNoCopy());
1790 bundlePathAddr
[kextFileInfo
->bundlePathLength
-1] = '\0'; // just in case!
1792 kextPath
= OSString::withCString(bundlePathAddr
);
1795 kOSKextLogErrorLevel
|
1796 kOSKextLogGeneralFlag
,
1797 "Failed to create wrapper for device tree entry %s kext path %s.",
1798 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
);
1803 if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) {
1807 /* An executable is not mandatory.
1809 if (kextFileInfo
->executablePhysAddr
&& kextFileInfo
->executableLength
) {
1810 executableAddr
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
);
1811 if (!executableAddr
) {
1813 kOSKextLogErrorLevel
|
1814 kOSKextLogGeneralFlag
,
1815 "Can't translate physical address 0x%x of kext executable "
1816 "for device tree entry %s.",
1817 (int)kextFileInfo
->executablePhysAddr
,
1818 deviceTreeName
->getCStringNoCopy());
1822 executable
= OSData::withBytesNoCopy(executableAddr
,
1823 kextFileInfo
->executableLength
);
1826 kOSKextLogErrorLevel
|
1827 kOSKextLogGeneralFlag
,
1828 "Failed to create executable wrapper for device tree entry %s.",
1829 deviceTreeName
->getCStringNoCopy());
1833 /* A kext with an executable needs to retain the whole booterData
1834 * object to keep the executable in memory.
1836 if (!setExecutable(executable
, booterData
)) {
1838 kOSKextLogErrorLevel
|
1839 kOSKextLogGeneralFlag
,
1840 "Failed to set kext executable for device tree entry %s.",
1841 deviceTreeName
->getCStringNoCopy());
1846 result
= registerIdentifier();
1849 OSSafeReleaseNULL(parsedXML
);
1850 OSSafeReleaseNULL(kextPath
);
1851 OSSafeReleaseNULL(errorString
);
1852 OSSafeReleaseNULL(executable
);
1857 /*********************************************************************
1858 *********************************************************************/
1860 OSKext::registerIdentifier(void)
1862 bool result
= false;
1863 OSKext
* existingKext
= NULL
; // do not release
1864 bool existingIsLoaded
= false;
1865 bool existingIsPrelinked
= false;
1866 OSKextVersion newVersion
= -1;
1867 OSKextVersion existingVersion
= -1;
1868 char newVersionCString
[kOSKextVersionMaxLength
];
1869 char existingVersionCString
[kOSKextVersionMaxLength
];
1870 OSData
* newUUID
= NULL
; // must release
1871 OSData
* existingUUID
= NULL
; // must release
1873 IORecursiveLockLock(sKextLock
);
1875 /* Get the new kext's version for checks & log messages.
1877 newVersion
= getVersion();
1878 OSKextVersionGetString(newVersion
, newVersionCString
,
1879 kOSKextVersionMaxLength
);
1881 /* If we don't have an existing kext with this identifier,
1882 * just record the new kext and we're done!
1884 existingKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
));
1885 if (!existingKext
) {
1886 sKextsByID
->setObject(bundleID
, this);
1891 /* Get the existing kext's version for checks & log messages.
1893 existingVersion
= existingKext
->getVersion();
1894 OSKextVersionGetString(existingVersion
,
1895 existingVersionCString
, kOSKextVersionMaxLength
);
1897 existingIsLoaded
= existingKext
->isLoaded();
1898 existingIsPrelinked
= existingKext
->isPrelinked();
1900 /* If we have a kext with this identifier that's already loaded/prelinked,
1901 * we can't use the new one, but let's be really thorough and check how
1902 * the two are related for a precise diagnostic log message.
1904 * Note that user space can't find out about nonloaded prelinked kexts,
1905 * so in this case we log a message when new & existing are equivalent
1906 * at the step rather than warning level, because we are always going
1907 * be getting a copy of the kext in the user load request mkext.
1909 if (existingIsLoaded
|| existingIsPrelinked
) {
1910 bool sameVersion
= (newVersion
== existingVersion
);
1911 bool sameExecutable
= true; // assume true unless we have UUIDs
1913 /* Only get the UUID if the existing kext is loaded. Doing so
1914 * might have to uncompress an mkext executable and we shouldn't
1915 * take that hit when neither kext is loaded.
1917 newUUID
= copyUUID();
1918 existingUUID
= existingKext
->copyUUID();
1920 /* I'm entirely too paranoid about checking equivalence of executables,
1921 * but I remember nasty problems with it in the past.
1923 * - If we have UUIDs for both kexts, compare them.
1924 * - If only one kext has a UUID, they're definitely different.
1926 if (newUUID
&& existingUUID
) {
1927 sameExecutable
= newUUID
->isEqualTo(existingUUID
);
1928 } else if (newUUID
|| existingUUID
) {
1929 sameExecutable
= false;
1932 if (!newUUID
&& !existingUUID
) {
1934 /* If there are no UUIDs, we can't really tell that the executables
1935 * are *different* without a lot of work; the loaded kext's
1936 * unrelocated executable is no longer around (and we never had it
1937 * in-kernel for a prelinked kext). We certainly don't want to do
1938 * a whole fake link for the new kext just to compare, either.
1941 OSKextVersionGetString(version
, newVersionCString
,
1942 sizeof(newVersionCString
));
1944 kOSKextLogWarningLevel
|
1945 kOSKextLogKextBookkeepingFlag
,
1946 "Notice - new kext %s, v%s matches %s kext "
1947 "but can't determine if executables are the same (no UUIDs).",
1948 getIdentifierCString(),
1950 (existingIsLoaded
? "loaded" : "prelinked"));
1953 if (sameVersion
&& sameExecutable
) {
1955 (existingIsLoaded
? kOSKextLogWarningLevel
: kOSKextLogStepLevel
) |
1956 kOSKextLogKextBookkeepingFlag
,
1957 "Refusing new kext %s, v%s: a %s copy is already present "
1958 "(same version and executable).",
1959 getIdentifierCString(), newVersionCString
,
1960 (existingIsLoaded
? "loaded" : "prelinked"));
1963 /* This condition is significant so log it under warnings.
1966 kOSKextLogWarningLevel
|
1967 kOSKextLogKextBookkeepingFlag
,
1968 "Refusing new kext %s, v%s: already have %s v%s.",
1969 getIdentifierCString(),
1971 (existingIsLoaded
? "loaded" : "prelinked"),
1972 existingVersionCString
);
1974 /* This condition is significant so log it under warnings.
1977 kOSKextLogWarningLevel
| kOSKextLogKextBookkeepingFlag
,
1978 "Refusing new kext %s, v%s: a %s copy with a different "
1979 "executable UUID is already present.",
1980 getIdentifierCString(), newVersionCString
,
1981 (existingIsLoaded
? "loaded" : "prelinked"));
1985 } /* if (existingIsLoaded || existingIsPrelinked) */
1987 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
1988 * user loads are happening or if we're still in early boot. User agents are
1989 * supposed to resolve dependencies topside and include only the exact
1990 * kexts needed; so we always accept the new kext (in fact we should never
1991 * see an older unloaded copy hanging around).
1993 if (sUserLoadsActive
) {
1994 sKextsByID
->setObject(bundleID
, this);
1998 kOSKextLogStepLevel
|
1999 kOSKextLogKextBookkeepingFlag
,
2000 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2001 getIdentifierCString(),
2002 existingVersionCString
,
2008 /* During early boot, the kext with the highest version always wins out.
2009 * Prelinked kernels will never hit this, but mkexts and booter-read
2010 * kexts might have duplicates.
2012 if (newVersion
> existingVersion
) {
2013 sKextsByID
->setObject(bundleID
, this);
2017 kOSKextLogStepLevel
|
2018 kOSKextLogKextBookkeepingFlag
,
2019 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2020 existingVersionCString
,
2021 getIdentifierCString(),
2026 kOSKextLogStepLevel
|
2027 kOSKextLogKextBookkeepingFlag
,
2028 "Kext %s is already registered with a higher/same version (v%s); "
2029 "dropping newly-added (v%s).",
2030 getIdentifierCString(),
2031 existingVersionCString
,
2035 /* result has been set appropriately by now. */
2039 IORecursiveLockUnlock(sKextLock
);
2043 kOSKextLogStepLevel
|
2044 kOSKextLogKextBookkeepingFlag
,
2045 "Kext %s, v%s registered and available for loading.",
2046 getIdentifierCString(), newVersionCString
);
2049 OSSafeReleaseNULL(newUUID
);
2050 OSSafeReleaseNULL(existingUUID
);
2055 /*********************************************************************
2056 * Does the bare minimum validation to look up a kext.
2057 * All other validation is done on the spot as needed.
2058 **********************************************************************/
2060 OSKext::setInfoDictionaryAndPath(
2061 OSDictionary
* aDictionary
,
2064 bool result
= false;
2065 OSString
* bundleIDString
= NULL
; // do not release
2066 OSString
* versionString
= NULL
; // do not release
2067 OSString
* compatibleVersionString
= NULL
; // do not release
2068 const char * versionCString
= NULL
; // do not free
2069 const char * compatibleVersionCString
= NULL
; // do not free
2070 OSBoolean
* scratchBool
= NULL
; // do not release
2071 OSDictionary
* scratchDict
= NULL
; // do not release
2074 panic("Attempt to set info dictionary on a kext "
2075 "that already has one (%s).",
2076 getIdentifierCString());
2079 if (!aDictionary
|| !OSDynamicCast(OSDictionary
, aDictionary
)) {
2083 infoDict
= aDictionary
;
2086 /* Check right away if the info dictionary has any log flags.
2088 scratchBool
= OSDynamicCast(OSBoolean
,
2089 getPropertyForHostArch(kOSBundleEnableKextLoggingKey
));
2090 if (scratchBool
== kOSBooleanTrue
) {
2091 flags
.loggingEnabled
= 1;
2094 /* The very next thing to get is the bundle identifier. Unlike
2095 * in user space, a kext with no bundle identifier gets axed
2098 bundleIDString
= OSDynamicCast(OSString
,
2099 getPropertyForHostArch(kCFBundleIdentifierKey
));
2100 if (!bundleIDString
) {
2102 kOSKextLogErrorLevel
|
2103 kOSKextLogValidationFlag
,
2104 "CFBundleIdentifier missing/invalid type in kext %s.",
2105 aPath
? aPath
->getCStringNoCopy() : "(unknown)");
2108 bundleID
= OSSymbol::withString(bundleIDString
);
2111 kOSKextLogErrorLevel
|
2112 kOSKextLogValidationFlag
,
2113 "Can't copy bundle identifier as symbol for kext %s.",
2114 bundleIDString
->getCStringNoCopy());
2118 /* Save the path if we got one (it should always be available but it's
2119 * just something nice to have for bookkeeping).
2127 * Minimal validation to initialize. We'll do other validation on the spot.
2129 if (bundleID
->getLength() >= KMOD_MAX_NAME
) {
2131 kOSKextLogErrorLevel
|
2132 kOSKextLogValidationFlag
,
2133 "Kext %s error - CFBundleIdentifier over max length %d.",
2134 getIdentifierCString(), KMOD_MAX_NAME
- 1);
2138 version
= compatibleVersion
= -1;
2140 versionString
= OSDynamicCast(OSString
,
2141 getPropertyForHostArch(kCFBundleVersionKey
));
2142 if (!versionString
) {
2144 kOSKextLogErrorLevel
|
2145 kOSKextLogValidationFlag
,
2146 "Kext %s error - CFBundleVersion missing/invalid type.",
2147 getIdentifierCString());
2150 versionCString
= versionString
->getCStringNoCopy();
2151 version
= OSKextParseVersionString(versionCString
);
2154 kOSKextLogErrorLevel
|
2155 kOSKextLogValidationFlag
,
2156 "Kext %s error - CFBundleVersion bad value '%s'.",
2157 getIdentifierCString(), versionCString
);
2161 compatibleVersion
= -1; // set to illegal value for kexts that don't have
2163 compatibleVersionString
= OSDynamicCast(OSString
,
2164 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
2165 if (compatibleVersionString
) {
2166 compatibleVersionCString
= compatibleVersionString
->getCStringNoCopy();
2167 compatibleVersion
= OSKextParseVersionString(compatibleVersionCString
);
2168 if (compatibleVersion
< 0) {
2170 kOSKextLogErrorLevel
|
2171 kOSKextLogValidationFlag
,
2172 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2173 getIdentifierCString(), compatibleVersionCString
);
2177 if (compatibleVersion
> version
) {
2179 kOSKextLogErrorLevel
|
2180 kOSKextLogValidationFlag
,
2181 "Kext %s error - %s %s > %s %s (must be <=).",
2182 getIdentifierCString(),
2183 kOSBundleCompatibleVersionKey
, compatibleVersionCString
,
2184 kCFBundleVersionKey
, versionCString
);
2189 /* Check to see if this kext is in exclude list */
2190 if ( isInExcludeList() ) {
2192 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
2193 "Kext %s is in exclude list, not loadable",
2194 getIdentifierCString());
2198 /* Set flags for later use if the infoDict gets flushed. We only
2199 * check for true values, not false ones(!)
2201 scratchBool
= OSDynamicCast(OSBoolean
,
2202 getPropertyForHostArch(kOSBundleIsInterfaceKey
));
2203 if (scratchBool
== kOSBooleanTrue
) {
2204 flags
.interface
= 1;
2207 scratchBool
= OSDynamicCast(OSBoolean
,
2208 getPropertyForHostArch(kOSKernelResourceKey
));
2209 if (scratchBool
== kOSBooleanTrue
) {
2210 flags
.kernelComponent
= 1;
2211 flags
.interface
= 1; // xxx - hm. the kernel itself isn't an interface...
2214 /* A kernel component has one implicit dependency on the kernel.
2216 flags
.hasAllDependencies
= 1;
2219 /* Make sure common string values in personalities are uniqued to OSSymbols.
2221 scratchDict
= OSDynamicCast(OSDictionary
,
2222 getPropertyForHostArch(kIOKitPersonalitiesKey
));
2224 uniquePersonalityProperties(scratchDict
);
2234 /*********************************************************************
2235 * Not used for prelinked kernel boot as there is no unrelocated
2237 *********************************************************************/
2239 OSKext::setExecutable(
2240 OSData
* anExecutable
,
2241 OSData
* externalData
,
2242 bool externalDataIsMkext
)
2244 bool result
= false;
2245 const char * executableKey
= NULL
; // do not free
2247 if (!anExecutable
) {
2248 infoDict
->removeObject(_kOSKextExecutableKey
);
2249 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
2250 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
2255 if (infoDict
->getObject(_kOSKextExecutableKey
) ||
2256 infoDict
->getObject(_kOSKextMkextExecutableReferenceKey
)) {
2258 panic("Attempt to set an executable on a kext "
2259 "that already has one (%s).",
2260 getIdentifierCString());
2264 if (externalDataIsMkext
) {
2265 executableKey
= _kOSKextMkextExecutableReferenceKey
;
2267 executableKey
= _kOSKextExecutableKey
;
2271 infoDict
->setObject(executableKey
, anExecutable
);
2273 infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
);
2283 /*********************************************************************
2284 *********************************************************************/
2286 uniqueStringPlistProperty(OSDictionary
* dict
, const char * key
)
2288 OSString
* stringValue
= NULL
; // do not release
2289 const OSSymbol
* symbolValue
= NULL
; // must release
2291 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2296 symbolValue
= OSSymbol::withString(stringValue
);
2301 dict
->setObject(key
, symbolValue
);
2304 if (symbolValue
) symbolValue
->release();
2309 /*********************************************************************
2310 *********************************************************************/
2312 uniqueStringPlistProperty(OSDictionary
* dict
, const OSString
* key
)
2314 OSString
* stringValue
= NULL
; // do not release
2315 const OSSymbol
* symbolValue
= NULL
; // must release
2317 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2322 symbolValue
= OSSymbol::withString(stringValue
);
2327 dict
->setObject(key
, symbolValue
);
2330 if (symbolValue
) symbolValue
->release();
2335 /*********************************************************************
2336 * Replace common personality property values with uniqued instances
2337 * to save on wired memory.
2338 *********************************************************************/
2341 OSKext::uniquePersonalityProperties(OSDictionary
* personalityDict
)
2343 /* Properties every personality has.
2345 uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKey
);
2346 uniqueStringPlistProperty(personalityDict
, kIOProviderClassKey
);
2347 uniqueStringPlistProperty(personalityDict
, gIOClassKey
);
2349 /* Other commonly used properties.
2351 uniqueStringPlistProperty(personalityDict
, gIOMatchCategoryKey
);
2352 uniqueStringPlistProperty(personalityDict
, gIOResourceMatchKey
);
2353 uniqueStringPlistProperty(personalityDict
, gIOUserClientClassKey
);
2355 uniqueStringPlistProperty(personalityDict
, "HIDDefaultBehavior");
2356 uniqueStringPlistProperty(personalityDict
, "HIDPointerAccelerationType");
2357 uniqueStringPlistProperty(personalityDict
, "HIDRemoteControlType");
2358 uniqueStringPlistProperty(personalityDict
, "HIDScrollAccelerationType");
2359 uniqueStringPlistProperty(personalityDict
, "IOPersonalityPublisher");
2360 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect");
2361 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect Location");
2362 uniqueStringPlistProperty(personalityDict
, "Vendor");
2363 uniqueStringPlistProperty(personalityDict
, "Vendor Identification");
2364 uniqueStringPlistProperty(personalityDict
, "Vendor Name");
2365 uniqueStringPlistProperty(personalityDict
, "bConfigurationValue");
2366 uniqueStringPlistProperty(personalityDict
, "bInterfaceNumber");
2367 uniqueStringPlistProperty(personalityDict
, "idProduct");
2372 /*********************************************************************
2373 *********************************************************************/
2378 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2381 OSSafeReleaseNULL(infoDict
);
2382 OSSafeReleaseNULL(bundleID
);
2383 OSSafeReleaseNULL(path
);
2384 OSSafeReleaseNULL(executableRelPath
);
2385 OSSafeReleaseNULL(dependencies
);
2386 OSSafeReleaseNULL(linkedExecutable
);
2387 OSSafeReleaseNULL(metaClasses
);
2388 OSSafeReleaseNULL(interfaceUUID
);
2390 if (isInterface() && kmod_info
) {
2391 kfree(kmod_info
, sizeof(kmod_info_t
));
2399 #pragma mark Mkext files
2401 /*********************************************************************
2402 *********************************************************************/
2404 OSKext::readMkextArchive(OSData
* mkextData
,
2405 uint32_t * checksumPtr
)
2407 OSReturn result
= kOSKextReturnBadData
;
2408 uint32_t mkextLength
= 0;
2409 mkext_header
* mkextHeader
= 0; // do not free
2410 uint32_t mkextVersion
= 0;
2412 /* Note default return of kOSKextReturnBadData above.
2414 mkextLength
= mkextData
->getLength();
2415 if (mkextLength
< sizeof(mkext_basic_header
)) {
2416 OSKextLog(/* kext */ NULL
,
2417 kOSKextLogErrorLevel
|
2418 kOSKextLogArchiveFlag
,
2419 "Mkext archive too small to be valid.");
2423 mkextHeader
= (mkext_header
*)mkextData
->getBytesNoCopy();
2425 if (MKEXT_GET_MAGIC(mkextHeader
) != MKEXT_MAGIC
||
2426 MKEXT_GET_SIGNATURE(mkextHeader
) != MKEXT_SIGN
) {
2427 OSKextLog(/* kext */ NULL
,
2428 kOSKextLogErrorLevel
|
2429 kOSKextLogArchiveFlag
,
2430 "Mkext archive has invalid magic or signature.");
2434 if (MKEXT_GET_LENGTH(mkextHeader
) != mkextLength
) {
2435 OSKextLog(/* kext */ NULL
,
2436 kOSKextLogErrorLevel
|
2437 kOSKextLogArchiveFlag
,
2438 "Mkext archive recorded length doesn't match actual file length.");
2442 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2444 if (mkextVersion
== MKEXT_VERS_2
) {
2445 result
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
);
2447 OSKextLog(/* kext */ NULL
,
2448 kOSKextLogErrorLevel
|
2449 kOSKextLogArchiveFlag
,
2450 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
);
2451 result
= kOSKextReturnUnsupported
;
2458 /*********************************************************************
2459 * Assumes magic, signature, version, length have been checked.
2460 * xxx - need to add further bounds checking for each file entry
2462 * Should keep track of all kexts created so far, and if we hit a
2463 * fatal error halfway through, remove those kexts. If we've dropped
2464 * an older version that had already been read, whoops! Might want to
2465 * add a level of buffering?
2466 *********************************************************************/
2469 OSKext::readMkext2Archive(
2471 OSDictionary
** mkextPlistOut
,
2472 uint32_t * checksumPtr
)
2474 OSReturn result
= kOSReturnError
;
2475 uint32_t mkextLength
;
2476 mkext2_header
* mkextHeader
= NULL
; // do not free
2477 void * mkextEnd
= NULL
; // do not free
2478 uint32_t mkextVersion
;
2479 uint8_t * crc_address
= NULL
;
2481 uint32_t mkextPlistOffset
;
2482 uint32_t mkextPlistCompressedSize
;
2483 char * mkextPlistEnd
= NULL
; // do not free
2484 uint32_t mkextPlistFullSize
;
2485 OSString
* errorString
= NULL
; // must release
2486 OSData
* mkextPlistUncompressedData
= NULL
; // must release
2487 const char * mkextPlistDataBuffer
= NULL
; // do not free
2488 OSObject
* parsedXML
= NULL
; // must release
2489 OSDictionary
* mkextPlist
= NULL
; // do not release
2490 OSArray
* mkextInfoDictArray
= NULL
; // do not release
2493 mkextLength
= mkextData
->getLength();
2494 mkextHeader
= (mkext2_header
*)mkextData
->getBytesNoCopy();
2495 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2496 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2498 crc_address
= (u_int8_t
*)&mkextHeader
->version
;
2499 checksum
= mkext_adler32(crc_address
,
2500 (uintptr_t)mkextHeader
+
2501 MKEXT_GET_LENGTH(mkextHeader
) - (uintptr_t)crc_address
);
2503 if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) {
2504 OSKextLog(/* kext */ NULL
,
2505 kOSKextLogErrorLevel
|
2506 kOSKextLogArchiveFlag
,
2507 "Mkext archive has bad checksum.");
2508 result
= kOSKextReturnBadData
;
2513 *checksumPtr
= checksum
;
2516 /* Check that the CPU type & subtype match that of the running kernel. */
2517 if (MKEXT_GET_CPUTYPE(mkextHeader
) == (UInt32
)CPU_TYPE_ANY
) {
2518 OSKextLog(/* kext */ NULL
,
2519 kOSKextLogErrorLevel
|
2520 kOSKextLogArchiveFlag
,
2521 "Mkext archive must have a specific CPU type.");
2522 result
= kOSKextReturnBadData
;
2525 if ((UInt32
)_mh_execute_header
.cputype
!=
2526 MKEXT_GET_CPUTYPE(mkextHeader
)) {
2528 OSKextLog(/* kext */ NULL
,
2529 kOSKextLogErrorLevel
|
2530 kOSKextLogArchiveFlag
,
2531 "Mkext archive does not match the running kernel's CPU type.");
2532 result
= kOSKextReturnArchNotFound
;
2537 mkextPlistOffset
= MKEXT2_GET_PLIST(mkextHeader
);
2538 mkextPlistCompressedSize
= MKEXT2_GET_PLIST_COMPSIZE(mkextHeader
);
2539 mkextPlistEnd
= (char *)mkextHeader
+ mkextPlistOffset
+
2540 mkextPlistCompressedSize
;
2541 if (mkextPlistEnd
> mkextEnd
) {
2542 OSKextLog(/* kext */ NULL
,
2543 kOSKextLogErrorLevel
|
2544 kOSKextLogArchiveFlag
,
2545 "Mkext archive file overrun.");
2546 result
= kOSKextReturnBadData
;
2549 mkextPlistFullSize
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
);
2550 if (mkextPlistCompressedSize
) {
2551 mkextPlistUncompressedData
= sKernelKext
->extractMkext2FileData(
2552 (UInt8
*)mkextHeader
+ mkextPlistOffset
,
2554 mkextPlistCompressedSize
, mkextPlistFullSize
);
2555 if (!mkextPlistUncompressedData
) {
2558 mkextPlistDataBuffer
= (const char *)
2559 mkextPlistUncompressedData
->getBytesNoCopy();
2561 mkextPlistDataBuffer
= (const char *)mkextHeader
+ mkextPlistOffset
;
2564 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2566 parsedXML
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
);
2568 mkextPlist
= OSDynamicCast(OSDictionary
, parsedXML
);
2571 const char * errorCString
= "(unknown error)";
2573 if (errorString
&& errorString
->getCStringNoCopy()) {
2574 errorCString
= errorString
->getCStringNoCopy();
2575 } else if (parsedXML
) {
2576 errorCString
= "not a dictionary";
2578 OSKextLog(/* kext */ NULL
,
2579 kOSKextLogErrorLevel
|
2580 kOSKextLogArchiveFlag
,
2581 "Error unserializing mkext plist: %s.", errorCString
);
2585 /* If the caller needs the plist, hand it back and retain it.
2586 * (This function releases it at the end.)
2588 if (mkextPlistOut
) {
2589 *mkextPlistOut
= mkextPlist
;
2590 (*mkextPlistOut
)->retain();
2593 mkextInfoDictArray
= OSDynamicCast(OSArray
,
2594 mkextPlist
->getObject(kMKEXTInfoDictionariesKey
));
2595 if (!mkextInfoDictArray
) {
2596 OSKextLog(/* kext */ NULL
,
2597 kOSKextLogErrorLevel
|
2598 kOSKextLogArchiveFlag
,
2599 "Mkext archive contains no kext info dictionaries.");
2603 count
= mkextInfoDictArray
->getCount();
2604 for (i
= 0; i
< count
; i
++) {
2605 OSDictionary
* infoDict
;
2608 infoDict
= OSDynamicCast(OSDictionary
,
2609 mkextInfoDictArray
->getObject(i
));
2611 /* Create the kext for the entry, then release it, because the
2612 * kext system keeps them around until explicitly removed.
2613 * Any creation/registration failures are already logged for us.
2616 OSKext
* newKext
= OSKext::withMkext2Info(infoDict
, mkextData
);
2617 OSSafeReleaseNULL(newKext
);
2621 /* Even if we didn't keep any kexts from the mkext, we may have a load
2622 * request to process, so we are successful (no errors occurred).
2624 result
= kOSReturnSuccess
;
2628 OSSafeReleaseNULL(parsedXML
);
2629 OSSafeReleaseNULL(mkextPlistUncompressedData
);
2630 OSSafeReleaseNULL(errorString
);
2635 /*********************************************************************
2636 *********************************************************************/
2639 OSKext::withMkext2Info(
2640 OSDictionary
* anInfoDict
,
2643 OSKext
* newKext
= new OSKext
;
2645 if (newKext
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) {
2653 /*********************************************************************
2654 *********************************************************************/
2656 OSKext::initWithMkext2Info(
2657 OSDictionary
* anInfoDict
,
2660 bool result
= false;
2661 OSString
* kextPath
= NULL
; // do not release
2662 OSNumber
* executableOffsetNum
= NULL
; // do not release
2663 OSCollectionIterator
* iterator
= NULL
; // must release
2664 OSData
* executable
= NULL
; // must release
2666 if (anInfoDict
== NULL
|| !super::init()) {
2670 /* Get the path. Don't look for an arch-specific path property.
2672 kextPath
= OSDynamicCast(OSString
,
2673 anInfoDict
->getObject(kMKEXTBundlePathKey
));
2675 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
2679 /* If we have a path to the executable, save it.
2681 executableRelPath
= OSDynamicCast(OSString
,
2682 anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
));
2683 if (executableRelPath
) {
2684 executableRelPath
->retain();
2687 /* Don't need the paths to be in the info dictionary any more.
2689 anInfoDict
->removeObject(kMKEXTBundlePathKey
);
2690 anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
);
2692 executableOffsetNum
= OSDynamicCast(OSNumber
,
2693 infoDict
->getObject(kMKEXTExecutableKey
));
2694 if (executableOffsetNum
) {
2695 executable
= createMkext2FileEntry(mkextData
,
2696 executableOffsetNum
, "executable");
2697 infoDict
->removeObject(kMKEXTExecutableKey
);
2701 if (!setExecutable(executable
, mkextData
, true)) {
2706 result
= registerIdentifier();
2710 OSSafeReleaseNULL(executable
);
2711 OSSafeReleaseNULL(iterator
);
2715 /*********************************************************************
2716 *********************************************************************/
2718 OSKext::createMkext2FileEntry(
2720 OSNumber
* offsetNum
,
2723 OSData
* result
= NULL
;
2724 MkextEntryRef entryRef
;
2725 uint8_t * mkextBuffer
= (uint8_t *)mkextData
->getBytesNoCopy();
2726 uint32_t entryOffset
= offsetNum
->unsigned32BitValue();
2728 result
= OSData::withCapacity(sizeof(entryRef
));
2733 entryRef
.mkext
= (mkext_basic_header
*)mkextBuffer
;
2734 entryRef
.fileinfo
= mkextBuffer
+ entryOffset
;
2735 if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) {
2736 OSSafeReleaseNULL(result
);
2743 kOSKextLogErrorLevel
|
2744 kOSKextLogArchiveFlag
,
2745 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2746 name
, getIdentifierCString());
2751 /*********************************************************************
2752 *********************************************************************/
2754 static void * z_alloc(void *, u_int items
, u_int size
);
2755 static void z_free(void *, void *ptr
);
2757 typedef struct z_mem
{
2758 uint32_t alloc_size
;
2763 * Space allocation and freeing routines for use by zlib routines.
2766 z_alloc(void * notused __unused
, u_int num_items
, u_int size
)
2768 void * result
= NULL
;
2769 z_mem
* zmem
= NULL
;
2771 uint64_t total
= ((uint64_t)num_items
) * ((uint64_t)size
);
2772 //Check for overflow due to multiplication
2773 if (total
> UINT32_MAX
){
2774 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
2775 notused
, num_items
, size
, num_items
, size
);
2778 uint64_t allocSize64
= total
+ ((uint64_t)sizeof(zmem
));
2779 //Check for overflow due to addition
2780 if (allocSize64
> UINT32_MAX
){
2781 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
2782 notused
, num_items
, size
, (uint32_t)total
, sizeof(zmem
));
2784 uint32_t allocSize
= (uint32_t)allocSize64
;
2786 zmem
= (z_mem
*)kalloc_tag(allocSize
, VM_KERN_MEMORY_OSKEXT
);
2790 zmem
->alloc_size
= allocSize
;
2791 result
= (void *)&(zmem
->data
);
2797 z_free(void * notused __unused
, void * ptr
)
2799 uint32_t * skipper
= (uint32_t *)ptr
- 1;
2800 z_mem
* zmem
= (z_mem
*)skipper
;
2801 kfree((void *)zmem
, zmem
->alloc_size
);
2807 OSKext::extractMkext2FileData(
2810 uint32_t compressedSize
,
2813 OSData
* result
= NULL
;
2815 OSData
* uncompressedData
= NULL
; // release on error
2817 uint8_t * uncompressedDataBuffer
= 0; // do not free
2818 unsigned long uncompressedSize
;
2820 bool zstream_inited
= false;
2823 /* If the file isn't compressed, we want to make a copy
2824 * so that we don't have the tie to the larger mkext file buffer any more.
2826 if (!compressedSize
) {
2827 uncompressedData
= OSData::withBytes(data
, fullSize
);
2828 // xxx - no check for failure?
2829 result
= uncompressedData
;
2833 if (KERN_SUCCESS
!= kmem_alloc(kernel_map
,
2834 (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
, VM_KERN_MEMORY_OSKEXT
)) {
2836 /* How's this for cheesy? The kernel is only asked to extract
2837 * kext plists so we tailor the log messages.
2841 kOSKextLogErrorLevel
|
2842 kOSKextLogArchiveFlag
,
2843 "Allocation failure extracting %s from mkext.", name
);
2846 kOSKextLogErrorLevel
|
2847 kOSKextLogArchiveFlag
,
2848 "Allocation failure extracting %s from mkext for kext %s.",
2849 name
, getIdentifierCString());
2854 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
);
2855 if (!uncompressedData
) {
2858 kOSKextLogErrorLevel
|
2859 kOSKextLogArchiveFlag
,
2860 "Allocation failure extracting %s from mkext.", name
);
2863 kOSKextLogErrorLevel
|
2864 kOSKextLogArchiveFlag
,
2865 "Allocation failure extracting %s from mkext for kext %s.",
2866 name
, getIdentifierCString());
2870 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
2874 kOSKextLogDetailLevel
|
2875 kOSKextLogArchiveFlag
,
2876 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2877 name
, compressedSize
, fullSize
);
2880 kOSKextLogDetailLevel
|
2881 kOSKextLogArchiveFlag
,
2882 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2883 getIdentifierCString(), name
, compressedSize
, fullSize
);
2886 bzero(&zstream
, sizeof(zstream
));
2887 zstream
.next_in
= (UInt8
*)data
;
2888 zstream
.avail_in
= compressedSize
;
2890 zstream
.next_out
= uncompressedDataBuffer
;
2891 zstream
.avail_out
= fullSize
;
2893 zstream
.zalloc
= z_alloc
;
2894 zstream
.zfree
= z_free
;
2896 zlib_result
= inflateInit(&zstream
);
2897 if (Z_OK
!= zlib_result
) {
2900 kOSKextLogErrorLevel
|
2901 kOSKextLogArchiveFlag
,
2902 "Mkext error; zlib inflateInit failed (%d) for %s.",
2906 kOSKextLogErrorLevel
|
2907 kOSKextLogArchiveFlag
,
2908 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2909 getIdentifierCString(), zlib_result
, name
);
2913 zstream_inited
= true;
2916 zlib_result
= inflate(&zstream
, Z_FINISH
);
2918 if (zlib_result
== Z_STREAM_END
|| zlib_result
== Z_OK
) {
2919 uncompressedSize
= zstream
.total_out
;
2923 kOSKextLogErrorLevel
|
2924 kOSKextLogArchiveFlag
,
2925 "Mkext error; zlib inflate failed (%d) for %s.",
2929 kOSKextLogErrorLevel
|
2930 kOSKextLogArchiveFlag
,
2931 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
2932 getIdentifierCString(), zlib_result
, name
);
2936 kOSKextLogErrorLevel
|
2937 kOSKextLogArchiveFlag
,
2938 "zlib error: %s.", zstream
.msg
);
2943 if (uncompressedSize
!= fullSize
) {
2946 kOSKextLogErrorLevel
|
2947 kOSKextLogArchiveFlag
,
2948 "Mkext error; zlib inflate discrepancy for %s, "
2949 "uncompressed size != original size.", name
);
2952 kOSKextLogErrorLevel
|
2953 kOSKextLogArchiveFlag
,
2954 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
2955 "uncompressed size != original size.",
2956 getIdentifierCString(), name
);
2961 result
= uncompressedData
;
2964 /* Don't bother checking return, nothing we can do on fail.
2966 if (zstream_inited
) inflateEnd(&zstream
);
2969 OSSafeReleaseNULL(uncompressedData
);
2975 /*********************************************************************
2976 *********************************************************************/
2979 OSKext::loadFromMkext(
2980 OSKextLogSpec clientLogFilter
,
2982 uint32_t mkextBufferLength
,
2984 uint32_t * logInfoLengthOut
)
2986 OSReturn result
= kOSReturnError
;
2987 OSReturn tempResult
= kOSReturnError
;
2989 OSData
* mkextData
= NULL
; // must release
2990 OSDictionary
* mkextPlist
= NULL
; // must release
2992 OSArray
* logInfoArray
= NULL
; // must release
2993 OSSerialize
* serializer
= NULL
; // must release
2995 OSString
* predicate
= NULL
; // do not release
2996 OSDictionary
* requestArgs
= NULL
; // do not release
2998 OSString
* kextIdentifier
= NULL
; // do not release
2999 OSNumber
* startKextExcludeNum
= NULL
; // do not release
3000 OSNumber
* startMatchingExcludeNum
= NULL
; // do not release
3001 OSBoolean
* delayAutounloadBool
= NULL
; // do not release
3002 OSArray
* personalityNames
= NULL
; // do not release
3004 /* Default values for these two options: regular autounload behavior,
3005 * load all kexts, send no personalities.
3007 Boolean delayAutounload
= false;
3008 OSKextExcludeLevel startKextExcludeLevel
= kOSKextExcludeNone
;
3009 OSKextExcludeLevel startMatchingExcludeLevel
= kOSKextExcludeAll
;
3011 IORecursiveLockLock(sKextLock
);
3015 *logInfoLengthOut
= 0;
3018 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
3020 OSKextLog(/* kext */ NULL
,
3021 kOSKextLogDebugLevel
|
3023 "Received kext load request from user space.");
3025 /* Regardless of processing, the fact that we have gotten here means some
3026 * user-space program is up and talking to us, so we'll switch our kext
3027 * registration to reflect that.
3029 if (!sUserLoadsActive
) {
3030 OSKextLog(/* kext */ NULL
,
3031 kOSKextLogProgressLevel
|
3032 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
3033 "Switching to late startup (user-space) kext loading policy.");
3035 sUserLoadsActive
= true;
3038 if (!sLoadEnabled
) {
3039 OSKextLog(/* kext */ NULL
,
3040 kOSKextLogErrorLevel
|
3042 "Kext loading is disabled.");
3043 result
= kOSKextReturnDisabled
;
3047 /* Note that we do not set a dealloc function on this OSData
3048 * object! No references to it can remain after the loadFromMkext()
3049 * call since we are in a MIG function, and will vm_deallocate()
3052 mkextData
= OSData::withBytesNoCopy(mkextBuffer
,
3055 OSKextLog(/* kext */ NULL
,
3056 kOSKextLogErrorLevel
|
3057 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3058 "Failed to create wrapper for kext load request.");
3059 result
= kOSKextReturnNoMemory
;
3063 result
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
);
3064 if (result
!= kOSReturnSuccess
) {
3065 OSKextLog(/* kext */ NULL
,
3066 kOSKextLogErrorLevel
|
3068 "Failed to read kext load request.");
3072 predicate
= _OSKextGetRequestPredicate(mkextPlist
);
3073 if (!predicate
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) {
3074 OSKextLog(/* kext */ NULL
,
3075 kOSKextLogErrorLevel
|
3077 "Received kext load request with no predicate; skipping.");
3078 result
= kOSKextReturnInvalidArgument
;
3082 requestArgs
= OSDynamicCast(OSDictionary
,
3083 mkextPlist
->getObject(kKextRequestArgumentsKey
));
3084 if (!requestArgs
|| !requestArgs
->getCount()) {
3085 OSKextLog(/* kext */ NULL
,
3086 kOSKextLogErrorLevel
|
3088 "Received kext load request with no arguments.");
3089 result
= kOSKextReturnInvalidArgument
;
3093 kextIdentifier
= OSDynamicCast(OSString
,
3094 requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
));
3095 if (!kextIdentifier
) {
3096 OSKextLog(/* kext */ NULL
,
3097 kOSKextLogErrorLevel
|
3099 "Received kext load request with no kext identifier.");
3100 result
= kOSKextReturnInvalidArgument
;
3104 startKextExcludeNum
= OSDynamicCast(OSNumber
,
3105 requestArgs
->getObject(kKextRequestArgumentStartExcludeKey
));
3106 startMatchingExcludeNum
= OSDynamicCast(OSNumber
,
3107 requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
));
3108 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
3109 requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
));
3110 personalityNames
= OSDynamicCast(OSArray
,
3111 requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
));
3113 if (delayAutounloadBool
) {
3114 delayAutounload
= delayAutounloadBool
->getValue();
3116 if (startKextExcludeNum
) {
3117 startKextExcludeLevel
= startKextExcludeNum
->unsigned8BitValue();
3119 if (startMatchingExcludeNum
) {
3120 startMatchingExcludeLevel
= startMatchingExcludeNum
->unsigned8BitValue();
3123 OSKextLog(/* kext */ NULL
,
3124 kOSKextLogProgressLevel
|
3126 "Received request from user space to load kext %s.",
3127 kextIdentifier
->getCStringNoCopy());
3129 /* Load the kext, with no deferral, since this is a load from outside
3131 * xxx - Would like a better way to handle the default values for the
3132 * xxx - start/match opt args.
3134 result
= OSKext::loadKextWithIdentifier(
3136 /* allowDefer */ false,
3138 startKextExcludeLevel
,
3139 startMatchingExcludeLevel
,
3141 if (result
!= kOSReturnSuccess
) {
3144 /* If the load came down from kextd, it will shortly inform IOCatalogue
3145 * for matching via a separate IOKit calldown.
3150 /* Gather up the collected log messages for user space. Any
3151 * error messages past this call will not make it up as log messages
3152 * but will be in the system log.
3154 logInfoArray
= OSKext::clearUserSpaceLogFilter();
3156 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
3157 tempResult
= OSKext::serializeLogInfo(logInfoArray
,
3158 logInfoOut
, logInfoLengthOut
);
3159 if (tempResult
!= kOSReturnSuccess
) {
3160 result
= tempResult
;
3164 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3166 /* Note: mkextDataObject will have been retained by every kext w/an
3167 * executable in it. That should all have been flushed out at the
3168 * and of the load operation, but you never know....
3170 if (mkextData
&& mkextData
->getRetainCount() > 1) {
3171 OSKextLog(/* kext */ NULL
,
3172 kOSKextLogErrorLevel
|
3173 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3174 "Kext load request buffer from user space still retained by a kext; "
3175 "probable memory leak.");
3178 IORecursiveLockUnlock(sKextLock
);
3180 OSSafeReleaseNULL(mkextData
);
3181 OSSafeReleaseNULL(mkextPlist
);
3182 OSSafeReleaseNULL(serializer
);
3183 OSSafeReleaseNULL(logInfoArray
);
3188 /*********************************************************************
3189 *********************************************************************/
3192 OSKext::serializeLogInfo(
3193 OSArray
* logInfoArray
,
3195 uint32_t * logInfoLengthOut
)
3197 OSReturn result
= kOSReturnError
;
3198 char * buffer
= NULL
;
3199 kern_return_t kmem_result
= KERN_FAILURE
;
3200 OSSerialize
* serializer
= NULL
; // must release; reused
3201 char * logInfo
= NULL
; // returned by reference
3202 uint32_t logInfoLength
= 0;
3204 if (!logInfoArray
|| !logInfoOut
|| !logInfoLengthOut
) {
3205 OSKextLog(/* kext */ NULL
,
3206 kOSKextLogErrorLevel
|
3208 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3209 /* Bad programmer. */
3210 result
= kOSKextReturnInvalidArgument
;
3214 serializer
= OSSerialize::withCapacity(0);
3216 OSKextLog(/* kext */ NULL
,
3217 kOSKextLogErrorLevel
|
3219 "Failed to create serializer on log info for request from user space.");
3220 /* Incidental error; we're going to (try to) allow the request
3221 * itself to succeed. */
3224 if (!logInfoArray
->serialize(serializer
)) {
3225 OSKextLog(/* kext */ NULL
,
3226 kOSKextLogErrorLevel
|
3228 "Failed to serialize log info for request from user space.");
3229 /* Incidental error; we're going to (try to) allow the request
3230 * itself to succeed. */
3232 logInfo
= serializer
->text();
3233 logInfoLength
= serializer
->getLength();
3235 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
, round_page(logInfoLength
), VM_KERN_MEMORY_OSKEXT
);
3236 if (kmem_result
!= KERN_SUCCESS
) {
3237 OSKextLog(/* kext */ NULL
,
3238 kOSKextLogErrorLevel
|
3240 "Failed to copy log info for request from user space.");
3241 /* Incidental error; we're going to (try to) allow the request
3244 /* 11981737 - clear uninitialized data in last page */
3245 bzero((void *)(buffer
+ logInfoLength
),
3246 (round_page(logInfoLength
) - logInfoLength
));
3247 memcpy(buffer
, logInfo
, logInfoLength
);
3248 *logInfoOut
= buffer
;
3249 *logInfoLengthOut
= logInfoLength
;
3253 result
= kOSReturnSuccess
;
3255 OSSafeReleaseNULL(serializer
);
3260 #pragma mark Instance Management Methods
3262 /*********************************************************************
3263 *********************************************************************/
3265 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
)
3267 OSKext
* foundKext
= NULL
;
3269 IORecursiveLockLock(sKextLock
);
3270 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3272 foundKext
->retain();
3274 IORecursiveLockUnlock(sKextLock
);
3279 /*********************************************************************
3280 *********************************************************************/
3282 OSKext::lookupKextWithIdentifier(OSString
* kextIdentifier
)
3284 return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy());
3287 /*********************************************************************
3288 *********************************************************************/
3290 OSKext::lookupKextWithLoadTag(uint32_t aTag
)
3292 OSKext
* foundKext
= NULL
; // returned
3295 IORecursiveLockLock(sKextLock
);
3297 count
= sLoadedKexts
->getCount();
3298 for (i
= 0; i
< count
; i
++) {
3299 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3300 if (thisKext
->getLoadTag() == aTag
) {
3301 foundKext
= thisKext
;
3302 foundKext
->retain();
3308 IORecursiveLockUnlock(sKextLock
);
3313 /*********************************************************************
3314 *********************************************************************/
3316 OSKext::lookupKextWithAddress(vm_address_t address
)
3318 OSKext
* foundKext
= NULL
; // returned
3321 IORecursiveLockLock(sKextLock
);
3323 count
= sLoadedKexts
->getCount();
3324 for (i
= 0; i
< count
; i
++) {
3325 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3326 if (thisKext
->linkedExecutable
) {
3327 vm_address_t kext_start
=
3328 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy();
3329 vm_address_t kext_end
= kext_start
+
3330 thisKext
->linkedExecutable
->getLength();
3331 if ((kext_start
<= address
) && (address
< kext_end
)) {
3332 foundKext
= thisKext
;
3333 foundKext
->retain();
3340 IORecursiveLockUnlock(sKextLock
);
3346 OSKext::copyKextUUIDForAddress(OSNumber
*address
)
3348 OSData
*uuid
= NULL
;
3354 uintptr_t addr
= (uintptr_t)address
->unsigned64BitValue() + vm_kernel_slide
;
3357 /* Is the calling process allowed to query kext info? */
3358 if (current_task() != kernel_task
) {
3359 int macCheckResult
= 0;
3360 kauth_cred_t cred
= NULL
;
3362 cred
= kauth_cred_get_with_ref();
3363 macCheckResult
= mac_kext_check_query(cred
);
3364 kauth_cred_unref(&cred
);
3366 if (macCheckResult
!= 0) {
3367 OSKextLog(/* kext */ NULL
,
3368 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
3369 "Failed to query kext UUID (MAC policy error 0x%x).",
3376 if (((vm_offset_t
)addr
>= vm_kernel_stext
) && ((vm_offset_t
)addr
< vm_kernel_etext
)) {
3377 /* address in xnu proper */
3378 unsigned long uuid_len
= 0;
3379 uuid
= OSData::withBytes(getuuidfromheader(&_mh_execute_header
, &uuid_len
), uuid_len
);
3381 IOLockLock(sKextSummariesLock
);
3382 OSKextLoadedKextSummary
*summary
= OSKext::summaryForAddress(addr
);
3384 uuid
= OSData::withBytes(summary
->uuid
, sizeof(uuid_t
));
3386 IOLockUnlock(sKextSummariesLock
);
3392 /*********************************************************************
3393 *********************************************************************/
3395 OSKext::lookupKextWithUUID(uuid_t wanted
)
3397 OSKext
* foundKext
= NULL
; // returned
3400 IORecursiveLockLock(sKextLock
);
3402 count
= sLoadedKexts
->getCount();
3404 for (i
= 0; i
< count
; i
++) {
3405 OSKext
* thisKext
= NULL
;
3407 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3412 OSData
*uuid_data
= thisKext
->copyUUID();
3418 memcpy(&uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
3419 uuid_data
->release();
3421 if (0 == uuid_compare(wanted
, uuid
)) {
3422 foundKext
= thisKext
;
3423 foundKext
->retain();
3430 IORecursiveLockUnlock(sKextLock
);
3438 /*********************************************************************
3439 *********************************************************************/
3441 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
)
3443 bool result
= false;
3444 OSKext
* foundKext
= NULL
; // returned
3446 IORecursiveLockLock(sKextLock
);
3448 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3449 if (foundKext
&& foundKext
->isLoaded()) {
3453 IORecursiveLockUnlock(sKextLock
);
3458 /*********************************************************************
3459 * xxx - should spawn a separate thread so a kext can safely have
3460 * xxx - itself unloaded.
3461 *********************************************************************/
3469 bool terminateServicesAndRemovePersonalitiesFlag
)
3473 kOSKextLogErrorLevel
|
3474 kOSKextLogKextBookkeepingFlag
,
3475 "removeKext() called for %s, not supported on embedded",
3476 aKext
->getIdentifier() ? aKext
->getIdentifierCString() : "unknown kext");
3478 return kOSReturnSuccess
;
3479 #else /* CONFIG_EMBEDDED */
3481 OSReturn result
= kOSKextReturnInUse
;
3482 OSKext
* checkKext
= NULL
; // do not release
3484 int macCheckResult
= 0;
3485 kauth_cred_t cred
= NULL
;
3488 IORecursiveLockLock(sKextLock
);
3490 /* If the kext has no identifier, it failed to init
3491 * so isn't in sKextsByID and it isn't loaded.
3493 if (!aKext
->getIdentifier()) {
3494 result
= kOSReturnSuccess
;
3498 checkKext
= OSDynamicCast(OSKext
,
3499 sKextsByID
->getObject(aKext
->getIdentifier()));
3500 if (checkKext
!= aKext
) {
3501 result
= kOSKextReturnNotFound
;
3505 if (aKext
->isLoaded()) {
3507 if (current_task() != kernel_task
) {
3508 cred
= kauth_cred_get_with_ref();
3509 macCheckResult
= mac_kext_check_unload(cred
, aKext
->getIdentifierCString());
3510 kauth_cred_unref(&cred
);
3513 if (macCheckResult
!= 0) {
3514 result
= kOSReturnError
;
3516 kOSKextLogErrorLevel
|
3517 kOSKextLogKextBookkeepingFlag
,
3518 "Failed to remove kext %s (MAC policy error 0x%x).",
3519 aKext
->getIdentifierCString(), macCheckResult
);
3524 /* make sure there are no resource requests in flight - 17187548 */
3525 if (aKext
->countRequestCallbacks()) {
3529 /* If we are terminating, send the request to the IOCatalogue
3530 * (which will actually call us right back but that's ok we have
3531 * a recursive lock don't you know) but do not ask the IOCatalogue
3532 * to call back with an unload, we'll do that right here.
3534 if (terminateServicesAndRemovePersonalitiesFlag
) {
3535 result
= gIOCatalogue
->terminateDriversForModule(
3536 aKext
->getIdentifierCString(), /* unload */ false);
3537 if (result
!= kOSReturnSuccess
) {
3539 kOSKextLogErrorLevel
|
3540 kOSKextLogKextBookkeepingFlag
,
3541 "Can't remove kext %s; services failed to terminate - 0x%x.",
3542 aKext
->getIdentifierCString(), result
);
3547 result
= aKext
->unload();
3548 if (result
!= kOSReturnSuccess
) {
3553 /* Remove personalities as requested. This is a bit redundant for a loaded
3554 * kext as IOCatalogue::terminateDriversForModule() removes driver
3555 * personalities, but it doesn't restart matching, which we always want
3556 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3559 if (terminateServicesAndRemovePersonalitiesFlag
) {
3560 aKext
->removePersonalitiesFromCatalog();
3564 kOSKextLogProgressLevel
|
3565 kOSKextLogKextBookkeepingFlag
,
3566 "Removing kext %s.",
3567 aKext
->getIdentifierCString());
3569 sKextsByID
->removeObject(aKext
->getIdentifier());
3570 result
= kOSReturnSuccess
;
3573 IORecursiveLockUnlock(sKextLock
);
3575 #endif /* CONFIG_EMBEDDED */
3578 /*********************************************************************
3579 *********************************************************************/
3582 OSKext::removeKextWithIdentifier(
3583 const char * kextIdentifier
,
3584 bool terminateServicesAndRemovePersonalitiesFlag
)
3586 OSReturn result
= kOSReturnError
;
3588 IORecursiveLockLock(sKextLock
);
3590 OSKext
* aKext
= OSDynamicCast(OSKext
,
3591 sKextsByID
->getObject(kextIdentifier
));
3593 result
= kOSKextReturnNotFound
;
3594 OSKextLog(/* kext */ NULL
,
3595 kOSKextLogErrorLevel
|
3596 kOSKextLogKextBookkeepingFlag
,
3597 "Can't remove kext %s - not found.",
3602 result
= OSKext::removeKext(aKext
,
3603 terminateServicesAndRemovePersonalitiesFlag
);
3606 IORecursiveLockUnlock(sKextLock
);
3611 /*********************************************************************
3612 *********************************************************************/
3615 OSKext::removeKextWithLoadTag(
3616 OSKextLoadTag loadTag
,
3617 bool terminateServicesAndRemovePersonalitiesFlag
)
3619 OSReturn result
= kOSReturnError
;
3620 OSKext
* foundKext
= NULL
;
3623 IORecursiveLockLock(sKextLock
);
3625 count
= sLoadedKexts
->getCount();
3626 for (i
= 0; i
< count
; i
++) {
3627 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3628 if (thisKext
->loadTag
== loadTag
) {
3629 foundKext
= thisKext
;
3635 result
= kOSKextReturnNotFound
;
3636 OSKextLog(/* kext */ NULL
,
3637 kOSKextLogErrorLevel
|
3638 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
3639 "Can't remove kext with load tag %d - not found.",
3644 result
= OSKext::removeKext(foundKext
,
3645 terminateServicesAndRemovePersonalitiesFlag
);
3648 IORecursiveLockUnlock(sKextLock
);
3653 /*********************************************************************
3654 *********************************************************************/
3656 OSKext::copyKexts(void)
3658 OSDictionary
* result
;
3660 IORecursiveLockLock(sKextLock
);
3661 result
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection());
3662 IORecursiveLockUnlock(sKextLock
);
3667 /*********************************************************************
3668 *********************************************************************/
3669 #define BOOTER_KEXT_PREFIX "Driver-"
3671 typedef struct _DeviceTreeBuffer
{
3674 } _DeviceTreeBuffer
;
3676 /*********************************************************************
3677 * Create a dictionary of excluded kexts from the given booter data.
3678 *********************************************************************/
3681 OSKext::createExcludeListFromBooterData(
3682 OSDictionary
* theDictionary
,
3683 OSCollectionIterator
* theIterator
)
3685 OSString
* deviceTreeName
= NULL
; // do not release
3686 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not release
3687 char * booterDataPtr
= NULL
; // do not release
3688 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not release
3689 char * infoDictAddr
= NULL
; // do not release
3690 OSObject
* parsedXML
= NULL
; // must release
3691 OSDictionary
* theInfoDict
= NULL
; // do not release
3693 theIterator
->reset();
3695 /* look for AppleKextExcludeList.kext */
3696 while ( (deviceTreeName
=
3697 OSDynamicCast(OSString
, theIterator
->getNextObject())) ) {
3699 const char * devTreeNameCString
;
3700 OSData
* deviceTreeEntry
;
3701 OSString
* myBundleID
; // do not release
3703 OSSafeReleaseNULL(parsedXML
);
3706 OSDynamicCast(OSData
, theDictionary
->getObject(deviceTreeName
));
3707 if (!deviceTreeEntry
) {
3711 /* Make sure it is a kext */
3712 devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
3713 if (strncmp(devTreeNameCString
, BOOTER_KEXT_PREFIX
,
3714 (sizeof(BOOTER_KEXT_PREFIX
) - 1)) != 0) {
3716 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3717 "\"%s\" not a kext",
3718 devTreeNameCString
);
3722 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
3723 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
3724 if (!deviceTreeBuffer
) {
3728 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
3729 if (!booterDataPtr
) {
3733 kextFileInfo
= (_BooterKextFileInfo
*) booterDataPtr
;
3734 if (!kextFileInfo
->infoDictPhysAddr
||
3735 !kextFileInfo
->infoDictLength
) {
3739 infoDictAddr
= (char *)
3740 ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
3741 if (!infoDictAddr
) {
3745 parsedXML
= OSUnserializeXML(infoDictAddr
);
3750 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
3756 OSDynamicCast(OSString
,
3757 theInfoDict
->getObject(kCFBundleIdentifierKey
));
3759 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3761 boolean_t updated
= updateExcludeList(theInfoDict
);
3764 panic("Missing OSKextExcludeList dictionary\n");
3769 } // while ( (deviceTreeName = ...) )
3771 OSSafeReleaseNULL(parsedXML
);
3775 /*********************************************************************
3776 * Create a dictionary of excluded kexts from the given prelink
3777 * info (kernelcache).
3778 *********************************************************************/
3781 OSKext::createExcludeListFromPrelinkInfo( OSArray
* theInfoArray
)
3783 OSDictionary
* myInfoDict
= NULL
; // do not release
3784 OSString
* myBundleID
; // do not release
3787 /* Find com.apple.driver.KextExcludeList. */
3788 for (i
= 0; i
< theInfoArray
->getCount(); i
++) {
3789 myInfoDict
= OSDynamicCast(OSDictionary
, theInfoArray
->getObject(i
));
3794 OSDynamicCast(OSString
,
3795 myInfoDict
->getObject(kCFBundleIdentifierKey
));
3797 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3799 boolean_t updated
= updateExcludeList(myInfoDict
);
3802 panic("Missing OSKextExcludeList dictionary\n");
3806 } // for (i = 0; i < theInfoArray->getCount()...
3813 OSKext::updateExcludeList(OSDictionary
*infoDict
)
3815 OSDictionary
*myTempDict
= NULL
; // do not free
3816 OSString
*myTempString
= NULL
; // do not free
3817 OSKextVersion newVersion
= 0;
3818 boolean_t updated
= false;
3824 myTempDict
= OSDynamicCast(OSDictionary
, infoDict
->getObject("OSKextExcludeList"));
3829 myTempString
= OSDynamicCast(OSString
, infoDict
->getObject(kCFBundleVersionKey
));
3830 if (!myTempString
) {
3834 newVersion
= OSKextParseVersionString(myTempString
->getCStringNoCopy());
3835 if (newVersion
== 0) {
3839 IORecursiveLockLock(sKextLock
);
3841 if (newVersion
> sExcludeListVersion
) {
3842 OSSafeReleaseNULL(sExcludeListByID
);
3843 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3844 sExcludeListVersion
= newVersion
;
3848 IORecursiveLockUnlock(sKextLock
);
3853 #pragma mark Accessors
3855 /*********************************************************************
3856 *********************************************************************/
3858 OSKext::getIdentifier(void)
3863 /*********************************************************************
3864 * A kext must have a bundle identifier to even survive initialization;
3865 * this is guaranteed to exist past then.
3866 *********************************************************************/
3868 OSKext::getIdentifierCString(void)
3870 return bundleID
->getCStringNoCopy();
3873 /*********************************************************************
3874 *********************************************************************/
3876 OSKext::getVersion(void)
3881 /*********************************************************************
3882 *********************************************************************/
3884 OSKext::getCompatibleVersion(void)
3886 return compatibleVersion
;
3889 /*********************************************************************
3890 *********************************************************************/
3892 OSKext::isLibrary(void)
3894 return (getCompatibleVersion() > 0);
3897 /*********************************************************************
3898 *********************************************************************/
3900 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
)
3902 if ((compatibleVersion
> -1 && version
> -1) &&
3903 (compatibleVersion
<= version
&& aVersion
<= version
)) {
3909 /*********************************************************************
3910 *********************************************************************/
3912 OSKext::declaresExecutable(void)
3914 return (getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
);
3917 /*********************************************************************
3918 *********************************************************************/
3920 OSKext::getExecutable(void)
3922 OSData
* result
= NULL
;
3923 OSData
* extractedExecutable
= NULL
; // must release
3924 OSData
* mkextExecutableRef
= NULL
; // do not release
3926 result
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
));
3931 mkextExecutableRef
= OSDynamicCast(OSData
,
3932 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
));
3934 if (mkextExecutableRef
) {
3936 MkextEntryRef
* mkextEntryRef
= (MkextEntryRef
*)
3937 mkextExecutableRef
->getBytesNoCopy();
3938 uint32_t mkextVersion
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
);
3939 if (mkextVersion
== MKEXT_VERS_2
) {
3940 mkext2_file_entry
* fileinfo
=
3941 (mkext2_file_entry
*)mkextEntryRef
->fileinfo
;
3942 uint32_t compressedSize
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
);
3943 uint32_t fullSize
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
);
3944 extractedExecutable
= extractMkext2FileData(
3945 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable",
3946 compressedSize
, fullSize
);
3948 OSKextLog(this, kOSKextLogErrorLevel
|
3949 kOSKextLogArchiveFlag
,
3950 "Kext %s - unknown mkext version 0x%x for executable.",
3951 getIdentifierCString(), mkextVersion
);
3954 /* Regardless of success, remove the mkext executable,
3955 * and drop one reference on the mkext. (setExecutable() does not
3956 * replace, it removes, or panics if asked to replace.)
3958 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
3959 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
3961 if (extractedExecutable
&& extractedExecutable
->getLength()) {
3962 if (!setExecutable(extractedExecutable
)) {
3965 result
= extractedExecutable
;
3973 OSSafeReleaseNULL(extractedExecutable
);
3978 /*********************************************************************
3979 *********************************************************************/
3981 OSKext::isInterface(void)
3983 return flags
.interface
;
3986 /*********************************************************************
3987 *********************************************************************/
3989 OSKext::isKernel(void)
3991 return (this == sKernelKext
);
3994 /*********************************************************************
3995 *********************************************************************/
3997 OSKext::isKernelComponent(void)
3999 return flags
.kernelComponent
? true : false;
4002 /*********************************************************************
4003 *********************************************************************/
4005 OSKext::isExecutable(void)
4007 return (!isKernel() && !isInterface() && declaresExecutable());
4010 /*********************************************************************
4011 * We might want to check this recursively for all dependencies,
4012 * since a subtree of dependencies could get loaded before we hit
4013 * a dependency that isn't safe-boot-loadable.
4015 * xxx - Might want to return false if OSBundleEnableKextLogging or
4016 * OSBundleDebugLevel
4017 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4018 * the point except it's usually development drivers, which might
4019 * cause panics on startup, that have those properties). Heh; could
4020 * use a "kx" boot-arg!
4021 *********************************************************************/
4023 OSKext::isLoadableInSafeBoot(void)
4025 bool result
= false;
4026 OSString
* required
= NULL
; // do not release
4033 required
= OSDynamicCast(OSString
,
4034 getPropertyForHostArch(kOSBundleRequiredKey
));
4038 if (required
->isEqualTo(kOSBundleRequiredRoot
) ||
4039 required
->isEqualTo(kOSBundleRequiredLocalRoot
) ||
4040 required
->isEqualTo(kOSBundleRequiredNetworkRoot
) ||
4041 required
->isEqualTo(kOSBundleRequiredSafeBoot
) ||
4042 required
->isEqualTo(kOSBundleRequiredConsole
)) {
4051 /*********************************************************************
4052 *********************************************************************/
4054 OSKext::isPrelinked(void)
4056 return flags
.prelinked
? true : false;
4059 /*********************************************************************
4060 *********************************************************************/
4061 bool OSKext::isLoaded(void)
4063 return flags
.loaded
? true : false;
4066 /*********************************************************************
4067 *********************************************************************/
4069 OSKext::isStarted(void)
4071 return flags
.started
? true : false;
4074 /*********************************************************************
4075 *********************************************************************/
4077 OSKext::isCPPInitialized(void)
4079 return flags
.CPPInitialized
;
4082 /*********************************************************************
4083 *********************************************************************/
4085 OSKext::setCPPInitialized(bool initialized
)
4087 flags
.CPPInitialized
= initialized
;
4090 /*********************************************************************
4091 *********************************************************************/
4093 OSKext::getLoadTag(void)
4098 /*********************************************************************
4099 *********************************************************************/
4100 void OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
)
4102 if (linkedExecutable
) {
4103 *loadSize
= linkedExecutable
->getLength();
4105 /* If we have a kmod_info struct, calculated the wired size
4106 * from that. Otherwise it's the full load size.
4109 *wiredSize
= *loadSize
- kmod_info
->hdr_size
;
4111 *wiredSize
= *loadSize
;
4120 /*********************************************************************
4121 *********************************************************************/
4123 OSKext::copyUUID(void)
4125 OSData
* result
= NULL
;
4126 OSData
* theExecutable
= NULL
; // do not release
4127 const kernel_mach_header_t
* header
= NULL
;
4128 const struct load_command
* load_cmd
= NULL
;
4129 const struct uuid_command
* uuid_cmd
= NULL
;
4132 /* An interface kext doesn't have a linked executable with an LC_UUID,
4133 * we create one when it's linked.
4135 if (interfaceUUID
) {
4136 result
= interfaceUUID
;
4141 /* For real kexts, try to get the UUID from the linked executable,
4142 * or if is hasn't been linked yet, the unrelocated executable.
4144 theExecutable
= linkedExecutable
;
4145 if (!theExecutable
) {
4146 theExecutable
= getExecutable();
4148 if (!theExecutable
) {
4152 header
= (const kernel_mach_header_t
*)theExecutable
->getBytesNoCopy();
4153 load_cmd
= (const struct load_command
*)&header
[1];
4155 if (header
->magic
!= MH_MAGIC_KERNEL
) {
4157 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4158 "%s: bad header %p",
4164 for (i
= 0; i
< header
->ncmds
; i
++) {
4165 if (load_cmd
->cmd
== LC_UUID
) {
4166 uuid_cmd
= (struct uuid_command
*)load_cmd
;
4167 result
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
));
4170 load_cmd
= (struct load_command
*)((caddr_t
)load_cmd
+ load_cmd
->cmdsize
);
4177 /*********************************************************************
4178 *********************************************************************/
4179 #if defined (__arm__)
4180 #include <arm/arch.h>
4183 #if defined (__x86_64__)
4184 #define ARCHNAME "x86_64"
4185 #elif defined (__arm64__)
4186 #define ARCHNAME "arm64"
4187 #elif defined (__arm__)
4189 #if defined (__ARM_ARCH_7S__)
4190 #define ARCHNAME "armv7s"
4191 #elif defined (__ARM_ARCH_7F__)
4192 #define ARCHNAME "armv7f"
4193 #elif defined (__ARM_ARCH_7K__)
4194 #define ARCHNAME "armv7k"
4195 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
4196 #define ARCHNAME "armv7"
4197 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
4198 #define ARCHNAME "armv6"
4201 #elif defined (__arm64__)
4202 #define ARCHNAME "arm64"
4204 #error architecture not supported
4207 #define ARCH_SEPARATOR_CHAR '_'
4209 static char * makeHostArchKey(const char * key
, uint32_t * keySizeOut
)
4211 char * result
= NULL
;
4212 uint32_t keyLength
= strlen(key
);
4215 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4217 keySize
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
);
4218 result
= (char *)kalloc_tag(keySize
, VM_KERN_MEMORY_OSKEXT
);
4222 strlcpy(result
, key
, keySize
);
4223 result
[keyLength
++] = ARCH_SEPARATOR_CHAR
;
4224 result
[keyLength
] = '\0';
4225 strlcat(result
, ARCHNAME
, keySize
);
4226 *keySizeOut
= keySize
;
4232 /*********************************************************************
4233 *********************************************************************/
4235 OSKext::getPropertyForHostArch(const char * key
)
4237 OSObject
* result
= NULL
; // do not release
4238 uint32_t hostArchKeySize
= 0;
4239 char * hostArchKey
= NULL
; // must kfree
4241 if (!key
|| !infoDict
) {
4245 /* Some properties are not allowed to be arch-variant:
4246 * - Any CFBundle... property.
4247 * - OSBundleIsInterface.
4248 * - OSKernelResource.
4250 if (STRING_HAS_PREFIX(key
, "OS") ||
4251 STRING_HAS_PREFIX(key
, "IO")) {
4253 hostArchKey
= makeHostArchKey(key
, &hostArchKeySize
);
4255 OSKextLog(/* kext (this isn't about a kext) */ NULL
,
4256 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4257 "Allocation failure.");
4260 result
= infoDict
->getObject(hostArchKey
);
4264 result
= infoDict
->getObject(key
);
4268 if (hostArchKey
) kfree(hostArchKey
, hostArchKeySize
);
4273 #pragma mark Load/Start/Stop/Unload
4276 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4278 /*********************************************************************
4279 * sExcludeListByID is a dictionary with keys / values of:
4280 * key = bundleID string of kext we will not allow to load
4281 * value = version string(s) of the kext that is to be denied loading.
4282 * The version strings can be comma delimited. For example if kext
4283 * com.foocompany.fookext has two versions that we want to deny
4284 * loading then the version strings might look like:
4286 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4287 * not load the kext.
4289 * Value may also be in the form of "LE 2.0.0" (version numbers
4290 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4291 * number less than 2.0.0 will not load)
4293 * NOTE - we cannot use the characters "<=" or "<" because we have code
4294 * that serializes plists and treats '<' as a special character.
4295 *********************************************************************/
4297 OSKext::isInExcludeList(void)
4299 OSString
* versionString
= NULL
; // do not release
4300 char * versionCString
= NULL
; // do not free
4302 boolean_t wantLessThan
= false;
4303 boolean_t wantLessThanEqualTo
= false;
4304 boolean_t isInExcludeList
= true;
4307 IORecursiveLockLock(sKextLock
);
4309 if (!sExcludeListByID
) {
4310 isInExcludeList
= false;
4312 /* look up by bundleID in our exclude list and if found get version
4313 * string (or strings) that we will not allow to load
4315 versionString
= OSDynamicCast(OSString
, sExcludeListByID
->getObject(bundleID
));
4316 if (versionString
== NULL
|| versionString
->getLength() > (sizeof(myBuffer
) - 1)) {
4317 isInExcludeList
= false;
4321 IORecursiveLockUnlock(sKextLock
);
4323 if (!isInExcludeList
) {
4327 /* parse version strings */
4328 versionCString
= (char *) versionString
->getCStringNoCopy();
4330 /* look for "LT" or "LE" form of version string, must be in first two
4333 if (*versionCString
== 'L' && *(versionCString
+ 1) == 'T') {
4334 wantLessThan
= true;
4337 else if (*versionCString
== 'L' && *(versionCString
+ 1) == 'E') {
4338 wantLessThanEqualTo
= true;
4342 for (i
= 0; *versionCString
!= 0x00; versionCString
++) {
4343 /* skip whitespace */
4344 if (isWhiteSpace(*versionCString
)) {
4348 /* peek ahead for version string separator or null terminator */
4349 if (*(versionCString
+ 1) == ',' || *(versionCString
+ 1) == 0x00) {
4351 /* OK, we have a version string */
4352 myBuffer
[i
++] = *versionCString
;
4355 OSKextVersion excludeVers
;
4356 excludeVers
= OSKextParseVersionString(myBuffer
);
4358 if (wantLessThanEqualTo
) {
4359 if (version
<= excludeVers
) {
4363 else if (wantLessThan
) {
4364 if (version
< excludeVers
) {
4368 else if ( version
== excludeVers
) {
4372 /* reset for the next (if any) version string */
4374 wantLessThan
= false;
4375 wantLessThanEqualTo
= false;
4378 /* save valid version character */
4379 myBuffer
[i
++] = *versionCString
;
4381 /* make sure bogus version string doesn't overrun local buffer */
4382 if ( i
>= sizeof(myBuffer
) ) {
4391 /*********************************************************************
4392 *********************************************************************/
4395 OSKext::loadKextWithIdentifier(
4396 const char * kextIdentifierCString
,
4397 Boolean allowDeferFlag
,
4398 Boolean delayAutounloadFlag
,
4399 OSKextExcludeLevel startOpt
,
4400 OSKextExcludeLevel startMatchingOpt
,
4401 OSArray
* personalityNames
)
4403 OSReturn result
= kOSReturnError
;
4404 OSString
* kextIdentifier
= NULL
; // must release
4406 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
4407 if (!kextIdentifier
) {
4408 result
= kOSKextReturnNoMemory
;
4411 result
= OSKext::loadKextWithIdentifier(kextIdentifier
,
4412 allowDeferFlag
, delayAutounloadFlag
,
4413 startOpt
, startMatchingOpt
, personalityNames
);
4416 OSSafeReleaseNULL(kextIdentifier
);
4420 /*********************************************************************
4421 *********************************************************************/
4423 OSKext::loadKextWithIdentifier(
4424 OSString
* kextIdentifier
,
4425 Boolean allowDeferFlag
,
4426 Boolean delayAutounloadFlag
,
4427 OSKextExcludeLevel startOpt
,
4428 OSKextExcludeLevel startMatchingOpt
,
4429 OSArray
* personalityNames
)
4431 OSReturn result
= kOSReturnError
;
4432 OSReturn pingResult
= kOSReturnError
;
4433 OSKext
* theKext
= NULL
; // do not release
4434 OSDictionary
* loadRequest
= NULL
; // must release
4435 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4437 IORecursiveLockLock(sKextLock
);
4439 if (!kextIdentifier
) {
4440 result
= kOSKextReturnInvalidArgument
;
4444 OSKext::recordIdentifierRequest(kextIdentifier
);
4446 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
4448 if (!allowDeferFlag
) {
4449 OSKextLog(/* kext */ NULL
,
4450 kOSKextLogErrorLevel
|
4452 "Can't load kext %s - not found.",
4453 kextIdentifier
->getCStringNoCopy());
4457 if (!sKernelRequestsEnabled
) {
4459 kOSKextLogErrorLevel
|
4461 "Can't load kext %s - requests to user space are disabled.",
4462 kextIdentifier
->getCStringNoCopy());
4463 result
= kOSKextReturnDisabled
;
4467 /* Create a new request unless one is already sitting
4468 * in sKernelRequests for this bundle identifier
4470 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4471 if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4472 result
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
,
4474 if (result
!= kOSReturnSuccess
) {
4477 if (!_OSKextSetRequestArgument(loadRequest
,
4478 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
4480 result
= kOSKextReturnNoMemory
;
4483 if (!sKernelRequests
->setObject(loadRequest
)) {
4484 result
= kOSKextReturnNoMemory
;
4488 if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4489 result
= kOSKextReturnNoMemory
;
4494 kOSKextLogDebugLevel
|
4496 "Kext %s not found; queued load request to user space.",
4497 kextIdentifier
->getCStringNoCopy());
4500 pingResult
= OSKext::pingKextd();
4501 if (pingResult
== kOSKextReturnDisabled
) {
4502 OSKextLog(/* kext */ NULL
,
4503 ((sPrelinkBoot
) ? kOSKextLogDebugLevel
: kOSKextLogErrorLevel
) |
4505 "Kext %s might not load - kextd is currently unavailable.",
4506 kextIdentifier
->getCStringNoCopy());
4509 result
= kOSKextReturnDeferred
;
4513 result
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
);
4515 if (result
!= kOSReturnSuccess
) {
4517 kOSKextLogErrorLevel
|
4519 "Failed to load kext %s (error 0x%x).",
4520 kextIdentifier
->getCStringNoCopy(), (int)result
);
4522 OSKext::removeKext(theKext
,
4523 /* terminateService/removePersonalities */ true);
4527 if (delayAutounloadFlag
) {
4529 kOSKextLogProgressLevel
|
4530 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4531 "Setting delayed autounload for %s.",
4532 kextIdentifier
->getCStringNoCopy());
4533 theKext
->flags
.delayAutounload
= 1;
4537 OSSafeReleaseNULL(loadRequest
);
4538 OSSafeReleaseNULL(kextIdentifierSymbol
);
4540 IORecursiveLockUnlock(sKextLock
);
4545 /*********************************************************************
4546 *********************************************************************/
4549 OSKext::recordIdentifierRequest(
4550 OSString
* kextIdentifier
)
4552 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4555 if (!sAllKextLoadIdentifiers
|| !kextIdentifier
) {
4559 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4560 if (!kextIdentifierSymbol
) {
4561 // xxx - this is really a basic alloc failure
4566 IORecursiveLockLock(sKextLock
);
4567 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4568 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4571 // xxx - need to find a way to associate this whole func w/the kext
4572 OSKextLog(/* kext */ NULL
,
4573 // xxx - check level
4574 kOSKextLogStepLevel
|
4575 kOSKextLogArchiveFlag
,
4576 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4577 kextIdentifier
->getCStringNoCopy());
4580 IORecursiveLockUnlock(sKextLock
);
4585 OSKextLog(/* kext */ NULL
,
4586 kOSKextLogErrorLevel
|
4587 kOSKextLogArchiveFlag
,
4588 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4589 kextIdentifier
->getCStringNoCopy());
4591 OSSafeReleaseNULL(kextIdentifierSymbol
);
4595 /*********************************************************************
4596 *********************************************************************/
4599 OSKextExcludeLevel startOpt
,
4600 OSKextExcludeLevel startMatchingOpt
,
4601 OSArray
* personalityNames
)
4603 OSReturn result
= kOSReturnError
;
4604 kern_return_t kxldResult
;
4605 OSKextExcludeLevel dependenciesStartOpt
= startOpt
;
4606 OSKextExcludeLevel dependenciesStartMatchingOpt
= startMatchingOpt
;
4607 unsigned int i
, count
;
4608 Boolean alreadyLoaded
= false;
4609 OSKext
* lastLoadedKext
= NULL
;
4611 if (isInExcludeList()) {
4613 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
|
4615 "Kext %s is in exclude list, not loadable",
4616 getIdentifierCString());
4618 result
= kOSKextReturnNotLoadable
;
4623 alreadyLoaded
= true;
4624 result
= kOSReturnSuccess
;
4627 kOSKextLogDebugLevel
|
4628 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4629 "Kext %s is already loaded.",
4630 getIdentifierCString());
4635 if (current_task() != kernel_task
) {
4636 int macCheckResult
= 0;
4637 kauth_cred_t cred
= NULL
;
4639 cred
= kauth_cred_get_with_ref();
4640 macCheckResult
= mac_kext_check_load(cred
, getIdentifierCString());
4641 kauth_cred_unref(&cred
);
4643 if (macCheckResult
!= 0) {
4644 result
= kOSReturnError
;
4646 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4647 "Failed to load kext %s (MAC policy error 0x%x).",
4648 getIdentifierCString(), macCheckResult
);
4654 if (!sLoadEnabled
) {
4656 kOSKextLogErrorLevel
|
4658 "Kext loading is disabled (attempt to load kext %s).",
4659 getIdentifierCString());
4660 result
= kOSKextReturnDisabled
;
4664 /* If we've pushed the next available load tag to the invalid value,
4665 * we can't load any more kexts.
4667 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4669 kOSKextLogErrorLevel
|
4671 "Can't load kext %s - no more load tags to assign.",
4672 getIdentifierCString());
4673 result
= kOSKextReturnNoResources
;
4677 /* This is a bit of a hack, because we shouldn't be handling
4678 * personalities within the load function.
4680 if (!declaresExecutable()) {
4681 /* There is a special case where a non-executable kext can be loaded: the
4682 * AppleKextExcludeList. Detect that special kext by bundle identifier and
4683 * load its metadata into the global data structures, if appropriate
4685 if (strcmp(getIdentifierCString(), "com.apple.driver.KextExcludeList") == 0) {
4686 boolean_t updated
= updateExcludeList(infoDict
);
4689 kOSKextLogDebugLevel
| kOSKextLogLoadFlag
,
4690 "KextExcludeList was updated to version: %lld", sExcludeListVersion
);
4693 result
= kOSReturnSuccess
;
4697 /* Are we in safe boot?
4699 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4701 kOSKextLogErrorLevel
|
4703 "Can't load kext %s - not loadable during safe boot.",
4704 getIdentifierCString());
4705 result
= kOSKextReturnBootLevel
;
4710 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4712 getIdentifierCString());
4714 if (!sKxldContext
) {
4715 kxldResult
= kxld_create_context(&sKxldContext
, &kern_allocate
,
4716 &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,
4717 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
4720 kOSKextLogErrorLevel
|
4721 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4722 "Can't load kext %s - failed to create link context.",
4723 getIdentifierCString());
4724 result
= kOSKextReturnNoMemory
;
4729 /* We only need to resolve dependencies once for the whole graph, but
4730 * resolveDependencies will just return if there's no work to do, so it's
4731 * safe to call it more than once.
4733 if (!resolveDependencies()) {
4734 // xxx - check resolveDependencies() for log msg
4736 kOSKextLogErrorLevel
|
4737 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4738 "Can't load kext %s - failed to resolve library dependencies.",
4739 getIdentifierCString());
4740 result
= kOSKextReturnDependencies
;
4744 /* If we are excluding just the kext being loaded now (and not its
4745 * dependencies), drop the exclusion level to none so dependencies
4746 * start and/or add their personalities.
4748 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4749 dependenciesStartOpt
= kOSKextExcludeNone
;
4752 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4753 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4756 /* Load the dependencies, recursively.
4758 count
= getNumDependencies();
4759 for (i
= 0; i
< count
; i
++) {
4760 OSKext
* dependency
= OSDynamicCast(OSKext
,
4761 dependencies
->getObject(i
));
4762 if (dependency
== NULL
) {
4764 kOSKextLogErrorLevel
|
4765 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4766 "Internal error loading kext %s; dependency disappeared.",
4767 getIdentifierCString());
4768 result
= kOSKextReturnInternalError
;
4772 /* Dependencies must be started accorting to the opt,
4773 * but not given the personality names of the main kext.
4775 result
= dependency
->load(dependenciesStartOpt
,
4776 dependenciesStartMatchingOpt
,
4777 /* personalityNames */ NULL
);
4778 if (result
!= KERN_SUCCESS
) {
4780 kOSKextLogErrorLevel
|
4781 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4782 "Dependency %s of kext %s failed to load.",
4783 dependency
->getIdentifierCString(),
4784 getIdentifierCString());
4786 OSKext::removeKext(dependency
,
4787 /* terminateService/removePersonalities */ true);
4788 result
= kOSKextReturnDependencyLoadError
;
4794 result
= loadExecutable();
4795 if (result
!= KERN_SUCCESS
) {
4799 pendingPgoHead
.next
= &pendingPgoHead
;
4800 pendingPgoHead
.prev
= &pendingPgoHead
;
4802 uuid_generate(instance_uuid
);
4803 account
= IONew(OSKextAccount
, 1);
4805 result
= KERN_MEMORY_ERROR
;
4808 bzero(account
, sizeof(*account
));
4809 account
->loadTag
= kmod_info
->id
;
4810 account
->site
.refcount
= 0;
4811 account
->site
.flags
= VM_TAG_KMOD
;
4812 account
->kext
= this;
4814 flags
.loaded
= true;
4816 /* Add the kext to the list of loaded kexts and update the kmod_info
4817 * struct to point to that of the last loaded kext (which is the way
4818 * it's always been done, though I'd rather do them in order now).
4820 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
4821 sLoadedKexts
->setObject(this);
4823 /* Keep the kernel itself out of the kmod list.
4825 if (lastLoadedKext
->isKernel()) {
4826 lastLoadedKext
= NULL
;
4829 if (lastLoadedKext
) {
4830 kmod_info
->next
= lastLoadedKext
->kmod_info
;
4833 notifyKextLoadObservers(this, kmod_info
);
4835 /* Make the global kmod list point at the just-loaded kext. Note that the
4836 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4837 * although we do report it in kextstat these days by using the newer
4838 * OSArray of loaded kexts, which does contain it.
4840 * (The OSKext object representing the kernel doesn't even have a kmod_info
4841 * struct, though I suppose we could stick a pointer to it from the
4842 * static struct in OSRuntime.cpp.)
4846 /* Save the list of loaded kexts in case we panic.
4848 OSKext::saveLoadedKextPanicList();
4850 if (isExecutable()) {
4851 OSKext::updateLoadedKextSummaries();
4852 savePanicString(/* isLoading */ true);
4855 registerWithDTrace();
4857 jettisonLinkeditSegment();
4858 #endif /* CONFIG_DTRACE */
4860 #if !VM_MAPPED_KEXTS
4861 /* If there is a page (or more) worth of padding after the end
4862 * of the last data section but before the end of the data segment
4863 * then free it in the same manner the LinkeditSegment is freed
4865 jettisonDATASegmentPadding();
4870 if (isExecutable() && !flags
.started
) {
4871 if (startOpt
== kOSKextExcludeNone
) {
4873 if (result
!= kOSReturnSuccess
) {
4875 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4876 "Kext %s start failed (result 0x%x).",
4877 getIdentifierCString(), result
);
4878 result
= kOSKextReturnStartStopError
;
4883 /* If not excluding matching, send the personalities to the kernel.
4884 * This never affects the result of the load operation.
4885 * This is a bit of a hack, because we shouldn't be handling
4886 * personalities within the load function.
4888 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
4889 result
= sendPersonalitiesToCatalog(true, personalityNames
);
4894 /* More hack! If the kext doesn't declare an executable, even if we
4895 * "loaded" it, we have to remove any personalities naming it, or we'll
4896 * never see the registry go quiet. Errors here do not count for the
4897 * load operation itself.
4899 * Note that in every other regard it's perfectly ok for a kext to
4900 * not declare an executable and serve only as a package for personalities
4901 * naming another kext, so we do have to allow such kexts to be "loaded"
4902 * so that those other personalities get added & matched.
4904 if (!declaresExecutable()) {
4906 kOSKextLogStepLevel
| kOSKextLogLoadFlag
,
4907 "Kext %s has no executable; removing any personalities naming it.",
4908 getIdentifierCString());
4909 removePersonalitiesFromCatalog();
4912 if (result
!= kOSReturnSuccess
) {
4914 kOSKextLogErrorLevel
|
4916 "Kext %s failed to load (0x%x).",
4917 getIdentifierCString(), (int)result
);
4918 } else if (!alreadyLoaded
) {
4920 kOSKextLogProgressLevel
|
4923 getIdentifierCString());
4925 queueKextNotification(kKextRequestPredicateLoadNotification
,
4926 OSDynamicCast(OSString
, bundleID
));
4931 /*********************************************************************
4933 *********************************************************************/
4934 static char * strdup(const char * string
)
4936 char * result
= NULL
;
4943 size
= 1 + strlen(string
);
4944 result
= (char *)kalloc_tag(size
, VM_KERN_MEMORY_OSKEXT
);
4949 memcpy(result
, string
, size
);
4955 /*********************************************************************
4957 *********************************************************************/
4960 OSKext::lookupSection(const char *segname
, const char *secname
)
4962 kernel_section_t
* found_section
= NULL
;
4963 kernel_mach_header_t
* mh
= NULL
;
4964 kernel_segment_command_t
* seg
= NULL
;
4965 kernel_section_t
* sec
= NULL
;
4967 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4969 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4971 if (0 != strcmp(seg
->segname
, segname
)) {
4975 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4977 if (0 == strcmp(sec
->sectname
, secname
)) {
4978 found_section
= sec
;
4985 return found_section
;
4988 /*********************************************************************
4990 *********************************************************************/
4993 OSKext::slidePrelinkedExecutable(bool doCoalesedSlides
)
4995 OSReturn result
= kOSKextReturnBadData
;
4996 kernel_mach_header_t
* mh
= NULL
;
4997 kernel_segment_command_t
* seg
= NULL
;
4998 kernel_segment_command_t
* linkeditSeg
= NULL
;
4999 kernel_section_t
* sec
= NULL
;
5000 char * linkeditBase
= NULL
;
5001 bool haveLinkeditBase
= false;
5002 char * relocBase
= NULL
;
5003 bool haveRelocBase
= false;
5004 struct dysymtab_command
* dysymtab
= NULL
;
5005 struct linkedit_data_command
* segmentSplitInfo
= NULL
;
5006 struct symtab_command
* symtab
= NULL
;
5007 kernel_nlist_t
* sym
= NULL
;
5008 struct relocation_info
* reloc
= NULL
;
5011 vm_offset_t new_kextsize
;
5013 if (linkedExecutable
== NULL
|| vm_kernel_slide
== 0) {
5014 result
= kOSReturnSuccess
;
5018 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
5019 segmentSplitInfo
= (struct linkedit_data_command
*) getcommandfromheader(mh
, LC_SEGMENT_SPLIT_INFO
);
5021 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
5025 seg
->vmaddr
+= vm_kernel_slide
;
5027 #if KASLR_KEXT_DEBUG
5028 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
5030 (unsigned long)VM_KERNEL_UNSLIDE(seg
->vmaddr
),
5031 (unsigned long)seg
->vmaddr
);
5034 if (!haveRelocBase
) {
5035 relocBase
= (char *) seg
->vmaddr
;
5036 haveRelocBase
= true;
5038 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
5039 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
5040 haveLinkeditBase
= true;
5043 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
5044 sec
->addr
+= vm_kernel_slide
;
5046 #if KASLR_KEXT_DEBUG
5047 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
5049 (unsigned long)VM_KERNEL_UNSLIDE(sec
->addr
),
5050 (unsigned long)sec
->addr
);
5055 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
5057 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
5059 if (symtab
!= NULL
&& doCoalesedSlides
== false) {
5060 /* Some pseudo-kexts have symbol tables without segments.
5062 if (symtab
->nsyms
> 0 && haveLinkeditBase
) {
5063 sym
= (kernel_nlist_t
*) (linkeditBase
+ symtab
->symoff
);
5064 for (i
= 0; i
< symtab
->nsyms
; i
++) {
5065 if (sym
[i
].n_type
& N_STAB
) {
5068 sym
[i
].n_value
+= vm_kernel_slide
;
5070 #if KASLR_KEXT_DEBUG
5071 #define MAX_SYMS_TO_LOG 5
5072 if ( i
< MAX_SYMS_TO_LOG
) {
5073 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
5074 (unsigned long)VM_KERNEL_UNSLIDE(sym
[i
].n_value
),
5075 (unsigned long)sym
[i
].n_value
);
5082 if (dysymtab
!= NULL
&& doCoalesedSlides
== false) {
5083 if (dysymtab
->nextrel
> 0) {
5085 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5087 "Sliding kext %s: External relocations found.",
5088 getIdentifierCString());
5092 if (dysymtab
->nlocrel
> 0) {
5093 if (!haveLinkeditBase
) {
5095 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5097 "Sliding kext %s: No linkedit segment.",
5098 getIdentifierCString());
5102 if (!haveRelocBase
) {
5104 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5107 "Sliding kext %s: No writable segments.",
5109 "Sliding kext %s: No segments.",
5111 getIdentifierCString());
5115 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
5116 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
5118 for (i
= 0; i
< dysymtab
->nlocrel
; i
++) {
5119 if ( reloc
[i
].r_extern
!= 0
5120 || reloc
[i
].r_type
!= 0
5121 || reloc
[i
].r_length
!= (sizeof(void *) == 8 ? 3 : 2)
5124 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5126 "Sliding kext %s: Unexpected relocation found.",
5127 getIdentifierCString());
5130 if (reloc
[i
].r_pcrel
!= 0) {
5133 *((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)) += vm_kernel_slide
;
5135 #if KASLR_KEXT_DEBUG
5136 #define MAX_DYSYMS_TO_LOG 5
5137 if ( i
< MAX_DYSYMS_TO_LOG
) {
5138 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
5139 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
))),
5140 (unsigned long)*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)));
5145 /* We should free these relocations, not just delete the reference to them.
5146 * <rdar://problem/10535549> Free relocations from PIE kexts.
5148 * For now, we do not free LINKEDIT for kexts with split segments.
5150 new_kextsize
= round_page(kmod_info
->size
- reloc_size
);
5151 if (((kmod_info
->size
- new_kextsize
) > PAGE_SIZE
) && (!segmentSplitInfo
)) {
5152 vm_offset_t endofkext
= kmod_info
->address
+ kmod_info
->size
;
5153 vm_offset_t new_endofkext
= kmod_info
->address
+ new_kextsize
;
5154 vm_offset_t endofrelocInfo
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
);
5155 int bytes_remaining
= endofkext
- endofrelocInfo
;
5156 OSData
* new_osdata
= NULL
;
5158 /* fix up symbol offsets if they are after the dsymtab local relocs */
5160 if (dysymtab
->locreloff
< symtab
->symoff
){
5161 symtab
->symoff
-= reloc_size
;
5163 if (dysymtab
->locreloff
< symtab
->stroff
) {
5164 symtab
->stroff
-= reloc_size
;
5167 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
5168 dysymtab
->extreloff
-= reloc_size
;
5171 /* move data behind reloc info down to new offset */
5172 if (endofrelocInfo
< endofkext
) {
5173 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
5176 /* Create a new OSData for the smaller kext object and reflect
5177 * new linkedit segment size.
5179 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
5180 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
5182 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
5184 /* Fix up kmod info and linkedExecutable.
5186 kmod_info
->size
= new_kextsize
;
5188 new_osdata
->setDeallocFunction(osdata_kext_free
);
5190 new_osdata
->setDeallocFunction(osdata_phys_free
);
5192 linkedExecutable
->setDeallocFunction(NULL
);
5193 linkedExecutable
->release();
5194 linkedExecutable
= new_osdata
;
5197 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
5199 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
5203 dysymtab
->nlocrel
= 0;
5204 dysymtab
->locreloff
= 0;
5208 result
= kOSReturnSuccess
;
5213 /*********************************************************************
5214 * called only by load()
5215 *********************************************************************/
5217 OSKext::loadExecutable()
5219 OSReturn result
= kOSReturnError
;
5220 kern_return_t kxldResult
;
5221 KXLDDependency
* kxlddeps
= NULL
; // must kfree
5222 uint32_t num_kxlddeps
= 0;
5223 OSArray
* linkDependencies
= NULL
; // must release
5224 uint32_t numDirectDependencies
= 0;
5225 uint32_t num_kmod_refs
= 0;
5226 struct mach_header
** kxldHeaderPtr
= NULL
; // do not free
5227 struct mach_header
* kxld_header
= NULL
; // xxx - need to free here?
5228 OSData
* theExecutable
= NULL
; // do not release
5229 OSString
* versString
= NULL
; // do not release
5230 const char * versCString
= NULL
; // do not free
5231 const char * string
= NULL
; // do not free
5234 /* We need the version string for a variety of bits below.
5236 versString
= OSDynamicCast(OSString
,
5237 getPropertyForHostArch(kCFBundleVersionKey
));
5241 versCString
= versString
->getCStringNoCopy();
5243 if (isKernelComponent()) {
5244 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
5246 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
5248 kOSKextLogErrorLevel
|
5250 "Kernel component %s has incorrect version %s; "
5252 getIdentifierCString(),
5253 versCString
, KERNEL6_VERSION
);
5254 result
= kOSKextReturnInternalError
;
5256 } else if (strcmp(versCString
, osrelease
)) {
5258 kOSKextLogErrorLevel
|
5260 "Kernel component %s has incorrect version %s; "
5262 getIdentifierCString(),
5263 versCString
, osrelease
);
5264 result
= kOSKextReturnInternalError
;
5270 if (isPrelinked()) {
5274 /* <rdar://problem/21444003> all callers must be entitled */
5275 if (FALSE
== IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management")) {
5277 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5278 "Not entitled to link kext '%s'",
5279 getIdentifierCString());
5280 result
= kOSKextReturnNotPrivileged
;
5284 theExecutable
= getExecutable();
5285 if (!theExecutable
) {
5286 if (declaresExecutable()) {
5288 kOSKextLogErrorLevel
|
5290 "Can't load kext %s - executable is missing.",
5291 getIdentifierCString());
5292 result
= kOSKextReturnValidation
;
5298 if (isInterface()) {
5299 OSData
*executableCopy
= OSData::withData(theExecutable
);
5300 setLinkedExecutable(executableCopy
);
5301 executableCopy
->release();
5305 numDirectDependencies
= getNumDependencies();
5307 if (flags
.hasBleedthrough
) {
5308 linkDependencies
= dependencies
;
5309 linkDependencies
->retain();
5311 linkDependencies
= OSArray::withArray(dependencies
);
5312 if (!linkDependencies
) {
5314 kOSKextLogErrorLevel
|
5315 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5316 "Can't allocate link dependencies to load kext %s.",
5317 getIdentifierCString());
5321 for (i
= 0; i
< numDirectDependencies
; ++i
) {
5322 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
5323 dependencies
->getObject(i
));
5324 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
5328 num_kxlddeps
= linkDependencies
->getCount();
5329 if (!num_kxlddeps
) {
5331 kOSKextLogErrorLevel
|
5332 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
5333 "Can't load kext %s - it has no library dependencies.",
5334 getIdentifierCString());
5338 kxlddeps
= (KXLDDependency
*)kalloc_tag(num_kxlddeps
* sizeof(*kxlddeps
), VM_KERN_MEMORY_OSKEXT
);
5341 kOSKextLogErrorLevel
|
5342 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5343 "Can't allocate link context to load kext %s.",
5344 getIdentifierCString());
5347 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
5349 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5350 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
5352 if (dependency
->isInterface()) {
5353 OSKext
*interfaceTargetKext
= NULL
;
5354 OSData
* interfaceTarget
= NULL
;
5356 if (dependency
->isKernelComponent()) {
5357 interfaceTargetKext
= sKernelKext
;
5358 interfaceTarget
= sKernelKext
->linkedExecutable
;
5360 interfaceTargetKext
= OSDynamicCast(OSKext
,
5361 dependency
->dependencies
->getObject(0));
5363 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
5366 if (!interfaceTarget
) {
5371 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5372 * it will be useful to have them in the debugger.
5373 * strdup() failing isn't critical right here so we don't check that.
5375 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
5376 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
5377 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
5379 kxlddeps
[i
].interface
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5380 kxlddeps
[i
].interface_size
= dependency
->linkedExecutable
->getLength();
5381 kxlddeps
[i
].interface_name
= strdup(dependency
->getIdentifierCString());
5383 kxlddeps
[i
].kext
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5384 kxlddeps
[i
].kext_size
= dependency
->linkedExecutable
->getLength();
5385 kxlddeps
[i
].kext_name
= strdup(dependency
->getIdentifierCString());
5388 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
5391 kxldHeaderPtr
= &kxld_header
;
5395 kOSKextLogExplicitLevel
|
5396 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5397 "Kext %s - calling kxld_link_file:\n"
5398 " kxld_context: %p\n"
5399 " executable: %p executable_length: %d\n"
5401 " kxld_dependencies: %p num_dependencies: %d\n"
5402 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5403 getIdentifierCString(), sKxldContext
,
5404 theExecutable
->getBytesNoCopy(), theExecutable
->getLength(),
5405 this, kxlddeps
, num_kxlddeps
,
5406 kxldHeaderPtr
, &kmod_info
);
5409 /* After this call, the linkedExecutable instance variable
5412 kxldResult
= kxld_link_file(sKxldContext
,
5413 (u_char
*)theExecutable
->getBytesNoCopy(),
5414 theExecutable
->getLength(),
5415 getIdentifierCString(), this, kxlddeps
, num_kxlddeps
,
5416 (u_char
**)kxldHeaderPtr
, (kxld_addr_t
*)&kmod_info
);
5418 if (kxldResult
!= KERN_SUCCESS
) {
5419 // xxx - add kxldResult here?
5421 kOSKextLogErrorLevel
|
5423 "Can't load kext %s - link failed.",
5424 getIdentifierCString());
5425 result
= kOSKextReturnLinkError
;
5429 /* We've written data & instructions into kernel memory, so flush the data
5430 * cache and invalidate the instruction cache.
5431 * I/D caches are coherent on x86
5433 #if !defined(__i386__) && !defined(__x86_64__)
5434 flush_dcache(kmod_info
->address
, kmod_info
->size
, false);
5435 invalidate_icache(kmod_info
->address
, kmod_info
->size
, false);
5439 if (isInterface()) {
5441 /* Whip up a fake kmod_info entry for the interface kext.
5443 kmod_info
= (kmod_info_t
*)kalloc_tag(sizeof(kmod_info_t
), VM_KERN_MEMORY_OSKEXT
);
5445 result
= KERN_MEMORY_ERROR
;
5449 /* A pseudokext has almost nothing in its kmod_info struct.
5451 bzero(kmod_info
, sizeof(kmod_info_t
));
5453 kmod_info
->info_version
= KMOD_INFO_VERSION
;
5455 /* An interface kext doesn't have a linkedExecutable, so save a
5456 * copy of the UUID out of the original executable via copyUUID()
5457 * while we still have the original executable.
5459 interfaceUUID
= copyUUID();
5462 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5463 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5465 /* Stamp the bundle ID and version from the OSKext over anything
5466 * resident inside the kmod_info.
5468 string
= getIdentifierCString();
5469 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5471 string
= versCString
;
5472 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5474 /* Add the dependencies' kmod_info structs as kmod_references.
5476 num_kmod_refs
= getNumDependencies();
5477 if (num_kmod_refs
) {
5478 kmod_info
->reference_list
= (kmod_reference_t
*)kalloc_tag(
5479 num_kmod_refs
* sizeof(kmod_reference_t
), VM_KERN_MEMORY_OSKEXT
);
5480 if (!kmod_info
->reference_list
) {
5481 result
= KERN_MEMORY_ERROR
;
5484 bzero(kmod_info
->reference_list
,
5485 num_kmod_refs
* sizeof(kmod_reference_t
));
5486 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5487 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5488 OSKext
* refKext
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
));
5489 ref
->info
= refKext
->kmod_info
;
5490 ref
->info
->reference_count
++;
5492 if (refIndex
+ 1 < num_kmod_refs
) {
5493 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5498 if (!isInterface() && linkedExecutable
) {
5500 kOSKextLogProgressLevel
|
5502 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5504 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5505 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5506 (unsigned)kmod_info
->id
);
5509 /* if prelinked, VM protections are already set */
5510 result
= setVMAttributes(!isPrelinked(), true);
5511 if (result
!= KERN_SUCCESS
) {
5516 kasan_load_kext((vm_offset_t
)linkedExecutable
->getBytesNoCopy(),
5517 linkedExecutable
->getLength(), getIdentifierCString());
5519 if (lookupSection(KASAN_GLOBAL_SEGNAME
, KASAN_GLOBAL_SECTNAME
)) {
5521 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5522 "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
5523 getIdentifierCString()
5525 result
= KERN_FAILURE
;
5530 result
= kOSReturnSuccess
;
5533 OSSafeReleaseNULL(linkDependencies
);
5535 /* Clear up locally allocated dependency info.
5537 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5540 if (kxlddeps
[i
].kext_name
) {
5541 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5542 kfree(kxlddeps
[i
].kext_name
, size
);
5544 if (kxlddeps
[i
].interface_name
) {
5545 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5546 kfree(kxlddeps
[i
].interface_name
, size
);
5549 if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5551 /* We no longer need the unrelocated executable (which the linker
5552 * has altered anyhow).
5554 setExecutable(NULL
);
5556 if (result
!= kOSReturnSuccess
) {
5558 kOSKextLogErrorLevel
|
5560 "Failed to load executable for kext %s.",
5561 getIdentifierCString());
5563 if (kmod_info
&& kmod_info
->reference_list
) {
5564 kfree(kmod_info
->reference_list
,
5565 num_kmod_refs
* sizeof(kmod_reference_t
));
5567 if (isInterface()) {
5568 kfree(kmod_info
, sizeof(kmod_info_t
));
5571 if (linkedExecutable
) {
5572 linkedExecutable
->release();
5573 linkedExecutable
= NULL
;
5580 /*********************************************************************
5581 * The linkedit segment is used by the kext linker for dependency
5582 * resolution, and by dtrace for probe initialization. We can free it
5583 * for non-library kexts, since no kexts depend on non-library kexts
5584 * by definition, once dtrace has been initialized.
5585 *********************************************************************/
5587 OSKext::jettisonLinkeditSegment(void)
5589 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5590 kernel_segment_command_t
* linkedit
= NULL
;
5592 vm_size_t linkeditsize
, kextsize
;
5593 OSData
* data
= NULL
;
5596 /* We can free symbol tables for all embedded kexts because we don't
5597 * support runtime kext linking.
5599 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5601 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5606 /* Find the linkedit segment. If it's not the last segment, then freeing
5607 * it will fragment the kext into multiple VM regions, which OSKext is not
5608 * designed to handle, so we'll have to skip it.
5610 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5615 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5616 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
))
5621 /* Create a new OSData for the smaller kext object.
5623 linkeditsize
= round_page(linkedit
->vmsize
);
5624 kextsize
= kmod_info
->size
- linkeditsize
;
5625 start
= linkedit
->vmaddr
;
5627 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5632 /* Fix the kmod info and linkedExecutable.
5634 kmod_info
->size
= kextsize
;
5637 data
->setDeallocFunction(osdata_kext_free
);
5639 data
->setDeallocFunction(osdata_phys_free
);
5641 linkedExecutable
->setDeallocFunction(NULL
);
5642 linkedExecutable
->release();
5643 linkedExecutable
= data
;
5644 flags
.jettisonLinkeditSeg
= 1;
5646 /* Free the linkedit segment.
5649 kext_free(start
, linkeditsize
);
5651 ml_static_mfree(start
, linkeditsize
);
5658 /*********************************************************************
5659 * If there are whole pages that are unused betweem the last section
5660 * of the DATA segment and the end of the DATA segment then we can free
5662 *********************************************************************/
5664 OSKext::jettisonDATASegmentPadding(void)
5666 kernel_mach_header_t
* mh
;
5667 kernel_segment_command_t
* dataSeg
;
5668 kernel_section_t
* sec
, * lastSec
;
5669 vm_offset_t dataSegEnd
, lastSecEnd
;
5672 mh
= (kernel_mach_header_t
*)kmod_info
->address
;
5674 dataSeg
= getsegbynamefromheader(mh
, SEG_DATA
);
5675 if (dataSeg
== NULL
) {
5680 sec
= firstsect(dataSeg
);
5681 while (sec
!= NULL
) {
5683 sec
= nextsect(dataSeg
, sec
);
5686 if (lastSec
== NULL
) {
5690 if ((dataSeg
->vmaddr
!= round_page(dataSeg
->vmaddr
)) ||
5691 (dataSeg
->vmsize
!= round_page(dataSeg
->vmsize
))) {
5695 dataSegEnd
= dataSeg
->vmaddr
+ dataSeg
->vmsize
;
5696 lastSecEnd
= round_page(lastSec
->addr
+ lastSec
->size
);
5698 if (dataSegEnd
<= lastSecEnd
) {
5702 padSize
= dataSegEnd
- lastSecEnd
;
5704 if (padSize
>= PAGE_SIZE
) {
5706 kext_free(lastSecEnd
, padSize
);
5708 ml_static_mfree(lastSecEnd
, padSize
);
5713 /*********************************************************************
5714 *********************************************************************/
5716 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5718 if (linkedExecutable
) {
5719 panic("Attempt to set linked executable on kext "
5720 "that already has one (%s).\n",
5721 getIdentifierCString());
5723 linkedExecutable
= anExecutable
;
5724 linkedExecutable
->retain();
5729 /*********************************************************************
5730 * Go through all loaded kexts and tell them to register with dtrace.
5731 * The instance method only registers if necessary.
5732 *********************************************************************/
5735 OSKext::registerKextsWithDTrace(void)
5737 uint32_t count
= sLoadedKexts
->getCount();
5740 IORecursiveLockLock(sKextLock
);
5742 for (i
= 0; i
< count
; i
++) {
5743 OSKext
* thisKext
= NULL
; // do not release
5745 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5746 if (!thisKext
|| !thisKext
->isExecutable()) {
5750 thisKext
->registerWithDTrace();
5753 IORecursiveLockUnlock(sKextLock
);
5759 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5760 extern int (*dtrace_modunload
)(struct kmod_info
*);
5763 /*********************************************************************
5764 *********************************************************************/
5766 OSKext::registerWithDTrace(void)
5768 /* Register kext with dtrace. A dtrace_modload failure should not
5769 * prevent a kext from loading, so we ignore the return code.
5771 if (!flags
.dtraceInitialized
&& (dtrace_modload
!= NULL
)) {
5772 uint32_t modflag
= 0;
5773 OSObject
* forceInit
= getPropertyForHostArch("OSBundleForceDTraceInit");
5774 if (forceInit
== kOSBooleanTrue
) {
5775 modflag
|= KMOD_DTRACE_FORCE_INIT
;
5778 (void)(*dtrace_modload
)(kmod_info
, modflag
);
5779 flags
.dtraceInitialized
= true;
5780 jettisonLinkeditSegment();
5784 /*********************************************************************
5785 *********************************************************************/
5787 OSKext::unregisterWithDTrace(void)
5789 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5790 * prevent a kext from loading, so we ignore the return code.
5792 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
5793 (void)(*dtrace_modunload
)(kmod_info
);
5794 flags
.dtraceInitialized
= false;
5798 #endif /* CONFIG_DTRACE */
5801 /*********************************************************************
5802 * called only by loadExecutable()
5803 *********************************************************************/
5804 #if !VM_MAPPED_KEXTS
5805 #if defined(__arm__) || defined(__arm64__)
5806 static inline kern_return_t
5809 vm_map_offset_t start
,
5810 vm_map_offset_t end
,
5815 assert(map
== kernel_map
); // we can handle KEXTs arising from the PRELINK segment and no others
5816 assert(start
<= end
);
5818 return KERN_SUCCESS
; // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
5820 return KERN_SUCCESS
; // Punt set_max, as there's no mechanism to record that state
5822 return ml_static_protect(start
, end
- start
, new_prot
);
5825 static inline kern_return_t
5828 vm_map_offset_t start
,
5829 vm_map_offset_t end
,
5830 vm_prot_t access_type
,
5831 boolean_t user_wire
)
5833 #pragma unused(map,start,end,access_type,user_wire)
5834 return KERN_SUCCESS
; // No-op as PRELINK kexts are cemented into physical memory at boot
5837 #error Unrecognized architecture
5840 static inline kern_return_t
5843 vm_map_offset_t start
,
5844 vm_map_offset_t end
,
5848 if (start
== end
) { // 10538581
5849 return(KERN_SUCCESS
);
5851 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
5854 static inline kern_return_t
5857 vm_map_offset_t start
,
5858 vm_map_offset_t end
,
5859 vm_prot_t access_type
,
5860 boolean_t user_wire
)
5862 return vm_map_wire_kernel(map
, start
, end
, access_type
, VM_KERN_MEMORY_KEXT
, user_wire
);
5867 OSKext::setVMAttributes(bool protect
, bool wire
)
5869 vm_map_t kext_map
= NULL
;
5870 kernel_segment_command_t
* seg
= NULL
;
5871 vm_map_offset_t start
= 0;
5872 vm_map_offset_t end
= 0;
5873 OSReturn result
= kOSReturnError
;
5875 if (isInterface() || !declaresExecutable()) {
5876 result
= kOSReturnSuccess
;
5880 /* Get the kext's vm map */
5881 kext_map
= kext_get_vm_map(kmod_info
);
5883 result
= KERN_MEMORY_ERROR
;
5887 #if !VM_MAPPED_KEXTS
5888 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
5889 /* This is a split kext in a prelinked kernelcache; we'll let the
5890 * platform code take care of protecting it. It is already wired.
5892 /* TODO: Should this still allow protections for the first segment
5893 * to go through, in the event that we have a mix of split and
5896 result
= KERN_SUCCESS
;
5901 /* Protect the headers as read-only; they do not need to be wired */
5902 result
= (protect
) ? OSKext_protect(kext_map
, kmod_info
->address
,
5903 kmod_info
->address
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
)
5905 if (result
!= KERN_SUCCESS
) {
5909 /* Set the VM protections and wire down each of the segments */
5910 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5914 /* We build all ARM kexts, so we can ensure they are aligned */
5915 assert((seg
->vmaddr
& PAGE_MASK
) == 0);
5916 assert((seg
->vmsize
& PAGE_MASK
) == 0);
5919 start
= round_page(seg
->vmaddr
);
5920 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
5923 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
5924 if (result
!= KERN_SUCCESS
) {
5926 kOSKextLogErrorLevel
|
5928 "Kext %s failed to set maximum VM protections "
5929 "for segment %s - 0x%x.",
5930 getIdentifierCString(), seg
->segname
, (int)result
);
5934 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5935 if (result
!= KERN_SUCCESS
) {
5937 kOSKextLogErrorLevel
|
5939 "Kext %s failed to set initial VM protections "
5940 "for segment %s - 0x%x.",
5941 getIdentifierCString(), seg
->segname
, (int)result
);
5946 if (segmentShouldBeWired(seg
) && wire
) {
5947 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5948 if (result
!= KERN_SUCCESS
) {
5953 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5960 /*********************************************************************
5961 *********************************************************************/
5963 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
5965 return (sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
)));
5968 /*********************************************************************
5969 *********************************************************************/
5971 OSKext::validateKextMapping(bool startFlag
)
5973 OSReturn result
= kOSReturnError
;
5974 const char * whichOp
= startFlag
? "start" : "stop";
5975 kern_return_t kern_result
= 0;
5976 vm_map_t kext_map
= NULL
;
5977 kernel_segment_command_t
* seg
= NULL
;
5978 mach_vm_address_t address
= 0;
5979 mach_vm_size_t size
= 0;
5981 mach_msg_type_number_t count
;
5982 vm_region_submap_short_info_data_64_t info
;
5984 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
5985 bzero(&info
, sizeof(info
));
5987 // xxx - do we need a distinct OSReturn value for these or is "bad data"
5988 // xxx - sufficient?
5990 /* Verify that the kmod_info and start/stop pointers are non-NULL.
5994 kOSKextLogErrorLevel
|
5996 "Kext %s - NULL kmod_info pointer.",
5997 getIdentifierCString());
5998 result
= kOSKextReturnBadData
;
6003 address
= (mach_vm_address_t
)kmod_info
->start
;
6005 address
= (mach_vm_address_t
)kmod_info
->stop
;
6010 kOSKextLogErrorLevel
|
6012 "Kext %s - NULL module %s pointer.",
6013 getIdentifierCString(), whichOp
);
6014 result
= kOSKextReturnBadData
;
6018 kext_map
= kext_get_vm_map(kmod_info
);
6019 depth
= (kernel_map
== kext_map
) ? 1 : 2;
6021 /* Verify that the start/stop function lies within the kext's address range.
6023 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
6024 /* This will likely be how we deal with split kexts; walk the segments to
6025 * check that the function lies inside one of the segments of this kext.
6027 for (seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6029 seg
= nextsegfromheader((kernel_mach_header_t
*)kmod_info
->address
, seg
)) {
6030 if ((address
>= seg
->vmaddr
) && address
< (seg
->vmaddr
+ seg
->vmsize
)) {
6037 kOSKextLogErrorLevel
|
6039 "Kext %s module %s pointer is outside of kext range "
6040 "(%s %p - kext starts at %p).",
6041 getIdentifierCString(),
6044 (void *)VM_KERNEL_UNSLIDE(address
),
6045 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
));
6046 result
= kOSKextReturnBadData
;
6052 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
6053 kmod_info
->address
+ kmod_info
->size
<= address
)
6056 kOSKextLogErrorLevel
|
6058 "Kext %s module %s pointer is outside of kext range "
6059 "(%s %p - kext at %p-%p).",
6060 getIdentifierCString(),
6063 (void *)VM_KERNEL_UNSLIDE(address
),
6064 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
),
6065 (void *)(VM_KERNEL_UNSLIDE(kmod_info
->address
) + kmod_info
->size
));
6066 result
= kOSKextReturnBadData
;
6071 /* Only do these checks before calling the start function;
6072 * If anything goes wrong with the mapping while the kext is running,
6073 * we'll likely have panicked well before any attempt to stop the kext.
6077 /* Verify that the start/stop function is executable.
6079 kern_result
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
,
6080 (vm_region_recurse_info_t
)&info
, &count
);
6081 if (kern_result
!= KERN_SUCCESS
) {
6083 kOSKextLogErrorLevel
|
6085 "Kext %s - bad %s pointer %p.",
6086 getIdentifierCString(),
6087 whichOp
, (void *)VM_KERNEL_UNSLIDE(address
));
6088 result
= kOSKextReturnBadData
;
6093 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
6095 kOSKextLogErrorLevel
|
6097 "Kext %s - memory region containing module %s function "
6098 "is not executable.",
6099 getIdentifierCString(), whichOp
);
6100 result
= kOSKextReturnBadData
;
6105 /* Verify that the kext's segments are backed by physical memory.
6107 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6109 if (!verifySegmentMapping(seg
)) {
6110 result
= kOSKextReturnBadData
;
6114 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6119 result
= kOSReturnSuccess
;
6124 /*********************************************************************
6125 *********************************************************************/
6127 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
6129 mach_vm_address_t address
= 0;
6131 if (!segmentShouldBeWired(seg
)) return true;
6133 for (address
= seg
->vmaddr
;
6134 address
< round_page(seg
->vmaddr
+ seg
->vmsize
);
6135 address
+= PAGE_SIZE
)
6137 if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) {
6139 kOSKextLogErrorLevel
|
6141 "Kext %s - page %p is not backed by physical memory.",
6142 getIdentifierCString(),
6151 /*********************************************************************
6152 *********************************************************************/
6154 OSKextLogKextInfo(OSKext
*aKext
, uint64_t address
, uint64_t size
, firehose_tracepoint_code_t code
)
6158 firehose_tracepoint_id_u trace_id
;
6159 struct firehose_trace_uuid_info_s uuid_info_s
;
6160 firehose_trace_uuid_info_t uuid_info
= &uuid_info_s
;
6161 size_t uuid_info_len
= sizeof(struct firehose_trace_uuid_info_s
);
6164 stamp
= firehose_tracepoint_time(firehose_activity_flags_default
);
6165 trace_id
.ftid_value
= FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata
, _firehose_tracepoint_type_metadata_kext
, (firehose_tracepoint_flags_t
)0, code
);
6167 uuid_data
= aKext
->copyUUID();
6169 memcpy(uuid_info
->ftui_uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_info
->ftui_uuid
));
6170 OSSafeReleaseNULL(uuid_data
);
6173 uuid_info
->ftui_size
= size
;
6174 uuid_info
->ftui_address
= VM_KERNEL_UNSLIDE(address
);
6176 firehose_trace_metadata(firehose_stream_metadata
, trace_id
, stamp
, uuid_info
, uuid_info_len
);
6180 /*********************************************************************
6181 *********************************************************************/
6183 OSKext::start(bool startDependenciesFlag
)
6185 OSReturn result
= kOSReturnError
;
6186 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
6187 unsigned int i
, count
;
6188 void * kmodStartData
= NULL
;
6190 if (isStarted() || isInterface() || isKernelComponent()) {
6191 result
= kOSReturnSuccess
;
6197 kOSKextLogErrorLevel
|
6199 "Attempt to start nonloaded kext %s.",
6200 getIdentifierCString());
6201 result
= kOSKextReturnInvalidArgument
;
6205 if (!sLoadEnabled
) {
6207 kOSKextLogErrorLevel
|
6209 "Kext loading is disabled (attempt to start kext %s).",
6210 getIdentifierCString());
6211 result
= kOSKextReturnDisabled
;
6215 result
= validateKextMapping(/* start? */ true);
6216 if (result
!= kOSReturnSuccess
) {
6220 startfunc
= kmod_info
->start
;
6222 count
= getNumDependencies();
6223 for (i
= 0; i
< count
; i
++) {
6224 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
6225 if (dependency
== NULL
) {
6227 kOSKextLogErrorLevel
|
6229 "Kext %s start - internal error, dependency disappeared.",
6230 getIdentifierCString());
6233 if (!dependency
->isStarted()) {
6234 if (startDependenciesFlag
) {
6235 OSReturn dependencyResult
=
6236 dependency
->start(startDependenciesFlag
);
6237 if (dependencyResult
!= KERN_SUCCESS
) {
6239 kOSKextLogErrorLevel
|
6241 "Kext %s start - dependency %s failed to start (error 0x%x).",
6242 getIdentifierCString(),
6243 dependency
->getIdentifierCString(),
6249 kOSKextLogErrorLevel
|
6251 "Not starting %s - dependency %s not started yet.",
6252 getIdentifierCString(),
6253 dependency
->getIdentifierCString());
6254 result
= kOSKextReturnStartStopError
; // xxx - make new return?
6261 kOSKextLogDetailLevel
|
6263 "Kext %s calling module start function.",
6264 getIdentifierCString());
6268 // Drop a log message so logd can grab the needed information to decode this kext
6269 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_load
);
6271 #if !CONFIG_STATIC_CPPINIT
6272 result
= OSRuntimeInitializeCPP(kmod_info
, NULL
);
6273 if (result
== KERN_SUCCESS
) {
6277 kmodStartData
= GetAppleTEXTHashForKext(this, this->infoDict
);
6280 if (kmodStartData
) {
6282 kOSKextLogErrorLevel
|
6283 kOSKextLogGeneralFlag
,
6284 "Kext %s calling module start function. kmodStartData %p. arch %s",
6285 getIdentifierCString(), kmodStartData
, ARCHNAME
);
6288 #endif // CONFIG_KEC_FIPS
6289 result
= startfunc(kmod_info
, kmodStartData
);
6291 #if !CONFIG_STATIC_CPPINIT
6292 if (result
!= KERN_SUCCESS
) {
6293 (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6300 /* On success overlap the setting of started/starting. On failure just
6303 if (result
== KERN_SUCCESS
) {
6306 // xxx - log start error from kernel?
6308 kOSKextLogProgressLevel
|
6310 "Kext %s is now started.",
6311 getIdentifierCString());
6313 invokeOrCancelRequestCallbacks(
6314 /* result not actually used */ kOSKextReturnStartStopError
,
6315 /* invokeFlag */ false);
6317 kOSKextLogProgressLevel
|
6319 "Kext %s did not start (return code 0x%x).",
6320 getIdentifierCString(), result
);
6327 /*********************************************************************
6328 *********************************************************************/
6330 bool OSKext::canUnloadKextWithIdentifier(
6331 OSString
* kextIdentifier
,
6332 bool checkClassesFlag
)
6334 bool result
= false;
6335 OSKext
* aKext
= NULL
; // do not release
6337 IORecursiveLockLock(sKextLock
);
6339 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
6342 goto finish
; // can't unload what's not loaded
6345 if (aKext
->isLoaded()) {
6346 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
6349 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
6357 IORecursiveLockUnlock(sKextLock
);
6361 /*********************************************************************
6362 *********************************************************************/
6366 OSReturn result
= kOSReturnError
;
6367 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
6369 if (!isStarted() || isInterface()) {
6370 result
= kOSReturnSuccess
;
6376 kOSKextLogErrorLevel
|
6378 "Attempt to stop nonloaded kext %s.",
6379 getIdentifierCString());
6380 result
= kOSKextReturnInvalidArgument
;
6384 /* Refuse to stop if we have clients or instances. It is up to
6385 * the caller to make sure those aren't true.
6387 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6389 kOSKextLogErrorLevel
|
6391 "Kext %s - C++ instances; can't stop.",
6392 getIdentifierCString());
6393 result
= kOSKextReturnInUse
;
6397 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6400 kOSKextLogErrorLevel
|
6402 "Kext %s - has references (linkage or tracking object); "
6404 getIdentifierCString());
6405 result
= kOSKextReturnInUse
;
6409 /* Note: If validateKextMapping fails on the stop & unload path,
6410 * we are in serious trouble and a kernel panic is likely whether
6411 * we stop & unload the kext or not.
6413 result
= validateKextMapping(/* start? */ false);
6414 if (result
!= kOSReturnSuccess
) {
6418 stopfunc
= kmod_info
->stop
;
6421 kOSKextLogDetailLevel
|
6423 "Kext %s calling module stop function.",
6424 getIdentifierCString());
6428 result
= stopfunc(kmod_info
, /* userData */ NULL
);
6429 #if !CONFIG_STATIC_CPPINIT
6430 if (result
== KERN_SUCCESS
) {
6431 result
= OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6437 if (result
== KERN_SUCCESS
) {
6441 kOSKextLogDetailLevel
|
6443 "Kext %s is now stopped and ready to unload.",
6444 getIdentifierCString());
6447 kOSKextLogErrorLevel
|
6449 "Kext %s did not stop (return code 0x%x).",
6450 getIdentifierCString(), result
);
6451 result
= kOSKextReturnStartStopError
;
6456 // Drop a log message so logd can update this kext's metadata
6457 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_unload
);
6461 /*********************************************************************
6462 *********************************************************************/
6464 OSKext::unload(void)
6466 OSReturn result
= kOSReturnError
;
6468 uint32_t num_kmod_refs
= 0;
6469 OSKextAccount
* freeAccount
;
6471 if (!sUnloadEnabled
) {
6473 kOSKextLogErrorLevel
|
6475 "Kext unloading is disabled (%s).",
6476 this->getIdentifierCString());
6478 result
= kOSKextReturnDisabled
;
6482 /* Refuse to unload if we have clients or instances. It is up to
6483 * the caller to make sure those aren't true.
6485 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6486 // xxx - Don't log under errors? this is more of an info thing
6488 kOSKextLogErrorLevel
|
6489 kOSKextLogKextBookkeepingFlag
,
6490 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6491 getIdentifierCString());
6492 result
= kOSKextReturnInUse
;
6497 result
= kOSReturnSuccess
;
6501 if (isKernelComponent()) {
6502 result
= kOSKextReturnInvalidArgument
;
6506 if (metaClasses
&& !OSMetaClass::removeClasses(metaClasses
)) {
6508 kOSKextLogErrorLevel
|
6509 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6510 "Can't unload kext %s; classes have instances:",
6511 getIdentifierCString());
6512 reportOSMetaClassInstances(kOSKextLogErrorLevel
|
6513 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
);
6514 result
= kOSKextReturnInUse
;
6518 /* Note that the kext is unloading before running any code that
6519 * might be in the kext (request callbacks, module stop function).
6520 * We will deny certain requests made against a kext in the process
6523 flags
.unloading
= 1;
6525 /* Update the string describing the last kext to unload in case we panic.
6527 savePanicString(/* isLoading */ false);
6531 if (result
!= KERN_SUCCESS
) {
6533 kOSKextLogErrorLevel
|
6535 "Kext %s can't unload - module stop returned 0x%x.",
6536 getIdentifierCString(), (unsigned)result
);
6537 result
= kOSKextReturnStartStopError
;
6543 kOSKextLogProgressLevel
|
6545 "Kext %s unloading.",
6546 getIdentifierCString());
6549 struct list_head
*p
;
6550 struct list_head
*prev
;
6551 struct list_head
*next
;
6552 for (p
= pendingPgoHead
.next
; p
!= &pendingPgoHead
; p
= next
) {
6553 OSKextGrabPgoStruct
*s
= container_of(p
, OSKextGrabPgoStruct
, list_head
);
6554 s
->err
= OSKextGrabPgoDataLocked(this, s
->metadata
, instance_uuid
, s
->pSize
, s
->pBuffer
, s
->bufferSize
);
6561 IORecursiveLockWakeup(sKextLock
, s
, false);
6566 /* Even if we don't call the stop function, we want to be sure we
6567 * have no OSMetaClass references before unloading the kext executable
6568 * from memory. OSMetaClasses may have pointers into the kext executable
6569 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6572 metaClasses
->flushCollection();
6575 /* Remove the kext from the list of loaded kexts, patch the gap
6576 * in the kmod_info_t linked list, and reset "kmod" to point to the
6577 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6579 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
6580 if (index
!= (unsigned int)-1) {
6582 sLoadedKexts
->removeObject(index
);
6584 OSKext
* nextKext
= OSDynamicCast(OSKext
,
6585 sLoadedKexts
->getObject(index
));
6589 OSKext
* gapKext
= OSDynamicCast(OSKext
,
6590 sLoadedKexts
->getObject(index
- 1));
6592 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
6594 } else /* index == 0 */ {
6595 nextKext
->kmod_info
->next
= NULL
;
6599 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
6600 if (lastKext
&& !lastKext
->isKernel()) {
6601 kmod
= lastKext
->kmod_info
;
6603 kmod
= NULL
; // clear the global kmod variable
6607 /* Clear out the kmod references that we're keeping for compatibility
6608 * with current panic backtrace code & kgmacros.
6609 * xxx - will want to update those bits sometime and remove this.
6611 num_kmod_refs
= getNumDependencies();
6612 if (num_kmod_refs
&& kmod_info
&& kmod_info
->reference_list
) {
6613 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
6614 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
6615 ref
->info
->reference_count
--;
6617 kfree(kmod_info
->reference_list
,
6618 num_kmod_refs
* sizeof(kmod_reference_t
));
6622 unregisterWithDTrace();
6623 #endif /* CONFIG_DTRACE */
6625 notifyKextUnloadObservers(this);
6628 IOSimpleLockLock(sKextAccountsLock
);
6629 account
->kext
= NULL
;
6630 if (account
->site
.tag
) account
->site
.flags
|= VM_TAG_UNLOAD
;
6631 else freeAccount
= account
;
6632 IOSimpleLockUnlock(sKextAccountsLock
);
6633 if (freeAccount
) IODelete(freeAccount
, OSKextAccount
, 1);
6635 /* Unwire and free the linked executable.
6637 if (linkedExecutable
) {
6639 kasan_unload_kext((vm_offset_t
)linkedExecutable
->getBytesNoCopy(), linkedExecutable
->getLength());
6643 if (!isInterface()) {
6644 kernel_segment_command_t
*seg
= NULL
;
6645 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6649 kOSKextLogErrorLevel
|
6651 "Failed to free kext %s; couldn't find the kext map.",
6652 getIdentifierCString());
6653 result
= kOSKextReturnInternalError
;
6658 kOSKextLogProgressLevel
|
6660 "Kext %s unwiring and unmapping linked executable.",
6661 getIdentifierCString());
6663 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6665 if (segmentShouldBeWired(seg
)) {
6666 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6667 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6668 if (result
!= KERN_SUCCESS
) {
6670 kOSKextLogErrorLevel
|
6672 "Failed to unwire kext %s.",
6673 getIdentifierCString());
6674 result
= kOSKextReturnInternalError
;
6679 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6683 OSSafeReleaseNULL(linkedExecutable
);
6686 /* An interface kext has a fake kmod_info that was allocated,
6687 * so we have to free it.
6689 if (isInterface()) {
6690 kfree(kmod_info
, sizeof(kmod_info_t
));
6695 flags
.loaded
= false;
6696 flushDependencies();
6698 /* save a copy of the bundle ID for us to check when deciding to
6699 * rebuild the kernel cache file. If a kext was already in the kernel
6700 * cache and unloaded then later loaded we do not need to rebuild the
6701 * kernel cache. 9055303
6703 if (isPrelinked()) {
6704 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6705 IORecursiveLockLock(sKextLock
);
6706 if (sUnloadedPrelinkedKexts
) {
6707 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6709 IORecursiveLockUnlock(sKextLock
);
6714 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6715 "Kext %s unloaded.", getIdentifierCString());
6717 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6718 OSDynamicCast(OSString
, bundleID
));
6721 OSKext::saveLoadedKextPanicList();
6722 OSKext::updateLoadedKextSummaries();
6724 flags
.unloading
= 0;
6728 /*********************************************************************
6729 * Assumes sKextLock is held.
6730 *********************************************************************/
6733 OSKext::queueKextNotification(
6734 const char * notificationName
,
6735 OSString
* kextIdentifier
)
6737 OSReturn result
= kOSReturnError
;
6738 OSDictionary
* loadRequest
= NULL
; // must release
6740 if (!kextIdentifier
) {
6741 result
= kOSKextReturnInvalidArgument
;
6745 /* Create a new request unless one is already sitting
6746 * in sKernelRequests for this bundle identifier
6748 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6749 if (result
!= kOSReturnSuccess
) {
6752 if (!_OSKextSetRequestArgument(loadRequest
,
6753 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6755 result
= kOSKextReturnNoMemory
;
6758 if (!sKernelRequests
->setObject(loadRequest
)) {
6759 result
= kOSKextReturnNoMemory
;
6763 /* We might want to only queue the notification if kextd is active,
6764 * but that wouldn't work for embedded. Note that we don't care if
6765 * the ping immediately succeeds here so don't do anything with the
6766 * result of this call.
6768 OSKext::pingKextd();
6770 result
= kOSReturnSuccess
;
6773 OSSafeReleaseNULL(loadRequest
);
6778 /*********************************************************************
6779 *********************************************************************/
6781 _OSKextConsiderDestroyingLinkContext(
6782 __unused thread_call_param_t p0
,
6783 __unused thread_call_param_t p1
)
6785 /* Take multiple locks in the correct order.
6787 IORecursiveLockLock(sKextLock
);
6788 IORecursiveLockLock(sKextInnerLock
);
6790 /* The first time we destroy the kxldContext is in the first
6791 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6792 * before calling this function. Thereafter any call to this function
6793 * will actually destroy the context.
6795 if (sConsiderUnloadsCalled
&& sKxldContext
) {
6796 kxld_destroy_context(sKxldContext
);
6797 sKxldContext
= NULL
;
6800 /* Free the thread_call that was allocated to execute this function.
6802 if (sDestroyLinkContextThread
) {
6803 if (!thread_call_free(sDestroyLinkContextThread
)) {
6804 OSKextLog(/* kext */ NULL
,
6805 kOSKextLogErrorLevel
|
6806 kOSKextLogGeneralFlag
,
6807 "thread_call_free() failed for kext link context.");
6809 sDestroyLinkContextThread
= 0;
6812 IORecursiveLockUnlock(sKextInnerLock
);
6813 IORecursiveLockUnlock(sKextLock
);
6818 /*********************************************************************
6819 * Destroying the kxldContext requires checking variables under both
6820 * sKextInnerLock and sKextLock, so we do it on a separate thread
6821 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6822 * call relationship.
6824 * This function must be invoked with sKextInnerLock held.
6825 * Do not call any function that takes sKextLock here!
6826 *********************************************************************/
6829 OSKext::considerDestroyingLinkContext(void)
6831 IORecursiveLockLock(sKextInnerLock
);
6833 /* If we have already queued a thread to destroy the link context,
6834 * don't bother resetting; that thread will take care of it.
6836 if (sDestroyLinkContextThread
) {
6840 /* The function to be invoked in the thread will deallocate
6841 * this thread_call, so don't share it around.
6843 sDestroyLinkContextThread
= thread_call_allocate(
6844 &_OSKextConsiderDestroyingLinkContext
, 0);
6845 if (!sDestroyLinkContextThread
) {
6846 OSKextLog(/* kext */ NULL
,
6847 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
| kOSKextLogLinkFlag
,
6848 "Can't create thread to destroy kext link context.");
6852 thread_call_enter(sDestroyLinkContextThread
);
6855 IORecursiveLockUnlock(sKextInnerLock
);
6860 #pragma mark Autounload
6862 /*********************************************************************
6863 * This is a static method because the kext will be deallocated if it
6865 *********************************************************************/
6868 OSKext::autounloadKext(OSKext
* aKext
)
6870 OSReturn result
= kOSKextReturnInUse
;
6872 /* Check for external references to this kext (usu. dependents),
6873 * instances of defined classes (or classes derived from them),
6874 * outstanding requests.
6876 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
6877 !aKext
->flags
.autounloadEnabled
||
6878 aKext
->isKernelComponent()) {
6883 /* Skip a delay-autounload kext, once.
6885 if (aKext
->flags
.delayAutounload
) {
6887 kOSKextLogProgressLevel
|
6888 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6889 "Kext %s has delayed autounload set; skipping and clearing flag.",
6890 aKext
->getIdentifierCString());
6891 aKext
->flags
.delayAutounload
= 0;
6895 if (aKext
->hasOSMetaClassInstances() ||
6896 aKext
->countRequestCallbacks()) {
6900 result
= OSKext::removeKext(aKext
);
6906 /*********************************************************************
6907 *********************************************************************/
6909 _OSKextConsiderUnloads(
6910 __unused thread_call_param_t p0
,
6911 __unused thread_call_param_t p1
)
6913 bool didUnload
= false;
6914 unsigned int count
, i
;
6916 /* Take multiple locks in the correct order
6917 * (note also sKextSummaries lock further down).
6919 IORecursiveLockLock(sKextLock
);
6920 IORecursiveLockLock(sKextInnerLock
);
6922 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6924 /* If the system is powering down, don't try to unload anything.
6930 OSKextLog(/* kext */ NULL
,
6931 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6932 "Checking for unused kexts to autounload.");
6935 * Remove any request callbacks marked as stale,
6936 * and mark as stale any currently in flight.
6938 count
= sRequestCallbackRecords
->getCount();
6942 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
6943 sRequestCallbackRecords
->getObject(i
));
6944 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
6945 callbackRecord
->getObject(kKextRequestStaleKey
));
6947 if (stale
== kOSBooleanTrue
) {
6948 OSKext::invokeRequestCallback(callbackRecord
,
6949 kOSKextReturnTimeout
);
6951 callbackRecord
->setObject(kKextRequestStaleKey
,
6958 * Make multiple passes through the array of loaded kexts until
6959 * we don't unload any. This handles unwinding of dependency
6960 * chains. We have to go *backwards* through the array because
6961 * kexts are removed from it when unloaded, and we cannot make
6962 * a copy or we'll mess up the retain counts we rely on to
6963 * check whether a kext will unload. If only we could have
6964 * nonretaining collections like CF has....
6969 count
= sLoadedKexts
->getCount();
6973 OSKext
* thisKext
= OSDynamicCast(OSKext
,
6974 sLoadedKexts
->getObject(i
));
6975 didUnload
|= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
6978 } while (didUnload
);
6981 sConsiderUnloadsPending
= false;
6982 sConsiderUnloadsExecuted
= true;
6984 (void) OSKext::considerRebuildOfPrelinkedKernel();
6986 IORecursiveLockUnlock(sKextInnerLock
);
6987 IORecursiveLockUnlock(sKextLock
);
6992 /*********************************************************************
6993 * Do not call any function that takes sKextLock here!
6994 *********************************************************************/
6995 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
6999 IORecursiveLockLock(sKextInnerLock
);
7001 if (!sUnloadCallout
) {
7002 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, 0);
7005 /* we only reset delay value for unloading if we already have something
7006 * pending. rescheduleOnlyFlag should not start the count down.
7008 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
7012 thread_call_cancel(sUnloadCallout
);
7013 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
7014 clock_interval_to_deadline(sConsiderUnloadDelay
,
7015 1000 * 1000 * 1000, &when
);
7017 OSKextLog(/* kext */ NULL
,
7018 kOSKextLogProgressLevel
|
7020 "%scheduling %sscan for unused kexts in %lu seconds.",
7021 sConsiderUnloadsPending
? "Res" : "S",
7022 sConsiderUnloadsCalled
? "" : "initial ",
7023 (unsigned long)sConsiderUnloadDelay
);
7025 sConsiderUnloadsPending
= true;
7026 thread_call_enter_delayed(sUnloadCallout
, when
);
7030 /* The kxld context should be reused throughout boot. We mark the end of
7031 * period as the first time considerUnloads() is called, and we destroy
7032 * the first kxld context in that function. Afterwards, it will be
7033 * destroyed in flushNonloadedKexts.
7035 if (!sConsiderUnloadsCalled
) {
7036 sConsiderUnloadsCalled
= true;
7037 OSKext::considerDestroyingLinkContext();
7040 IORecursiveLockUnlock(sKextInnerLock
);
7044 /*********************************************************************
7045 * Do not call any function that takes sKextLock here!
7046 *********************************************************************/
7049 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
);
7050 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
)
7052 IORecursiveLockLock(sKextInnerLock
);
7054 /* If the system is going to sleep, cancel the reaper thread timer,
7055 * and note that we're in a sleep state in case it just fired but hasn't
7056 * taken the lock yet. If we are coming back from sleep, just
7057 * clear the sleep flag; IOService's normal operation will cause
7058 * unloads to be considered soon enough.
7060 if (messageType
== kIOMessageSystemWillSleep
) {
7061 if (sUnloadCallout
) {
7062 thread_call_cancel(sUnloadCallout
);
7064 sSystemSleep
= true;
7065 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
7066 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
7067 sSystemSleep
= false;
7068 clock_get_uptime(&sLastWakeTime
);
7070 IORecursiveLockUnlock(sKextInnerLock
);
7072 return kIOReturnSuccess
;
7079 #pragma mark Prelinked Kernel
7081 /*********************************************************************
7082 * Do not access sConsiderUnloads... variables other than
7083 * sConsiderUnloadsExecuted in this function. They are guarded by a
7085 *********************************************************************/
7088 OSKext::considerRebuildOfPrelinkedKernel(void)
7090 static bool requestedPrelink
= false;
7091 OSReturn checkResult
= kOSReturnError
;
7092 OSDictionary
* prelinkRequest
= NULL
; // must release
7093 OSCollectionIterator
* kextIterator
= NULL
; // must release
7094 const OSSymbol
* thisID
= NULL
; // do not release
7095 bool doRebuild
= false;
7096 AbsoluteTime my_abstime
;
7100 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
7101 if (requestedPrelink
|| !sPrelinkBoot
) {
7105 /* no direct return from this point */
7106 IORecursiveLockLock(sKextLock
);
7108 /* We need to wait for kextd to get up and running with unloads already done
7109 * and any new startup kexts loaded.
7111 if (!sConsiderUnloadsExecuted
||
7112 !sDeferredLoadSucceeded
) {
7116 /* we really only care about boot / system start up related kexts so bail
7117 * if we're here after REBUILD_MAX_TIME.
7119 if (!_OSKextInPrelinkRebuildWindow()) {
7120 OSKextLog(/* kext */ NULL
,
7121 kOSKextLogArchiveFlag
,
7122 "%s prebuild rebuild has expired",
7124 requestedPrelink
= true;
7128 /* we do not want to trigger a rebuild if we get here too close to waking
7129 * up. (see radar 10233768)
7131 IORecursiveLockLock(sKextInnerLock
);
7133 clock_get_uptime(&my_abstime
);
7134 delta_secs
= MINIMUM_WAKEUP_SECONDS
+ 1;
7135 if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) {
7136 SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
);
7137 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
7138 delta_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
7140 IORecursiveLockUnlock(sKextInnerLock
);
7142 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
7143 /* too close to time of last wake from sleep */
7146 requestedPrelink
= true;
7148 /* Now it's time to see if we have a reason to rebuild. We may have done
7149 * some loads and unloads but the kernel cache didn't actually change.
7150 * We will rebuild if any kext is not marked prelinked AND is not in our
7151 * list of prelinked kexts that got unloaded. (see radar 9055303)
7153 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
7154 if (!kextIterator
) {
7158 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
7159 OSKext
* thisKext
; // do not release
7161 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
7162 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
7166 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
7169 /* kext is loaded and was not in current kernel cache so let's rebuild
7172 OSKextLog(/* kext */ NULL
,
7173 kOSKextLogArchiveFlag
,
7174 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
7175 thisKext
->bundleID
->getCStringNoCopy());
7178 sUnloadedPrelinkedKexts
->flushCollection();
7184 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
7186 if (checkResult
!= kOSReturnSuccess
) {
7190 if (!sKernelRequests
->setObject(prelinkRequest
)) {
7194 OSKext::pingKextd();
7197 IORecursiveLockUnlock(sKextLock
);
7198 OSSafeReleaseNULL(prelinkRequest
);
7199 OSSafeReleaseNULL(kextIterator
);
7205 #pragma mark Dependencies
7207 /*********************************************************************
7208 *********************************************************************/
7210 OSKext::resolveDependencies(
7211 OSArray
* loopStack
)
7213 bool result
= false;
7214 OSArray
* localLoopStack
= NULL
; // must release
7215 bool addedToLoopStack
= false;
7216 OSDictionary
* libraries
= NULL
; // do not release
7217 OSCollectionIterator
* libraryIterator
= NULL
; // must release
7218 OSString
* libraryID
= NULL
; // do not release
7219 OSString
* infoString
= NULL
; // do not release
7220 OSString
* readableString
= NULL
; // do not release
7221 OSKext
* libraryKext
= NULL
; // do not release
7222 bool hasRawKernelDependency
= false;
7223 bool hasKernelDependency
= false;
7224 bool hasKPIDependency
= false;
7225 bool hasPrivateKPIDependency
= false;
7228 /* A kernel component will automatically have this flag set,
7229 * and a loaded kext should also have it set (as should all its
7230 * loaded dependencies).
7232 if (flags
.hasAllDependencies
) {
7237 /* Check for loops in the dependency graph.
7240 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
7242 kOSKextLogErrorLevel
|
7243 kOSKextLogDependenciesFlag
,
7244 "Kext %s has a dependency loop; can't resolve dependencies.",
7245 getIdentifierCString());
7250 kOSKextLogStepLevel
|
7251 kOSKextLogDependenciesFlag
,
7252 "Kext %s resolving dependencies.",
7253 getIdentifierCString());
7255 loopStack
= OSArray::withCapacity(6); // any small capacity will do
7258 kOSKextLogErrorLevel
|
7259 kOSKextLogDependenciesFlag
,
7260 "Kext %s can't create bookkeeping stack to resolve dependencies.",
7261 getIdentifierCString());
7264 localLoopStack
= loopStack
;
7266 if (!loopStack
->setObject(this)) {
7268 kOSKextLogErrorLevel
|
7269 kOSKextLogDependenciesFlag
,
7270 "Kext %s - internal error resolving dependencies.",
7271 getIdentifierCString());
7274 addedToLoopStack
= true;
7276 /* Purge any existing kexts in the dependency list and start over.
7278 flushDependencies();
7281 kOSKextLogErrorLevel
|
7282 kOSKextLogDependenciesFlag
,
7283 "Kext %s - internal error resolving dependencies.",
7284 getIdentifierCString());
7287 libraries
= OSDynamicCast(OSDictionary
,
7288 getPropertyForHostArch(kOSBundleLibrariesKey
));
7289 if (libraries
== NULL
|| libraries
->getCount() == 0) {
7291 kOSKextLogErrorLevel
|
7292 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7293 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7294 getIdentifierCString(), kOSBundleLibrariesKey
);
7298 /* Make a new array to hold the dependencies (flush freed the old one).
7300 dependencies
= OSArray::withCapacity(libraries
->getCount());
7301 if (!dependencies
) {
7303 kOSKextLogErrorLevel
|
7304 kOSKextLogDependenciesFlag
,
7305 "Kext %s - can't allocate dependencies array.",
7306 getIdentifierCString());
7310 // xxx - compat: We used to add an implicit dependency on kernel 6.0
7311 // xxx - compat: if none were declared.
7313 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
7314 if (!libraryIterator
) {
7316 kOSKextLogErrorLevel
|
7317 kOSKextLogDependenciesFlag
,
7318 "Kext %s - can't allocate dependencies iterator.",
7319 getIdentifierCString());
7323 while ((libraryID
= OSDynamicCast(OSString
,
7324 libraryIterator
->getNextObject()))) {
7326 const char * library_id
= libraryID
->getCStringNoCopy();
7328 OSString
* libraryVersion
= OSDynamicCast(OSString
,
7329 libraries
->getObject(libraryID
));
7330 if (libraryVersion
== NULL
) {
7332 kOSKextLogErrorLevel
|
7333 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7334 "Kext %s - illegal type in OSBundleLibraries.",
7335 getIdentifierCString());
7339 OSKextVersion libraryVers
=
7340 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
7341 if (libraryVers
== -1) {
7343 kOSKextLogErrorLevel
|
7344 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7345 "Kext %s - invalid library version %s.",
7346 getIdentifierCString(),
7347 libraryVersion
->getCStringNoCopy());
7351 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
7352 if (libraryKext
== NULL
) {
7354 kOSKextLogErrorLevel
|
7355 kOSKextLogDependenciesFlag
,
7356 "Kext %s - library kext %s not found.",
7357 getIdentifierCString(), library_id
);
7361 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
7363 kOSKextLogErrorLevel
|
7364 kOSKextLogDependenciesFlag
,
7365 "Kext %s - library kext %s not compatible "
7366 "with requested version %s.",
7367 getIdentifierCString(), library_id
,
7368 libraryVersion
->getCStringNoCopy());
7372 /* If a nonprelinked library somehow got into the mix for a
7373 * prelinked kext, at any point in the chain, we must fail
7374 * because the prelinked relocs for the library will be all wrong.
7376 if (this->isPrelinked() &&
7377 libraryKext
->declaresExecutable() &&
7378 !libraryKext
->isPrelinked()) {
7381 kOSKextLogErrorLevel
|
7382 kOSKextLogDependenciesFlag
,
7383 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7384 getIdentifierCString(), library_id
,
7385 libraryVersion
->getCStringNoCopy());
7389 if (!libraryKext
->resolveDependencies(loopStack
)) {
7393 /* Add the library directly only if it has an executable to link.
7394 * Otherwise it's just used to collect other dependencies, so put
7395 * *its* dependencies on the list for this kext.
7397 // xxx - We are losing info here; would like to make fake entries or
7398 // xxx - keep these in the dependency graph for loaded kexts.
7399 // xxx - I really want to make kernel components not a special case!
7400 if (libraryKext
->declaresExecutable() ||
7401 libraryKext
->isInterface()) {
7403 if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) {
7404 dependencies
->setObject(libraryKext
);
7407 kOSKextLogDetailLevel
|
7408 kOSKextLogDependenciesFlag
,
7409 "Kext %s added dependency %s.",
7410 getIdentifierCString(),
7411 libraryKext
->getIdentifierCString());
7414 int numLibDependencies
= libraryKext
->getNumDependencies();
7415 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
7418 if (numLibDependencies
) {
7419 // xxx - this msg level should be 1 lower than the per-kext one
7421 kOSKextLogDetailLevel
|
7422 kOSKextLogDependenciesFlag
,
7423 "Kext %s pulling %d dependencies from codeless library %s.",
7424 getIdentifierCString(),
7426 libraryKext
->getIdentifierCString());
7428 for (index
= 0; index
< numLibDependencies
; index
++) {
7429 OSKext
* thisLibDependency
= OSDynamicCast(OSKext
,
7430 libraryDependencies
->getObject(index
));
7431 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) {
7432 dependencies
->setObject(thisLibDependency
);
7434 kOSKextLogDetailLevel
|
7435 kOSKextLogDependenciesFlag
,
7436 "Kext %s added dependency %s from codeless library %s.",
7437 getIdentifierCString(),
7438 thisLibDependency
->getIdentifierCString(),
7439 libraryKext
->getIdentifierCString());
7444 if ((strlen(library_id
) == strlen(KERNEL_LIB
)) &&
7445 0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) {
7447 hasRawKernelDependency
= true;
7448 } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) {
7449 hasKernelDependency
= true;
7450 } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) {
7451 hasKPIDependency
= true;
7452 if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) {
7453 hasPrivateKPIDependency
= true;
7458 if (hasRawKernelDependency
) {
7460 kOSKextLogErrorLevel
|
7461 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7462 "Error - kext %s declares a dependency on %s, which is not permitted.",
7463 getIdentifierCString(), KERNEL_LIB
);
7467 if (hasKernelDependency
) {
7469 kOSKextLogErrorLevel
|
7470 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7471 "Error - kext %s declares %s dependencies. "
7472 "Only %s* dependencies are supported for 64-bit kexts.",
7473 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7476 if (!hasKPIDependency
) {
7478 kOSKextLogWarningLevel
|
7479 kOSKextLogDependenciesFlag
,
7480 "Warning - kext %s declares no %s* dependencies. "
7481 "If it uses any KPIs, the link may fail with undefined symbols.",
7482 getIdentifierCString(), KPI_LIB_PREFIX
);
7484 #else /* __LP64__ */
7485 // xxx - will change to flatly disallow "kernel" dependencies at some point
7486 // xxx - is it invalid to do both "com.apple.kernel" and any
7487 // xxx - "com.apple.kernel.*"?
7489 if (hasKernelDependency
&& hasKPIDependency
) {
7491 kOSKextLogWarningLevel
|
7492 kOSKextLogDependenciesFlag
,
7493 "Warning - kext %s has immediate dependencies on both "
7494 "%s* and %s* components; use only one style.",
7495 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7498 if (!hasKernelDependency
&& !hasKPIDependency
) {
7499 // xxx - do we want to use validation flag for these too?
7501 kOSKextLogWarningLevel
|
7502 kOSKextLogDependenciesFlag
,
7503 "Warning - %s declares no kernel dependencies; using %s.",
7504 getIdentifierCString(), KERNEL6_LIB
);
7505 OSKext
* kernelKext
= OSDynamicCast(OSKext
,
7506 sKextsByID
->getObject(KERNEL6_LIB
));
7508 dependencies
->setObject(kernelKext
);
7511 kOSKextLogErrorLevel
|
7512 kOSKextLogDependenciesFlag
,
7513 "Error - Library %s not found for %s.",
7514 KERNEL6_LIB
, getIdentifierCString());
7518 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7519 * its indirect dependencies to simulate old-style linking. XXX - Should
7520 * check for duplicates.
7522 if (!hasKPIDependency
) {
7525 flags
.hasBleedthrough
= true;
7527 count
= getNumDependencies();
7529 /* We add to the dependencies array in this loop, but do not iterate
7530 * past its original count.
7532 for (i
= 0; i
< count
; i
++) {
7533 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
7534 dependencies
->getObject(i
));
7535 dependencyKext
->addBleedthroughDependencies(dependencies
);
7538 #endif /* __LP64__ */
7540 if (hasPrivateKPIDependency
) {
7541 bool hasApplePrefix
= false;
7542 bool infoCopyrightIsValid
= false;
7543 bool readableCopyrightIsValid
= false;
7545 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
7548 infoString
= OSDynamicCast(OSString
,
7549 getPropertyForHostArch("CFBundleGetInfoString"));
7551 infoCopyrightIsValid
=
7552 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
7555 readableString
= OSDynamicCast(OSString
,
7556 getPropertyForHostArch("NSHumanReadableCopyright"));
7557 if (readableString
) {
7558 readableCopyrightIsValid
=
7559 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
7562 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
7564 kOSKextLogErrorLevel
|
7565 kOSKextLogDependenciesFlag
,
7566 "Error - kext %s declares a dependency on %s. "
7567 "Only Apple kexts may declare a dependency on %s.",
7568 getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
);
7574 flags
.hasAllDependencies
= 1;
7578 if (addedToLoopStack
) {
7579 count
= loopStack
->getCount();
7580 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
7581 loopStack
->removeObject(count
- 1);
7584 kOSKextLogErrorLevel
|
7585 kOSKextLogDependenciesFlag
,
7586 "Kext %s - internal error resolving dependencies.",
7587 getIdentifierCString());
7591 if (result
&& localLoopStack
) {
7593 kOSKextLogStepLevel
|
7594 kOSKextLogDependenciesFlag
,
7595 "Kext %s successfully resolved dependencies.",
7596 getIdentifierCString());
7599 OSSafeReleaseNULL(localLoopStack
);
7600 OSSafeReleaseNULL(libraryIterator
);
7605 /*********************************************************************
7606 *********************************************************************/
7608 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
7610 bool result
= false;
7611 unsigned int dependencyIndex
, dependencyCount
;
7613 dependencyCount
= getNumDependencies();
7615 for (dependencyIndex
= 0;
7616 dependencyIndex
< dependencyCount
;
7617 dependencyIndex
++) {
7619 OSKext
* dependency
= OSDynamicCast(OSKext
,
7620 dependencies
->getObject(dependencyIndex
));
7623 kOSKextLogErrorLevel
|
7624 kOSKextLogDependenciesFlag
,
7625 "Kext %s - internal error propagating compatibility dependencies.",
7626 getIdentifierCString());
7629 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7630 anArray
->setObject(dependency
);
7632 dependency
->addBleedthroughDependencies(anArray
);
7641 /*********************************************************************
7642 *********************************************************************/
7644 OSKext::flushDependencies(bool forceFlag
)
7646 bool result
= false;
7648 /* Only clear the dependencies if the kext isn't loaded;
7649 * we need the info for loaded kexts to track references.
7651 if (!isLoaded() || forceFlag
) {
7653 // xxx - check level
7655 kOSKextLogProgressLevel
|
7656 kOSKextLogDependenciesFlag
,
7657 "Kext %s flushing dependencies.",
7658 getIdentifierCString());
7659 OSSafeReleaseNULL(dependencies
);
7662 if (!isKernelComponent()) {
7663 flags
.hasAllDependencies
= 0;
7671 /*********************************************************************
7672 *********************************************************************/
7674 OSKext::getNumDependencies(void)
7676 if (!dependencies
) {
7679 return dependencies
->getCount();
7682 /*********************************************************************
7683 *********************************************************************/
7685 OSKext::getDependencies(void)
7687 return dependencies
;
7691 #pragma mark OSMetaClass Support
7693 /*********************************************************************
7694 *********************************************************************/
7697 OSMetaClass
* aClass
,
7698 uint32_t numClasses
)
7700 OSReturn result
= kOSMetaClassNoInsKModSet
;
7703 metaClasses
= OSSet::withCapacity(numClasses
);
7709 if (metaClasses
->containsObject(aClass
)) {
7711 kOSKextLogWarningLevel
|
7713 "Notice - kext %s has already registered class %s.",
7714 getIdentifierCString(),
7715 aClass
->getClassName());
7716 result
= kOSReturnSuccess
;
7720 if (!metaClasses
->setObject(aClass
)) {
7724 kOSKextLogDetailLevel
|
7726 "Kext %s registered class %s.",
7727 getIdentifierCString(),
7728 aClass
->getClassName());
7731 if (!flags
.autounloadEnabled
) {
7732 const OSMetaClass
* metaScan
= NULL
; // do not release
7734 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7735 if (metaScan
== OSTypeID(IOService
)) {
7738 kOSKextLogProgressLevel
|
7740 "Kext %s has IOService subclass %s; enabling autounload.",
7741 getIdentifierCString(),
7742 aClass
->getClassName());
7744 flags
.autounloadEnabled
= 1;
7750 notifyAddClassObservers(this, aClass
, flags
);
7752 result
= kOSReturnSuccess
;
7755 if (result
!= kOSReturnSuccess
) {
7757 kOSKextLogErrorLevel
|
7759 "Kext %s failed to register class %s.",
7760 getIdentifierCString(),
7761 aClass
->getClassName());
7767 /*********************************************************************
7768 *********************************************************************/
7770 OSKext::removeClass(
7771 OSMetaClass
* aClass
)
7773 OSReturn result
= kOSMetaClassNoKModSet
;
7779 if (!metaClasses
->containsObject(aClass
)) {
7781 kOSKextLogWarningLevel
|
7783 "Notice - kext %s asked to unregister unknown class %s.",
7784 getIdentifierCString(),
7785 aClass
->getClassName());
7786 result
= kOSReturnSuccess
;
7791 kOSKextLogDetailLevel
|
7793 "Kext %s unregistering class %s.",
7794 getIdentifierCString(),
7795 aClass
->getClassName());
7797 metaClasses
->removeObject(aClass
);
7799 notifyRemoveClassObservers(this, aClass
, flags
);
7801 result
= kOSReturnSuccess
;
7804 if (result
!= kOSReturnSuccess
) {
7806 kOSKextLogErrorLevel
|
7808 "Failed to unregister kext %s class %s.",
7809 getIdentifierCString(),
7810 aClass
->getClassName());
7815 /*********************************************************************
7816 *********************************************************************/
7818 OSKext::getMetaClasses(void)
7823 /*********************************************************************
7824 *********************************************************************/
7826 OSKext::hasOSMetaClassInstances(void)
7828 bool result
= false;
7829 OSCollectionIterator
* classIterator
= NULL
; // must release
7830 OSMetaClass
* checkClass
= NULL
; // do not release
7836 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7837 if (!classIterator
) {
7838 // xxx - log alloc failure?
7841 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7842 if (checkClass
->getInstanceCount()) {
7850 OSSafeReleaseNULL(classIterator
);
7854 /*********************************************************************
7855 *********************************************************************/
7858 OSKext::reportOSMetaClassInstances(
7859 const char * kextIdentifier
,
7860 OSKextLogSpec msgLogSpec
)
7862 OSKext
* theKext
= NULL
; // must release
7864 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
7869 theKext
->reportOSMetaClassInstances(msgLogSpec
);
7871 OSSafeReleaseNULL(theKext
);
7875 /*********************************************************************
7876 *********************************************************************/
7878 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
7880 OSCollectionIterator
* classIterator
= NULL
; // must release
7881 OSMetaClass
* checkClass
= NULL
; // do not release
7887 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7888 if (!classIterator
) {
7891 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7892 if (checkClass
->getInstanceCount()) {
7895 " Kext %s class %s has %d instance%s.",
7896 getIdentifierCString(),
7897 checkClass
->getClassName(),
7898 checkClass
->getInstanceCount(),
7899 checkClass
->getInstanceCount() == 1 ? "" : "s");
7904 OSSafeReleaseNULL(classIterator
);
7909 #pragma mark User-Space Requests
7911 /*********************************************************************
7912 * XXX - this function is a big ugly mess
7913 *********************************************************************/
7916 OSKext::handleRequest(
7917 host_priv_t hostPriv
,
7918 OSKextLogSpec clientLogFilter
,
7919 char * requestBuffer
,
7920 uint32_t requestLength
,
7921 char ** responseOut
,
7922 uint32_t * responseLengthOut
,
7924 uint32_t * logInfoLengthOut
)
7926 OSReturn result
= kOSReturnError
;
7927 kern_return_t kmem_result
= KERN_FAILURE
;
7929 char * response
= NULL
; // returned by reference
7930 uint32_t responseLength
= 0;
7932 OSObject
* parsedXML
= NULL
; // must release
7933 OSDictionary
* requestDict
= NULL
; // do not release
7934 OSString
* errorString
= NULL
; // must release
7936 OSObject
* responseObject
= NULL
; // must release
7938 OSSerialize
* serializer
= NULL
; // must release
7940 OSArray
* logInfoArray
= NULL
; // must release
7942 OSString
* predicate
= NULL
; // do not release
7943 OSString
* kextIdentifier
= NULL
; // do not release
7944 OSArray
* kextIdentifiers
= NULL
; // do not release
7945 OSKext
* theKext
= NULL
; // do not release
7946 OSBoolean
* boolArg
= NULL
; // do not release
7948 IORecursiveLockLock(sKextLock
);
7951 *responseOut
= NULL
;
7952 *responseLengthOut
= 0;
7956 *logInfoLengthOut
= 0;
7959 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
7961 /* XML must be nul-terminated.
7963 if (requestBuffer
[requestLength
- 1] != '\0') {
7964 OSKextLog(/* kext */ NULL
,
7965 kOSKextLogErrorLevel
|
7967 "Invalid request from user space (not nul-terminated).");
7968 result
= kOSKextReturnBadData
;
7971 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
7973 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
7976 const char * errorCString
= "(unknown error)";
7978 if (errorString
&& errorString
->getCStringNoCopy()) {
7979 errorCString
= errorString
->getCStringNoCopy();
7980 } else if (parsedXML
) {
7981 errorCString
= "not a dictionary";
7983 OSKextLog(/* kext */ NULL
,
7984 kOSKextLogErrorLevel
|
7986 "Error unserializing request from user space: %s.",
7988 result
= kOSKextReturnSerialization
;
7992 predicate
= _OSKextGetRequestPredicate(requestDict
);
7994 OSKextLog(/* kext */ NULL
,
7995 kOSKextLogErrorLevel
|
7997 "Recieved kext request from user space with no predicate.");
7998 result
= kOSKextReturnInvalidArgument
;
8002 OSKextLog(/* kext */ NULL
,
8003 kOSKextLogDebugLevel
|
8005 "Received '%s' request from user space.",
8006 predicate
->getCStringNoCopy());
8008 result
= kOSKextReturnNotPrivileged
;
8009 if (hostPriv
== HOST_PRIV_NULL
) {
8010 /* must be root to use these kext requests */
8011 if (predicate
->isEqualTo(kKextRequestPredicateUnload
) ||
8012 predicate
->isEqualTo(kKextRequestPredicateStart
) ||
8013 predicate
->isEqualTo(kKextRequestPredicateStop
) ||
8014 predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
) ||
8015 predicate
->isEqualTo(kKextRequestPredicateSendResource
) ) {
8016 OSKextLog(/* kext */ NULL
,
8017 kOSKextLogErrorLevel
|
8019 "Access Failure - must be root user.");
8024 /* Get common args in anticipation of use.
8026 kextIdentifier
= OSDynamicCast(OSString
, _OSKextGetRequestArgument(
8027 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
8028 kextIdentifiers
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument(
8029 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
8030 if (kextIdentifier
) {
8031 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
8033 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
8034 requestDict
, kKextRequestArgumentValueKey
));
8036 result
= kOSKextReturnInvalidArgument
;
8038 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
8039 if (!kextIdentifier
) {
8040 OSKextLog(/* kext */ NULL
,
8041 kOSKextLogErrorLevel
|
8043 "Invalid arguments to kext start request.");
8044 } else if (!theKext
) {
8045 OSKextLog(/* kext */ NULL
,
8046 kOSKextLogErrorLevel
|
8048 "Kext %s not found for start request.",
8049 kextIdentifier
->getCStringNoCopy());
8050 result
= kOSKextReturnNotFound
;
8052 result
= theKext
->start();
8055 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
8056 if (!kextIdentifier
) {
8057 OSKextLog(/* kext */ NULL
,
8058 kOSKextLogErrorLevel
|
8060 "Invalid arguments to kext stop request.");
8061 } else if (!theKext
) {
8062 OSKextLog(/* kext */ NULL
,
8063 kOSKextLogErrorLevel
|
8065 "Kext %s not found for stop request.",
8066 kextIdentifier
->getCStringNoCopy());
8067 result
= kOSKextReturnNotFound
;
8069 result
= theKext
->stop();
8072 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
8073 if (!kextIdentifier
) {
8074 OSKextLog(/* kext */ NULL
,
8075 kOSKextLogErrorLevel
|
8077 "Invalid arguments to kext unload request.");
8078 } else if (!theKext
) {
8079 OSKextLog(/* kext */ NULL
,
8080 kOSKextLogErrorLevel
|
8082 "Kext %s not found for unload request.",
8083 kextIdentifier
->getCStringNoCopy());
8084 result
= kOSKextReturnNotFound
;
8086 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
8087 _OSKextGetRequestArgument(requestDict
,
8088 kKextRequestArgumentTerminateIOServicesKey
));
8089 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
8092 } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
8093 result
= OSKext::dispatchResource(requestDict
);
8095 } else if (predicate
->isEqualTo(kKextRequestPredicateGetUUIDByAddress
)) {
8097 OSNumber
*lookupNum
= NULL
;
8098 lookupNum
= OSDynamicCast(OSNumber
,
8099 _OSKextGetRequestArgument(requestDict
,
8100 kKextRequestArgumentLookupAddressKey
));
8102 responseObject
= OSKext::copyKextUUIDForAddress(lookupNum
);
8103 if (responseObject
) {
8104 result
= kOSReturnSuccess
;
8109 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
) ||
8110 predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
8111 OSBoolean
* delayAutounloadBool
= NULL
;
8112 OSObject
* infoKeysRaw
= NULL
;
8113 OSArray
* infoKeys
= NULL
;
8114 uint32_t infoKeysCount
= 0;
8116 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
8117 _OSKextGetRequestArgument(requestDict
,
8118 kKextRequestArgumentDelayAutounloadKey
));
8120 /* If asked to delay autounload, reset the timer if it's currently set.
8121 * (That is, don't schedule an unload if one isn't already pending.
8123 if (delayAutounloadBool
== kOSBooleanTrue
) {
8124 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8127 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
8128 kKextRequestArgumentInfoKeysKey
);
8129 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
8130 if (infoKeysRaw
&& !infoKeys
) {
8131 OSKextLog(/* kext */ NULL
,
8132 kOSKextLogErrorLevel
|
8134 "Invalid arguments to kext info request.");
8139 infoKeysCount
= infoKeys
->getCount();
8140 for (uint32_t i
= 0; i
< infoKeysCount
; i
++) {
8141 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) {
8142 OSKextLog(/* kext */ NULL
,
8143 kOSKextLogErrorLevel
|
8145 "Invalid arguments to kext info request.");
8151 if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
8152 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
8154 else if (predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
8155 responseObject
= OSKext::copyLoadedKextInfoByUUID(kextIdentifiers
, infoKeys
);
8157 if (!responseObject
) {
8158 result
= kOSKextReturnInternalError
;
8160 OSKextLog(/* kext */ NULL
,
8161 kOSKextLogDebugLevel
|
8163 "Returning loaded kext info.");
8164 result
= kOSReturnSuccess
;
8166 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) {
8168 /* Hand the current sKernelRequests array to the caller
8169 * (who must release it), and make a new one.
8171 responseObject
= sKernelRequests
;
8172 sKernelRequests
= OSArray::withCapacity(0);
8173 sPostedKextLoadIdentifiers
->flushCollection();
8174 OSKextLog(/* kext */ NULL
,
8175 kOSKextLogDebugLevel
|
8177 "Returning kernel requests.");
8178 result
= kOSReturnSuccess
;
8180 } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) {
8182 /* Return the set of all requested bundle identifiers */
8183 responseObject
= sAllKextLoadIdentifiers
;
8184 responseObject
->retain();
8185 OSKextLog(/* kext */ NULL
,
8186 kOSKextLogDebugLevel
|
8188 "Returning load requests.");
8189 result
= kOSReturnSuccess
;
8192 OSKextLog(/* kext */ NULL
,
8193 kOSKextLogDebugLevel
|
8195 "Received '%s' invalid request from user space.",
8196 predicate
->getCStringNoCopy());
8201 * Now we have handle the request, or not. Gather up the response & logging
8202 * info to ship to user space.
8205 /* Note: Nothing in OSKext is supposed to retain requestDict,
8206 * but you never know....
8208 if (requestDict
->getRetainCount() > 1) {
8209 OSKextLog(/* kext */ NULL
,
8210 kOSKextLogWarningLevel
|
8212 "Request from user space still retained by a kext; "
8213 "probable memory leak.");
8216 if (responseOut
&& responseObject
) {
8217 serializer
= OSSerialize::withCapacity(0);
8219 result
= kOSKextReturnNoMemory
;
8223 if (!responseObject
->serialize(serializer
)) {
8224 OSKextLog(/* kext */ NULL
,
8225 kOSKextLogGeneralFlag
| kOSKextLogErrorLevel
,
8226 "Failed to serialize response to request from user space.");
8227 result
= kOSKextReturnSerialization
;
8231 response
= (char *)serializer
->text();
8232 responseLength
= serializer
->getLength();
8235 if (responseOut
&& response
) {
8238 /* This kmem_alloc sets the return value of the function.
8240 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
,
8241 round_page(responseLength
), VM_KERN_MEMORY_OSKEXT
);
8242 if (kmem_result
!= KERN_SUCCESS
) {
8243 OSKextLog(/* kext */ NULL
,
8244 kOSKextLogErrorLevel
|
8246 "Failed to copy response to request from user space.");
8247 result
= kmem_result
;
8250 /* 11981737 - clear uninitialized data in last page */
8251 bzero((void *)(buffer
+ responseLength
),
8252 (round_page(responseLength
) - responseLength
));
8253 memcpy(buffer
, response
, responseLength
);
8254 *responseOut
= buffer
;
8255 *responseLengthOut
= responseLength
;
8261 /* Gather up the collected log messages for user space. Any messages
8262 * messages past this call will not make it up as log messages but
8263 * will be in the system log. Note that we ignore the return of the
8264 * serialize; it has no bearing on the operation at hand even if we
8265 * fail to get the log messages.
8267 logInfoArray
= OSKext::clearUserSpaceLogFilter();
8269 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
8270 (void)OSKext::serializeLogInfo(logInfoArray
,
8271 logInfoOut
, logInfoLengthOut
);
8274 IORecursiveLockUnlock(sKextLock
);
8276 OSSafeReleaseNULL(parsedXML
);
8277 OSSafeReleaseNULL(errorString
);
8278 OSSafeReleaseNULL(responseObject
);
8279 OSSafeReleaseNULL(serializer
);
8280 OSSafeReleaseNULL(logInfoArray
);
8286 // #include <InstrProfiling.h>
8289 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin
,
8290 const char *DataEnd
,
8291 const char *CountersBegin
,
8292 const char *CountersEnd
,
8293 const char *NamesBegin
,
8294 const char *NamesEnd
);
8295 int __llvm_profile_write_buffer_internal(char *Buffer
,
8296 const char *DataBegin
,
8297 const char *DataEnd
,
8298 const char *CountersBegin
,
8299 const char *CountersEnd
,
8300 const char *NamesBegin
,
8301 const char *NamesEnd
);
8306 void OSKextPgoMetadataPut(char *pBuffer
,
8309 uint32_t *num_pairs
,
8313 size_t strlen_key
= strlen(key
);
8314 size_t strlen_value
= strlen(value
);
8315 size_t len
= strlen(key
) + 1 + strlen(value
) + 1;
8316 char *pos
= pBuffer
+ *position
;
8318 if (pBuffer
&& bufferSize
&& *position
<= bufferSize
) {
8319 memcpy(pos
, key
, strlen_key
); pos
+= strlen_key
;
8321 memcpy(pos
, value
, strlen_value
); pos
+= strlen_value
;
8331 void OSKextPgoMetadataPutMax(size_t *position
, const char *key
, size_t value_max
)
8333 *position
+= strlen(key
) + 1 + value_max
+ 1;
8338 void OSKextPgoMetadataPutAll(OSKext
*kext
,
8339 uuid_t instance_uuid
,
8343 uint32_t *num_pairs
)
8345 _static_assert_1_arg(sizeof(clock_sec_t
) % 2 == 0);
8346 //log_10 2^16 ≈ 4.82
8347 const size_t max_secs_string_size
= 5 * sizeof(clock_sec_t
)/2;
8348 const size_t max_timestamp_string_size
= max_secs_string_size
+ 1 + 6;
8351 OSKextPgoMetadataPutMax(position
, "INSTANCE", 36);
8352 OSKextPgoMetadataPutMax(position
, "UUID", 36);
8353 OSKextPgoMetadataPutMax(position
, "TIMESTAMP", max_timestamp_string_size
);
8355 uuid_string_t instance_uuid_string
;
8356 uuid_unparse(instance_uuid
, instance_uuid_string
);
8357 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8358 "INSTANCE", instance_uuid_string
);
8362 uuid_string_t uuid_string
;
8363 uuid_data
= kext
->copyUUID();
8365 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
8366 OSSafeReleaseNULL(uuid_data
);
8367 uuid_unparse(uuid
, uuid_string
);
8368 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8369 "UUID", uuid_string
);
8374 clock_get_calendar_microtime(&secs
, &usecs
);
8375 assert(usecs
< 1000000);
8376 char timestamp
[max_timestamp_string_size
+ 1];
8377 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t
));
8378 snprintf(timestamp
, sizeof(timestamp
), "%lu.%06d", (unsigned long)secs
, (int)usecs
);
8379 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8380 "TIMESTAMP", timestamp
);
8383 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8384 "NAME", kext
->getIdentifierCString());
8386 char versionCString
[kOSKextVersionMaxLength
];
8387 OSKextVersionGetString(kext
->getVersion(), versionCString
, kOSKextVersionMaxLength
);
8388 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8389 "VERSION", versionCString
);
8394 size_t OSKextPgoMetadataSize(OSKext
*kext
)
8396 size_t position
= 0;
8397 uuid_t fakeuuid
= {};
8398 OSKextPgoMetadataPutAll(kext
, fakeuuid
, NULL
, &position
, 0, NULL
);
8402 int OSKextGrabPgoDataLocked(OSKext
*kext
,
8404 uuid_t instance_uuid
,
8407 uint64_t bufferSize
)
8411 kernel_section_t
*sect_prf_data
= NULL
;
8412 kernel_section_t
*sect_prf_name
= NULL
;
8413 kernel_section_t
*sect_prf_cnts
= NULL
;
8415 size_t metadata_size
= 0;
8417 sect_prf_data
= kext
->lookupSection("__DATA", "__llvm_prf_data");
8418 sect_prf_name
= kext
->lookupSection("__DATA", "__llvm_prf_name");
8419 sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8421 if (!sect_prf_data
|| !sect_prf_name
|| !sect_prf_cnts
) {
8426 size
= __llvm_profile_get_size_for_buffer_internal(
8427 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8428 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8429 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8432 metadata_size
= OSKextPgoMetadataSize(kext
);
8433 size
+= metadata_size
;
8434 size
+= sizeof(pgo_metadata_footer
);
8442 if (pBuffer
&& bufferSize
) {
8443 if (bufferSize
< size
) {
8448 err
= __llvm_profile_write_buffer_internal(
8450 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8451 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8452 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8460 char *end_of_buffer
= pBuffer
+ size
;
8461 struct pgo_metadata_footer
*footerp
= (struct pgo_metadata_footer
*) (end_of_buffer
- sizeof(struct pgo_metadata_footer
));
8462 char *metadata_buffer
= end_of_buffer
- (sizeof(struct pgo_metadata_footer
) + metadata_size
);
8464 size_t metadata_position
= 0;
8465 uint32_t num_pairs
= 0;
8466 OSKextPgoMetadataPutAll(kext
, instance_uuid
, metadata_buffer
, &metadata_position
, metadata_size
, &num_pairs
);
8467 while (metadata_position
< metadata_size
) {
8468 metadata_buffer
[metadata_position
++] = 0;
8471 struct pgo_metadata_footer footer
;
8472 footer
.magic
= htonl(0x6d657461);
8473 footer
.number_of_pairs
= htonl( num_pairs
);
8474 footer
.offset_to_pairs
= htonl( sizeof(struct pgo_metadata_footer
) + metadata_size
);
8475 memcpy(footerp
, &footer
, sizeof(footer
));
8486 OSKextGrabPgoData(uuid_t uuid
,
8489 uint64_t bufferSize
,
8490 int wait_for_unload
,
8494 OSKext
*kext
= NULL
;
8497 IORecursiveLockLock(sKextLock
);
8499 kext
= OSKext::lookupKextWithUUID(uuid
);
8505 if (wait_for_unload
) {
8506 OSKextGrabPgoStruct s
;
8508 s
.metadata
= metadata
;
8510 s
.pBuffer
= pBuffer
;
8511 s
.bufferSize
= bufferSize
;
8514 struct list_head
*prev
= &kext
->pendingPgoHead
;
8515 struct list_head
*next
= kext
->pendingPgoHead
.next
;
8517 s
.list_head
.prev
= prev
;
8518 s
.list_head
.next
= next
;
8520 prev
->next
= &s
.list_head
;
8521 next
->prev
= &s
.list_head
;
8526 IORecursiveLockSleep(sKextLock
, &s
, THREAD_ABORTSAFE
);
8528 prev
= s
.list_head
.prev
;
8529 next
= s
.list_head
.next
;
8537 err
= OSKextGrabPgoDataLocked(kext
, metadata
, kext
->instance_uuid
, pSize
, pBuffer
, bufferSize
);
8545 IORecursiveLockUnlock(sKextLock
);
8551 OSKextResetPgoCountersLock()
8553 IORecursiveLockLock(sKextLock
);
8557 OSKextResetPgoCountersUnlock()
8559 IORecursiveLockUnlock(sKextLock
);
8563 extern unsigned int not_in_kdp
;
8566 OSKextResetPgoCounters()
8568 assert(!not_in_kdp
);
8569 uint32_t count
= sLoadedKexts
->getCount();
8570 for (uint32_t i
= 0; i
< count
; i
++) {
8571 OSKext
*kext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8572 kernel_section_t
*sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8573 if (!sect_prf_cnts
) {
8576 memset((void*)sect_prf_cnts
->addr
, 0, sect_prf_cnts
->size
);
8581 OSKext::copyLoadedKextInfoByUUID(
8582 OSArray
* kextIdentifiers
,
8585 OSDictionary
* result
= NULL
;
8586 OSDictionary
* kextInfo
= NULL
; // must release
8588 uint32_t idCount
= 0;
8589 uint32_t idIndex
= 0;
8591 IORecursiveLockLock(sKextLock
);
8594 /* Is the calling process allowed to query kext info? */
8595 if (current_task() != kernel_task
) {
8596 int macCheckResult
= 0;
8597 kauth_cred_t cred
= NULL
;
8599 cred
= kauth_cred_get_with_ref();
8600 macCheckResult
= mac_kext_check_query(cred
);
8601 kauth_cred_unref(&cred
);
8603 if (macCheckResult
!= 0) {
8604 OSKextLog(/* kext */ NULL
,
8605 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8606 "Failed to query kext info (MAC policy error 0x%x).",
8613 /* Empty list of UUIDs is equivalent to no list (get all).
8615 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8616 kextIdentifiers
= NULL
;
8617 } else if (kextIdentifiers
) {
8618 idCount
= kextIdentifiers
->getCount();
8623 if (infoKeys
&& !infoKeys
->getCount()) {
8627 count
= sLoadedKexts
->getCount();
8628 result
= OSDictionary::withCapacity(count
);
8633 for (i
= 0; i
< count
; i
++) {
8634 OSKext
*thisKext
= NULL
; // do not release
8635 Boolean includeThis
= true;
8636 uuid_t thisKextUUID
;
8638 uuid_string_t uuid_key
;
8641 kextInfo
->release();
8645 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8650 uuid_data
= thisKext
->copyUUID();
8655 memcpy(&thisKextUUID
, uuid_data
->getBytesNoCopy(), sizeof(thisKextUUID
));
8656 OSSafeReleaseNULL(uuid_data
);
8658 uuid_unparse(thisKextUUID
, uuid_key
);
8660 /* Skip current kext if we have a list of UUIDs and
8661 * it isn't in the list.
8663 if (kextIdentifiers
) {
8664 includeThis
= false;
8666 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8667 const OSString
* wantedUUID
= OSDynamicCast(OSString
,
8668 kextIdentifiers
->getObject(idIndex
));
8671 uuid_parse(wantedUUID
->getCStringNoCopy(), uuid
);
8673 if (0 == uuid_compare(uuid
, thisKextUUID
)) {
8685 kextInfo
= thisKext
->copyInfo(infoKeys
);
8687 result
->setObject(uuid_key
, kextInfo
);
8692 IORecursiveLockUnlock(sKextLock
);
8694 if (kextInfo
) kextInfo
->release();
8699 /*********************************************************************
8700 *********************************************************************/
8703 OSKext::copyLoadedKextInfo(
8704 OSArray
* kextIdentifiers
,
8707 OSDictionary
* result
= NULL
;
8708 OSDictionary
* kextInfo
= NULL
; // must release
8710 uint32_t idCount
= 0;
8711 uint32_t idIndex
= 0;
8713 IORecursiveLockLock(sKextLock
);
8716 /* Is the calling process allowed to query kext info? */
8717 if (current_task() != kernel_task
) {
8718 int macCheckResult
= 0;
8719 kauth_cred_t cred
= NULL
;
8721 cred
= kauth_cred_get_with_ref();
8722 macCheckResult
= mac_kext_check_query(cred
);
8723 kauth_cred_unref(&cred
);
8725 if (macCheckResult
!= 0) {
8726 OSKextLog(/* kext */ NULL
,
8727 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8728 "Failed to query kext info (MAC policy error 0x%x).",
8735 /* Empty list of bundle ids is equivalent to no list (get all).
8737 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8738 kextIdentifiers
= NULL
;
8739 } else if (kextIdentifiers
) {
8740 idCount
= kextIdentifiers
->getCount();
8745 if (infoKeys
&& !infoKeys
->getCount()) {
8749 count
= sLoadedKexts
->getCount();
8750 result
= OSDictionary::withCapacity(count
);
8756 OSKextLog(/* kext */ NULL
,
8757 kOSKextLogErrorLevel
|
8758 kOSKextLogGeneralFlag
,
8759 "kaslr: vm_kernel_slide 0x%lx \n",
8761 OSKextLog(/* kext */ NULL
,
8762 kOSKextLogErrorLevel
|
8763 kOSKextLogGeneralFlag
,
8764 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
8765 vm_kernel_stext
, vm_kernel_etext
);
8766 OSKextLog(/* kext */ NULL
,
8767 kOSKextLogErrorLevel
|
8768 kOSKextLogGeneralFlag
,
8769 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
8770 vm_kernel_base
, vm_kernel_top
);
8771 OSKextLog(/* kext */ NULL
,
8772 kOSKextLogErrorLevel
|
8773 kOSKextLogGeneralFlag
,
8774 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
8775 vm_kext_base
, vm_kext_top
);
8776 OSKextLog(/* kext */ NULL
,
8777 kOSKextLogErrorLevel
|
8778 kOSKextLogGeneralFlag
,
8779 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
8780 vm_prelink_stext
, vm_prelink_etext
);
8781 OSKextLog(/* kext */ NULL
,
8782 kOSKextLogErrorLevel
|
8783 kOSKextLogGeneralFlag
,
8784 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
8785 vm_prelink_sinfo
, vm_prelink_einfo
);
8786 OSKextLog(/* kext */ NULL
,
8787 kOSKextLogErrorLevel
|
8788 kOSKextLogGeneralFlag
,
8789 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
8790 vm_slinkedit
, vm_elinkedit
);
8793 for (i
= 0; i
< count
; i
++) {
8794 OSKext
* thisKext
= NULL
; // do not release
8795 Boolean includeThis
= true;
8798 kextInfo
->release();
8801 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8806 /* Skip current kext if we have a list of bundle IDs and
8807 * it isn't in the list.
8809 if (kextIdentifiers
) {
8810 const OSString
* thisKextID
= thisKext
->getIdentifier();
8812 includeThis
= false;
8814 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8815 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
8816 kextIdentifiers
->getObject(idIndex
));
8817 if (thisKextID
->isEqualTo(thisRequestID
)) {
8828 kextInfo
= thisKext
->copyInfo(infoKeys
);
8830 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
8835 IORecursiveLockUnlock(sKextLock
);
8837 if (kextInfo
) kextInfo
->release();
8842 /*********************************************************************
8843 * Any info that needs to do allocations must goto finish on alloc
8844 * failure. Info that is just a lookup should just not set the object
8845 * if the info does not exist.
8846 *********************************************************************/
8847 #define _OSKextLoadInfoDictCapacity (12)
8850 OSKext::copyInfo(OSArray
* infoKeys
)
8852 OSDictionary
* result
= NULL
;
8853 bool success
= false;
8854 OSData
* headerData
= NULL
; // must release
8855 OSData
* logData
= NULL
; // must release
8856 OSNumber
* cpuTypeNumber
= NULL
; // must release
8857 OSNumber
* cpuSubtypeNumber
= NULL
; // must release
8858 OSString
* versionString
= NULL
; // do not release
8859 uint32_t executablePathCStringSize
= 0;
8860 char * executablePathCString
= NULL
; // must release
8861 OSString
* executablePathString
= NULL
; // must release
8862 OSData
* uuid
= NULL
; // must release
8863 OSNumber
* scratchNumber
= NULL
; // must release
8864 OSArray
* dependencyLoadTags
= NULL
; // must release
8865 OSCollectionIterator
* metaClassIterator
= NULL
; // must release
8866 OSArray
* metaClassInfo
= NULL
; // must release
8867 OSDictionary
* metaClassDict
= NULL
; // must release
8868 OSMetaClass
* thisMetaClass
= NULL
; // do not release
8869 OSString
* metaClassName
= NULL
; // must release
8870 OSString
* superclassName
= NULL
; // must release
8873 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
8879 /* Empty keys means no keys, but NULL is quicker to check.
8881 if (infoKeys
&& !infoKeys
->getCount()) {
8885 /* Headers, CPU type, and CPU subtype.
8888 _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) ||
8889 _OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
) ||
8890 _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) ||
8891 _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
))
8894 if (linkedExecutable
&& !isInterface()) {
8896 kernel_mach_header_t
*kext_mach_hdr
= (kernel_mach_header_t
*)
8897 linkedExecutable
->getBytesNoCopy();
8900 // do not return macho header info on shipping iOS - 19095897
8901 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) {
8902 kernel_mach_header_t
* temp_kext_mach_hdr
;
8903 struct load_command
* lcp
;
8905 headerData
= OSData::withBytes(kext_mach_hdr
,
8906 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
8911 // unslide any vmaddrs we return to userspace - 10726716
8912 temp_kext_mach_hdr
= (kernel_mach_header_t
*)
8913 headerData
->getBytesNoCopy();
8914 if (temp_kext_mach_hdr
== NULL
) {
8918 lcp
= (struct load_command
*) (temp_kext_mach_hdr
+ 1);
8919 for (i
= 0; i
< temp_kext_mach_hdr
->ncmds
; i
++) {
8920 if (lcp
->cmd
== LC_SEGMENT_KERNEL
) {
8921 kernel_segment_command_t
* segp
;
8922 kernel_section_t
* secp
;
8924 segp
= (kernel_segment_command_t
*) lcp
;
8925 // 10543468 - if we jettisoned __LINKEDIT clear size info
8926 if (flags
.jettisonLinkeditSeg
) {
8927 if (strncmp(segp
->segname
, SEG_LINKEDIT
, sizeof(segp
->segname
)) == 0) {
8935 OSKextLog(/* kext */ NULL
,
8936 kOSKextLogErrorLevel
|
8937 kOSKextLogGeneralFlag
,
8938 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
8939 __FUNCTION__
, segp
->segname
, segp
->vmaddr
,
8940 VM_KERNEL_UNSLIDE(segp
->vmaddr
),
8941 segp
->vmsize
, segp
->nsects
);
8942 if ( (VM_KERNEL_IS_SLID(segp
->vmaddr
) == false) &&
8943 (VM_KERNEL_IS_KEXT(segp
->vmaddr
) == false) &&
8944 (VM_KERNEL_IS_PRELINKTEXT(segp
->vmaddr
) == false) &&
8945 (VM_KERNEL_IS_PRELINKINFO(segp
->vmaddr
) == false) &&
8946 (VM_KERNEL_IS_KEXT_LINKEDIT(segp
->vmaddr
) == false) ) {
8947 OSKextLog(/* kext */ NULL
,
8948 kOSKextLogErrorLevel
|
8949 kOSKextLogGeneralFlag
,
8950 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
8951 __FUNCTION__
, segp
->vmaddr
, vm_kext_base
, vm_kext_top
);
8954 segp
->vmaddr
= VM_KERNEL_UNSLIDE(segp
->vmaddr
);
8956 for (secp
= firstsect(segp
); secp
!= NULL
; secp
= nextsect(segp
, secp
)) {
8957 secp
->addr
= VM_KERNEL_UNSLIDE(secp
->addr
);
8960 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
8962 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
8964 #endif // SECURE_KERNEL
8966 if (_OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
)) {
8967 osLogDataHeaderRef
*header
;
8968 char headerBytes
[offsetof(osLogDataHeaderRef
, sections
) + NUM_OS_LOG_SECTIONS
* sizeof(header
->sections
[0])];
8970 void *os_log_data
= NULL
;
8971 void *cstring_data
= NULL
;
8972 unsigned long os_log_size
= 0;
8973 unsigned long cstring_size
= 0;
8974 uint32_t os_log_offset
= 0;
8975 uint32_t cstring_offset
= 0;
8978 os_log_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__os_log", &os_log_size
);
8979 os_log_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__os_log");
8980 cstring_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__cstring", &cstring_size
);
8981 cstring_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__cstring");
8983 header
= (osLogDataHeaderRef
*) headerBytes
;
8984 header
->version
= OS_LOG_HDR_VERSION
;
8985 header
->sect_count
= NUM_OS_LOG_SECTIONS
;
8986 header
->sections
[OS_LOG_SECT_IDX
].sect_offset
= os_log_offset
;
8987 header
->sections
[OS_LOG_SECT_IDX
].sect_size
= (uint32_t) os_log_size
;
8988 header
->sections
[CSTRING_SECT_IDX
].sect_offset
= cstring_offset
;
8989 header
->sections
[CSTRING_SECT_IDX
].sect_size
= (uint32_t) cstring_size
;
8992 logData
= OSData::withBytes(header
, (u_int
) (sizeof(osLogDataHeaderRef
)));
8996 res
= logData
->appendBytes(&(header
->sections
[0]), (u_int
)(header
->sect_count
* sizeof(header
->sections
[0])));
9001 res
= logData
->appendBytes(os_log_data
, (u_int
)header
->sections
[OS_LOG_SECT_IDX
].sect_size
);
9007 res
= logData
->appendBytes(cstring_data
, (u_int
)header
->sections
[CSTRING_SECT_IDX
].sect_size
);
9012 result
->setObject(kOSBundleLogStringsKey
, logData
);
9015 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) {
9016 cpuTypeNumber
= OSNumber::withNumber(
9017 (uint64_t) kext_mach_hdr
->cputype
,
9018 8 * sizeof(kext_mach_hdr
->cputype
));
9019 if (!cpuTypeNumber
) {
9022 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
9025 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
9026 cpuSubtypeNumber
= OSNumber::withNumber(
9027 (uint64_t) kext_mach_hdr
->cpusubtype
,
9028 8 * sizeof(kext_mach_hdr
->cpusubtype
));
9029 if (!cpuSubtypeNumber
) {
9032 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
9037 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
9039 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
9043 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
9044 versionString
= OSDynamicCast(OSString
,
9045 getPropertyForHostArch(kCFBundleVersionKey
));
9046 if (versionString
) {
9047 result
->setObject(kCFBundleVersionKey
, versionString
);
9051 /* OSBundleCompatibleVersion.
9053 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
9054 versionString
= OSDynamicCast(OSString
,
9055 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
9056 if (versionString
) {
9057 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
9063 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
9065 result
->setObject(kOSBundlePathKey
, path
);
9070 /* OSBundleExecutablePath.
9072 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
9073 if (path
&& executableRelPath
) {
9075 uint32_t pathLength
= path
->getLength(); // gets incremented below
9077 // +1 for slash, +1 for \0
9078 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
9080 executablePathCString
= (char *)kalloc_tag((executablePathCStringSize
) *
9081 sizeof(char), VM_KERN_MEMORY_OSKEXT
); // +1 for \0
9082 if (!executablePathCString
) {
9085 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
9086 executablePathCStringSize
);
9087 executablePathCString
[pathLength
++] = '/';
9088 executablePathCString
[pathLength
++] = '\0';
9089 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
9090 executablePathCStringSize
);
9092 executablePathString
= OSString::withCString(executablePathCString
);
9094 if (!executablePathString
) {
9098 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
9102 /* UUID, if the kext has one.
9104 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
9107 result
->setObject(kOSBundleUUIDKey
, uuid
);
9112 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
9114 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSKernelResourceKey
)) {
9115 result
->setObject(kOSKernelResourceKey
,
9116 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
9119 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
9120 result
->setObject(kOSBundleIsInterfaceKey
,
9121 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
9124 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
9125 result
->setObject(kOSBundlePrelinkedKey
,
9126 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
9129 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
9130 result
->setObject(kOSBundleStartedKey
,
9131 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
9136 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
9137 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
9138 /* numBits */ 8 * sizeof(loadTag
));
9139 if (!scratchNumber
) {
9142 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
9143 OSSafeReleaseNULL(scratchNumber
);
9146 /* LoadAddress, LoadSize.
9149 _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) ||
9150 _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) ||
9151 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
) ||
9152 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
) ||
9153 _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
))
9155 if (isInterface() || linkedExecutable
) {
9156 /* These go to userspace via serialization, so we don't want any doubts
9159 uint64_t loadAddress
= 0;
9160 uint32_t loadSize
= 0;
9161 uint32_t wiredSize
= 0;
9162 uint64_t execLoadAddress
= 0;
9163 uint32_t execLoadSize
= 0;
9165 /* Interfaces always report 0 load address & size.
9166 * Just the way they roll.
9168 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
9169 * xxx - shouldn't have one!
9171 if (linkedExecutable
/* && !isInterface() */) {
9172 kernel_mach_header_t
*mh
= NULL
;
9173 kernel_segment_command_t
*seg
= NULL
;
9175 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
9176 mh
= (kernel_mach_header_t
*)loadAddress
;
9177 loadAddress
= VM_KERNEL_UNSLIDE(loadAddress
);
9178 loadSize
= linkedExecutable
->getLength();
9180 /* Walk through the kext, looking for the first executable
9181 * segment in case we were asked for its size/address.
9183 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
9184 if (seg
->initprot
& VM_PROT_EXECUTE
) {
9185 execLoadAddress
= VM_KERNEL_UNSLIDE(seg
->vmaddr
);
9186 execLoadSize
= seg
->vmsize
;
9191 /* If we have a kmod_info struct, calculated the wired size
9192 * from that. Otherwise it's the full load size.
9195 wiredSize
= loadSize
- kmod_info
->hdr_size
;
9197 wiredSize
= loadSize
;
9201 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
9202 scratchNumber
= OSNumber::withNumber(
9203 (unsigned long long)(loadAddress
),
9204 /* numBits */ 8 * sizeof(loadAddress
));
9205 if (!scratchNumber
) {
9208 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
9209 OSSafeReleaseNULL(scratchNumber
);
9211 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
)) {
9212 scratchNumber
= OSNumber::withNumber(
9213 (unsigned long long)(execLoadAddress
),
9214 /* numBits */ 8 * sizeof(execLoadAddress
));
9215 if (!scratchNumber
) {
9218 result
->setObject(kOSBundleExecLoadAddressKey
, scratchNumber
);
9219 OSSafeReleaseNULL(scratchNumber
);
9221 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
9222 scratchNumber
= OSNumber::withNumber(
9223 (unsigned long long)(loadSize
),
9224 /* numBits */ 8 * sizeof(loadSize
));
9225 if (!scratchNumber
) {
9228 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
9229 OSSafeReleaseNULL(scratchNumber
);
9231 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
)) {
9232 scratchNumber
= OSNumber::withNumber(
9233 (unsigned long long)(execLoadSize
),
9234 /* numBits */ 8 * sizeof(execLoadSize
));
9235 if (!scratchNumber
) {
9238 result
->setObject(kOSBundleExecLoadSizeKey
, scratchNumber
);
9239 OSSafeReleaseNULL(scratchNumber
);
9241 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
9242 scratchNumber
= OSNumber::withNumber(
9243 (unsigned long long)(wiredSize
),
9244 /* numBits */ 8 * sizeof(wiredSize
));
9245 if (!scratchNumber
) {
9248 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
9249 OSSafeReleaseNULL(scratchNumber
);
9254 /* OSBundleDependencies. In descending order for
9255 * easy compatibility with kextstat(8).
9257 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
9258 if ((count
= getNumDependencies())) {
9259 dependencyLoadTags
= OSArray::withCapacity(count
);
9260 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
9264 OSKext
* dependency
= OSDynamicCast(OSKext
,
9265 dependencies
->getObject(i
));
9267 OSSafeReleaseNULL(scratchNumber
);
9272 scratchNumber
= OSNumber::withNumber(
9273 (unsigned long long)dependency
->getLoadTag(),
9274 /* numBits*/ 8 * sizeof(loadTag
));
9275 if (!scratchNumber
) {
9278 dependencyLoadTags
->setObject(scratchNumber
);
9283 OSSafeReleaseNULL(scratchNumber
);
9285 /* OSBundleMetaClasses.
9287 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) {
9288 if (metaClasses
&& metaClasses
->getCount()) {
9289 metaClassIterator
= OSCollectionIterator::withCollection(metaClasses
);
9290 metaClassInfo
= OSArray::withCapacity(metaClasses
->getCount());
9291 if (!metaClassIterator
|| !metaClassInfo
) {
9294 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
9296 while ( (thisMetaClass
= OSDynamicCast(OSMetaClass
,
9297 metaClassIterator
->getNextObject())) ) {
9299 OSSafeReleaseNULL(metaClassDict
);
9300 OSSafeReleaseNULL(scratchNumber
);
9301 OSSafeReleaseNULL(metaClassName
);
9302 OSSafeReleaseNULL(superclassName
);
9304 metaClassDict
= OSDictionary::withCapacity(3);
9305 if (!metaClassDict
) {
9309 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
9310 if (thisMetaClass
->getSuperClass()) {
9311 superclassName
= OSString::withCString(
9312 thisMetaClass
->getSuperClass()->getClassName());
9314 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
9315 8 * sizeof(unsigned int));
9317 /* Bail if any of the essentials is missing. The root class lacks a superclass,
9320 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
9324 metaClassInfo
->setObject(metaClassDict
);
9325 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
9326 if (superclassName
) {
9327 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
9329 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
9334 /* OSBundleRetainCount.
9336 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
9337 OSSafeReleaseNULL(scratchNumber
);
9339 int kextRetainCount
= getRetainCount() - 1;
9343 scratchNumber
= OSNumber::withNumber(
9344 (int)kextRetainCount
,
9345 /* numBits*/ 8 * sizeof(int));
9346 if (scratchNumber
) {
9347 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
9355 OSSafeReleaseNULL(headerData
);
9356 OSSafeReleaseNULL(logData
);
9357 OSSafeReleaseNULL(cpuTypeNumber
);
9358 OSSafeReleaseNULL(cpuSubtypeNumber
);
9359 OSSafeReleaseNULL(executablePathString
);
9360 if (executablePathCString
) kfree(executablePathCString
, executablePathCStringSize
);
9361 OSSafeReleaseNULL(uuid
);
9362 OSSafeReleaseNULL(scratchNumber
);
9363 OSSafeReleaseNULL(dependencyLoadTags
);
9364 OSSafeReleaseNULL(metaClassIterator
);
9365 OSSafeReleaseNULL(metaClassInfo
);
9366 OSSafeReleaseNULL(metaClassDict
);
9367 OSSafeReleaseNULL(metaClassName
);
9368 OSSafeReleaseNULL(superclassName
);
9370 OSSafeReleaseNULL(result
);
9375 /*********************************************************************
9376 *********************************************************************/
9379 OSKext::requestResource(
9380 const char * kextIdentifierCString
,
9381 const char * resourceNameCString
,
9382 OSKextRequestResourceCallback callback
,
9384 OSKextRequestTag
* requestTagOut
)
9386 OSReturn result
= kOSReturnError
;
9387 OSKext
* callbackKext
= NULL
; // must release (looked up)
9389 OSKextRequestTag requestTag
= -1;
9390 OSNumber
* requestTagNum
= NULL
; // must release
9392 OSDictionary
* requestDict
= NULL
; // must release
9393 OSString
* kextIdentifier
= NULL
; // must release
9394 OSString
* resourceName
= NULL
; // must release
9396 OSDictionary
* callbackRecord
= NULL
; // must release
9397 OSData
* callbackWrapper
= NULL
; // must release
9399 OSData
* contextWrapper
= NULL
; // must release
9401 IORecursiveLockLock(sKextLock
);
9403 if (requestTagOut
) {
9404 *requestTagOut
= kOSKextRequestTagInvalid
;
9407 /* If requests to user space are disabled, don't go any further */
9408 if (!sKernelRequestsEnabled
) {
9409 OSKextLog(/* kext */ NULL
,
9410 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9411 "Can't request resource %s for %s - requests to user space are disabled.",
9412 resourceNameCString
,
9413 kextIdentifierCString
);
9414 result
= kOSKextReturnDisabled
;
9418 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
9419 result
= kOSKextReturnInvalidArgument
;
9423 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9424 if (!callbackKext
) {
9425 OSKextLog(/* kext */ NULL
,
9426 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9427 "Resource request has bad callback address.");
9428 result
= kOSKextReturnInvalidArgument
;
9431 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9432 OSKextLog(/* kext */ NULL
,
9433 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9434 "Resource request callback is in a kext that is not started.");
9435 result
= kOSKextReturnInvalidArgument
;
9439 /* Do not allow any new requests to be made on a kext that is unloading.
9441 if (callbackKext
->flags
.stopping
) {
9442 result
= kOSKextReturnStopping
;
9446 /* If we're wrapped the next available request tag around to the negative
9447 * numbers, we can't service any more requests.
9449 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
9450 OSKextLog(/* kext */ NULL
,
9451 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9452 "No more request tags available; restart required.");
9453 result
= kOSKextReturnNoResources
;
9456 requestTag
= sNextRequestTag
++;
9458 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
9460 if (result
!= kOSReturnSuccess
) {
9464 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
9465 resourceName
= OSString::withCString(resourceNameCString
);
9466 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9467 8 * sizeof(requestTag
));
9468 if (!kextIdentifier
||
9471 !_OSKextSetRequestArgument(requestDict
,
9472 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
9473 !_OSKextSetRequestArgument(requestDict
,
9474 kKextRequestArgumentNameKey
, resourceName
) ||
9475 !_OSKextSetRequestArgument(requestDict
,
9476 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
9478 result
= kOSKextReturnNoMemory
;
9482 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
9483 if (!callbackRecord
) {
9484 result
= kOSKextReturnNoMemory
;
9487 // we validate callback address at call time
9488 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
9490 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
9492 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9493 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
9495 result
= kOSKextReturnNoMemory
;
9500 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9501 kKextRequestArgumentContextKey
, contextWrapper
)) {
9503 result
= kOSKextReturnNoMemory
;
9508 /* Only post the requests after all the other potential failure points
9511 if (!sKernelRequests
->setObject(requestDict
) ||
9512 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
9514 result
= kOSKextReturnNoMemory
;
9518 OSKext::pingKextd();
9520 result
= kOSReturnSuccess
;
9521 if (requestTagOut
) {
9522 *requestTagOut
= requestTag
;
9527 /* If we didn't succeed, yank the request & callback
9528 * from their holding arrays.
9530 if (result
!= kOSReturnSuccess
) {
9533 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
9534 if (index
!= (unsigned int)-1) {
9535 sKernelRequests
->removeObject(index
);
9537 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
9538 if (index
!= (unsigned int)-1) {
9539 sRequestCallbackRecords
->removeObject(index
);
9543 OSKext::considerUnloads(/* rescheduleOnly? */ true);
9545 IORecursiveLockUnlock(sKextLock
);
9547 if (callbackKext
) callbackKext
->release();
9548 if (requestTagNum
) requestTagNum
->release();
9550 if (requestDict
) requestDict
->release();
9551 if (kextIdentifier
) kextIdentifier
->release();
9552 if (resourceName
) resourceName
->release();
9554 if (callbackRecord
) callbackRecord
->release();
9555 if (callbackWrapper
) callbackWrapper
->release();
9556 if (contextWrapper
) contextWrapper
->release();
9561 /*********************************************************************
9562 * Assumes sKextLock is held.
9563 *********************************************************************/
9566 OSKext::dequeueCallbackForRequestTag(
9567 OSKextRequestTag requestTag
,
9568 OSDictionary
** callbackRecordOut
)
9570 OSReturn result
= kOSReturnError
;
9571 OSNumber
* requestTagNum
= NULL
; // must release
9573 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9574 8 * sizeof(requestTag
));
9575 if (!requestTagNum
) {
9579 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
9583 OSSafeReleaseNULL(requestTagNum
);
9588 /*********************************************************************
9589 * Assumes sKextLock is held.
9590 *********************************************************************/
9593 OSKext::dequeueCallbackForRequestTag(
9594 OSNumber
* requestTagNum
,
9595 OSDictionary
** callbackRecordOut
)
9597 OSReturn result
= kOSKextReturnInvalidArgument
;
9598 OSDictionary
* callbackRecord
= NULL
; // retain if matched!
9599 OSNumber
* callbackTagNum
= NULL
; // do not release
9600 unsigned int count
, i
;
9602 result
= kOSReturnError
;
9603 count
= sRequestCallbackRecords
->getCount();
9604 for (i
= 0; i
< count
; i
++) {
9605 callbackRecord
= OSDynamicCast(OSDictionary
,
9606 sRequestCallbackRecords
->getObject(i
));
9607 if (!callbackRecord
) {
9611 /* If we don't find a tag, we basically have a leak here. Maybe
9612 * we should just remove it.
9614 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
9615 callbackRecord
, kKextRequestArgumentRequestTagKey
));
9616 if (!callbackTagNum
) {
9620 /* We could be even more paranoid and check that all the incoming
9621 * args match what's in the callback record.
9623 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
9624 if (callbackRecordOut
) {
9625 *callbackRecordOut
= callbackRecord
;
9626 callbackRecord
->retain();
9628 sRequestCallbackRecords
->removeObject(i
);
9629 result
= kOSReturnSuccess
;
9633 result
= kOSKextReturnNotFound
;
9640 /*********************************************************************
9641 * Busy timeout triage
9642 *********************************************************************/
9645 OSKext::isWaitingKextd(void)
9647 return sRequestCallbackRecords
&& sRequestCallbackRecords
->getCount();
9650 /*********************************************************************
9651 * Assumes sKextLock is held.
9652 *********************************************************************/
9655 OSKext::dispatchResource(OSDictionary
* requestDict
)
9657 OSReturn result
= kOSReturnError
;
9658 OSDictionary
* callbackRecord
= NULL
; // must release
9659 OSNumber
* requestTag
= NULL
; // do not release
9660 OSNumber
* requestResult
= NULL
; // do not release
9661 OSData
* dataObj
= NULL
; // do not release
9662 uint32_t dataLength
= 0;
9663 const void * dataPtr
= NULL
; // do not free
9664 OSData
* callbackWrapper
= NULL
; // do not release
9665 OSKextRequestResourceCallback callback
= NULL
;
9666 OSData
* contextWrapper
= NULL
; // do not release
9667 void * context
= NULL
; // do not free
9668 OSKext
* callbackKext
= NULL
; // must release (looked up)
9670 /* Get the args from the request. Right now we need the tag
9671 * to look up the callback record, and the result for invoking the callback.
9673 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9674 kKextRequestArgumentRequestTagKey
));
9675 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9676 kKextRequestArgumentResultKey
));
9677 if (!requestTag
|| !requestResult
) {
9678 result
= kOSKextReturnInvalidArgument
;
9682 /* Look for a callback record matching this request's tag.
9684 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
9685 if (result
!= kOSReturnSuccess
) {
9690 * Get the context pointer of the callback record (if there is one).
9692 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
9693 kKextRequestArgumentContextKey
));
9694 context
= _OSKextExtractPointer(contextWrapper
);
9695 if (contextWrapper
&& !context
) {
9699 callbackWrapper
= OSDynamicCast(OSData
,
9700 _OSKextGetRequestArgument(callbackRecord
,
9701 kKextRequestArgumentCallbackKey
));
9702 callback
= (OSKextRequestResourceCallback
)
9703 _OSKextExtractPointer(callbackWrapper
);
9708 /* Check for a data obj. We might not have one and that's ok, that means
9709 * we didn't find the requested resource, and we still have to tell the
9710 * caller that via the callback.
9712 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
9713 kKextRequestArgumentValueKey
));
9715 dataPtr
= dataObj
->getBytesNoCopy();
9716 dataLength
= dataObj
->getLength();
9719 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9720 if (!callbackKext
) {
9721 OSKextLog(/* kext */ NULL
,
9722 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9723 "Can't invoke callback for resource request; ");
9726 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9727 OSKextLog(/* kext */ NULL
,
9728 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9729 "Can't invoke kext resource callback; ");
9733 (void)callback(requestTag
->unsigned32BitValue(),
9734 (OSReturn
)requestResult
->unsigned32BitValue(),
9735 dataPtr
, dataLength
, context
);
9737 result
= kOSReturnSuccess
;
9740 if (callbackKext
) callbackKext
->release();
9741 if (callbackRecord
) callbackRecord
->release();
9746 /*********************************************************************
9747 *********************************************************************/
9750 OSKext::invokeRequestCallback(
9751 OSDictionary
* callbackRecord
,
9752 OSReturn callbackResult
)
9754 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
9755 OSNumber
* resultNum
= NULL
; // must release
9761 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
9762 8 * sizeof(callbackResult
));
9767 /* Insert the result into the callback record and dispatch it as if it
9768 * were the reply coming down from user space.
9770 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
9773 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
9774 /* This removes the pending callback record.
9776 OSKext::dispatchResource(callbackRecord
);
9780 if (resultNum
) resultNum
->release();
9784 /*********************************************************************
9785 * Assumes sKextLock is held.
9786 *********************************************************************/
9789 OSKext::cancelRequest(
9790 OSKextRequestTag requestTag
,
9793 OSReturn result
= kOSKextReturnNoMemory
;
9794 OSDictionary
* callbackRecord
= NULL
; // must release
9795 OSData
* contextWrapper
= NULL
; // do not release
9797 IORecursiveLockLock(sKextLock
);
9798 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
9800 IORecursiveLockUnlock(sKextLock
);
9802 if (result
== kOSReturnSuccess
&& contextOut
) {
9803 contextWrapper
= OSDynamicCast(OSData
,
9804 _OSKextGetRequestArgument(callbackRecord
,
9805 kKextRequestArgumentContextKey
));
9806 *contextOut
= _OSKextExtractPointer(contextWrapper
);
9809 if (callbackRecord
) callbackRecord
->release();
9814 /*********************************************************************
9815 * Assumes sKextLock is held.
9816 *********************************************************************/
9818 OSKext::invokeOrCancelRequestCallbacks(
9819 OSReturn callbackResult
,
9822 unsigned int count
, i
;
9824 count
= sRequestCallbackRecords
->getCount();
9831 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9832 sRequestCallbackRecords
->getObject(i
));
9837 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9838 _OSKextGetRequestArgument(request
,
9839 kKextRequestArgumentCallbackKey
));
9841 if (!callbackWrapper
) {
9842 sRequestCallbackRecords
->removeObject(i
);
9846 vm_address_t callbackAddress
= (vm_address_t
)
9847 _OSKextExtractPointer(callbackWrapper
);
9849 if ((kmod_info
->address
<= callbackAddress
) &&
9850 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9853 /* This removes the callback record.
9855 invokeRequestCallback(request
, callbackResult
);
9857 sRequestCallbackRecords
->removeObject(i
);
9866 /*********************************************************************
9867 * Assumes sKextLock is held.
9868 *********************************************************************/
9870 OSKext::countRequestCallbacks(void)
9872 uint32_t result
= 0;
9873 unsigned int count
, i
;
9875 count
= sRequestCallbackRecords
->getCount();
9882 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9883 sRequestCallbackRecords
->getObject(i
));
9888 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9889 _OSKextGetRequestArgument(request
,
9890 kKextRequestArgumentCallbackKey
));
9892 if (!callbackWrapper
) {
9896 vm_address_t callbackAddress
= (vm_address_t
)
9897 _OSKextExtractPointer(callbackWrapper
);
9899 if ((kmod_info
->address
<= callbackAddress
) &&
9900 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9910 /*********************************************************************
9911 *********************************************************************/
9912 static OSReturn
_OSKextCreateRequest(
9913 const char * predicate
,
9914 OSDictionary
** requestP
)
9916 OSReturn result
= kOSKextReturnNoMemory
;
9917 OSDictionary
* request
= NULL
; // must release on error
9919 request
= OSDictionary::withCapacity(2);
9923 result
= _OSDictionarySetCStringValue(request
,
9924 kKextRequestPredicateKey
, predicate
);
9925 if (result
!= kOSReturnSuccess
) {
9928 result
= kOSReturnSuccess
;
9931 if (result
!= kOSReturnSuccess
) {
9932 if (request
) request
->release();
9934 *requestP
= request
;
9940 /*********************************************************************
9941 *********************************************************************/
9942 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
9944 return OSDynamicCast(OSString
,
9945 requestDict
->getObject(kKextRequestPredicateKey
));
9948 /*********************************************************************
9949 *********************************************************************/
9950 static OSObject
* _OSKextGetRequestArgument(
9951 OSDictionary
* requestDict
,
9952 const char * argName
)
9954 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9955 requestDict
->getObject(kKextRequestArgumentsKey
));
9957 return args
->getObject(argName
);
9962 /*********************************************************************
9963 *********************************************************************/
9964 static bool _OSKextSetRequestArgument(
9965 OSDictionary
* requestDict
,
9966 const char * argName
,
9969 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9970 requestDict
->getObject(kKextRequestArgumentsKey
));
9972 args
= OSDictionary::withCapacity(2);
9976 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
9980 return args
->setObject(argName
, value
);
9986 /*********************************************************************
9987 *********************************************************************/
9988 static void * _OSKextExtractPointer(OSData
* wrapper
)
9990 void * result
= NULL
;
9991 const void * resultPtr
= NULL
;
9996 resultPtr
= wrapper
->getBytesNoCopy();
9997 result
= *(void **)resultPtr
;
10002 /*********************************************************************
10003 *********************************************************************/
10004 static OSReturn
_OSDictionarySetCStringValue(
10005 OSDictionary
* dict
,
10007 const char * cValue
)
10009 OSReturn result
= kOSKextReturnNoMemory
;
10010 const OSSymbol
* key
= NULL
; // must release
10011 OSString
* value
= NULL
; // must release
10013 key
= OSSymbol::withCString(cKey
);
10014 value
= OSString::withCString(cValue
);
10015 if (!key
|| !value
) {
10018 if (dict
->setObject(key
, value
)) {
10019 result
= kOSReturnSuccess
;
10023 if (key
) key
->release();
10024 if (value
) value
->release();
10029 /*********************************************************************
10030 *********************************************************************/
10031 static bool _OSArrayContainsCString(
10033 const char * cString
)
10035 bool result
= false;
10036 const OSSymbol
* symbol
= NULL
;
10039 if (!array
|| !cString
) {
10043 symbol
= OSSymbol::withCStringNoCopy(cString
);
10048 count
= array
->getCount();
10049 for (i
= 0; i
< count
; i
++) {
10050 OSObject
* thisObject
= array
->getObject(i
);
10051 if (symbol
->isEqualTo(thisObject
)) {
10058 if (symbol
) symbol
->release();
10062 /*********************************************************************
10063 * We really only care about boot / system start up related kexts.
10064 * We return true if we're less than REBUILD_MAX_TIME since start up,
10065 * otherwise return false.
10066 *********************************************************************/
10067 bool _OSKextInPrelinkRebuildWindow(void)
10069 static bool outside_the_window
= false;
10070 AbsoluteTime my_abstime
;
10074 if (outside_the_window
) {
10077 clock_get_uptime(&my_abstime
);
10078 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
10079 my_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
10080 if (my_secs
> REBUILD_MAX_TIME
) {
10081 outside_the_window
= true;
10087 /*********************************************************************
10088 *********************************************************************/
10089 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
10091 int unLoadedCount
, i
;
10092 bool result
= false;
10094 IORecursiveLockLock(sKextLock
);
10096 if (sUnloadedPrelinkedKexts
== NULL
) {
10099 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
10100 if (unLoadedCount
== 0) {
10104 for (i
= 0; i
< unLoadedCount
; i
++) {
10105 const OSSymbol
* myBundleID
; // do not release
10107 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
10108 if (!myBundleID
) continue;
10109 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
10115 IORecursiveLockUnlock(sKextLock
);
10120 #pragma mark Personalities (IOKit Drivers)
10122 /*********************************************************************
10123 *********************************************************************/
10126 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
10128 OSArray
* result
= NULL
; // returned
10129 OSCollectionIterator
* kextIterator
= NULL
; // must release
10130 OSArray
* personalities
= NULL
; // must release
10131 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
10133 OSString
* kextID
= NULL
; // do not release
10134 OSKext
* theKext
= NULL
; // do not release
10136 IORecursiveLockLock(sKextLock
);
10138 /* Let's conservatively guess that any given kext has around 3
10139 * personalities for now.
10141 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
10146 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
10147 if (!kextIterator
) {
10151 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
10152 if (personalitiesIterator
) {
10153 personalitiesIterator
->release();
10154 personalitiesIterator
= NULL
;
10156 if (personalities
) {
10157 personalities
->release();
10158 personalities
= NULL
;
10161 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
10162 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
10163 personalities
= theKext
->copyPersonalitiesArray();
10164 if (!personalities
) {
10167 result
->merge(personalities
);
10169 // xxx - check for better place to put this log msg
10171 kOSKextLogWarningLevel
|
10172 kOSKextLogLoadFlag
,
10173 "Kext %s is not loadable during safe boot; "
10174 "omitting its personalities.",
10175 theKext
->getIdentifierCString());
10181 IORecursiveLockUnlock(sKextLock
);
10183 if (kextIterator
) kextIterator
->release();
10184 if (personalitiesIterator
) personalitiesIterator
->release();
10185 if (personalities
) personalities
->release();
10190 /*********************************************************************
10191 *********************************************************************/
10194 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
10196 int numPersonalities
= 0;
10198 OSKextLog(/* kext */ NULL
,
10199 kOSKextLogStepLevel
|
10200 kOSKextLogLoadFlag
,
10201 "Sending all eligible registered kexts' personalities "
10202 "to the IOCatalogue %s.",
10203 startMatching
? "and starting matching" : "but not starting matching");
10205 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
10206 /* filterSafeBootFlag */ true);
10208 if (personalities
) {
10209 gIOCatalogue
->addDrivers(personalities
, startMatching
);
10210 numPersonalities
= personalities
->getCount();
10211 personalities
->release();
10214 OSKextLog(/* kext */ NULL
,
10215 kOSKextLogStepLevel
|
10216 kOSKextLogLoadFlag
,
10217 "%d kext personalit%s sent to the IOCatalogue; %s.",
10218 numPersonalities
, numPersonalities
> 0 ? "ies" : "y",
10219 startMatching
? "matching started" : "matching not started");
10223 /*********************************************************************
10224 * Do not make a deep copy, just convert the IOKitPersonalities dict
10225 * to an array for sending to the IOCatalogue.
10226 *********************************************************************/
10228 OSKext::copyPersonalitiesArray(void)
10230 OSArray
* result
= NULL
;
10231 OSDictionary
* personalities
= NULL
; // do not release
10232 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
10234 OSString
* personalityName
= NULL
; // do not release
10235 OSString
* personalityBundleIdentifier
= NULL
; // do not release
10237 personalities
= OSDynamicCast(OSDictionary
,
10238 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10239 if (!personalities
) {
10243 result
= OSArray::withCapacity(personalities
->getCount());
10248 personalitiesIterator
=
10249 OSCollectionIterator::withCollection(personalities
);
10250 if (!personalitiesIterator
) {
10253 while ((personalityName
= OSDynamicCast(OSString
,
10254 personalitiesIterator
->getNextObject()))) {
10256 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10257 personalities
->getObject(personalityName
));
10260 * If the personality doesn't have a CFBundleIdentifier, or if it
10261 * differs from the kext's, insert the kext's ID so we can find it.
10262 * The publisher ID is used to remove personalities from bundles
10265 personalityBundleIdentifier
= OSDynamicCast(OSString
,
10266 personality
->getObject(kCFBundleIdentifierKey
));
10268 if (!personalityBundleIdentifier
) {
10269 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
10270 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
10271 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
10274 result
->setObject(personality
);
10278 if (personalitiesIterator
) personalitiesIterator
->release();
10283 /*********************************************************************
10284 Might want to change this to a bool return?
10285 *********************************************************************/
10287 OSKext::sendPersonalitiesToCatalog(
10288 bool startMatching
,
10289 OSArray
* personalityNames
)
10291 OSReturn result
= kOSReturnSuccess
;
10292 OSArray
* personalitiesToSend
= NULL
; // must release
10293 OSDictionary
* kextPersonalities
= NULL
; // do not release
10296 if (!sLoadEnabled
) {
10298 kOSKextLogErrorLevel
|
10299 kOSKextLogLoadFlag
,
10300 "Kext loading is disabled (attempt to start matching for kext %s).",
10301 getIdentifierCString());
10302 result
= kOSKextReturnDisabled
;
10306 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
10308 kOSKextLogErrorLevel
|
10309 kOSKextLogLoadFlag
,
10310 "Kext %s is not loadable during safe boot; "
10311 "not sending personalities to the IOCatalogue.",
10312 getIdentifierCString());
10313 result
= kOSKextReturnNotLoadable
;
10317 if (!personalityNames
|| !personalityNames
->getCount()) {
10318 personalitiesToSend
= copyPersonalitiesArray();
10320 kextPersonalities
= OSDynamicCast(OSDictionary
,
10321 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10322 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
10326 personalitiesToSend
= OSArray::withCapacity(0);
10327 if (!personalitiesToSend
) {
10328 result
= kOSKextReturnNoMemory
;
10331 count
= personalityNames
->getCount();
10332 for (i
= 0; i
< count
; i
++) {
10333 OSString
* name
= OSDynamicCast(OSString
,
10334 personalityNames
->getObject(i
));
10338 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10339 kextPersonalities
->getObject(name
));
10341 personalitiesToSend
->setObject(personality
);
10345 if (personalitiesToSend
) {
10346 unsigned numPersonalities
= personalitiesToSend
->getCount();
10348 kOSKextLogStepLevel
|
10349 kOSKextLogLoadFlag
,
10350 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
10351 getIdentifierCString(),
10353 numPersonalities
> 1 ? "ies" : "y",
10354 startMatching
? " and starting matching" : " but not starting matching");
10355 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
10358 if (personalitiesToSend
) {
10359 personalitiesToSend
->release();
10364 /*********************************************************************
10365 * xxx - We should allow removing the kext's declared personalities,
10366 * xxx - even with other bundle identifiers.
10367 *********************************************************************/
10369 OSKext::removePersonalitiesFromCatalog(void)
10371 OSDictionary
* personality
= NULL
; // do not release
10373 personality
= OSDictionary::withCapacity(1);
10374 if (!personality
) {
10377 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
10380 kOSKextLogStepLevel
|
10381 kOSKextLogLoadFlag
,
10382 "Kext %s removing all personalities naming it from the IOCatalogue.",
10383 getIdentifierCString());
10385 /* Have the IOCatalog remove all personalities matching this kext's
10386 * bundle ID and trigger matching anew.
10388 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
10391 if (personality
) personality
->release();
10398 #pragma mark Logging
10400 /*********************************************************************
10401 * Do not call any function that takes sKextLock here!
10402 *********************************************************************/
10405 OSKext::setUserSpaceLogFilter(
10406 OSKextLogSpec newUserLogFilter
,
10409 OSKextLogSpec result
;
10410 bool allocError
= false;
10412 /* Do not call any function that takes sKextLoggingLock during
10413 * this critical block. That means do logging after.
10415 IOLockLock(sKextLoggingLock
);
10417 result
= sUserSpaceKextLogFilter
;
10418 sUserSpaceKextLogFilter
= newUserLogFilter
;
10420 if (newUserLogFilter
&& captureFlag
&&
10421 !sUserSpaceLogSpecArray
&& !sUserSpaceLogMessageArray
) {
10423 // xxx - do some measurements for a good initial capacity?
10424 sUserSpaceLogSpecArray
= OSArray::withCapacity(0);
10425 sUserSpaceLogMessageArray
= OSArray::withCapacity(0);
10427 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
10428 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10429 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10434 IOLockUnlock(sKextLoggingLock
);
10436 /* If the config flag itself is changing, log the state change
10437 * going both ways, before setting up the user-space log arrays,
10438 * so that this is only logged in the kernel.
10440 if (result
!= newUserLogFilter
) {
10441 OSKextLog(/* kext */ NULL
,
10442 kOSKextLogDebugLevel
|
10443 kOSKextLogGeneralFlag
,
10444 "User-space log flags changed from 0x%x to 0x%x.",
10445 result
, newUserLogFilter
);
10448 OSKextLog(/* kext */ NULL
,
10449 kOSKextLogErrorLevel
|
10450 kOSKextLogGeneralFlag
,
10451 "Failed to allocate user-space log message arrays.");
10457 /*********************************************************************
10458 * Do not call any function that takes sKextLock here!
10459 *********************************************************************/
10462 OSKext::clearUserSpaceLogFilter(void)
10464 OSArray
* result
= NULL
;
10465 OSKextLogSpec oldLogFilter
;
10466 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
10468 /* Do not call any function that takes sKextLoggingLock during
10469 * this critical block. That means do logging after.
10471 IOLockLock(sKextLoggingLock
);
10473 result
= OSArray::withCapacity(2);
10475 result
->setObject(sUserSpaceLogSpecArray
);
10476 result
->setObject(sUserSpaceLogMessageArray
);
10478 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10479 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10481 oldLogFilter
= sUserSpaceKextLogFilter
;
10482 sUserSpaceKextLogFilter
= newLogFilter
;
10484 IOLockUnlock(sKextLoggingLock
);
10486 /* If the config flag itself is changing, log the state change
10487 * going both ways, after tearing down the user-space log
10488 * arrays, so this is only logged within the kernel.
10490 if (oldLogFilter
!= newLogFilter
) {
10491 OSKextLog(/* kext */ NULL
,
10492 kOSKextLogDebugLevel
|
10493 kOSKextLogGeneralFlag
,
10494 "User-space log flags changed from 0x%x to 0x%x.",
10495 oldLogFilter
, newLogFilter
);
10502 /*********************************************************************
10503 * Do not call any function that takes sKextLock here!
10504 *********************************************************************/
10507 OSKext::getUserSpaceLogFilter(void)
10509 OSKextLogSpec result
;
10511 IOLockLock(sKextLoggingLock
);
10512 result
= sUserSpaceKextLogFilter
;
10513 IOLockUnlock(sKextLoggingLock
);
10518 /*********************************************************************
10519 * This function is called by OSMetaClass during kernel C++ setup.
10520 * Be careful what you access here; assume only OSKext::initialize()
10523 * Do not call any function that takes sKextLock here!
10524 *********************************************************************/
10525 #define VTRESET "\033[0m"
10527 #define VTBOLD "\033[1m"
10528 #define VTUNDER "\033[4m"
10530 #define VTRED "\033[31m"
10531 #define VTGREEN "\033[32m"
10532 #define VTYELLOW "\033[33m"
10533 #define VTBLUE "\033[34m"
10534 #define VTMAGENTA "\033[35m"
10535 #define VTCYAN "\033[36m"
10537 inline const char * colorForFlags(OSKextLogSpec flags
)
10539 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
10541 switch (logLevel
) {
10542 case kOSKextLogErrorLevel
:
10543 return VTRED VTBOLD
;
10544 case kOSKextLogWarningLevel
:
10546 case kOSKextLogBasicLevel
:
10547 return VTYELLOW VTUNDER
;
10548 case kOSKextLogProgressLevel
:
10550 case kOSKextLogStepLevel
:
10552 case kOSKextLogDetailLevel
:
10554 case kOSKextLogDebugLevel
:
10557 return ""; // white
10561 inline bool logSpecMatch(
10562 OSKextLogSpec msgLogSpec
,
10563 OSKextLogSpec logFilter
)
10565 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
10566 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
10567 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
10569 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
10570 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
10571 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
10573 /* Explicit messages always get logged.
10575 if (msgLevel
== kOSKextLogExplicitLevel
) {
10579 /* Warnings and errors are logged regardless of the flags.
10581 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
10585 /* A verbose message that isn't for a logging-enabled kext and isn't global
10586 * does *not* get logged.
10588 if (!msgKextGlobal
&& !filterKextGlobal
) {
10592 /* Warnings and errors are logged regardless of the flags.
10593 * All other messages must fit the flags and
10594 * have a level at or below the filter.
10597 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
10608 OSKextLogSpec msgLogSpec
,
10609 const char * format
, ...)
10613 va_start(argList
, format
);
10614 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
10621 OSKextLogSpec msgLogSpec
,
10622 const char * format
,
10623 va_list srcArgList
)
10625 extern int disableConsoleOutput
;
10627 bool logForKernel
= false;
10628 bool logForUser
= false;
10630 char stackBuffer
[120];
10631 uint32_t length
= 0;
10632 char * allocBuffer
= NULL
; // must kfree
10633 OSNumber
* logSpecNum
= NULL
; // must release
10634 OSString
* logString
= NULL
; // must release
10635 char * buffer
= stackBuffer
; // do not free
10637 IOLockLock(sKextLoggingLock
);
10639 /* Set the kext/global bit in the message spec if we have no
10640 * kext or if the kext requests logging.
10642 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
10643 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
10646 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
10647 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10648 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
10651 if (! (logForKernel
|| logForUser
) ) {
10655 /* No goto from here until past va_end()!
10657 va_copy(argList
, srcArgList
);
10658 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
10661 if (length
+ 1 >= sizeof(stackBuffer
)) {
10662 allocBuffer
= (char *)kalloc_tag((length
+ 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT
);
10663 if (!allocBuffer
) {
10667 /* No goto from here until past va_end()!
10669 va_copy(argList
, srcArgList
);
10670 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
10673 buffer
= allocBuffer
;
10676 /* If user space wants the log message, queue it up.
10678 if (logForUser
&& sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10679 logSpecNum
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
));
10680 logString
= OSString::withCString(buffer
);
10681 if (logSpecNum
&& logString
) {
10682 sUserSpaceLogSpecArray
->setObject(logSpecNum
);
10683 sUserSpaceLogMessageArray
->setObject(logString
);
10687 /* Always log messages from the kernel according to the kernel's
10690 if (logForKernel
) {
10692 /* If we are in console mode and have a custom log filter,
10693 * colorize the log message.
10695 if (!disableConsoleOutput
&& sBootArgLogFilterFound
) {
10696 const char * color
= ""; // do not free
10697 color
= colorForFlags(msgLogSpec
);
10698 printf("%s%s%s\n", colorForFlags(msgLogSpec
),
10699 buffer
, color
[0] ? VTRESET
: "");
10701 printf("%s\n", buffer
);
10706 IOLockUnlock(sKextLoggingLock
);
10709 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
10711 OSSafeReleaseNULL(logString
);
10712 OSSafeReleaseNULL(logSpecNum
);
10716 #if KASLR_IOREG_DEBUG
10718 #define IOLOG_INDENT( the_indention ) \
10721 for ( i = 0; i < (the_indention); i++ ) { \
10726 extern vm_offset_t vm_kernel_stext
;
10727 extern vm_offset_t vm_kernel_etext
;
10728 extern mach_vm_offset_t kext_alloc_base
;
10729 extern mach_vm_offset_t kext_alloc_max
;
10731 bool ScanForAddrInObject(OSObject
* theObject
,
10734 bool ScanForAddrInObject(OSObject
* theObject
,
10737 const OSMetaClass
* myTypeID
;
10738 OSCollectionIterator
* myIter
;
10740 OSObject
* myValue
;
10741 bool myResult
= false;
10743 if ( theObject
== NULL
) {
10744 IOLog("%s: theObject is NULL \n",
10749 myTypeID
= OSTypeIDInst(theObject
);
10751 if ( myTypeID
== OSTypeID(OSDictionary
) ) {
10752 OSDictionary
* myDictionary
;
10754 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
10755 myIter
= OSCollectionIterator::withCollection( myDictionary
);
10756 if ( myIter
== NULL
)
10760 while ( (myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject())) ) {
10763 myValue
= myDictionary
->getObject(myKey
);
10764 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10765 if (myTempResult
) {
10766 // if we ever get a true result return true
10768 IOLOG_INDENT(indent
);
10769 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
10774 else if ( myTypeID
== OSTypeID(OSArray
) ) {
10777 myArray
= OSDynamicCast(OSArray
, theObject
);
10778 myIter
= OSCollectionIterator::withCollection(myArray
);
10779 if ( myIter
== NULL
)
10783 while ( (myValue
= myIter
->getNextObject()) ) {
10785 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10786 if (myTempResult
) {
10787 // if we ever get a true result return true
10789 IOLOG_INDENT(indent
);
10790 IOLog("OSArray: \n");
10795 else if ( myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
) ) {
10797 // should we look for addresses in strings?
10799 else if ( myTypeID
== OSTypeID(OSData
) ) {
10802 unsigned int myLen
;
10803 OSData
* myDataObj
;
10805 myDataObj
= OSDynamicCast(OSData
, theObject
);
10806 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
10807 myLen
= myDataObj
->getLength();
10809 if (myPtrPtr
&& myLen
&& myLen
> 7) {
10811 int myPtrCount
= (myLen
/ sizeof(void *));
10813 for (i
= 0; i
< myPtrCount
; i
++) {
10814 UInt64 numberValue
= (UInt64
) *(myPtrPtr
);
10816 if ( kext_alloc_max
!= 0 &&
10817 numberValue
>= kext_alloc_base
&&
10818 numberValue
< kext_alloc_max
) {
10820 OSKext
* myKext
= NULL
; // must release (looked up)
10821 // IOLog("found OSData %p in kext map %p to %p \n",
10823 // (void *) kext_alloc_base,
10824 // (void *) kext_alloc_max);
10826 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) *(myPtrPtr
) );
10828 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
10830 myKext
->getIdentifierCString());
10835 if ( vm_kernel_etext
!= 0 &&
10836 numberValue
>= vm_kernel_stext
&&
10837 numberValue
< vm_kernel_etext
) {
10838 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
10840 (void *) vm_kernel_stext
,
10841 (void *) vm_kernel_etext
);
10848 else if ( myTypeID
== OSTypeID(OSBoolean
) ) {
10850 // do nothing here...
10852 else if ( myTypeID
== OSTypeID(OSNumber
) ) {
10854 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
10856 UInt64 numberValue
= number
->unsigned64BitValue();
10858 if ( kext_alloc_max
!= 0 &&
10859 numberValue
>= kext_alloc_base
&&
10860 numberValue
< kext_alloc_max
) {
10862 OSKext
* myKext
= NULL
; // must release (looked up)
10863 IOLog("found OSNumber in kext map %p to %p \n",
10864 (void *) kext_alloc_base
,
10865 (void *) kext_alloc_max
);
10866 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10868 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) numberValue
);
10870 IOLog("found in kext \"%s\" \n",
10871 myKext
->getIdentifierCString());
10877 if ( vm_kernel_etext
!= 0 &&
10878 numberValue
>= vm_kernel_stext
&&
10879 numberValue
< vm_kernel_etext
) {
10880 IOLog("found OSNumber in kernel text segment %p to %p \n",
10881 (void *) vm_kernel_stext
,
10882 (void *) vm_kernel_etext
);
10883 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10889 const OSMetaClass
* myMetaClass
= NULL
;
10891 myMetaClass
= theObject
->getMetaClass();
10892 if ( myMetaClass
) {
10893 IOLog("class %s \n", myMetaClass
->getClassName() );
10896 IOLog("Unknown object \n" );
10903 #endif // KASLR_KEXT_DEBUG
10905 }; /* extern "C" */
10908 #pragma mark Backtrace Dump & kmod_get_info() support
10910 /*********************************************************************
10911 * This function must be safe to call in panic context.
10912 *********************************************************************/
10915 OSKext::printKextsInBacktrace(
10916 vm_offset_t
* addr
,
10918 int (* printf_func
)(const char *fmt
, ...),
10921 addr64_t summary_page
= 0;
10922 addr64_t last_summary_page
= 0;
10923 bool found_kmod
= false;
10926 if (kPrintKextsLock
& flags
) {
10927 if (!sKextSummariesLock
) return;
10928 IOLockLock(sKextSummariesLock
);
10931 if (!gLoadedKextSummaries
) {
10932 (*printf_func
)(" can't perform kext scan: no kext summary");
10936 summary_page
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
);
10937 last_summary_page
= round_page(summary_page
+ sLoadedKextSummariesAllocSize
);
10938 for (; summary_page
< last_summary_page
; summary_page
+= PAGE_SIZE
) {
10939 if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) {
10940 (*printf_func
)(" can't perform kext scan: "
10941 "missing kext summary page %p", summary_page
);
10946 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10947 OSKextLoadedKextSummary
* summary
;
10949 summary
= gLoadedKextSummaries
->summaries
+ i
;
10950 if (!summary
->address
) {
10954 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
10959 if (!(kPrintKextsTerse
& flags
)) {
10960 (*printf_func
)(" Kernel Extensions in backtrace:\n");
10965 printSummary(summary
, printf_func
, flags
);
10969 if (kPrintKextsLock
& flags
) {
10970 IOLockUnlock(sKextSummariesLock
);
10976 /*********************************************************************
10977 * This function must be safe to call in panic context.
10978 *********************************************************************/
10981 OSKext::summaryIsInBacktrace(
10982 OSKextLoadedKextSummary
* summary
,
10983 vm_offset_t
* addr
,
10988 for (i
= 0; i
< cnt
; i
++) {
10989 vm_offset_t kscan_addr
= addr
[i
];
10990 if ((kscan_addr
>= summary
->address
) &&
10991 (kscan_addr
< (summary
->address
+ summary
->size
)))
11001 * Get the kext summary object for the kext where 'addr' lies. Must be called with
11002 * sKextSummariesLock held.
11004 OSKextLoadedKextSummary
*
11005 OSKext::summaryForAddress(const uintptr_t addr
)
11007 for (unsigned i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
11009 OSKextLoadedKextSummary
*summary
= &gLoadedKextSummaries
->summaries
[i
];
11010 if (!summary
->address
) {
11014 #if VM_MAPPED_KEXTS
11015 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not
11016 * support split kexts, but we also may unmap the kexts, which can
11017 * race with the above codepath (see OSKext::unload). As such,
11018 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
11020 if ((addr
>= summary
->address
) && (addr
< (summary
->address
+ summary
->size
))) {
11024 kernel_mach_header_t
*mh
= (kernel_mach_header_t
*)summary
->address
;
11025 kernel_segment_command_t
*seg
;
11027 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
11028 if ((addr
>= seg
->vmaddr
) && (addr
< (seg
->vmaddr
+ seg
->vmsize
))) {
11035 /* addr did not map to any kext */
11041 OSKext::kextForAddress(const void *addr
)
11043 void *image
= NULL
;
11045 if (((vm_offset_t
)(uintptr_t)addr
>= vm_kernel_stext
) &&
11046 ((vm_offset_t
)(uintptr_t)addr
< vm_kernel_etext
)) {
11047 return (void *)&_mh_execute_header
;
11050 if (!sKextSummariesLock
) {
11053 IOLockLock(sKextSummariesLock
);
11054 OSKextLoadedKextSummary
*summary
= OSKext::summaryForAddress((uintptr_t)addr
);
11056 image
= (void *)summary
->address
;
11058 IOLockUnlock(sKextSummariesLock
);
11063 /*********************************************************************
11064 * scan list of loaded kext summaries looking for a load address match and if
11065 * found return the UUID C string. If not found then set empty string.
11066 *********************************************************************/
11067 static void findSummaryUUID(
11069 uuid_string_t uuid
);
11071 static void findSummaryUUID(
11073 uuid_string_t uuid
)
11077 uuid
[0] = 0x00; // default to no UUID
11079 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
11080 OSKextLoadedKextSummary
* summary
;
11082 summary
= gLoadedKextSummaries
->summaries
+ i
;
11084 if (summary
->loadTag
== tag_ID
) {
11085 (void) uuid_unparse(summary
->uuid
, uuid
);
11092 /*********************************************************************
11093 * This function must be safe to call in panic context.
11094 *********************************************************************/
11095 void OSKext::printSummary(
11096 OSKextLoadedKextSummary
* summary
,
11097 int (* printf_func
)(const char *fmt
, ...),
11100 kmod_reference_t
* kmod_ref
= NULL
;
11101 uuid_string_t uuid
;
11102 char version
[kOSKextVersionMaxLength
];
11105 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
11106 strlcpy(version
, "unknown version", sizeof(version
));
11108 (void) uuid_unparse(summary
->uuid
, uuid
);
11110 if (kPrintKextsUnslide
& flags
) {
11111 tmpAddr
= VM_KERNEL_UNSLIDE(summary
->address
);
11114 tmpAddr
= summary
->address
;
11116 (*printf_func
)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
11117 (kPrintKextsTerse
& flags
) ? "" : " ",
11118 summary
->name
, version
, uuid
,
11119 tmpAddr
, tmpAddr
+ summary
->size
- 1);
11121 if (kPrintKextsTerse
& flags
) return;
11123 /* print dependency info */
11124 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
11126 kmod_ref
= kmod_ref
->next
) {
11127 kmod_info_t
* rinfo
;
11129 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) {
11130 (*printf_func
)(" kmod dependency scan stopped "
11131 "due to missing dependency page: %p\n",
11132 (kPrintKextsUnslide
& flags
) ? (void *)VM_KERNEL_UNSLIDE(kmod_ref
) : kmod_ref
);
11135 rinfo
= kmod_ref
->info
;
11137 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) {
11138 (*printf_func
)(" kmod dependency scan stopped "
11139 "due to missing kmod page: %p\n",
11140 (kPrintKextsUnslide
& flags
) ? (void *)VM_KERNEL_UNSLIDE(rinfo
) : rinfo
);
11144 if (!rinfo
->address
) {
11145 continue; // skip fake entries for built-ins
11148 /* locate UUID in gLoadedKextSummaries */
11149 findSummaryUUID(rinfo
->id
, uuid
);
11151 if (kPrintKextsUnslide
& flags
) {
11152 tmpAddr
= VM_KERNEL_UNSLIDE(rinfo
->address
);
11155 tmpAddr
= rinfo
->address
;
11157 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
11158 rinfo
->name
, rinfo
->version
, uuid
, tmpAddr
);
11164 /*******************************************************************************
11165 * substitute() looks at an input string (a pointer within a larger buffer)
11166 * for a match to a substring, and on match it writes the marker & substitution
11167 * character to an output string, updating the scan (from) and
11168 * output (to) indexes as appropriate.
11169 *******************************************************************************/
11170 static int substitute(
11171 const char * scan_string
,
11173 uint32_t * to_index
,
11174 uint32_t * from_index
,
11175 const char * substring
,
11177 char substitution
);
11179 /* string_out must be at least KMOD_MAX_NAME bytes.
11183 const char * scan_string
,
11185 uint32_t * to_index
,
11186 uint32_t * from_index
,
11187 const char * substring
,
11191 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
11193 /* On a substring match, append the marker (if there is one) and then
11194 * the substitution character, updating the output (to) index accordingly.
11195 * Then update the input (from) length by the length of the substring
11196 * that got replaced.
11198 if (!strncmp(scan_string
, substring
, substring_length
)) {
11200 string_out
[(*to_index
)++] = marker
;
11202 string_out
[(*to_index
)++] = substitution
;
11203 (*from_index
) += substring_length
;
11209 /*******************************************************************************
11210 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
11211 * KMOD_MAX_NAME characters and performs various substitutions of common
11212 * prefixes & substrings as defined by tables in kext_panic_report.h.
11213 *******************************************************************************/
11214 static void compactIdentifier(
11215 const char * identifier
,
11216 char * identifier_out
,
11217 char ** identifier_out_end
);
11221 const char * identifier
,
11222 char * identifier_out
,
11223 char ** identifier_out_end
)
11225 uint32_t from_index
, to_index
;
11226 uint32_t scan_from_index
= 0;
11227 uint32_t scan_to_index
= 0;
11228 subs_entry_t
* subs_entry
= NULL
;
11231 from_index
= to_index
= 0;
11232 identifier_out
[0] = '\0';
11234 /* Replace certain identifier prefixes with shorter @+character sequences.
11235 * Check the return value of substitute() so we only replace the prefix.
11237 for (subs_entry
= &kext_identifier_prefix_subs
[0];
11238 subs_entry
->substring
&& !did_sub
;
11241 did_sub
= substitute(identifier
, identifier_out
,
11242 &scan_to_index
, &scan_from_index
,
11243 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
11247 /* Now scan through the identifier looking for the common substrings
11248 * and replacing them with shorter !+character sequences via substitute().
11250 for (/* see above */;
11251 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
11254 const char * scan_string
= &identifier
[scan_from_index
];
11258 if (scan_from_index
) {
11259 for (subs_entry
= &kext_identifier_substring_subs
[0];
11260 subs_entry
->substring
&& !did_sub
;
11263 did_sub
= substitute(scan_string
, identifier_out
,
11264 &scan_to_index
, &scan_from_index
,
11265 subs_entry
->substring
, '!', subs_entry
->substitute
);
11269 /* If we didn't substitute, copy the input character to the output.
11272 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
11276 identifier_out
[scan_to_index
] = '\0';
11277 if (identifier_out_end
) {
11278 *identifier_out_end
= &identifier_out
[scan_to_index
];
11284 /*******************************************************************************
11285 * assemble_identifier_and_version() adds to a string buffer a compacted
11286 * bundle identifier followed by a version string.
11287 *******************************************************************************/
11289 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
11291 static int assemble_identifier_and_version(
11292 kmod_info_t
* kmod_info
,
11293 char * identPlusVers
,
11297 assemble_identifier_and_version(
11298 kmod_info_t
* kmod_info
,
11299 char * identPlusVers
,
11304 compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
);
11305 result
= strnlen(identPlusVers
, KMOD_MAX_NAME
- 1);
11306 identPlusVers
[result
++] = '\t'; // increment for real char
11307 identPlusVers
[result
] = '\0'; // don't increment for nul char
11308 result
= strlcat(identPlusVers
, kmod_info
->version
, bufSize
);
11309 if (result
>= bufSize
) {
11310 identPlusVers
[bufSize
- 1] = '\0';
11311 result
= bufSize
- 1;
11317 /*******************************************************************************
11318 * Assumes sKextLock is held.
11319 *******************************************************************************/
11322 OSKext::saveLoadedKextPanicListTyped(
11323 const char * prefix
,
11327 uint32_t list_size
)
11330 unsigned int count
, i
;
11332 count
= sLoadedKexts
->getCount();
11339 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
11340 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
11342 uint32_t identPlusVersLength
;
11344 char identPlusVers
[2*KMOD_MAX_NAME
];
11347 printf("OSKext::saveLoadedKextPanicListTyped - "
11348 "NULL kext in loaded kext list; continuing\n");
11353 printf("OSKext::saveLoadedKextPanicListTyped - "
11354 "Kext type cast failed in loaded kext list; continuing\n");
11358 /* Skip all built-in kexts.
11360 if (theKext
->isKernelComponent()) {
11364 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
11366 /* Filter for kmod name (bundle identifier).
11368 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
11369 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
11373 /* Filter for libraries (kexts that have a compatible version).
11375 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
11376 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
11382 !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) {
11384 printf("kext scan stopped due to missing kmod_info page: %p\n",
11389 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
11391 sizeof(identPlusVers
));
11392 if (!identPlusVersLength
) {
11393 printf("error saving loaded kext info\n");
11397 /* make sure everything fits and we null terminate.
11399 tempLen
= strlcat(paniclist
, identPlusVers
, list_size
);
11400 if (tempLen
>= list_size
) {
11401 // panic list is full, keep it and null terminate
11402 paniclist
[list_size
- 1] = 0x00;
11406 tempLen
= strlcat(paniclist
, "\n", list_size
);
11407 if (tempLen
>= list_size
) {
11408 // panic list is full, keep it and null terminate
11409 paniclist
[list_size
- 1] = 0x00;
11421 /*********************************************************************
11422 *********************************************************************/
11425 OSKext::saveLoadedKextPanicList(void)
11427 char * newlist
= NULL
;
11428 uint32_t newlist_size
= 0;
11430 newlist_size
= KEXT_PANICLIST_SIZE
;
11431 newlist
= (char *)kalloc_tag(newlist_size
, VM_KERN_MEMORY_OSKEXT
);
11434 OSKextLog(/* kext */ NULL
,
11435 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
11436 "Couldn't allocate kext panic log buffer.");
11442 // non-"com.apple." kexts
11443 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
11444 /* libs? */ -1, newlist
, newlist_size
) != 0) {
11448 // "com.apple." nonlibrary kexts
11449 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11450 /* libs? */ 0, newlist
, newlist_size
) != 0) {
11454 // "com.apple." library kexts
11455 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11456 /* libs? */ 1, newlist
, newlist_size
) != 0) {
11461 if (loaded_kext_paniclist
) {
11462 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
11464 loaded_kext_paniclist
= newlist
;
11466 loaded_kext_paniclist_size
= newlist_size
;
11470 kfree(newlist
, newlist_size
);
11475 /*********************************************************************
11476 * Assumes sKextLock is held.
11477 *********************************************************************/
11479 OSKext::savePanicString(bool isLoading
)
11484 return; // do not goto finish here b/c of lock
11487 len
= assemble_identifier_and_version( kmod_info
,
11488 (isLoading
) ? last_loaded_str_buf
: last_unloaded_str_buf
,
11489 (isLoading
) ? sizeof(last_loaded_str_buf
) : sizeof(last_unloaded_str_buf
) );
11491 printf("error saving unloaded kext info\n");
11496 last_loaded_strlen
= len
;
11497 last_loaded_address
= (void *)kmod_info
->address
;
11498 last_loaded_size
= kmod_info
->size
;
11499 clock_get_uptime(&last_loaded_timestamp
);
11501 last_unloaded_strlen
= len
;
11502 last_unloaded_address
= (void *)kmod_info
->address
;
11503 last_unloaded_size
= kmod_info
->size
;
11504 clock_get_uptime(&last_unloaded_timestamp
);
11511 /*********************************************************************
11512 *********************************************************************/
11515 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
11517 if (last_loaded_strlen
) {
11518 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
11519 AbsoluteTime_to_scalar(&last_loaded_timestamp
),
11520 last_loaded_strlen
, last_loaded_str_buf
,
11521 last_loaded_address
, last_loaded_size
);
11524 if (last_unloaded_strlen
) {
11525 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
11526 AbsoluteTime_to_scalar(&last_unloaded_timestamp
),
11527 last_unloaded_strlen
, last_unloaded_str_buf
,
11528 last_unloaded_address
, last_unloaded_size
);
11531 printf_func("loaded kexts:\n");
11532 if (loaded_kext_paniclist
&&
11533 pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) &&
11534 loaded_kext_paniclist
[0]) {
11536 printf_func("%.*s",
11537 strnlen(loaded_kext_paniclist
, loaded_kext_paniclist_size
),
11538 loaded_kext_paniclist
);
11540 printf_func("(none)\n");
11545 /*********************************************************************
11546 * Assumes sKextLock is held.
11547 *********************************************************************/
11550 OSKext::updateLoadedKextSummaries(void)
11552 kern_return_t result
= KERN_FAILURE
;
11553 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
11554 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
11556 vm_map_offset_t start
, end
;
11557 size_t summarySize
= 0;
11562 OSKextActiveAccount
* accountingList
;
11563 OSKextActiveAccount
* prevAccountingList
;
11564 uint32_t idx
, accountingListAlloc
, accountingListCount
, prevAccountingListCount
;
11566 prevAccountingList
= NULL
;
11567 prevAccountingListCount
= 0;
11569 #if DEVELOPMENT || DEBUG
11570 if (IORecursiveLockHaveLock(sKextLock
) == false) {
11571 panic("sKextLock must be held");
11575 IOLockLock(sKextSummariesLock
);
11577 count
= sLoadedKexts
->getCount();
11578 for (i
= 0, maxKexts
= 0; i
< count
; ++i
) {
11579 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11580 maxKexts
+= (aKext
&& aKext
->isExecutable());
11583 if (!maxKexts
) goto finish
;
11584 if (maxKexts
< kOSKextTypicalLoadCount
) maxKexts
= kOSKextTypicalLoadCount
;
11586 /* Calculate the size needed for the new summary headers.
11589 size
= sizeof(*gLoadedKextSummaries
);
11590 size
+= maxKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
11591 size
= round_page(size
);
11593 if (gLoadedKextSummaries
== NULL
|| sLoadedKextSummariesAllocSize
< size
) {
11594 if (gLoadedKextSummaries
) {
11595 kmem_free(kernel_map
, (vm_offset_t
)gLoadedKextSummaries
, sLoadedKextSummariesAllocSize
);
11596 gLoadedKextSummaries
= NULL
;
11597 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11598 sLoadedKextSummariesAllocSize
= 0;
11600 result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&summaryHeaderAlloc
, size
, VM_KERN_MEMORY_OSKEXT
);
11601 if (result
!= KERN_SUCCESS
) goto finish
;
11602 summaryHeader
= summaryHeaderAlloc
;
11603 summarySize
= size
;
11606 summaryHeader
= gLoadedKextSummaries
;
11607 summarySize
= sLoadedKextSummariesAllocSize
;
11609 start
= (vm_map_offset_t
) summaryHeader
;
11610 end
= start
+ summarySize
;
11611 result
= vm_map_protect(kernel_map
,
11616 if (result
!= KERN_SUCCESS
) goto finish
;
11619 /* Populate the summary header.
11622 bzero(summaryHeader
, summarySize
);
11623 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
11624 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
11626 /* Populate each kext summary.
11629 count
= sLoadedKexts
->getCount();
11630 accountingListAlloc
= 0;
11631 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11632 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11633 if (!aKext
|| !aKext
->isExecutable()) {
11637 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
11638 summaryHeader
->numSummaries
++;
11639 accountingListAlloc
++;
11642 accountingList
= IONew(typeof(accountingList
[0]), accountingListAlloc
);
11643 accountingListCount
= 0;
11644 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11645 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11646 if (!aKext
|| !aKext
->isExecutable()) {
11650 OSKextActiveAccount activeAccount
;
11651 aKext
->updateActiveAccount(&activeAccount
);
11652 // order by address
11653 for (idx
= 0; idx
< accountingListCount
; idx
++)
11655 if (activeAccount
.address
< accountingList
[idx
].address
) break;
11657 bcopy(&accountingList
[idx
], &accountingList
[idx
+ 1], (accountingListCount
- idx
) * sizeof(accountingList
[0]));
11658 accountingList
[idx
] = activeAccount
;
11659 accountingListCount
++;
11661 assert(accountingListCount
== accountingListAlloc
);
11662 /* Write protect the buffer and move it into place.
11665 start
= (vm_map_offset_t
) summaryHeader
;
11666 end
= start
+ summarySize
;
11668 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_READ
, FALSE
);
11669 if (result
!= KERN_SUCCESS
)
11672 gLoadedKextSummaries
= summaryHeader
;
11673 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11674 sLoadedKextSummariesAllocSize
= summarySize
;
11675 summaryHeaderAlloc
= NULL
;
11677 /* Call the magic breakpoint function through a static function pointer so
11678 * the compiler can't optimize the function away.
11680 if (sLoadedKextSummariesUpdated
) (*sLoadedKextSummariesUpdated
)();
11682 IOSimpleLockLock(sKextAccountsLock
);
11683 prevAccountingList
= sKextAccounts
;
11684 prevAccountingListCount
= sKextAccountsCount
;
11685 sKextAccounts
= accountingList
;
11686 sKextAccountsCount
= accountingListCount
;
11687 IOSimpleLockUnlock(sKextAccountsLock
);
11690 IOLockUnlock(sKextSummariesLock
);
11692 /* If we had to allocate a new buffer but failed to generate the summaries,
11695 if (summaryHeaderAlloc
) {
11696 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
11698 if (prevAccountingList
) {
11699 IODelete(prevAccountingList
, typeof(accountingList
[0]), prevAccountingListCount
);
11705 /*********************************************************************
11706 *********************************************************************/
11708 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
11712 strlcpy(summary
->name
, getIdentifierCString(),
11713 sizeof(summary
->name
));
11717 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
11718 OSSafeReleaseNULL(uuid
);
11721 summary
->address
= kmod_info
->address
;
11722 summary
->size
= kmod_info
->size
;
11723 summary
->version
= getVersion();
11724 summary
->loadTag
= kmod_info
->id
;
11725 summary
->flags
= 0;
11726 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
11731 /*********************************************************************
11732 *********************************************************************/
11735 OSKext::updateActiveAccount(OSKextActiveAccount
*accountp
)
11737 kernel_mach_header_t
*hdr
= NULL
;
11738 kernel_segment_command_t
*seg
= NULL
;
11740 hdr
= (kernel_mach_header_t
*)kmod_info
->address
;
11742 if (getcommandfromheader(hdr
, LC_SEGMENT_SPLIT_INFO
)) {
11743 /* If this kext supports split segments, use the first
11744 * executable segment as the range for instructions
11745 * (and thus for backtracing.
11747 for (seg
= firstsegfromheader(hdr
); seg
!= NULL
; seg
= nextsegfromheader(hdr
, seg
)) {
11748 if (seg
->initprot
& VM_PROT_EXECUTE
) {
11754 bzero(accountp
, sizeof(*accountp
));
11756 accountp
->address
= seg
->vmaddr
;
11757 if (accountp
->address
) {
11758 accountp
->address_end
= seg
->vmaddr
+ seg
->vmsize
;
11761 /* For non-split kexts and for kexts without executable
11762 * segments, just use the kmod_info range (as the kext
11763 * is either all in one range or should not show up in
11764 * instruction backtraces).
11766 accountp
->address
= kmod_info
->address
;
11767 if (accountp
->address
) {
11768 accountp
->address_end
= kmod_info
->address
+ kmod_info
->size
;
11771 accountp
->account
= this->account
;
11774 extern "C" const vm_allocation_site_t
*
11775 OSKextGetAllocationSiteForCaller(uintptr_t address
)
11777 OSKextActiveAccount
* active
;
11778 vm_allocation_site_t
* site
;
11779 vm_allocation_site_t
* releasesite
;
11784 IOSimpleLockLock(sKextAccountsLock
);
11785 site
= releasesite
= NULL
;
11787 // bsearch sKextAccounts list
11788 for (baseIdx
= 0, lim
= sKextAccountsCount
; lim
; lim
>>= 1)
11790 active
= &sKextAccounts
[baseIdx
+ (lim
>> 1)];
11791 if ((address
>= active
->address
) && (address
< active
->address_end
))
11793 site
= &active
->account
->site
;
11794 if (!site
->tag
) vm_tag_alloc_locked(site
, &releasesite
);
11797 else if (address
> active
->address
)
11800 baseIdx
+= (lim
>> 1) + 1;
11805 IOSimpleLockUnlock(sKextAccountsLock
);
11806 if (releasesite
) kern_allocation_name_release(releasesite
);
11811 extern "C" uint32_t
11812 OSKextGetKmodIDForSite(const vm_allocation_site_t
* site
, char * name
, vm_size_t namelen
)
11814 OSKextAccount
* account
= (typeof(account
)) site
;
11815 const char * kname
;
11819 if (account
->kext
) kname
= account
->kext
->getIdentifierCString();
11821 strlcpy(name
, kname
, namelen
);
11824 return (account
->loadTag
);
11828 OSKextFreeSite(vm_allocation_site_t
* site
)
11830 OSKextAccount
* freeAccount
= (typeof(freeAccount
)) site
;
11831 IODelete(freeAccount
, OSKextAccount
, 1);
11834 /*********************************************************************
11835 *********************************************************************/
11837 #if CONFIG_KEC_FIPS
11840 #pragma mark Kernel External Components for FIPS compliance
11843 /*********************************************************************
11844 * Kernel External Components for FIPS compliance (KEC_FIPS)
11845 *********************************************************************/
11847 GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
)
11849 AppleTEXTHash_t my_ath
= {2, 0, NULL
};
11850 AppleTEXTHash_t
* my_athp
= NULL
; // do not release
11851 OSData
* segmentHash
= NULL
; // do not release
11853 if (theKext
== NULL
|| theInfoDict
== NULL
) {
11857 // Get the part of the plist associate with kAppleTextHashesKey and let
11858 // the crypto library do further parsing (slice/architecture)
11859 segmentHash
= OSDynamicCast(OSData
, theInfoDict
->getObject(kAppleTextHashesKey
));
11860 // Support for ATH v1 while rolling out ATH v2 without revision locking submissions
11861 // Remove this when v2 PLIST are supported
11862 if (segmentHash
== NULL
) {
11863 // If this fails, we may be dealing with a v1 PLIST
11864 OSDictionary
* textHashDict
= NULL
; // do not release
11865 textHashDict
= OSDynamicCast(OSDictionary
, theInfoDict
->getObject(kAppleTextHashesKey
));
11866 if (textHashDict
== NULL
) {
11869 my_ath
.ath_version
=1;
11870 segmentHash
= OSDynamicCast(OSData
,textHashDict
->getObject(ARCHNAME
));
11871 } // end of v2 rollout
11873 if (segmentHash
== NULL
) {
11877 // KEC_FIPS type kexts never unload so we don't have to clean up our
11879 if (kmem_alloc(kernel_map
, (vm_offset_t
*) &my_athp
,
11880 sizeof(AppleTEXTHash_t
), VM_KERN_MEMORY_OSKEXT
) != KERN_SUCCESS
) {
11884 memcpy(my_athp
, &my_ath
, sizeof(my_ath
));
11885 my_athp
->ath_length
= segmentHash
->getLength();
11886 if (my_athp
->ath_length
> 0) {
11887 my_athp
->ath_hash
= (void *)segmentHash
->getBytesNoCopy();
11892 kOSKextLogErrorLevel
|
11893 kOSKextLogGeneralFlag
,
11894 "Kext %s ath_version %d ath_length %d ath_hash %p",
11895 theKext
->getIdentifierCString(),
11896 my_athp
->ath_version
,
11897 my_athp
->ath_length
,
11898 my_athp
->ath_hash
);
11901 return( (void *) my_athp
);
11904 #endif // CONFIG_KEC_FIPS
11906 #if CONFIG_IMAGEBOOT
11907 int OSKextGetUUIDForName(const char *name
, uuid_t uuid
)
11909 OSKext
*kext
= OSKext::lookupKextWithIdentifier(name
);
11914 OSData
*uuid_data
= kext
->copyUUID();
11916 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_t
));
11917 OSSafeReleaseNULL(uuid_data
);