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>
75 #pragma mark External & Internal Function Protos
77 /*********************************************************************
78 *********************************************************************/
80 extern int IODTGetLoaderInfo(const char * key
, void ** infoAddr
, int * infoSize
);
81 extern void IODTFreeLoaderInfo(const char * key
, void * infoAddr
, int infoSize
);
82 extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t
* segment
);
83 extern void OSRuntimeUnloadCPP(kmod_info_t
* ki
, void * data
);
85 extern ppnum_t
pmap_find_phys(pmap_t pmap
, addr64_t va
); /* osfmk/machine/pmap.h */
88 static OSReturn
_OSKextCreateRequest(
89 const char * predicate
,
90 OSDictionary
** requestP
);
91 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
);
92 static OSObject
* _OSKextGetRequestArgument(
93 OSDictionary
* requestDict
,
94 const char * argName
);
95 static bool _OSKextSetRequestArgument(
96 OSDictionary
* requestDict
,
99 static void * _OSKextExtractPointer(OSData
* wrapper
);
100 static OSReturn
_OSDictionarySetCStringValue(
104 static bool _OSKextInPrelinkRebuildWindow(void);
105 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol
* theBundleID
);
107 // We really should add containsObject() & containsCString to OSCollection & subclasses.
108 // So few pad slots, though....
109 static bool _OSArrayContainsCString(OSArray
* array
, const char * cString
);
112 static void * GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
);
113 #endif // CONFIG_KEC_FIPS
115 /* Prelinked arm kexts do not have VM entries because the method we use to
116 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
117 * not work on ARM. To get around that, we must free prelinked kext
118 * executables with ml_static_mfree() instead of kext_free().
120 #if __i386__ || __x86_64__
121 #define VM_MAPPED_KEXTS 1
122 #define KASLR_KEXT_DEBUG 0
123 #define KASLR_IOREG_DEBUG 0
125 #error Unsupported architecture
129 #pragma mark Constants & Macros
131 /*********************************************************************
133 *********************************************************************/
135 /* Use this number to create containers.
137 #define kOSKextTypicalLoadCount (150)
139 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
140 * A loaded kext will no dependents or external retains will have 2 retains.
142 #define kOSKextMinRetainCount (1)
143 #define kOSKextMinLoadedRetainCount (2)
146 * Strings and substrings used in dependency resolution.
148 #define APPLE_KEXT_PREFIX "com.apple."
149 #define KERNEL_LIB "com.apple.kernel"
151 #define PRIVATE_KPI "com.apple.kpi.private"
153 /* Version for compatbility pseudokexts (com.apple.kernel.*),
154 * compatible back to v6.0.
156 #define KERNEL6_LIB "com.apple.kernel.6.0"
157 #define KERNEL6_VERSION "7.9.9"
159 #define KERNEL_LIB_PREFIX "com.apple.kernel."
160 #define KPI_LIB_PREFIX "com.apple.kpi."
162 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0)
164 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
165 #define MINIMUM_WAKEUP_SECONDS (30)
167 /*********************************************************************
168 * infoDict keys for internally-stored data. Saves on ivar slots for
169 * objects we don't keep around past boot time or during active load.
170 *********************************************************************/
172 /* A usable, uncompressed file is stored under this key.
174 #define _kOSKextExecutableKey "_OSKextExecutable"
176 /* An indirect reference to the executable file from an mkext
177 * is stored under this key.
179 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference"
181 /* If the file is contained in a larger buffer laid down by the booter or
182 * sent from user space, the OSKext stores that OSData under this key so that
183 * references are properly tracked. This is always an mkext, right now.
185 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
187 #define OS_LOG_HDR_VERSION 1
188 #define NUM_OS_LOG_SECTIONS 2
190 #define OS_LOG_SECT_IDX 0
191 #define CSTRING_SECT_IDX 1
194 #pragma mark Typedefs
196 /*********************************************************************
198 *********************************************************************/
200 /*********************************************************************
201 * osLogDataHeaderRef describes the header information of an OSData
202 * object that is returned when querying for kOSBundleLogStringsKey.
203 * We currently return information regarding 2 sections - os_log and
204 * cstring. In the case that the os_log section doesn't exist, we just
205 * return an offset and length of 0 for that section.
206 *********************************************************************/
207 typedef struct osLogDataHeader
{
211 uint32_t sect_offset
;
214 } osLogDataHeaderRef
;
216 /*********************************************************************
217 * MkextEntryRef describes the contents of an OSData object
218 * referencing a file entry from an mkext so that we can uncompress
219 * (if necessary) and extract it on demand.
221 * It contains the mkextVersion in case we ever wind up supporting
222 * multiple mkext formats. Mkext format 1 is officially retired as of
224 *********************************************************************/
225 typedef struct MkextEntryRef
{
226 mkext_basic_header
* mkext
; // beginning of whole mkext file
227 void * fileinfo
; // mkext2_file_entry or equiv; see mkext.h
231 #pragma mark Global and static Module Variables
233 /*********************************************************************
234 * Global & static variables, used to keep track of kexts.
235 *********************************************************************/
237 static bool sPrelinkBoot
= false;
238 static bool sSafeBoot
= false;
239 static bool sKeepSymbols
= false;
241 /*********************************************************************
242 * sKextLock is the principal lock for OSKext, and guards all static
243 * and global variables not owned by other locks (declared further
244 * below). It must be taken by any entry-point method or function,
245 * including internal functions called on scheduled threads.
247 * sKextLock and sKextInnerLock are recursive due to multiple functions
248 * that are called both externally and internally. The other locks are
251 * Which locks are taken depends on what they protect, but if more than
252 * one must be taken, they must always be locked in this order
253 * (and unlocked in reverse order) to prevent deadlocks:
257 * 3. sKextSummariesLock
258 * 4. sKextLoggingLock
260 static IORecursiveLock
* sKextLock
= NULL
;
262 static OSDictionary
* sKextsByID
= NULL
;
263 static OSDictionary
* sExcludeListByID
= NULL
;
264 static OSArray
* sLoadedKexts
= NULL
;
265 static OSArray
* sUnloadedPrelinkedKexts
= NULL
;
267 // Requests to kextd waiting to be picked up.
268 static OSArray
* sKernelRequests
= NULL
;
269 // Identifier of kext load requests in sKernelRequests
270 static OSSet
* sPostedKextLoadIdentifiers
= NULL
;
271 static OSArray
* sRequestCallbackRecords
= NULL
;
273 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
274 static OSSet
* sAllKextLoadIdentifiers
= NULL
;
275 static KXLDContext
* sKxldContext
= NULL
;
276 static uint32_t sNextLoadTag
= 0;
277 static uint32_t sNextRequestTag
= 0;
279 static bool sUserLoadsActive
= false;
280 static bool sKextdActive
= false;
281 static bool sDeferredLoadSucceeded
= false;
282 static bool sConsiderUnloadsExecuted
= false;
285 static bool sKernelRequestsEnabled
= false;
287 static bool sKernelRequestsEnabled
= true;
289 static bool sLoadEnabled
= true;
290 static bool sUnloadEnabled
= true;
292 /*********************************************************************
293 * Stuff for the OSKext representing the kernel itself.
295 static OSKext
* sKernelKext
= NULL
;
297 /* Set up a fake kmod_info struct for the kernel.
298 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
299 * before OSKext is initialized; that call only needs the name
300 * and address to be set correctly.
302 * We don't do much else with the kerne's kmod_info; we never
303 * put it into the kmod list, never adjust the reference count,
304 * and never have kernel components reference it.
305 * For that matter, we don't do much with kmod_info structs
306 * at all anymore! We just keep them filled in for gdb and
307 * binary compability.
309 kmod_info_t g_kernel_kmod_info
= {
311 /* info_version */ KMOD_INFO_VERSION
,
312 /* id */ 0, // loadTag: kernel is always 0
313 /* name */ kOSKextKernelIdentifier
, // bundle identifier
314 /* version */ "0", // filled in in OSKext::initialize()
315 /* reference_count */ -1, // never adjusted; kernel never unloads
316 /* reference_list */ NULL
,
318 /* size */ 0, // filled in in OSKext::initialize()
325 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
326 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
327 // misc_protos.h, db_low_trace.c, kgmacros
328 // 'kmod' is a holdover from the old kmod system, we can't rename it.
329 kmod_info_t
* kmod
= NULL
;
331 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
334 static char * loaded_kext_paniclist
= NULL
;
335 static uint32_t loaded_kext_paniclist_size
= 0;
337 AbsoluteTime last_loaded_timestamp
;
338 static char last_loaded_str_buf
[2*KMOD_MAX_NAME
];
339 static u_long last_loaded_strlen
= 0;
340 static void * last_loaded_address
= NULL
;
341 static u_long last_loaded_size
= 0;
343 AbsoluteTime last_unloaded_timestamp
;
344 static char last_unloaded_str_buf
[2*KMOD_MAX_NAME
];
345 static u_long last_unloaded_strlen
= 0;
346 static void * last_unloaded_address
= NULL
;
347 static u_long last_unloaded_size
= 0;
349 /*********************************************************************
350 * sKextInnerLock protects against cross-calls with IOService and
351 * IOCatalogue, and owns the variables declared immediately below.
353 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
355 * When both sKextLock and sKextInnerLock need to be taken,
356 * always lock sKextLock first and unlock it second. Never take both
357 * locks in an entry point to OSKext; if you need to do so, you must
358 * spawn an independent thread to avoid potential deadlocks for threads
359 * calling into OSKext.
361 static IORecursiveLock
* sKextInnerLock
= NULL
;
363 static bool sAutounloadEnabled
= true;
364 static bool sConsiderUnloadsCalled
= false;
365 static bool sConsiderUnloadsPending
= false;
367 static unsigned int sConsiderUnloadDelay
= 60; // seconds
368 static thread_call_t sUnloadCallout
= 0;
369 static thread_call_t sDestroyLinkContextThread
= 0; // one-shot, one-at-a-time thread
370 static bool sSystemSleep
= false; // true when system going to sleep
371 static AbsoluteTime sLastWakeTime
; // last time we woke up
373 /*********************************************************************
374 * Backtraces can be printed at various times so we need a tight lock
375 * on data used for that. sKextSummariesLock protects the variables
376 * declared immediately below.
378 * gLoadedKextSummaries is accessed by other modules, but only during
379 * a panic so the lock isn't needed then.
381 * gLoadedKextSummaries has the "used" attribute in order to ensure
382 * that it remains visible even when we are performing extremely
383 * aggressive optimizations, as it is needed to allow the debugger
384 * to automatically parse the list of loaded kexts.
386 static IOLock
* sKextSummariesLock
= NULL
;
387 extern "C" lck_spin_t vm_allocation_sites_lock
;
388 static IOSimpleLock
* sKextAccountsLock
= &vm_allocation_sites_lock
;
390 void (*sLoadedKextSummariesUpdated
)(void) = OSKextLoadedKextSummariesUpdated
;
391 OSKextLoadedKextSummaryHeader
* gLoadedKextSummaries
__attribute__((used
)) = NULL
;
392 uint64_t gLoadedKextSummariesTimestamp
__attribute__((used
)) = 0;
393 static size_t sLoadedKextSummariesAllocSize
= 0;
395 static OSKextActiveAccount
* sKextAccounts
;
396 static uint32_t sKextAccountsCount
;
399 /*********************************************************************
400 * sKextLoggingLock protects the logging variables declared immediately below.
402 static IOLock
* sKextLoggingLock
= NULL
;
404 static const OSKextLogSpec kDefaultKernelLogFilter
= kOSKextLogBasicLevel
|
405 kOSKextLogVerboseFlagsMask
;
406 static OSKextLogSpec sKernelLogFilter
= kDefaultKernelLogFilter
;
407 static bool sBootArgLogFilterFound
= false;
408 SYSCTL_UINT(_debug
, OID_AUTO
, kextlog
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &sKernelLogFilter
,
409 0, "kernel kext logging");
411 static OSKextLogSpec sUserSpaceKextLogFilter
= kOSKextLogSilentFilter
;
412 static OSArray
* sUserSpaceLogSpecArray
= NULL
;
413 static OSArray
* sUserSpaceLogMessageArray
= NULL
;
416 * End scope for sKextInnerLock-protected variables.
417 *********************************************************************/
420 /*********************************************************************
421 helper function used for collecting PGO data upon unload of a kext
424 static int OSKextGrabPgoDataLocked(OSKext
*kext
,
426 uuid_t instance_uuid
,
429 uint64_t bufferSize
);
431 /**********************************************************************/
436 #pragma mark OSData callbacks (need to move to OSData)
438 /*********************************************************************
439 * C functions used for callbacks.
440 *********************************************************************/
442 void osdata_kmem_free(void * ptr
, unsigned int length
) {
443 kmem_free(kernel_map
, (vm_address_t
)ptr
, length
);
447 void osdata_phys_free(void * ptr
, unsigned int length
) {
448 ml_static_mfree((vm_offset_t
)ptr
, length
);
452 void osdata_vm_deallocate(void * ptr
, unsigned int length
)
454 (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
);
458 void osdata_kext_free(void * ptr
, unsigned int length
)
460 (void)kext_free((vm_offset_t
)ptr
, length
);
466 #pragma mark KXLD Allocation Callback
468 /*********************************************************************
469 * KXLD Allocation Callback
470 *********************************************************************/
474 KXLDAllocateFlags
* flags
,
477 vm_address_t result
= 0; // returned
478 kern_return_t mach_result
= KERN_FAILURE
;
479 bool success
= false;
480 OSKext
* theKext
= (OSKext
*)user_data
;
481 u_long roundSize
= round_page(size
);
482 OSData
* linkBuffer
= NULL
; // must release
484 mach_result
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
);
485 if (mach_result
!= KERN_SUCCESS
) {
487 kOSKextLogErrorLevel
|
488 kOSKextLogGeneralFlag
,
489 "Can't allocate kernel memory to link %s.",
490 theKext
->getIdentifierCString());
494 /* Create an OSData wrapper for the allocated buffer.
496 linkBuffer
= OSData::withBytesNoCopy((void *)result
, roundSize
);
499 kOSKextLogErrorLevel
|
500 kOSKextLogGeneralFlag
,
501 "Can't allocate linked executable wrapper for %s.",
502 theKext
->getIdentifierCString());
505 linkBuffer
->setDeallocFunction(osdata_kext_free
);
507 kOSKextLogProgressLevel
|
508 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
509 "Allocated link buffer for kext %s at %p (%lu bytes).",
510 theKext
->getIdentifierCString(),
511 (void *)result
, (unsigned long)roundSize
);
513 theKext
->setLinkedExecutable(linkBuffer
);
515 *flags
= kKxldAllocateWritable
;
519 if (!success
&& result
) {
520 kext_free(result
, roundSize
);
524 OSSafeReleaseNULL(linkBuffer
);
526 return (kxld_addr_t
)result
;
529 /*********************************************************************
530 *********************************************************************/
533 KXLDLogSubsystem subsystem
,
539 OSKext
*theKext
= (OSKext
*) user_data
;
540 OSKextLogSpec logSpec
= 0;
543 case kKxldLogLinking
:
544 logSpec
|= kOSKextLogLinkFlag
;
546 case kKxldLogPatching
:
547 logSpec
|= kOSKextLogPatchFlag
;
552 case kKxldLogExplicit
:
553 logSpec
|= kOSKextLogExplicitLevel
;
556 logSpec
|= kOSKextLogErrorLevel
;
559 logSpec
|= kOSKextLogWarningLevel
;
562 logSpec
|= kOSKextLogProgressLevel
;
565 logSpec
|= kOSKextLogDetailLevel
;
568 logSpec
|= kOSKextLogDebugLevel
;
572 OSKextVLog(theKext
, logSpec
, format
, argList
);
576 #pragma mark IOStatistics defines
581 #define notifyKextLoadObservers(kext, kmod_info) \
583 IOStatistics::onKextLoad(kext, kmod_info); \
586 #define notifyKextUnloadObservers(kext) \
588 IOStatistics::onKextUnload(kext); \
591 #define notifyAddClassObservers(kext, addedClass, flags) \
593 IOStatistics::onClassAdded(kext, addedClass); \
596 #define notifyRemoveClassObservers(kext, removedClass, flags) \
598 IOStatistics::onClassRemoved(kext, removedClass); \
603 #define notifyKextLoadObservers(kext, kmod_info)
604 #define notifyKextUnloadObservers(kext)
605 #define notifyAddClassObservers(kext, addedClass, flags)
606 #define notifyRemoveClassObservers(kext, removedClass, flags)
608 #endif /* IOKITSTATS */
611 #pragma mark Module Config (Startup & Shutdown)
613 /*********************************************************************
614 * Module Config (Class Definition & Class Methods)
615 *********************************************************************/
616 #define super OSObject
617 OSDefineMetaClassAndStructors(OSKext
, OSObject
)
619 /*********************************************************************
620 *********************************************************************/
623 OSKext::initialize(void)
625 OSData
* kernelExecutable
= NULL
; // do not release
626 u_char
* kernelStart
= NULL
; // do not free
627 size_t kernelLength
= 0;
628 OSString
* scratchString
= NULL
; // must release
629 IORegistryEntry
* registryRoot
= NULL
; // do not release
630 OSNumber
* kernelCPUType
= NULL
; // must release
631 OSNumber
* kernelCPUSubtype
= NULL
; // must release
632 OSKextLogSpec bootLogFilter
= kOSKextLogSilentFilter
;
633 bool setResult
= false;
634 uint64_t * timestamp
= 0;
635 char bootArgBuffer
[16]; // for PE_parse_boot_argn w/strings
637 /* This must be the first thing allocated. Everything else grabs this lock.
639 sKextLock
= IORecursiveLockAlloc();
640 sKextInnerLock
= IORecursiveLockAlloc();
641 sKextSummariesLock
= IOLockAlloc();
642 sKextLoggingLock
= IOLockAlloc();
644 assert(sKextInnerLock
);
645 assert(sKextSummariesLock
);
646 assert(sKextLoggingLock
);
648 sKextsByID
= OSDictionary::withCapacity(kOSKextTypicalLoadCount
);
649 sLoadedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
);
650 sUnloadedPrelinkedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
/ 10);
651 sKernelRequests
= OSArray::withCapacity(0);
652 sPostedKextLoadIdentifiers
= OSSet::withCapacity(0);
653 sAllKextLoadIdentifiers
= OSSet::withCapacity(kOSKextTypicalLoadCount
);
654 sRequestCallbackRecords
= OSArray::withCapacity(0);
655 assert(sKextsByID
&& sLoadedKexts
&& sKernelRequests
&&
656 sPostedKextLoadIdentifiers
&& sAllKextLoadIdentifiers
&&
657 sRequestCallbackRecords
&& sUnloadedPrelinkedKexts
);
659 /* Read the log flag boot-args and set the log flags.
661 if (PE_parse_boot_argn("kextlog", &bootLogFilter
, sizeof(bootLogFilter
))) {
662 sBootArgLogFilterFound
= true;
663 sKernelLogFilter
= bootLogFilter
;
664 // log this if any flags are set
665 OSKextLog(/* kext */ NULL
,
666 kOSKextLogBasicLevel
|
668 "Kernel kext log filter 0x%x per kextlog boot arg.",
669 (unsigned)sKernelLogFilter
);
672 sSafeBoot
= PE_parse_boot_argn("-x", bootArgBuffer
,
673 sizeof(bootArgBuffer
)) ? true : false;
676 OSKextLog(/* kext */ NULL
,
677 kOSKextLogWarningLevel
|
678 kOSKextLogGeneralFlag
,
679 "SAFE BOOT DETECTED - "
680 "only valid OSBundleRequired kexts will be loaded.");
683 PE_parse_boot_argn("keepsyms", &sKeepSymbols
, sizeof(sKeepSymbols
));
685 /* Set up an OSKext instance to represent the kernel itself.
687 sKernelKext
= new OSKext
;
690 kernelStart
= (u_char
*)&_mh_execute_header
;
691 kernelLength
= getlastaddr() - (vm_offset_t
)kernelStart
;
692 kernelExecutable
= OSData::withBytesNoCopy(
693 kernelStart
, kernelLength
);
694 assert(kernelExecutable
);
697 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %llu (0x%016lx) \n",
698 (unsigned long)kernelStart
,
699 (unsigned long)getlastaddr(),
701 vm_kernel_slide
, vm_kernel_slide
);
704 sKernelKext
->loadTag
= sNextLoadTag
++; // the kernel is load tag 0
705 sKernelKext
->bundleID
= OSSymbol::withCString(kOSKextKernelIdentifier
);
707 sKernelKext
->version
= OSKextParseVersionString(osrelease
);
708 sKernelKext
->compatibleVersion
= sKernelKext
->version
;
709 sKernelKext
->linkedExecutable
= kernelExecutable
;
711 sKernelKext
->flags
.hasAllDependencies
= 1;
712 sKernelKext
->flags
.kernelComponent
= 1;
713 sKernelKext
->flags
.prelinked
= 0;
714 sKernelKext
->flags
.loaded
= 1;
715 sKernelKext
->flags
.started
= 1;
716 sKernelKext
->flags
.CPPInitialized
= 0;
717 sKernelKext
->flags
.jettisonLinkeditSeg
= 0;
719 sKernelKext
->kmod_info
= &g_kernel_kmod_info
;
720 strlcpy(g_kernel_kmod_info
.version
, osrelease
,
721 sizeof(g_kernel_kmod_info
.version
));
722 g_kernel_kmod_info
.size
= kernelLength
;
723 g_kernel_kmod_info
.id
= sKernelKext
->loadTag
;
725 /* Cons up an info dict, so we don't have to have special-case
728 sKernelKext
->infoDict
= OSDictionary::withCapacity(5);
729 assert(sKernelKext
->infoDict
);
730 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
,
731 sKernelKext
->bundleID
);
733 setResult
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
,
737 scratchString
= OSString::withCStringNoCopy(osrelease
);
738 assert(scratchString
);
739 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
,
742 OSSafeReleaseNULL(scratchString
);
744 scratchString
= OSString::withCStringNoCopy("mach_kernel");
745 assert(scratchString
);
746 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
,
749 OSSafeReleaseNULL(scratchString
);
751 /* Add the kernel kext to the bookkeeping dictionaries. Note that
752 * the kernel kext doesn't have a kmod_info struct. copyInfo()
753 * gathers info from other places anyhow.
755 setResult
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
);
757 setResult
= sLoadedKexts
->setObject(sKernelKext
);
759 sKernelKext
->release();
761 registryRoot
= IORegistryEntry::getRegistryRoot();
762 kernelCPUType
= OSNumber::withNumber(
763 (long long unsigned int)_mh_execute_header
.cputype
,
764 8 * sizeof(_mh_execute_header
.cputype
));
765 kernelCPUSubtype
= OSNumber::withNumber(
766 (long long unsigned int)_mh_execute_header
.cpusubtype
,
767 8 * sizeof(_mh_execute_header
.cpusubtype
));
768 assert(registryRoot
&& kernelCPUSubtype
&& kernelCPUType
);
770 registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
);
771 registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
);
773 OSSafeReleaseNULL(kernelCPUType
);
774 OSSafeReleaseNULL(kernelCPUSubtype
);
776 timestamp
= __OSAbsoluteTimePtr(&last_loaded_timestamp
);
778 timestamp
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
);
780 timestamp
= __OSAbsoluteTimePtr(&sLastWakeTime
);
783 OSKextLog(/* kext */ NULL
,
784 kOSKextLogProgressLevel
|
785 kOSKextLogGeneralFlag
,
786 "Kext system initialized.");
788 notifyKextLoadObservers(sKernelKext
, sKernelKext
->kmod_info
);
793 /*********************************************************************
794 * This could be in OSKextLib.cpp but we need to hold a lock
795 * while removing all the segments and sKextLock will do.
796 *********************************************************************/
799 OSKext::removeKextBootstrap(void)
801 OSReturn result
= kOSReturnError
;
803 static bool alreadyDone
= false;
805 const char * dt_kernel_header_name
= "Kernel-__HEADER";
806 const char * dt_kernel_symtab_name
= "Kernel-__SYMTAB";
807 kernel_mach_header_t
* dt_mach_header
= NULL
;
808 int dt_mach_header_size
= 0;
809 struct symtab_command
* dt_symtab
= NULL
;
810 int dt_symtab_size
= 0;
813 kernel_segment_command_t
* seg_to_remove
= NULL
;
816 /* This must be the very first thing done by this function.
818 IORecursiveLockLock(sKextLock
);
820 /* If we already did this, it's a success.
823 result
= kOSReturnSuccess
;
827 OSKextLog(/* kext */ NULL
,
828 kOSKextLogProgressLevel
|
829 kOSKextLogGeneralFlag
,
830 "Jettisoning kext bootstrap segments.");
833 * Dispose of unnecessary stuff that the booter didn't need to load.
835 dt_result
= IODTGetLoaderInfo(dt_kernel_header_name
,
836 (void **)&dt_mach_header
, &dt_mach_header_size
);
837 if (dt_result
== 0 && dt_mach_header
) {
838 IODTFreeLoaderInfo(dt_kernel_header_name
, (void *)dt_mach_header
,
839 round_page_32(dt_mach_header_size
));
841 dt_result
= IODTGetLoaderInfo(dt_kernel_symtab_name
,
842 (void **)&dt_symtab
, &dt_symtab_size
);
843 if (dt_result
== 0 && dt_symtab
) {
844 IODTFreeLoaderInfo(dt_kernel_symtab_name
, (void *)dt_symtab
,
845 round_page_32(dt_symtab_size
));
849 * KLD bootstrap segment.
851 // xxx - should rename KLD segment
852 seg_to_remove
= getsegbyname("__KLD");
854 OSRuntimeUnloadCPPForSegment(seg_to_remove
);
857 #if __i386__ || __x86_64__
858 /* On x86, use the mapping data from the segment load command to
859 * unload KLD directly.
860 * This may invalidate any assumptions about "avail_start"
861 * defining the lower bound for valid physical addresses.
863 if (seg_to_remove
&& seg_to_remove
->vmaddr
&& seg_to_remove
->vmsize
) {
864 // 04/18/11 - gab: <rdar://problem/9236163>
865 // overwrite memory occupied by KLD segment with random data before
867 read_frandom((void *) seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
868 ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
874 seg_to_remove
= NULL
;
877 * Prelinked kernel's symtab (if there is one).
879 kernel_section_t
* sect
;
880 sect
= getsectbyname("__PRELINK", "__symtab");
881 if (sect
&& sect
->addr
&& sect
->size
) {
882 ml_static_mfree(sect
->addr
, sect
->size
);
885 seg_to_remove
= (kernel_segment_command_t
*)getsegbyname("__LINKEDIT");
887 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
888 * pageable, unless keepsyms is set. To do that, we have to copy it from
889 * its booter-allocated memory, free the booter memory, reallocate proper
890 * managed memory, then copy the segment back in.
894 kern_return_t mem_result
;
895 void *seg_copy
= NULL
;
896 void *seg_data
= NULL
;
897 vm_map_offset_t seg_offset
= 0;
898 vm_map_offset_t seg_copy_offset
= 0;
899 vm_map_size_t seg_length
= 0;
901 seg_data
= (void *) seg_to_remove
->vmaddr
;
902 seg_offset
= (vm_map_offset_t
) seg_to_remove
->vmaddr
;
903 seg_length
= (vm_map_size_t
) seg_to_remove
->vmsize
;
905 /* Allocate space for the LINKEDIT copy.
907 mem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*) &seg_copy
,
908 seg_length
, VM_KERN_MEMORY_KEXT
);
909 if (mem_result
!= KERN_SUCCESS
) {
910 OSKextLog(/* kext */ NULL
,
911 kOSKextLogErrorLevel
|
912 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
913 "Can't copy __LINKEDIT segment for VM reassign.");
916 seg_copy_offset
= (vm_map_offset_t
) seg_copy
;
920 memcpy(seg_copy
, seg_data
, seg_length
);
922 /* Dump the booter memory.
924 ml_static_mfree(seg_offset
, seg_length
);
926 /* Set up the VM region.
928 mem_result
= vm_map_enter_mem_object(
931 seg_length
, /* mask */ 0,
932 VM_FLAGS_FIXED
| VM_FLAGS_OVERWRITE
,
934 (vm_object_offset_t
) 0,
936 /* cur_protection */ VM_PROT_READ
| VM_PROT_WRITE
,
937 /* max_protection */ VM_PROT_ALL
,
938 /* inheritance */ VM_INHERIT_DEFAULT
);
939 if ((mem_result
!= KERN_SUCCESS
) ||
940 (seg_offset
!= (vm_map_offset_t
) seg_data
))
942 OSKextLog(/* kext */ NULL
,
943 kOSKextLogErrorLevel
|
944 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
945 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
946 seg_data
, seg_length
, mem_result
);
952 memcpy(seg_data
, seg_copy
, seg_length
);
956 kmem_free(kernel_map
, seg_copy_offset
, seg_length
);
958 #else /* we are not CONFIG_KXLD */
959 #error CONFIG_KXLD is expected for this arch
962 * Dump the LINKEDIT segment, unless keepsyms is set.
965 dt_segment_name
= "Kernel-__LINKEDIT";
966 if (0 == IODTGetLoaderInfo(dt_segment_name
,
967 &segment_paddress
, &segment_size
)) {
969 vm_offset_t vmaddr
= ml_static_ptovirt((vm_offset_t
)segment_paddress
);
970 bzero((void*)vmaddr
, segment_size
);
972 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
976 OSKextLog(/* kext */ NULL
,
977 kOSKextLogBasicLevel
|
978 kOSKextLogGeneralFlag
,
979 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
981 #endif /* CONFIG_KXLD */
983 seg_to_remove
= NULL
;
986 result
= kOSReturnSuccess
;
990 /* This must be the very last thing done before returning.
992 IORecursiveLockUnlock(sKextLock
);
997 /*********************************************************************
998 *********************************************************************/
1000 OSKext::flushNonloadedKexts(
1001 Boolean flushPrelinkedKexts
)
1003 OSSet
* prelinkedKexts
= NULL
; // must release
1004 OSCollectionIterator
* kextIterator
= NULL
; // must release
1005 OSCollectionIterator
* prelinkIterator
= NULL
; // must release
1006 const OSSymbol
* thisID
= NULL
; // do not release
1007 OSKext
* thisKext
= NULL
; // do not release
1010 IORecursiveLockLock(sKextLock
);
1012 OSKextLog(/* kext */ NULL
,
1013 kOSKextLogProgressLevel
|
1014 kOSKextLogKextBookkeepingFlag
,
1015 "Flushing nonloaded kexts and other unused data.");
1017 OSKext::considerDestroyingLinkContext();
1019 /* If we aren't flushing unused prelinked kexts, we have to put them
1020 * aside while we flush everything else so make a container for them.
1022 if (!flushPrelinkedKexts
) {
1023 prelinkedKexts
= OSSet::withCapacity(0);
1024 if (!prelinkedKexts
) {
1029 /* Set aside prelinked kexts (in-use or not) and break
1030 * any lingering inter-kext references for nonloaded kexts
1031 * so they have min. retain counts.
1033 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1034 if (!kextIterator
) {
1038 while ((thisID
= OSDynamicCast(OSSymbol
,
1039 kextIterator
->getNextObject()))) {
1041 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1044 if (prelinkedKexts
&& thisKext
->isPrelinked()) {
1045 prelinkedKexts
->setObject(thisKext
);
1047 thisKext
->flushDependencies(/* forceIfLoaded */ false);
1051 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1053 sKextsByID
->flushCollection();
1055 /* Now put the loaded kexts back into the ID dictionary.
1057 count
= sLoadedKexts
->getCount();
1058 for (i
= 0; i
< count
; i
++) {
1059 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
1060 sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
);
1063 /* Finally, put back the prelinked kexts if we saved any.
1065 if (prelinkedKexts
) {
1066 prelinkIterator
= OSCollectionIterator::withCollection(prelinkedKexts
);
1067 if (!prelinkIterator
) {
1071 while ((thisKext
= OSDynamicCast(OSKext
,
1072 prelinkIterator
->getNextObject()))) {
1074 sKextsByID
->setObject(thisKext
->getIdentifierCString(),
1080 IORecursiveLockUnlock(sKextLock
);
1082 OSSafeReleaseNULL(prelinkedKexts
);
1083 OSSafeReleaseNULL(kextIterator
);
1084 OSSafeReleaseNULL(prelinkIterator
);
1089 /*********************************************************************
1090 *********************************************************************/
1093 OSKext::setKextdActive(Boolean active
)
1095 IORecursiveLockLock(sKextLock
);
1096 sKextdActive
= active
;
1097 if (sKernelRequests
->getCount()) {
1098 OSKext::pingKextd();
1100 IORecursiveLockUnlock(sKextLock
);
1105 /*********************************************************************
1106 * OSKextLib.cpp might need access to this someday but for now it's
1108 *********************************************************************/
1110 extern void ipc_port_release_send(ipc_port_t
);
1115 OSKext::pingKextd(void)
1117 OSReturn result
= kOSReturnError
;
1119 mach_port_t kextd_port
= IPC_PORT_NULL
;
1121 if (!sKextdActive
) {
1122 result
= kOSKextReturnDisabled
; // basically unavailable
1126 result
= host_get_kextd_port(host_priv_self(), &kextd_port
);
1127 if (result
!= KERN_SUCCESS
|| !IPC_PORT_VALID(kextd_port
)) {
1128 OSKextLog(/* kext */ NULL
,
1129 kOSKextLogErrorLevel
|
1131 "Can't get kextd port.");
1135 result
= kextd_ping(kextd_port
);
1136 if (result
!= KERN_SUCCESS
) {
1137 OSKextLog(/* kext */ NULL
,
1138 kOSKextLogErrorLevel
|
1140 "kextd ping failed (0x%x).", (int)result
);
1145 if (IPC_PORT_VALID(kextd_port
)) {
1146 ipc_port_release_send(kextd_port
);
1153 /*********************************************************************
1154 *********************************************************************/
1157 OSKext::setDeferredLoadSucceeded(Boolean succeeded
)
1159 IORecursiveLockLock(sKextLock
);
1160 sDeferredLoadSucceeded
= succeeded
;
1161 IORecursiveLockUnlock(sKextLock
);
1166 /*********************************************************************
1167 * Called from IOSystemShutdownNotification.
1168 *********************************************************************/
1171 OSKext::willShutdown(void)
1174 OSReturn checkResult
= kOSReturnError
;
1176 OSDictionary
* exitRequest
= NULL
; // must release
1178 IORecursiveLockLock(sKextLock
);
1180 OSKext::setLoadEnabled(false);
1181 OSKext::setUnloadEnabled(false);
1182 OSKext::setAutounloadsEnabled(false);
1183 OSKext::setKernelRequestsEnabled(false);
1186 OSKextLog(/* kext */ NULL
,
1187 kOSKextLogProgressLevel
|
1188 kOSKextLogGeneralFlag
,
1189 "System shutdown; requesting immediate kextd exit.");
1191 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
,
1193 if (checkResult
!= kOSReturnSuccess
) {
1196 if (!sKernelRequests
->setObject(exitRequest
)) {
1200 OSKext::pingKextd();
1205 IORecursiveLockUnlock(sKextLock
);
1207 OSSafeReleaseNULL(exitRequest
);
1211 /*********************************************************************
1212 *********************************************************************/
1215 OSKext::getLoadEnabled(void)
1219 IORecursiveLockLock(sKextLock
);
1220 result
= sLoadEnabled
;
1221 IORecursiveLockUnlock(sKextLock
);
1225 /*********************************************************************
1226 *********************************************************************/
1229 OSKext::setLoadEnabled(bool flag
)
1233 IORecursiveLockLock(sKextLock
);
1234 result
= sLoadEnabled
;
1235 sLoadEnabled
= (flag
? true : false);
1237 if (sLoadEnabled
!= result
) {
1238 OSKextLog(/* kext */ NULL
,
1239 kOSKextLogBasicLevel
|
1241 "Kext loading now %sabled.", sLoadEnabled
? "en" : "dis");
1244 IORecursiveLockUnlock(sKextLock
);
1249 /*********************************************************************
1250 *********************************************************************/
1253 OSKext::getUnloadEnabled(void)
1257 IORecursiveLockLock(sKextLock
);
1258 result
= sUnloadEnabled
;
1259 IORecursiveLockUnlock(sKextLock
);
1263 /*********************************************************************
1264 *********************************************************************/
1267 OSKext::setUnloadEnabled(bool flag
)
1271 IORecursiveLockLock(sKextLock
);
1272 result
= sUnloadEnabled
;
1273 sUnloadEnabled
= (flag
? true : false);
1274 IORecursiveLockUnlock(sKextLock
);
1276 if (sUnloadEnabled
!= result
) {
1277 OSKextLog(/* kext */ NULL
,
1278 kOSKextLogBasicLevel
|
1279 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1280 "Kext unloading now %sabled.", sUnloadEnabled
? "en" : "dis");
1286 /*********************************************************************
1287 * Do not call any function that takes sKextLock here!
1288 *********************************************************************/
1291 OSKext::getAutounloadEnabled(void)
1295 IORecursiveLockLock(sKextInnerLock
);
1296 result
= sAutounloadEnabled
? true : false;
1297 IORecursiveLockUnlock(sKextInnerLock
);
1301 /*********************************************************************
1302 * Do not call any function that takes sKextLock here!
1303 *********************************************************************/
1306 OSKext::setAutounloadsEnabled(bool flag
)
1310 IORecursiveLockLock(sKextInnerLock
);
1312 result
= sAutounloadEnabled
;
1313 sAutounloadEnabled
= (flag
? true : false);
1314 if (!sAutounloadEnabled
&& sUnloadCallout
) {
1315 thread_call_cancel(sUnloadCallout
);
1318 if (sAutounloadEnabled
!= result
) {
1319 OSKextLog(/* kext */ NULL
,
1320 kOSKextLogBasicLevel
|
1321 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1322 "Kext autounloading now %sabled.",
1323 sAutounloadEnabled
? "en" : "dis");
1326 IORecursiveLockUnlock(sKextInnerLock
);
1331 /*********************************************************************
1332 *********************************************************************/
1333 /* instance method operating on OSKext field */
1335 OSKext::setAutounloadEnabled(bool flag
)
1337 bool result
= flags
.autounloadEnabled
? true : false;
1338 flags
.autounloadEnabled
= flag
? 1 : 0;
1340 if (result
!= (flag
? true : false)) {
1342 kOSKextLogProgressLevel
|
1343 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
1344 "Autounloading for kext %s now %sabled.",
1345 getIdentifierCString(),
1346 flags
.autounloadEnabled
? "en" : "dis");
1351 /*********************************************************************
1352 *********************************************************************/
1355 OSKext::setKernelRequestsEnabled(bool flag
)
1359 IORecursiveLockLock(sKextLock
);
1360 result
= sKernelRequestsEnabled
;
1361 sKernelRequestsEnabled
= flag
? true : false;
1363 if (sKernelRequestsEnabled
!= result
) {
1364 OSKextLog(/* kext */ NULL
,
1365 kOSKextLogBasicLevel
|
1366 kOSKextLogGeneralFlag
,
1367 "Kernel requests now %sabled.",
1368 sKernelRequestsEnabled
? "en" : "dis");
1370 IORecursiveLockUnlock(sKextLock
);
1374 /*********************************************************************
1375 *********************************************************************/
1378 OSKext::getKernelRequestsEnabled(void)
1382 IORecursiveLockLock(sKextLock
);
1383 result
= sKernelRequestsEnabled
;
1384 IORecursiveLockUnlock(sKextLock
);
1389 #pragma mark Kext Life Cycle
1391 /*********************************************************************
1392 *********************************************************************/
1394 OSKext::withPrelinkedInfoDict(
1395 OSDictionary
* anInfoDict
,
1396 bool doCoalesedSlides
)
1398 OSKext
* newKext
= new OSKext
;
1400 if (newKext
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
, doCoalesedSlides
)) {
1408 /*********************************************************************
1409 *********************************************************************/
1411 OSKext::initWithPrelinkedInfoDict(
1412 OSDictionary
* anInfoDict
,
1413 bool doCoalesedSlides
)
1415 bool result
= false;
1416 OSString
* kextPath
= NULL
; // do not release
1417 OSNumber
* addressNum
= NULL
; // reused; do not release
1418 OSNumber
* lengthNum
= NULL
; // reused; do not release
1419 void * data
= NULL
; // do not free
1420 void * srcData
= NULL
; // do not free
1421 OSData
* prelinkedExecutable
= NULL
; // must release
1422 uint32_t length
= 0; // reused
1424 if (!super::init()) {
1428 /* Get the path. Don't look for an arch-specific path property.
1430 kextPath
= OSDynamicCast(OSString
,
1431 anInfoDict
->getObject(kPrelinkBundlePathKey
));
1433 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
1436 #if KASLR_KEXT_DEBUG
1437 IOLog("kaslr: doCoalesedSlides %d kext %s \n", doCoalesedSlides
, getIdentifierCString());
1440 /* Also get the executable's bundle-relative path if present.
1441 * Don't look for an arch-specific path property.
1443 executableRelPath
= OSDynamicCast(OSString
,
1444 anInfoDict
->getObject(kPrelinkExecutableRelativePathKey
));
1445 if (executableRelPath
) {
1446 executableRelPath
->retain();
1449 /* Don't need the paths to be in the info dictionary any more.
1451 anInfoDict
->removeObject(kPrelinkBundlePathKey
);
1452 anInfoDict
->removeObject(kPrelinkExecutableRelativePathKey
);
1454 /* Create an OSData wrapper around the linked executable.
1456 addressNum
= OSDynamicCast(OSNumber
,
1457 anInfoDict
->getObject(kPrelinkExecutableLoadKey
));
1459 lengthNum
= OSDynamicCast(OSNumber
,
1460 anInfoDict
->getObject(kPrelinkExecutableSizeKey
));
1463 kOSKextLogErrorLevel
|
1464 kOSKextLogArchiveFlag
,
1465 "Kext %s can't find prelinked kext executable size.",
1466 getIdentifierCString());
1470 data
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1471 length
= (uint32_t) (lengthNum
->unsigned32BitValue());
1473 #if KASLR_KEXT_DEBUG
1474 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1475 (unsigned long)VM_KERNEL_UNSLIDE(data
),
1476 (unsigned long)data
,
1480 anInfoDict
->removeObject(kPrelinkExecutableLoadKey
);
1481 anInfoDict
->removeObject(kPrelinkExecutableSizeKey
);
1483 /* If the kext's load address differs from its source address, allocate
1484 * space in the kext map at the load address and copy the kext over.
1486 addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
));
1488 srcData
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1490 #if KASLR_KEXT_DEBUG
1491 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1492 (unsigned long)VM_KERNEL_UNSLIDE(srcData
),
1493 (unsigned long)srcData
);
1496 if (data
!= srcData
) {
1498 kern_return_t alloc_result
;
1500 alloc_result
= kext_alloc((vm_offset_t
*)&data
, length
, /* fixed */ TRUE
);
1501 if (alloc_result
!= KERN_SUCCESS
) {
1503 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1504 "Failed to allocate space for prelinked kext %s.",
1505 getIdentifierCString());
1508 memcpy(data
, srcData
, length
);
1511 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1512 "Error: prelinked kext %s - source and load addresses "
1513 "differ on ILP32 architecture.",
1514 getIdentifierCString());
1516 #endif /* __LP64__ */
1519 anInfoDict
->removeObject(kPrelinkExecutableSourceKey
);
1522 prelinkedExecutable
= OSData::withBytesNoCopy(data
, length
);
1523 if (!prelinkedExecutable
) {
1525 kOSKextLogErrorLevel
|
1526 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
1527 "Kext %s failed to create executable wrapper.",
1528 getIdentifierCString());
1533 prelinkedExecutable
->setDeallocFunction(osdata_kext_free
);
1535 prelinkedExecutable
->setDeallocFunction(osdata_phys_free
);
1537 setLinkedExecutable(prelinkedExecutable
);
1538 addressNum
= OSDynamicCast(OSNumber
,
1539 anInfoDict
->getObject(kPrelinkKmodInfoKey
));
1542 kOSKextLogErrorLevel
|
1543 kOSKextLogArchiveFlag
,
1544 "Kext %s can't find prelinked kext kmod_info address.",
1545 getIdentifierCString());
1549 if (addressNum
->unsigned64BitValue() != 0) {
1550 kmod_info
= (kmod_info_t
*) (intptr_t) (addressNum
->unsigned64BitValue() + vm_kernel_slide
);
1551 kmod_info
->address
+= vm_kernel_slide
;
1552 #if KASLR_KEXT_DEBUG
1553 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1554 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
),
1555 (unsigned long)kmod_info
);
1556 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1557 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
1558 (unsigned long)kmod_info
->address
);
1562 anInfoDict
->removeObject(kPrelinkKmodInfoKey
);
1565 /* If the plist has a UUID for an interface, save that off.
1567 if (isInterface()) {
1568 interfaceUUID
= OSDynamicCast(OSData
,
1569 anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
));
1570 if (interfaceUUID
) {
1571 interfaceUUID
->retain();
1572 anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
);
1576 result
= slidePrelinkedExecutable(doCoalesedSlides
);
1577 if (result
!= kOSReturnSuccess
) {
1581 if (doCoalesedSlides
== false) {
1582 /* set VM protections now, wire later at kext load */
1583 result
= setVMAttributes(true, false);
1584 if (result
!= KERN_SUCCESS
) {
1589 flags
.prelinked
= true;
1591 /* If we created a kext from prelink info,
1592 * we must be booting from a prelinked kernel.
1594 sPrelinkBoot
= true;
1596 result
= registerIdentifier();
1599 OSSafeReleaseNULL(prelinkedExecutable
);
1604 /*********************************************************************
1605 *********************************************************************/
1607 void OSKext::setAllVMAttributes(void)
1609 OSCollectionIterator
* kextIterator
= NULL
; // must release
1610 const OSSymbol
* thisID
= NULL
; // do not release
1612 IORecursiveLockLock(sKextLock
);
1614 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1615 if (!kextIterator
) {
1619 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
1620 OSKext
* thisKext
; // do not release
1622 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1623 if (!thisKext
|| thisKext
->isInterface() || !thisKext
->declaresExecutable()) {
1627 /* set VM protections now, wire later at kext load */
1628 thisKext
->setVMAttributes(true, false);
1632 IORecursiveLockUnlock(sKextLock
);
1633 OSSafeReleaseNULL(kextIterator
);
1638 /*********************************************************************
1639 *********************************************************************/
1641 OSKext::withBooterData(
1642 OSString
* deviceTreeName
,
1643 OSData
* booterData
)
1645 OSKext
* newKext
= new OSKext
;
1647 if (newKext
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) {
1655 /*********************************************************************
1656 *********************************************************************/
1657 typedef struct _BooterKextFileInfo
{
1658 uint32_t infoDictPhysAddr
;
1659 uint32_t infoDictLength
;
1660 uint32_t executablePhysAddr
;
1661 uint32_t executableLength
;
1662 uint32_t bundlePathPhysAddr
;
1663 uint32_t bundlePathLength
;
1664 } _BooterKextFileInfo
;
1667 OSKext::initWithBooterData(
1668 OSString
* deviceTreeName
,
1669 OSData
* booterData
)
1671 bool result
= false;
1672 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not free
1673 char * infoDictAddr
= NULL
; // do not free
1674 void * executableAddr
= NULL
; // do not free
1675 char * bundlePathAddr
= NULL
; // do not free
1677 OSObject
* parsedXML
= NULL
; // must release
1678 OSDictionary
* theInfoDict
= NULL
; // do not release
1679 OSString
* kextPath
= NULL
; // must release
1680 OSString
* errorString
= NULL
; // must release
1681 OSData
* executable
= NULL
; // must release
1683 if (!super::init()) {
1687 kextFileInfo
= (_BooterKextFileInfo
*)booterData
->getBytesNoCopy();
1688 if (!kextFileInfo
) {
1690 kOSKextLogErrorLevel
|
1691 kOSKextLogGeneralFlag
,
1692 "No booter-provided data for kext device tree entry %s.",
1693 deviceTreeName
->getCStringNoCopy());
1697 /* The info plist must exist or we can't read the kext.
1699 if (!kextFileInfo
->infoDictPhysAddr
|| !kextFileInfo
->infoDictLength
) {
1701 kOSKextLogErrorLevel
|
1702 kOSKextLogGeneralFlag
,
1703 "No kext info dictionary for booter device tree entry %s.",
1704 deviceTreeName
->getCStringNoCopy());
1708 infoDictAddr
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
1709 if (!infoDictAddr
) {
1711 kOSKextLogErrorLevel
|
1712 kOSKextLogGeneralFlag
,
1713 "Can't translate physical address 0x%x of kext info dictionary "
1714 "for device tree entry %s.",
1715 (int)kextFileInfo
->infoDictPhysAddr
,
1716 deviceTreeName
->getCStringNoCopy());
1720 parsedXML
= OSUnserializeXML(infoDictAddr
, &errorString
);
1722 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
1725 const char * errorCString
= "(unknown error)";
1727 if (errorString
&& errorString
->getCStringNoCopy()) {
1728 errorCString
= errorString
->getCStringNoCopy();
1729 } else if (parsedXML
) {
1730 errorCString
= "not a dictionary";
1733 kOSKextLogErrorLevel
|
1734 kOSKextLogGeneralFlag
,
1735 "Error unserializing info dictionary for device tree entry %s: %s.",
1736 deviceTreeName
->getCStringNoCopy(), errorCString
);
1740 /* A bundle path is not mandatory.
1742 if (kextFileInfo
->bundlePathPhysAddr
&& kextFileInfo
->bundlePathLength
) {
1743 bundlePathAddr
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
);
1744 if (!bundlePathAddr
) {
1746 kOSKextLogErrorLevel
|
1747 kOSKextLogGeneralFlag
,
1748 "Can't translate physical address 0x%x of kext bundle path "
1749 "for device tree entry %s.",
1750 (int)kextFileInfo
->bundlePathPhysAddr
,
1751 deviceTreeName
->getCStringNoCopy());
1754 bundlePathAddr
[kextFileInfo
->bundlePathLength
-1] = '\0'; // just in case!
1756 kextPath
= OSString::withCString(bundlePathAddr
);
1759 kOSKextLogErrorLevel
|
1760 kOSKextLogGeneralFlag
,
1761 "Failed to create wrapper for device tree entry %s kext path %s.",
1762 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
);
1767 if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) {
1771 /* An executable is not mandatory.
1773 if (kextFileInfo
->executablePhysAddr
&& kextFileInfo
->executableLength
) {
1774 executableAddr
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
);
1775 if (!executableAddr
) {
1777 kOSKextLogErrorLevel
|
1778 kOSKextLogGeneralFlag
,
1779 "Can't translate physical address 0x%x of kext executable "
1780 "for device tree entry %s.",
1781 (int)kextFileInfo
->executablePhysAddr
,
1782 deviceTreeName
->getCStringNoCopy());
1786 executable
= OSData::withBytesNoCopy(executableAddr
,
1787 kextFileInfo
->executableLength
);
1790 kOSKextLogErrorLevel
|
1791 kOSKextLogGeneralFlag
,
1792 "Failed to create executable wrapper for device tree entry %s.",
1793 deviceTreeName
->getCStringNoCopy());
1797 /* A kext with an executable needs to retain the whole booterData
1798 * object to keep the executable in memory.
1800 if (!setExecutable(executable
, booterData
)) {
1802 kOSKextLogErrorLevel
|
1803 kOSKextLogGeneralFlag
,
1804 "Failed to set kext executable for device tree entry %s.",
1805 deviceTreeName
->getCStringNoCopy());
1810 result
= registerIdentifier();
1813 OSSafeReleaseNULL(parsedXML
);
1814 OSSafeReleaseNULL(kextPath
);
1815 OSSafeReleaseNULL(errorString
);
1816 OSSafeReleaseNULL(executable
);
1821 /*********************************************************************
1822 *********************************************************************/
1824 OSKext::registerIdentifier(void)
1826 bool result
= false;
1827 OSKext
* existingKext
= NULL
; // do not release
1828 bool existingIsLoaded
= false;
1829 bool existingIsPrelinked
= false;
1830 OSKextVersion newVersion
= -1;
1831 OSKextVersion existingVersion
= -1;
1832 char newVersionCString
[kOSKextVersionMaxLength
];
1833 char existingVersionCString
[kOSKextVersionMaxLength
];
1834 OSData
* newUUID
= NULL
; // must release
1835 OSData
* existingUUID
= NULL
; // must release
1837 IORecursiveLockLock(sKextLock
);
1839 /* Get the new kext's version for checks & log messages.
1841 newVersion
= getVersion();
1842 OSKextVersionGetString(newVersion
, newVersionCString
,
1843 kOSKextVersionMaxLength
);
1845 /* If we don't have an existing kext with this identifier,
1846 * just record the new kext and we're done!
1848 existingKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
));
1849 if (!existingKext
) {
1850 sKextsByID
->setObject(bundleID
, this);
1855 /* Get the existing kext's version for checks & log messages.
1857 existingVersion
= existingKext
->getVersion();
1858 OSKextVersionGetString(existingVersion
,
1859 existingVersionCString
, kOSKextVersionMaxLength
);
1861 existingIsLoaded
= existingKext
->isLoaded();
1862 existingIsPrelinked
= existingKext
->isPrelinked();
1864 /* If we have a kext with this identifier that's already loaded/prelinked,
1865 * we can't use the new one, but let's be really thorough and check how
1866 * the two are related for a precise diagnostic log message.
1868 * Note that user space can't find out about nonloaded prelinked kexts,
1869 * so in this case we log a message when new & existing are equivalent
1870 * at the step rather than warning level, because we are always going
1871 * be getting a copy of the kext in the user load request mkext.
1873 if (existingIsLoaded
|| existingIsPrelinked
) {
1874 bool sameVersion
= (newVersion
== existingVersion
);
1875 bool sameExecutable
= true; // assume true unless we have UUIDs
1877 /* Only get the UUID if the existing kext is loaded. Doing so
1878 * might have to uncompress an mkext executable and we shouldn't
1879 * take that hit when neither kext is loaded.
1881 newUUID
= copyUUID();
1882 existingUUID
= existingKext
->copyUUID();
1884 /* I'm entirely too paranoid about checking equivalence of executables,
1885 * but I remember nasty problems with it in the past.
1887 * - If we have UUIDs for both kexts, compare them.
1888 * - If only one kext has a UUID, they're definitely different.
1890 if (newUUID
&& existingUUID
) {
1891 sameExecutable
= newUUID
->isEqualTo(existingUUID
);
1892 } else if (newUUID
|| existingUUID
) {
1893 sameExecutable
= false;
1896 if (!newUUID
&& !existingUUID
) {
1898 /* If there are no UUIDs, we can't really tell that the executables
1899 * are *different* without a lot of work; the loaded kext's
1900 * unrelocated executable is no longer around (and we never had it
1901 * in-kernel for a prelinked kext). We certainly don't want to do
1902 * a whole fake link for the new kext just to compare, either.
1905 OSKextVersionGetString(version
, newVersionCString
,
1906 sizeof(newVersionCString
));
1908 kOSKextLogWarningLevel
|
1909 kOSKextLogKextBookkeepingFlag
,
1910 "Notice - new kext %s, v%s matches %s kext "
1911 "but can't determine if executables are the same (no UUIDs).",
1912 getIdentifierCString(),
1914 (existingIsLoaded
? "loaded" : "prelinked"));
1917 if (sameVersion
&& sameExecutable
) {
1919 (existingIsLoaded
? kOSKextLogWarningLevel
: kOSKextLogStepLevel
) |
1920 kOSKextLogKextBookkeepingFlag
,
1921 "Refusing new kext %s, v%s: a %s copy is already present "
1922 "(same version and executable).",
1923 getIdentifierCString(), newVersionCString
,
1924 (existingIsLoaded
? "loaded" : "prelinked"));
1927 /* This condition is significant so log it under warnings.
1930 kOSKextLogWarningLevel
|
1931 kOSKextLogKextBookkeepingFlag
,
1932 "Refusing new kext %s, v%s: already have %s v%s.",
1933 getIdentifierCString(),
1935 (existingIsLoaded
? "loaded" : "prelinked"),
1936 existingVersionCString
);
1938 /* This condition is significant so log it under warnings.
1941 kOSKextLogWarningLevel
| kOSKextLogKextBookkeepingFlag
,
1942 "Refusing new kext %s, v%s: a %s copy with a different "
1943 "executable UUID is already present.",
1944 getIdentifierCString(), newVersionCString
,
1945 (existingIsLoaded
? "loaded" : "prelinked"));
1949 } /* if (existingIsLoaded || existingIsPrelinked) */
1951 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
1952 * user loads are happening or if we're still in early boot. User agents are
1953 * supposed to resolve dependencies topside and include only the exact
1954 * kexts needed; so we always accept the new kext (in fact we should never
1955 * see an older unloaded copy hanging around).
1957 if (sUserLoadsActive
) {
1958 sKextsByID
->setObject(bundleID
, this);
1962 kOSKextLogStepLevel
|
1963 kOSKextLogKextBookkeepingFlag
,
1964 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
1965 getIdentifierCString(),
1966 existingVersionCString
,
1972 /* During early boot, the kext with the highest version always wins out.
1973 * Prelinked kernels will never hit this, but mkexts and booter-read
1974 * kexts might have duplicates.
1976 if (newVersion
> existingVersion
) {
1977 sKextsByID
->setObject(bundleID
, this);
1981 kOSKextLogStepLevel
|
1982 kOSKextLogKextBookkeepingFlag
,
1983 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
1984 existingVersionCString
,
1985 getIdentifierCString(),
1990 kOSKextLogStepLevel
|
1991 kOSKextLogKextBookkeepingFlag
,
1992 "Kext %s is already registered with a higher/same version (v%s); "
1993 "dropping newly-added (v%s).",
1994 getIdentifierCString(),
1995 existingVersionCString
,
1999 /* result has been set appropriately by now. */
2003 IORecursiveLockUnlock(sKextLock
);
2007 kOSKextLogStepLevel
|
2008 kOSKextLogKextBookkeepingFlag
,
2009 "Kext %s, v%s registered and available for loading.",
2010 getIdentifierCString(), newVersionCString
);
2013 OSSafeReleaseNULL(newUUID
);
2014 OSSafeReleaseNULL(existingUUID
);
2019 /*********************************************************************
2020 * Does the bare minimum validation to look up a kext.
2021 * All other validation is done on the spot as needed.
2022 **********************************************************************/
2024 OSKext::setInfoDictionaryAndPath(
2025 OSDictionary
* aDictionary
,
2028 bool result
= false;
2029 OSString
* bundleIDString
= NULL
; // do not release
2030 OSString
* versionString
= NULL
; // do not release
2031 OSString
* compatibleVersionString
= NULL
; // do not release
2032 const char * versionCString
= NULL
; // do not free
2033 const char * compatibleVersionCString
= NULL
; // do not free
2034 OSBoolean
* scratchBool
= NULL
; // do not release
2035 OSDictionary
* scratchDict
= NULL
; // do not release
2038 panic("Attempt to set info dictionary on a kext "
2039 "that already has one (%s).",
2040 getIdentifierCString());
2043 if (!aDictionary
|| !OSDynamicCast(OSDictionary
, aDictionary
)) {
2047 infoDict
= aDictionary
;
2050 /* Check right away if the info dictionary has any log flags.
2052 scratchBool
= OSDynamicCast(OSBoolean
,
2053 getPropertyForHostArch(kOSBundleEnableKextLoggingKey
));
2054 if (scratchBool
== kOSBooleanTrue
) {
2055 flags
.loggingEnabled
= 1;
2058 /* The very next thing to get is the bundle identifier. Unlike
2059 * in user space, a kext with no bundle identifier gets axed
2062 bundleIDString
= OSDynamicCast(OSString
,
2063 getPropertyForHostArch(kCFBundleIdentifierKey
));
2064 if (!bundleIDString
) {
2066 kOSKextLogErrorLevel
|
2067 kOSKextLogValidationFlag
,
2068 "CFBundleIdentifier missing/invalid type in kext %s.",
2069 aPath
? aPath
->getCStringNoCopy() : "(unknown)");
2072 bundleID
= OSSymbol::withString(bundleIDString
);
2075 kOSKextLogErrorLevel
|
2076 kOSKextLogValidationFlag
,
2077 "Can't copy bundle identifier as symbol for kext %s.",
2078 bundleIDString
->getCStringNoCopy());
2082 /* Save the path if we got one (it should always be available but it's
2083 * just something nice to have for bookkeeping).
2091 * Minimal validation to initialize. We'll do other validation on the spot.
2093 if (bundleID
->getLength() >= KMOD_MAX_NAME
) {
2095 kOSKextLogErrorLevel
|
2096 kOSKextLogValidationFlag
,
2097 "Kext %s error - CFBundleIdentifier over max length %d.",
2098 getIdentifierCString(), KMOD_MAX_NAME
- 1);
2102 version
= compatibleVersion
= -1;
2104 versionString
= OSDynamicCast(OSString
,
2105 getPropertyForHostArch(kCFBundleVersionKey
));
2106 if (!versionString
) {
2108 kOSKextLogErrorLevel
|
2109 kOSKextLogValidationFlag
,
2110 "Kext %s error - CFBundleVersion missing/invalid type.",
2111 getIdentifierCString());
2114 versionCString
= versionString
->getCStringNoCopy();
2115 version
= OSKextParseVersionString(versionCString
);
2118 kOSKextLogErrorLevel
|
2119 kOSKextLogValidationFlag
,
2120 "Kext %s error - CFBundleVersion bad value '%s'.",
2121 getIdentifierCString(), versionCString
);
2125 compatibleVersion
= -1; // set to illegal value for kexts that don't have
2127 compatibleVersionString
= OSDynamicCast(OSString
,
2128 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
2129 if (compatibleVersionString
) {
2130 compatibleVersionCString
= compatibleVersionString
->getCStringNoCopy();
2131 compatibleVersion
= OSKextParseVersionString(compatibleVersionCString
);
2132 if (compatibleVersion
< 0) {
2134 kOSKextLogErrorLevel
|
2135 kOSKextLogValidationFlag
,
2136 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2137 getIdentifierCString(), compatibleVersionCString
);
2141 if (compatibleVersion
> version
) {
2143 kOSKextLogErrorLevel
|
2144 kOSKextLogValidationFlag
,
2145 "Kext %s error - %s %s > %s %s (must be <=).",
2146 getIdentifierCString(),
2147 kOSBundleCompatibleVersionKey
, compatibleVersionCString
,
2148 kCFBundleVersionKey
, versionCString
);
2153 /* Check to see if this kext is in exclude list */
2154 if ( isInExcludeList() ) {
2156 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
2157 "Kext %s is in exclude list, not loadable",
2158 getIdentifierCString());
2162 /* Set flags for later use if the infoDict gets flushed. We only
2163 * check for true values, not false ones(!)
2165 scratchBool
= OSDynamicCast(OSBoolean
,
2166 getPropertyForHostArch(kOSBundleIsInterfaceKey
));
2167 if (scratchBool
== kOSBooleanTrue
) {
2168 flags
.interface
= 1;
2171 scratchBool
= OSDynamicCast(OSBoolean
,
2172 getPropertyForHostArch(kOSKernelResourceKey
));
2173 if (scratchBool
== kOSBooleanTrue
) {
2174 flags
.kernelComponent
= 1;
2175 flags
.interface
= 1; // xxx - hm. the kernel itself isn't an interface...
2178 /* A kernel component has one implicit dependency on the kernel.
2180 flags
.hasAllDependencies
= 1;
2183 /* Make sure common string values in personalities are uniqued to OSSymbols.
2185 scratchDict
= OSDynamicCast(OSDictionary
,
2186 getPropertyForHostArch(kIOKitPersonalitiesKey
));
2188 uniquePersonalityProperties(scratchDict
);
2198 /*********************************************************************
2199 * Not used for prelinked kernel boot as there is no unrelocated
2201 *********************************************************************/
2203 OSKext::setExecutable(
2204 OSData
* anExecutable
,
2205 OSData
* externalData
,
2206 bool externalDataIsMkext
)
2208 bool result
= false;
2209 const char * executableKey
= NULL
; // do not free
2211 if (!anExecutable
) {
2212 infoDict
->removeObject(_kOSKextExecutableKey
);
2213 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
2214 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
2219 if (infoDict
->getObject(_kOSKextExecutableKey
) ||
2220 infoDict
->getObject(_kOSKextMkextExecutableReferenceKey
)) {
2222 panic("Attempt to set an executable on a kext "
2223 "that already has one (%s).",
2224 getIdentifierCString());
2228 if (externalDataIsMkext
) {
2229 executableKey
= _kOSKextMkextExecutableReferenceKey
;
2231 executableKey
= _kOSKextExecutableKey
;
2235 infoDict
->setObject(executableKey
, anExecutable
);
2237 infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
);
2247 /*********************************************************************
2248 *********************************************************************/
2250 uniqueStringPlistProperty(OSDictionary
* dict
, const char * key
)
2252 OSString
* stringValue
= NULL
; // do not release
2253 const OSSymbol
* symbolValue
= NULL
; // must release
2255 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2260 symbolValue
= OSSymbol::withString(stringValue
);
2265 dict
->setObject(key
, symbolValue
);
2268 if (symbolValue
) symbolValue
->release();
2273 /*********************************************************************
2274 *********************************************************************/
2276 uniqueStringPlistProperty(OSDictionary
* dict
, const OSString
* key
)
2278 OSString
* stringValue
= NULL
; // do not release
2279 const OSSymbol
* symbolValue
= NULL
; // must release
2281 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2286 symbolValue
= OSSymbol::withString(stringValue
);
2291 dict
->setObject(key
, symbolValue
);
2294 if (symbolValue
) symbolValue
->release();
2299 /*********************************************************************
2300 * Replace common personality property values with uniqued instances
2301 * to save on wired memory.
2302 *********************************************************************/
2305 OSKext::uniquePersonalityProperties(OSDictionary
* personalityDict
)
2307 /* Properties every personality has.
2309 uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKey
);
2310 uniqueStringPlistProperty(personalityDict
, kIOProviderClassKey
);
2311 uniqueStringPlistProperty(personalityDict
, gIOClassKey
);
2313 /* Other commonly used properties.
2315 uniqueStringPlistProperty(personalityDict
, gIOMatchCategoryKey
);
2316 uniqueStringPlistProperty(personalityDict
, gIOResourceMatchKey
);
2317 uniqueStringPlistProperty(personalityDict
, gIOUserClientClassKey
);
2319 uniqueStringPlistProperty(personalityDict
, "HIDDefaultBehavior");
2320 uniqueStringPlistProperty(personalityDict
, "HIDPointerAccelerationType");
2321 uniqueStringPlistProperty(personalityDict
, "HIDRemoteControlType");
2322 uniqueStringPlistProperty(personalityDict
, "HIDScrollAccelerationType");
2323 uniqueStringPlistProperty(personalityDict
, "IOPersonalityPublisher");
2324 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect");
2325 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect Location");
2326 uniqueStringPlistProperty(personalityDict
, "Vendor");
2327 uniqueStringPlistProperty(personalityDict
, "Vendor Identification");
2328 uniqueStringPlistProperty(personalityDict
, "Vendor Name");
2329 uniqueStringPlistProperty(personalityDict
, "bConfigurationValue");
2330 uniqueStringPlistProperty(personalityDict
, "bInterfaceNumber");
2331 uniqueStringPlistProperty(personalityDict
, "idProduct");
2336 /*********************************************************************
2337 *********************************************************************/
2342 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2345 OSSafeReleaseNULL(infoDict
);
2346 OSSafeReleaseNULL(bundleID
);
2347 OSSafeReleaseNULL(path
);
2348 OSSafeReleaseNULL(executableRelPath
);
2349 OSSafeReleaseNULL(dependencies
);
2350 OSSafeReleaseNULL(linkedExecutable
);
2351 OSSafeReleaseNULL(metaClasses
);
2352 OSSafeReleaseNULL(interfaceUUID
);
2354 if (isInterface() && kmod_info
) {
2355 kfree(kmod_info
, sizeof(kmod_info_t
));
2363 #pragma mark Mkext files
2365 /*********************************************************************
2366 *********************************************************************/
2368 OSKext::readMkextArchive(OSData
* mkextData
,
2369 uint32_t * checksumPtr
)
2371 OSReturn result
= kOSKextReturnBadData
;
2372 uint32_t mkextLength
= 0;
2373 mkext_header
* mkextHeader
= 0; // do not free
2374 uint32_t mkextVersion
= 0;
2376 /* Note default return of kOSKextReturnBadData above.
2378 mkextLength
= mkextData
->getLength();
2379 if (mkextLength
< sizeof(mkext_basic_header
)) {
2380 OSKextLog(/* kext */ NULL
,
2381 kOSKextLogErrorLevel
|
2382 kOSKextLogArchiveFlag
,
2383 "Mkext archive too small to be valid.");
2387 mkextHeader
= (mkext_header
*)mkextData
->getBytesNoCopy();
2389 if (MKEXT_GET_MAGIC(mkextHeader
) != MKEXT_MAGIC
||
2390 MKEXT_GET_SIGNATURE(mkextHeader
) != MKEXT_SIGN
) {
2391 OSKextLog(/* kext */ NULL
,
2392 kOSKextLogErrorLevel
|
2393 kOSKextLogArchiveFlag
,
2394 "Mkext archive has invalid magic or signature.");
2398 if (MKEXT_GET_LENGTH(mkextHeader
) != mkextLength
) {
2399 OSKextLog(/* kext */ NULL
,
2400 kOSKextLogErrorLevel
|
2401 kOSKextLogArchiveFlag
,
2402 "Mkext archive recorded length doesn't match actual file length.");
2406 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2408 if (mkextVersion
== MKEXT_VERS_2
) {
2409 result
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
);
2411 OSKextLog(/* kext */ NULL
,
2412 kOSKextLogErrorLevel
|
2413 kOSKextLogArchiveFlag
,
2414 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
);
2415 result
= kOSKextReturnUnsupported
;
2422 /*********************************************************************
2423 * Assumes magic, signature, version, length have been checked.
2424 * xxx - need to add further bounds checking for each file entry
2426 * Should keep track of all kexts created so far, and if we hit a
2427 * fatal error halfway through, remove those kexts. If we've dropped
2428 * an older version that had already been read, whoops! Might want to
2429 * add a level of buffering?
2430 *********************************************************************/
2433 OSKext::readMkext2Archive(
2435 OSDictionary
** mkextPlistOut
,
2436 uint32_t * checksumPtr
)
2438 OSReturn result
= kOSReturnError
;
2439 uint32_t mkextLength
;
2440 mkext2_header
* mkextHeader
= NULL
; // do not free
2441 void * mkextEnd
= NULL
; // do not free
2442 uint32_t mkextVersion
;
2443 uint8_t * crc_address
= NULL
;
2445 uint32_t mkextPlistOffset
;
2446 uint32_t mkextPlistCompressedSize
;
2447 char * mkextPlistEnd
= NULL
; // do not free
2448 uint32_t mkextPlistFullSize
;
2449 OSString
* errorString
= NULL
; // must release
2450 OSData
* mkextPlistUncompressedData
= NULL
; // must release
2451 const char * mkextPlistDataBuffer
= NULL
; // do not free
2452 OSObject
* parsedXML
= NULL
; // must release
2453 OSDictionary
* mkextPlist
= NULL
; // do not release
2454 OSArray
* mkextInfoDictArray
= NULL
; // do not release
2457 mkextLength
= mkextData
->getLength();
2458 mkextHeader
= (mkext2_header
*)mkextData
->getBytesNoCopy();
2459 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2460 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2462 crc_address
= (u_int8_t
*)&mkextHeader
->version
;
2463 checksum
= mkext_adler32(crc_address
,
2464 (uintptr_t)mkextHeader
+
2465 MKEXT_GET_LENGTH(mkextHeader
) - (uintptr_t)crc_address
);
2467 if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) {
2468 OSKextLog(/* kext */ NULL
,
2469 kOSKextLogErrorLevel
|
2470 kOSKextLogArchiveFlag
,
2471 "Mkext archive has bad checksum.");
2472 result
= kOSKextReturnBadData
;
2477 *checksumPtr
= checksum
;
2480 /* Check that the CPU type & subtype match that of the running kernel. */
2481 if (MKEXT_GET_CPUTYPE(mkextHeader
) == (UInt32
)CPU_TYPE_ANY
) {
2482 OSKextLog(/* kext */ NULL
,
2483 kOSKextLogErrorLevel
|
2484 kOSKextLogArchiveFlag
,
2485 "Mkext archive must have a specific CPU type.");
2486 result
= kOSKextReturnBadData
;
2489 if ((UInt32
)_mh_execute_header
.cputype
!=
2490 MKEXT_GET_CPUTYPE(mkextHeader
)) {
2492 OSKextLog(/* kext */ NULL
,
2493 kOSKextLogErrorLevel
|
2494 kOSKextLogArchiveFlag
,
2495 "Mkext archive does not match the running kernel's CPU type.");
2496 result
= kOSKextReturnArchNotFound
;
2501 mkextPlistOffset
= MKEXT2_GET_PLIST(mkextHeader
);
2502 mkextPlistCompressedSize
= MKEXT2_GET_PLIST_COMPSIZE(mkextHeader
);
2503 mkextPlistEnd
= (char *)mkextHeader
+ mkextPlistOffset
+
2504 mkextPlistCompressedSize
;
2505 if (mkextPlistEnd
> mkextEnd
) {
2506 OSKextLog(/* kext */ NULL
,
2507 kOSKextLogErrorLevel
|
2508 kOSKextLogArchiveFlag
,
2509 "Mkext archive file overrun.");
2510 result
= kOSKextReturnBadData
;
2513 mkextPlistFullSize
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
);
2514 if (mkextPlistCompressedSize
) {
2515 mkextPlistUncompressedData
= sKernelKext
->extractMkext2FileData(
2516 (UInt8
*)mkextHeader
+ mkextPlistOffset
,
2518 mkextPlistCompressedSize
, mkextPlistFullSize
);
2519 if (!mkextPlistUncompressedData
) {
2522 mkextPlistDataBuffer
= (const char *)
2523 mkextPlistUncompressedData
->getBytesNoCopy();
2525 mkextPlistDataBuffer
= (const char *)mkextHeader
+ mkextPlistOffset
;
2528 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2530 parsedXML
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
);
2532 mkextPlist
= OSDynamicCast(OSDictionary
, parsedXML
);
2535 const char * errorCString
= "(unknown error)";
2537 if (errorString
&& errorString
->getCStringNoCopy()) {
2538 errorCString
= errorString
->getCStringNoCopy();
2539 } else if (parsedXML
) {
2540 errorCString
= "not a dictionary";
2542 OSKextLog(/* kext */ NULL
,
2543 kOSKextLogErrorLevel
|
2544 kOSKextLogArchiveFlag
,
2545 "Error unserializing mkext plist: %s.", errorCString
);
2549 /* If the caller needs the plist, hand it back and retain it.
2550 * (This function releases it at the end.)
2552 if (mkextPlistOut
) {
2553 *mkextPlistOut
= mkextPlist
;
2554 (*mkextPlistOut
)->retain();
2557 mkextInfoDictArray
= OSDynamicCast(OSArray
,
2558 mkextPlist
->getObject(kMKEXTInfoDictionariesKey
));
2559 if (!mkextInfoDictArray
) {
2560 OSKextLog(/* kext */ NULL
,
2561 kOSKextLogErrorLevel
|
2562 kOSKextLogArchiveFlag
,
2563 "Mkext archive contains no kext info dictionaries.");
2567 count
= mkextInfoDictArray
->getCount();
2568 for (i
= 0; i
< count
; i
++) {
2569 OSDictionary
* infoDict
;
2572 infoDict
= OSDynamicCast(OSDictionary
,
2573 mkextInfoDictArray
->getObject(i
));
2575 /* Create the kext for the entry, then release it, because the
2576 * kext system keeps them around until explicitly removed.
2577 * Any creation/registration failures are already logged for us.
2580 OSKext
* newKext
= OSKext::withMkext2Info(infoDict
, mkextData
);
2581 OSSafeReleaseNULL(newKext
);
2585 /* Even if we didn't keep any kexts from the mkext, we may have a load
2586 * request to process, so we are successful (no errors occurred).
2588 result
= kOSReturnSuccess
;
2592 OSSafeReleaseNULL(parsedXML
);
2593 OSSafeReleaseNULL(mkextPlistUncompressedData
);
2594 OSSafeReleaseNULL(errorString
);
2599 /*********************************************************************
2600 *********************************************************************/
2603 OSKext::withMkext2Info(
2604 OSDictionary
* anInfoDict
,
2607 OSKext
* newKext
= new OSKext
;
2609 if (newKext
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) {
2617 /*********************************************************************
2618 *********************************************************************/
2620 OSKext::initWithMkext2Info(
2621 OSDictionary
* anInfoDict
,
2624 bool result
= false;
2625 OSString
* kextPath
= NULL
; // do not release
2626 OSNumber
* executableOffsetNum
= NULL
; // do not release
2627 OSCollectionIterator
* iterator
= NULL
; // must release
2628 OSData
* executable
= NULL
; // must release
2630 if (anInfoDict
== NULL
|| !super::init()) {
2634 /* Get the path. Don't look for an arch-specific path property.
2636 kextPath
= OSDynamicCast(OSString
,
2637 anInfoDict
->getObject(kMKEXTBundlePathKey
));
2639 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
2643 /* If we have a path to the executable, save it.
2645 executableRelPath
= OSDynamicCast(OSString
,
2646 anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
));
2647 if (executableRelPath
) {
2648 executableRelPath
->retain();
2651 /* Don't need the paths to be in the info dictionary any more.
2653 anInfoDict
->removeObject(kMKEXTBundlePathKey
);
2654 anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
);
2656 executableOffsetNum
= OSDynamicCast(OSNumber
,
2657 infoDict
->getObject(kMKEXTExecutableKey
));
2658 if (executableOffsetNum
) {
2659 executable
= createMkext2FileEntry(mkextData
,
2660 executableOffsetNum
, "executable");
2661 infoDict
->removeObject(kMKEXTExecutableKey
);
2665 if (!setExecutable(executable
, mkextData
, true)) {
2670 result
= registerIdentifier();
2674 OSSafeReleaseNULL(executable
);
2675 OSSafeReleaseNULL(iterator
);
2679 /*********************************************************************
2680 *********************************************************************/
2682 OSKext::createMkext2FileEntry(
2684 OSNumber
* offsetNum
,
2687 OSData
* result
= NULL
;
2688 MkextEntryRef entryRef
;
2689 uint8_t * mkextBuffer
= (uint8_t *)mkextData
->getBytesNoCopy();
2690 uint32_t entryOffset
= offsetNum
->unsigned32BitValue();
2692 result
= OSData::withCapacity(sizeof(entryRef
));
2697 entryRef
.mkext
= (mkext_basic_header
*)mkextBuffer
;
2698 entryRef
.fileinfo
= mkextBuffer
+ entryOffset
;
2699 if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) {
2700 OSSafeReleaseNULL(result
);
2707 kOSKextLogErrorLevel
|
2708 kOSKextLogArchiveFlag
,
2709 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2710 name
, getIdentifierCString());
2715 /*********************************************************************
2716 *********************************************************************/
2718 static void * z_alloc(void *, u_int items
, u_int size
);
2719 static void z_free(void *, void *ptr
);
2721 typedef struct z_mem
{
2722 uint32_t alloc_size
;
2727 * Space allocation and freeing routines for use by zlib routines.
2730 z_alloc(void * notused __unused
, u_int num_items
, u_int size
)
2732 void * result
= NULL
;
2733 z_mem
* zmem
= NULL
;
2735 uint64_t total
= ((uint64_t)num_items
) * ((uint64_t)size
);
2736 //Check for overflow due to multiplication
2737 if (total
> UINT32_MAX
){
2738 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
2739 notused
, num_items
, size
, num_items
, size
);
2742 uint64_t allocSize64
= total
+ ((uint64_t)sizeof(zmem
));
2743 //Check for overflow due to addition
2744 if (allocSize64
> UINT32_MAX
){
2745 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
2746 notused
, num_items
, size
, (uint32_t)total
, sizeof(zmem
));
2748 uint32_t allocSize
= (uint32_t)allocSize64
;
2750 zmem
= (z_mem
*)kalloc_tag(allocSize
, VM_KERN_MEMORY_OSKEXT
);
2754 zmem
->alloc_size
= allocSize
;
2755 result
= (void *)&(zmem
->data
);
2761 z_free(void * notused __unused
, void * ptr
)
2763 uint32_t * skipper
= (uint32_t *)ptr
- 1;
2764 z_mem
* zmem
= (z_mem
*)skipper
;
2765 kfree((void *)zmem
, zmem
->alloc_size
);
2771 OSKext::extractMkext2FileData(
2774 uint32_t compressedSize
,
2777 OSData
* result
= NULL
;
2779 OSData
* uncompressedData
= NULL
; // release on error
2781 uint8_t * uncompressedDataBuffer
= 0; // do not free
2782 unsigned long uncompressedSize
;
2784 bool zstream_inited
= false;
2787 /* If the file isn't compressed, we want to make a copy
2788 * so that we don't have the tie to the larger mkext file buffer any more.
2790 if (!compressedSize
) {
2791 uncompressedData
= OSData::withBytes(data
, fullSize
);
2792 // xxx - no check for failure?
2793 result
= uncompressedData
;
2797 if (KERN_SUCCESS
!= kmem_alloc(kernel_map
,
2798 (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
, VM_KERN_MEMORY_OSKEXT
)) {
2800 /* How's this for cheesy? The kernel is only asked to extract
2801 * kext plists so we tailor the log messages.
2805 kOSKextLogErrorLevel
|
2806 kOSKextLogArchiveFlag
,
2807 "Allocation failure extracting %s from mkext.", name
);
2810 kOSKextLogErrorLevel
|
2811 kOSKextLogArchiveFlag
,
2812 "Allocation failure extracting %s from mkext for kext %s.",
2813 name
, getIdentifierCString());
2818 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
);
2819 if (!uncompressedData
) {
2822 kOSKextLogErrorLevel
|
2823 kOSKextLogArchiveFlag
,
2824 "Allocation failure extracting %s from mkext.", name
);
2827 kOSKextLogErrorLevel
|
2828 kOSKextLogArchiveFlag
,
2829 "Allocation failure extracting %s from mkext for kext %s.",
2830 name
, getIdentifierCString());
2834 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
2838 kOSKextLogDetailLevel
|
2839 kOSKextLogArchiveFlag
,
2840 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2841 name
, compressedSize
, fullSize
);
2844 kOSKextLogDetailLevel
|
2845 kOSKextLogArchiveFlag
,
2846 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2847 getIdentifierCString(), name
, compressedSize
, fullSize
);
2850 bzero(&zstream
, sizeof(zstream
));
2851 zstream
.next_in
= (UInt8
*)data
;
2852 zstream
.avail_in
= compressedSize
;
2854 zstream
.next_out
= uncompressedDataBuffer
;
2855 zstream
.avail_out
= fullSize
;
2857 zstream
.zalloc
= z_alloc
;
2858 zstream
.zfree
= z_free
;
2860 zlib_result
= inflateInit(&zstream
);
2861 if (Z_OK
!= zlib_result
) {
2864 kOSKextLogErrorLevel
|
2865 kOSKextLogArchiveFlag
,
2866 "Mkext error; zlib inflateInit failed (%d) for %s.",
2870 kOSKextLogErrorLevel
|
2871 kOSKextLogArchiveFlag
,
2872 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2873 getIdentifierCString(), zlib_result
, name
);
2877 zstream_inited
= true;
2880 zlib_result
= inflate(&zstream
, Z_FINISH
);
2882 if (zlib_result
== Z_STREAM_END
|| zlib_result
== Z_OK
) {
2883 uncompressedSize
= zstream
.total_out
;
2887 kOSKextLogErrorLevel
|
2888 kOSKextLogArchiveFlag
,
2889 "Mkext error; zlib inflate failed (%d) for %s.",
2893 kOSKextLogErrorLevel
|
2894 kOSKextLogArchiveFlag
,
2895 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
2896 getIdentifierCString(), zlib_result
, name
);
2900 kOSKextLogErrorLevel
|
2901 kOSKextLogArchiveFlag
,
2902 "zlib error: %s.", zstream
.msg
);
2907 if (uncompressedSize
!= fullSize
) {
2910 kOSKextLogErrorLevel
|
2911 kOSKextLogArchiveFlag
,
2912 "Mkext error; zlib inflate discrepancy for %s, "
2913 "uncompressed size != original size.", name
);
2916 kOSKextLogErrorLevel
|
2917 kOSKextLogArchiveFlag
,
2918 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
2919 "uncompressed size != original size.",
2920 getIdentifierCString(), name
);
2925 result
= uncompressedData
;
2928 /* Don't bother checking return, nothing we can do on fail.
2930 if (zstream_inited
) inflateEnd(&zstream
);
2933 OSSafeReleaseNULL(uncompressedData
);
2939 /*********************************************************************
2940 *********************************************************************/
2943 OSKext::loadFromMkext(
2944 OSKextLogSpec clientLogFilter
,
2946 uint32_t mkextBufferLength
,
2948 uint32_t * logInfoLengthOut
)
2950 OSReturn result
= kOSReturnError
;
2951 OSReturn tempResult
= kOSReturnError
;
2953 OSData
* mkextData
= NULL
; // must release
2954 OSDictionary
* mkextPlist
= NULL
; // must release
2956 OSArray
* logInfoArray
= NULL
; // must release
2957 OSSerialize
* serializer
= NULL
; // must release
2959 OSString
* predicate
= NULL
; // do not release
2960 OSDictionary
* requestArgs
= NULL
; // do not release
2962 OSString
* kextIdentifier
= NULL
; // do not release
2963 OSNumber
* startKextExcludeNum
= NULL
; // do not release
2964 OSNumber
* startMatchingExcludeNum
= NULL
; // do not release
2965 OSBoolean
* delayAutounloadBool
= NULL
; // do not release
2966 OSArray
* personalityNames
= NULL
; // do not release
2968 /* Default values for these two options: regular autounload behavior,
2969 * load all kexts, send no personalities.
2971 Boolean delayAutounload
= false;
2972 OSKextExcludeLevel startKextExcludeLevel
= kOSKextExcludeNone
;
2973 OSKextExcludeLevel startMatchingExcludeLevel
= kOSKextExcludeAll
;
2975 IORecursiveLockLock(sKextLock
);
2979 *logInfoLengthOut
= 0;
2982 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
2984 OSKextLog(/* kext */ NULL
,
2985 kOSKextLogDebugLevel
|
2987 "Received kext load request from user space.");
2989 /* Regardless of processing, the fact that we have gotten here means some
2990 * user-space program is up and talking to us, so we'll switch our kext
2991 * registration to reflect that.
2993 if (!sUserLoadsActive
) {
2994 OSKextLog(/* kext */ NULL
,
2995 kOSKextLogProgressLevel
|
2996 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
2997 "Switching to late startup (user-space) kext loading policy.");
2999 sUserLoadsActive
= true;
3002 if (!sLoadEnabled
) {
3003 OSKextLog(/* kext */ NULL
,
3004 kOSKextLogErrorLevel
|
3006 "Kext loading is disabled.");
3007 result
= kOSKextReturnDisabled
;
3011 /* Note that we do not set a dealloc function on this OSData
3012 * object! No references to it can remain after the loadFromMkext()
3013 * call since we are in a MIG function, and will vm_deallocate()
3016 mkextData
= OSData::withBytesNoCopy(mkextBuffer
,
3019 OSKextLog(/* kext */ NULL
,
3020 kOSKextLogErrorLevel
|
3021 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3022 "Failed to create wrapper for kext load request.");
3023 result
= kOSKextReturnNoMemory
;
3027 result
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
);
3028 if (result
!= kOSReturnSuccess
) {
3029 OSKextLog(/* kext */ NULL
,
3030 kOSKextLogErrorLevel
|
3032 "Failed to read kext load request.");
3036 predicate
= _OSKextGetRequestPredicate(mkextPlist
);
3037 if (!predicate
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) {
3038 OSKextLog(/* kext */ NULL
,
3039 kOSKextLogErrorLevel
|
3041 "Received kext load request with no predicate; skipping.");
3042 result
= kOSKextReturnInvalidArgument
;
3046 requestArgs
= OSDynamicCast(OSDictionary
,
3047 mkextPlist
->getObject(kKextRequestArgumentsKey
));
3048 if (!requestArgs
|| !requestArgs
->getCount()) {
3049 OSKextLog(/* kext */ NULL
,
3050 kOSKextLogErrorLevel
|
3052 "Received kext load request with no arguments.");
3053 result
= kOSKextReturnInvalidArgument
;
3057 kextIdentifier
= OSDynamicCast(OSString
,
3058 requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
));
3059 if (!kextIdentifier
) {
3060 OSKextLog(/* kext */ NULL
,
3061 kOSKextLogErrorLevel
|
3063 "Received kext load request with no kext identifier.");
3064 result
= kOSKextReturnInvalidArgument
;
3068 startKextExcludeNum
= OSDynamicCast(OSNumber
,
3069 requestArgs
->getObject(kKextRequestArgumentStartExcludeKey
));
3070 startMatchingExcludeNum
= OSDynamicCast(OSNumber
,
3071 requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
));
3072 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
3073 requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
));
3074 personalityNames
= OSDynamicCast(OSArray
,
3075 requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
));
3077 if (delayAutounloadBool
) {
3078 delayAutounload
= delayAutounloadBool
->getValue();
3080 if (startKextExcludeNum
) {
3081 startKextExcludeLevel
= startKextExcludeNum
->unsigned8BitValue();
3083 if (startMatchingExcludeNum
) {
3084 startMatchingExcludeLevel
= startMatchingExcludeNum
->unsigned8BitValue();
3087 OSKextLog(/* kext */ NULL
,
3088 kOSKextLogProgressLevel
|
3090 "Received request from user space to load kext %s.",
3091 kextIdentifier
->getCStringNoCopy());
3093 /* Load the kext, with no deferral, since this is a load from outside
3095 * xxx - Would like a better way to handle the default values for the
3096 * xxx - start/match opt args.
3098 result
= OSKext::loadKextWithIdentifier(
3100 /* allowDefer */ false,
3102 startKextExcludeLevel
,
3103 startMatchingExcludeLevel
,
3105 if (result
!= kOSReturnSuccess
) {
3108 /* If the load came down from kextd, it will shortly inform IOCatalogue
3109 * for matching via a separate IOKit calldown.
3114 /* Gather up the collected log messages for user space. Any
3115 * error messages past this call will not make it up as log messages
3116 * but will be in the system log.
3118 logInfoArray
= OSKext::clearUserSpaceLogFilter();
3120 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
3121 tempResult
= OSKext::serializeLogInfo(logInfoArray
,
3122 logInfoOut
, logInfoLengthOut
);
3123 if (tempResult
!= kOSReturnSuccess
) {
3124 result
= tempResult
;
3128 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3130 /* Note: mkextDataObject will have been retained by every kext w/an
3131 * executable in it. That should all have been flushed out at the
3132 * and of the load operation, but you never know....
3134 if (mkextData
&& mkextData
->getRetainCount() > 1) {
3135 OSKextLog(/* kext */ NULL
,
3136 kOSKextLogErrorLevel
|
3137 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3138 "Kext load request buffer from user space still retained by a kext; "
3139 "probable memory leak.");
3142 IORecursiveLockUnlock(sKextLock
);
3144 OSSafeReleaseNULL(mkextData
);
3145 OSSafeReleaseNULL(mkextPlist
);
3146 OSSafeReleaseNULL(serializer
);
3147 OSSafeReleaseNULL(logInfoArray
);
3152 /*********************************************************************
3153 *********************************************************************/
3156 OSKext::serializeLogInfo(
3157 OSArray
* logInfoArray
,
3159 uint32_t * logInfoLengthOut
)
3161 OSReturn result
= kOSReturnError
;
3162 char * buffer
= NULL
;
3163 kern_return_t kmem_result
= KERN_FAILURE
;
3164 OSSerialize
* serializer
= NULL
; // must release; reused
3165 char * logInfo
= NULL
; // returned by reference
3166 uint32_t logInfoLength
= 0;
3168 if (!logInfoArray
|| !logInfoOut
|| !logInfoLengthOut
) {
3169 OSKextLog(/* kext */ NULL
,
3170 kOSKextLogErrorLevel
|
3172 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3173 /* Bad programmer. */
3174 result
= kOSKextReturnInvalidArgument
;
3178 serializer
= OSSerialize::withCapacity(0);
3180 OSKextLog(/* kext */ NULL
,
3181 kOSKextLogErrorLevel
|
3183 "Failed to create serializer on log info for request from user space.");
3184 /* Incidental error; we're going to (try to) allow the request
3185 * itself to succeed. */
3188 if (!logInfoArray
->serialize(serializer
)) {
3189 OSKextLog(/* kext */ NULL
,
3190 kOSKextLogErrorLevel
|
3192 "Failed to serialize log info for request from user space.");
3193 /* Incidental error; we're going to (try to) allow the request
3194 * itself to succeed. */
3196 logInfo
= serializer
->text();
3197 logInfoLength
= serializer
->getLength();
3199 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
, round_page(logInfoLength
), VM_KERN_MEMORY_OSKEXT
);
3200 if (kmem_result
!= KERN_SUCCESS
) {
3201 OSKextLog(/* kext */ NULL
,
3202 kOSKextLogErrorLevel
|
3204 "Failed to copy log info for request from user space.");
3205 /* Incidental error; we're going to (try to) allow the request
3208 /* 11981737 - clear uninitialized data in last page */
3209 bzero((void *)(buffer
+ logInfoLength
),
3210 (round_page(logInfoLength
) - logInfoLength
));
3211 memcpy(buffer
, logInfo
, logInfoLength
);
3212 *logInfoOut
= buffer
;
3213 *logInfoLengthOut
= logInfoLength
;
3217 result
= kOSReturnSuccess
;
3219 OSSafeReleaseNULL(serializer
);
3224 #pragma mark Instance Management Methods
3226 /*********************************************************************
3227 *********************************************************************/
3229 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
)
3231 OSKext
* foundKext
= NULL
;
3233 IORecursiveLockLock(sKextLock
);
3234 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3236 foundKext
->retain();
3238 IORecursiveLockUnlock(sKextLock
);
3243 /*********************************************************************
3244 *********************************************************************/
3246 OSKext::lookupKextWithIdentifier(OSString
* kextIdentifier
)
3248 return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy());
3251 /*********************************************************************
3252 *********************************************************************/
3254 OSKext::lookupKextWithLoadTag(uint32_t aTag
)
3256 OSKext
* foundKext
= NULL
; // returned
3259 IORecursiveLockLock(sKextLock
);
3261 count
= sLoadedKexts
->getCount();
3262 for (i
= 0; i
< count
; i
++) {
3263 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3264 if (thisKext
->getLoadTag() == aTag
) {
3265 foundKext
= thisKext
;
3266 foundKext
->retain();
3272 IORecursiveLockUnlock(sKextLock
);
3277 /*********************************************************************
3278 *********************************************************************/
3280 OSKext::lookupKextWithAddress(vm_address_t address
)
3282 OSKext
* foundKext
= NULL
; // returned
3285 IORecursiveLockLock(sKextLock
);
3287 count
= sLoadedKexts
->getCount();
3288 for (i
= 0; i
< count
; i
++) {
3289 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3290 if (thisKext
->linkedExecutable
) {
3291 vm_address_t kext_start
=
3292 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy();
3293 vm_address_t kext_end
= kext_start
+
3294 thisKext
->linkedExecutable
->getLength();
3295 if ((kext_start
<= address
) && (address
< kext_end
)) {
3296 foundKext
= thisKext
;
3297 foundKext
->retain();
3304 IORecursiveLockUnlock(sKextLock
);
3310 OSKext::copyKextUUIDForAddress(OSNumber
*address
)
3312 OSData
*uuid
= NULL
;
3318 uintptr_t addr
= (uintptr_t)address
->unsigned64BitValue() + vm_kernel_slide
;
3321 /* Is the calling process allowed to query kext info? */
3322 if (current_task() != kernel_task
) {
3323 int macCheckResult
= 0;
3324 kauth_cred_t cred
= NULL
;
3326 cred
= kauth_cred_get_with_ref();
3327 macCheckResult
= mac_kext_check_query(cred
);
3328 kauth_cred_unref(&cred
);
3330 if (macCheckResult
!= 0) {
3331 OSKextLog(/* kext */ NULL
,
3332 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
3333 "Failed to query kext UUID (MAC policy error 0x%x).",
3340 if (((vm_offset_t
)addr
>= vm_kernel_stext
) && ((vm_offset_t
)addr
< vm_kernel_etext
)) {
3341 /* address in xnu proper */
3342 unsigned long uuid_len
= 0;
3343 uuid
= OSData::withBytes(getuuidfromheader(&_mh_execute_header
, &uuid_len
), uuid_len
);
3345 IOLockLock(sKextSummariesLock
);
3346 OSKextLoadedKextSummary
*summary
= OSKext::summaryForAddress(addr
);
3348 uuid
= OSData::withBytes(summary
->uuid
, sizeof(uuid_t
));
3350 IOLockUnlock(sKextSummariesLock
);
3356 /*********************************************************************
3357 *********************************************************************/
3359 OSKext::lookupKextWithUUID(uuid_t wanted
)
3361 OSKext
* foundKext
= NULL
; // returned
3364 IORecursiveLockLock(sKextLock
);
3366 count
= sLoadedKexts
->getCount();
3368 for (i
= 0; i
< count
; i
++) {
3369 OSKext
* thisKext
= NULL
;
3371 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3376 OSData
*uuid_data
= thisKext
->copyUUID();
3382 memcpy(&uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
3383 uuid_data
->release();
3385 if (0 == uuid_compare(wanted
, uuid
)) {
3386 foundKext
= thisKext
;
3387 foundKext
->retain();
3394 IORecursiveLockUnlock(sKextLock
);
3402 /*********************************************************************
3403 *********************************************************************/
3405 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
)
3407 bool result
= false;
3408 OSKext
* foundKext
= NULL
; // returned
3410 IORecursiveLockLock(sKextLock
);
3412 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3413 if (foundKext
&& foundKext
->isLoaded()) {
3417 IORecursiveLockUnlock(sKextLock
);
3422 /*********************************************************************
3423 * xxx - should spawn a separate thread so a kext can safely have
3424 * xxx - itself unloaded.
3425 *********************************************************************/
3430 bool terminateServicesAndRemovePersonalitiesFlag
)
3433 OSReturn result
= kOSKextReturnInUse
;
3434 OSKext
* checkKext
= NULL
; // do not release
3436 int macCheckResult
= 0;
3437 kauth_cred_t cred
= NULL
;
3440 IORecursiveLockLock(sKextLock
);
3442 /* If the kext has no identifier, it failed to init
3443 * so isn't in sKextsByID and it isn't loaded.
3445 if (!aKext
->getIdentifier()) {
3446 result
= kOSReturnSuccess
;
3450 checkKext
= OSDynamicCast(OSKext
,
3451 sKextsByID
->getObject(aKext
->getIdentifier()));
3452 if (checkKext
!= aKext
) {
3453 result
= kOSKextReturnNotFound
;
3457 if (aKext
->isLoaded()) {
3459 if (current_task() != kernel_task
) {
3460 cred
= kauth_cred_get_with_ref();
3461 macCheckResult
= mac_kext_check_unload(cred
, aKext
->getIdentifierCString());
3462 kauth_cred_unref(&cred
);
3465 if (macCheckResult
!= 0) {
3466 result
= kOSReturnError
;
3468 kOSKextLogErrorLevel
|
3469 kOSKextLogKextBookkeepingFlag
,
3470 "Failed to remove kext %s (MAC policy error 0x%x).",
3471 aKext
->getIdentifierCString(), macCheckResult
);
3476 /* make sure there are no resource requests in flight - 17187548 */
3477 if (aKext
->countRequestCallbacks()) {
3481 /* If we are terminating, send the request to the IOCatalogue
3482 * (which will actually call us right back but that's ok we have
3483 * a recursive lock don't you know) but do not ask the IOCatalogue
3484 * to call back with an unload, we'll do that right here.
3486 if (terminateServicesAndRemovePersonalitiesFlag
) {
3487 result
= gIOCatalogue
->terminateDriversForModule(
3488 aKext
->getIdentifierCString(), /* unload */ false);
3489 if (result
!= kOSReturnSuccess
) {
3491 kOSKextLogErrorLevel
|
3492 kOSKextLogKextBookkeepingFlag
,
3493 "Can't remove kext %s; services failed to terminate - 0x%x.",
3494 aKext
->getIdentifierCString(), result
);
3499 result
= aKext
->unload();
3500 if (result
!= kOSReturnSuccess
) {
3505 /* Remove personalities as requested. This is a bit redundant for a loaded
3506 * kext as IOCatalogue::terminateDriversForModule() removes driver
3507 * personalities, but it doesn't restart matching, which we always want
3508 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3511 if (terminateServicesAndRemovePersonalitiesFlag
) {
3512 aKext
->removePersonalitiesFromCatalog();
3516 kOSKextLogProgressLevel
|
3517 kOSKextLogKextBookkeepingFlag
,
3518 "Removing kext %s.",
3519 aKext
->getIdentifierCString());
3521 sKextsByID
->removeObject(aKext
->getIdentifier());
3522 result
= kOSReturnSuccess
;
3525 IORecursiveLockUnlock(sKextLock
);
3529 /*********************************************************************
3530 *********************************************************************/
3533 OSKext::removeKextWithIdentifier(
3534 const char * kextIdentifier
,
3535 bool terminateServicesAndRemovePersonalitiesFlag
)
3537 OSReturn result
= kOSReturnError
;
3539 IORecursiveLockLock(sKextLock
);
3541 OSKext
* aKext
= OSDynamicCast(OSKext
,
3542 sKextsByID
->getObject(kextIdentifier
));
3544 result
= kOSKextReturnNotFound
;
3545 OSKextLog(/* kext */ NULL
,
3546 kOSKextLogErrorLevel
|
3547 kOSKextLogKextBookkeepingFlag
,
3548 "Can't remove kext %s - not found.",
3553 result
= OSKext::removeKext(aKext
,
3554 terminateServicesAndRemovePersonalitiesFlag
);
3557 IORecursiveLockUnlock(sKextLock
);
3562 /*********************************************************************
3563 *********************************************************************/
3566 OSKext::removeKextWithLoadTag(
3567 OSKextLoadTag loadTag
,
3568 bool terminateServicesAndRemovePersonalitiesFlag
)
3570 OSReturn result
= kOSReturnError
;
3571 OSKext
* foundKext
= NULL
;
3574 IORecursiveLockLock(sKextLock
);
3576 count
= sLoadedKexts
->getCount();
3577 for (i
= 0; i
< count
; i
++) {
3578 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3579 if (thisKext
->loadTag
== loadTag
) {
3580 foundKext
= thisKext
;
3586 result
= kOSKextReturnNotFound
;
3587 OSKextLog(/* kext */ NULL
,
3588 kOSKextLogErrorLevel
|
3589 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
3590 "Can't remove kext with load tag %d - not found.",
3595 result
= OSKext::removeKext(foundKext
,
3596 terminateServicesAndRemovePersonalitiesFlag
);
3599 IORecursiveLockUnlock(sKextLock
);
3604 /*********************************************************************
3605 *********************************************************************/
3607 OSKext::copyKexts(void)
3609 OSDictionary
* result
;
3611 IORecursiveLockLock(sKextLock
);
3612 result
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection());
3613 IORecursiveLockUnlock(sKextLock
);
3618 /*********************************************************************
3619 *********************************************************************/
3620 #define BOOTER_KEXT_PREFIX "Driver-"
3622 typedef struct _DeviceTreeBuffer
{
3625 } _DeviceTreeBuffer
;
3627 /*********************************************************************
3628 * Create a dictionary of excluded kexts from the given booter data.
3629 *********************************************************************/
3632 OSKext::createExcludeListFromBooterData(
3633 OSDictionary
* theDictionary
,
3634 OSCollectionIterator
* theIterator
)
3636 OSString
* deviceTreeName
= NULL
; // do not release
3637 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not release
3638 char * booterDataPtr
= NULL
; // do not release
3639 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not release
3640 char * infoDictAddr
= NULL
; // do not release
3641 OSObject
* parsedXML
= NULL
; // must release
3642 OSDictionary
* theInfoDict
= NULL
; // do not release
3644 theIterator
->reset();
3646 /* look for AppleKextExcludeList.kext */
3647 while ( (deviceTreeName
=
3648 OSDynamicCast(OSString
, theIterator
->getNextObject())) ) {
3650 const char * devTreeNameCString
;
3651 OSData
* deviceTreeEntry
;
3652 OSString
* myBundleID
; // do not release
3654 OSSafeReleaseNULL(parsedXML
);
3657 OSDynamicCast(OSData
, theDictionary
->getObject(deviceTreeName
));
3658 if (!deviceTreeEntry
) {
3662 /* Make sure it is a kext */
3663 devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
3664 if (strncmp(devTreeNameCString
, BOOTER_KEXT_PREFIX
,
3665 (sizeof(BOOTER_KEXT_PREFIX
) - 1)) != 0) {
3667 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3668 "\"%s\" not a kext",
3669 devTreeNameCString
);
3673 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
3674 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
3675 if (!deviceTreeBuffer
) {
3679 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
3680 if (!booterDataPtr
) {
3684 kextFileInfo
= (_BooterKextFileInfo
*) booterDataPtr
;
3685 if (!kextFileInfo
->infoDictPhysAddr
||
3686 !kextFileInfo
->infoDictLength
) {
3690 infoDictAddr
= (char *)
3691 ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
3692 if (!infoDictAddr
) {
3696 parsedXML
= OSUnserializeXML(infoDictAddr
);
3701 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
3707 OSDynamicCast(OSString
,
3708 theInfoDict
->getObject(kCFBundleIdentifierKey
));
3710 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3712 /* get copy of exclusion list dictionary */
3713 OSDictionary
* myTempDict
; // do not free
3715 myTempDict
= OSDynamicCast(
3717 theInfoDict
->getObject("OSKextExcludeList"));
3718 if ( NULL
== myTempDict
) {
3720 panic("Missing OSKextExcludeList dictionary\n");
3723 IORecursiveLockLock(sKextLock
);
3725 /* get rid of old exclusion list */
3726 if (sExcludeListByID
) {
3727 OSSafeReleaseNULL(sExcludeListByID
);
3729 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3730 IORecursiveLockUnlock(sKextLock
);
3735 } // while ( (deviceTreeName = ...) )
3737 OSSafeReleaseNULL(parsedXML
);
3741 /*********************************************************************
3742 * Create a dictionary of excluded kexts from the given prelink
3743 * info (kernelcache).
3744 *********************************************************************/
3747 OSKext::createExcludeListFromPrelinkInfo( OSArray
* theInfoArray
)
3749 OSDictionary
* myInfoDict
= NULL
; // do not release
3750 OSString
* myBundleID
; // do not release
3753 /* Find com.apple.driver.KextExcludeList. */
3754 for (i
= 0; i
< theInfoArray
->getCount(); i
++) {
3755 myInfoDict
= OSDynamicCast(OSDictionary
, theInfoArray
->getObject(i
));
3760 OSDynamicCast(OSString
,
3761 myInfoDict
->getObject(kCFBundleIdentifierKey
));
3763 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3764 // get copy of exclude list dictionary
3765 OSDictionary
* myTempDict
; // do not free
3766 myTempDict
= OSDynamicCast(OSDictionary
,
3767 myInfoDict
->getObject("OSKextExcludeList"));
3768 if ( NULL
== myTempDict
) {
3770 panic("Missing OSKextExcludeList dictionary\n");
3773 IORecursiveLockLock(sKextLock
);
3774 // get rid of old exclude list
3775 if (sExcludeListByID
) {
3776 OSSafeReleaseNULL(sExcludeListByID
);
3779 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3780 IORecursiveLockUnlock(sKextLock
);
3783 } // for (i = 0; i < theInfoArray->getCount()...
3789 #pragma mark Accessors
3791 /*********************************************************************
3792 *********************************************************************/
3794 OSKext::getIdentifier(void)
3799 /*********************************************************************
3800 * A kext must have a bundle identifier to even survive initialization;
3801 * this is guaranteed to exist past then.
3802 *********************************************************************/
3804 OSKext::getIdentifierCString(void)
3806 return bundleID
->getCStringNoCopy();
3809 /*********************************************************************
3810 *********************************************************************/
3812 OSKext::getVersion(void)
3817 /*********************************************************************
3818 *********************************************************************/
3820 OSKext::getCompatibleVersion(void)
3822 return compatibleVersion
;
3825 /*********************************************************************
3826 *********************************************************************/
3828 OSKext::isLibrary(void)
3830 return (getCompatibleVersion() > 0);
3833 /*********************************************************************
3834 *********************************************************************/
3836 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
)
3838 if ((compatibleVersion
> -1 && version
> -1) &&
3839 (compatibleVersion
<= version
&& aVersion
<= version
)) {
3845 /*********************************************************************
3846 *********************************************************************/
3848 OSKext::declaresExecutable(void)
3850 return (getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
);
3853 /*********************************************************************
3854 *********************************************************************/
3856 OSKext::getExecutable(void)
3858 OSData
* result
= NULL
;
3859 OSData
* extractedExecutable
= NULL
; // must release
3860 OSData
* mkextExecutableRef
= NULL
; // do not release
3862 result
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
));
3867 mkextExecutableRef
= OSDynamicCast(OSData
,
3868 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
));
3870 if (mkextExecutableRef
) {
3872 MkextEntryRef
* mkextEntryRef
= (MkextEntryRef
*)
3873 mkextExecutableRef
->getBytesNoCopy();
3874 uint32_t mkextVersion
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
);
3875 if (mkextVersion
== MKEXT_VERS_2
) {
3876 mkext2_file_entry
* fileinfo
=
3877 (mkext2_file_entry
*)mkextEntryRef
->fileinfo
;
3878 uint32_t compressedSize
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
);
3879 uint32_t fullSize
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
);
3880 extractedExecutable
= extractMkext2FileData(
3881 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable",
3882 compressedSize
, fullSize
);
3884 OSKextLog(this, kOSKextLogErrorLevel
|
3885 kOSKextLogArchiveFlag
,
3886 "Kext %s - unknown mkext version 0x%x for executable.",
3887 getIdentifierCString(), mkextVersion
);
3890 /* Regardless of success, remove the mkext executable,
3891 * and drop one reference on the mkext. (setExecutable() does not
3892 * replace, it removes, or panics if asked to replace.)
3894 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
3895 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
3897 if (extractedExecutable
&& extractedExecutable
->getLength()) {
3898 if (!setExecutable(extractedExecutable
)) {
3901 result
= extractedExecutable
;
3909 OSSafeReleaseNULL(extractedExecutable
);
3914 /*********************************************************************
3915 *********************************************************************/
3917 OSKext::isInterface(void)
3919 return flags
.interface
;
3922 /*********************************************************************
3923 *********************************************************************/
3925 OSKext::isKernel(void)
3927 return (this == sKernelKext
);
3930 /*********************************************************************
3931 *********************************************************************/
3933 OSKext::isKernelComponent(void)
3935 return flags
.kernelComponent
? true : false;
3938 /*********************************************************************
3939 *********************************************************************/
3941 OSKext::isExecutable(void)
3943 return (!isKernel() && !isInterface() && declaresExecutable());
3946 /*********************************************************************
3947 * We might want to check this recursively for all dependencies,
3948 * since a subtree of dependencies could get loaded before we hit
3949 * a dependency that isn't safe-boot-loadable.
3951 * xxx - Might want to return false if OSBundleEnableKextLogging or
3952 * OSBundleDebugLevel
3953 * or IOKitDebug is nonzero too (we used to do that, but I don't see
3954 * the point except it's usually development drivers, which might
3955 * cause panics on startup, that have those properties). Heh; could
3956 * use a "kx" boot-arg!
3957 *********************************************************************/
3959 OSKext::isLoadableInSafeBoot(void)
3961 bool result
= false;
3962 OSString
* required
= NULL
; // do not release
3969 required
= OSDynamicCast(OSString
,
3970 getPropertyForHostArch(kOSBundleRequiredKey
));
3974 if (required
->isEqualTo(kOSBundleRequiredRoot
) ||
3975 required
->isEqualTo(kOSBundleRequiredLocalRoot
) ||
3976 required
->isEqualTo(kOSBundleRequiredNetworkRoot
) ||
3977 required
->isEqualTo(kOSBundleRequiredSafeBoot
) ||
3978 required
->isEqualTo(kOSBundleRequiredConsole
)) {
3987 /*********************************************************************
3988 *********************************************************************/
3990 OSKext::isPrelinked(void)
3992 return flags
.prelinked
? true : false;
3995 /*********************************************************************
3996 *********************************************************************/
3997 bool OSKext::isLoaded(void)
3999 return flags
.loaded
? true : false;
4002 /*********************************************************************
4003 *********************************************************************/
4005 OSKext::isStarted(void)
4007 return flags
.started
? true : false;
4010 /*********************************************************************
4011 *********************************************************************/
4013 OSKext::isCPPInitialized(void)
4015 return flags
.CPPInitialized
;
4018 /*********************************************************************
4019 *********************************************************************/
4021 OSKext::setCPPInitialized(bool initialized
)
4023 flags
.CPPInitialized
= initialized
;
4026 /*********************************************************************
4027 *********************************************************************/
4029 OSKext::getLoadTag(void)
4034 /*********************************************************************
4035 *********************************************************************/
4036 void OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
)
4038 if (linkedExecutable
) {
4039 *loadSize
= linkedExecutable
->getLength();
4041 /* If we have a kmod_info struct, calculated the wired size
4042 * from that. Otherwise it's the full load size.
4045 *wiredSize
= *loadSize
- kmod_info
->hdr_size
;
4047 *wiredSize
= *loadSize
;
4056 /*********************************************************************
4057 *********************************************************************/
4059 OSKext::copyUUID(void)
4061 OSData
* result
= NULL
;
4062 OSData
* theExecutable
= NULL
; // do not release
4063 const kernel_mach_header_t
* header
= NULL
;
4064 const struct load_command
* load_cmd
= NULL
;
4065 const struct uuid_command
* uuid_cmd
= NULL
;
4068 /* An interface kext doesn't have a linked executable with an LC_UUID,
4069 * we create one when it's linked.
4071 if (interfaceUUID
) {
4072 result
= interfaceUUID
;
4077 /* For real kexts, try to get the UUID from the linked executable,
4078 * or if is hasn't been linked yet, the unrelocated executable.
4080 theExecutable
= linkedExecutable
;
4081 if (!theExecutable
) {
4082 theExecutable
= getExecutable();
4084 if (!theExecutable
) {
4088 header
= (const kernel_mach_header_t
*)theExecutable
->getBytesNoCopy();
4089 load_cmd
= (const struct load_command
*)&header
[1];
4091 if (header
->magic
!= MH_MAGIC_KERNEL
) {
4093 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4094 "%s: bad header %p",
4100 for (i
= 0; i
< header
->ncmds
; i
++) {
4101 if (load_cmd
->cmd
== LC_UUID
) {
4102 uuid_cmd
= (struct uuid_command
*)load_cmd
;
4103 result
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
));
4106 load_cmd
= (struct load_command
*)((caddr_t
)load_cmd
+ load_cmd
->cmdsize
);
4113 /*********************************************************************
4114 *********************************************************************/
4116 #if defined (__x86_64__)
4117 #define ARCHNAME "x86_64"
4119 #error architecture not supported
4122 #define ARCH_SEPARATOR_CHAR '_'
4124 static char * makeHostArchKey(const char * key
, uint32_t * keySizeOut
)
4126 char * result
= NULL
;
4127 uint32_t keyLength
= strlen(key
);
4130 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4132 keySize
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
);
4133 result
= (char *)kalloc_tag(keySize
, VM_KERN_MEMORY_OSKEXT
);
4137 strlcpy(result
, key
, keySize
);
4138 result
[keyLength
++] = ARCH_SEPARATOR_CHAR
;
4139 result
[keyLength
] = '\0';
4140 strlcat(result
, ARCHNAME
, keySize
);
4141 *keySizeOut
= keySize
;
4147 /*********************************************************************
4148 *********************************************************************/
4150 OSKext::getPropertyForHostArch(const char * key
)
4152 OSObject
* result
= NULL
; // do not release
4153 uint32_t hostArchKeySize
= 0;
4154 char * hostArchKey
= NULL
; // must kfree
4156 if (!key
|| !infoDict
) {
4160 /* Some properties are not allowed to be arch-variant:
4161 * - Any CFBundle... property.
4162 * - OSBundleIsInterface.
4163 * - OSKernelResource.
4165 if (STRING_HAS_PREFIX(key
, "OS") ||
4166 STRING_HAS_PREFIX(key
, "IO")) {
4168 hostArchKey
= makeHostArchKey(key
, &hostArchKeySize
);
4170 OSKextLog(/* kext (this isn't about a kext) */ NULL
,
4171 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4172 "Allocation failure.");
4175 result
= infoDict
->getObject(hostArchKey
);
4179 result
= infoDict
->getObject(key
);
4183 if (hostArchKey
) kfree(hostArchKey
, hostArchKeySize
);
4188 #pragma mark Load/Start/Stop/Unload
4191 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4193 /*********************************************************************
4194 * sExcludeListByID is a dictionary with keys / values of:
4195 * key = bundleID string of kext we will not allow to load
4196 * value = version string(s) of the kext that is to be denied loading.
4197 * The version strings can be comma delimited. For example if kext
4198 * com.foocompany.fookext has two versions that we want to deny
4199 * loading then the version strings might look like:
4201 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4202 * not load the kext.
4204 * Value may also be in the form of "LE 2.0.0" (version numbers
4205 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4206 * number less than 2.0.0 will not load)
4208 * NOTE - we cannot use the characters "<=" or "<" because we have code
4209 * that serializes plists and treats '<' as a special character.
4210 *********************************************************************/
4212 OSKext::isInExcludeList(void)
4214 OSString
* versionString
= NULL
; // do not release
4215 char * versionCString
= NULL
; // do not free
4217 boolean_t wantLessThan
= false;
4218 boolean_t wantLessThanEqualTo
= false;
4221 if (!sExcludeListByID
) {
4224 /* look up by bundleID in our exclude list and if found get version
4225 * string (or strings) that we will not allow to load
4227 versionString
= OSDynamicCast(OSString
, sExcludeListByID
->getObject(bundleID
));
4228 if (versionString
== NULL
|| versionString
->getLength() > (sizeof(myBuffer
) - 1)) {
4232 /* parse version strings */
4233 versionCString
= (char *) versionString
->getCStringNoCopy();
4235 /* look for "LT" or "LE" form of version string, must be in first two
4238 if (*versionCString
== 'L' && *(versionCString
+ 1) == 'T') {
4239 wantLessThan
= true;
4242 else if (*versionCString
== 'L' && *(versionCString
+ 1) == 'E') {
4243 wantLessThanEqualTo
= true;
4247 for (i
= 0; *versionCString
!= 0x00; versionCString
++) {
4248 /* skip whitespace */
4249 if (isWhiteSpace(*versionCString
)) {
4253 /* peek ahead for version string separator or null terminator */
4254 if (*(versionCString
+ 1) == ',' || *(versionCString
+ 1) == 0x00) {
4256 /* OK, we have a version string */
4257 myBuffer
[i
++] = *versionCString
;
4260 OSKextVersion excludeVers
;
4261 excludeVers
= OSKextParseVersionString(myBuffer
);
4263 if (wantLessThanEqualTo
) {
4264 if (version
<= excludeVers
) {
4268 else if (wantLessThan
) {
4269 if (version
< excludeVers
) {
4273 else if ( version
== excludeVers
) {
4277 /* reset for the next (if any) version string */
4279 wantLessThan
= false;
4280 wantLessThanEqualTo
= false;
4283 /* save valid version character */
4284 myBuffer
[i
++] = *versionCString
;
4286 /* make sure bogus version string doesn't overrun local buffer */
4287 if ( i
>= sizeof(myBuffer
) ) {
4296 /*********************************************************************
4297 *********************************************************************/
4300 OSKext::loadKextWithIdentifier(
4301 const char * kextIdentifierCString
,
4302 Boolean allowDeferFlag
,
4303 Boolean delayAutounloadFlag
,
4304 OSKextExcludeLevel startOpt
,
4305 OSKextExcludeLevel startMatchingOpt
,
4306 OSArray
* personalityNames
)
4308 OSReturn result
= kOSReturnError
;
4309 OSString
* kextIdentifier
= NULL
; // must release
4311 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
4312 if (!kextIdentifier
) {
4313 result
= kOSKextReturnNoMemory
;
4316 result
= OSKext::loadKextWithIdentifier(kextIdentifier
,
4317 allowDeferFlag
, delayAutounloadFlag
,
4318 startOpt
, startMatchingOpt
, personalityNames
);
4321 OSSafeReleaseNULL(kextIdentifier
);
4325 /*********************************************************************
4326 *********************************************************************/
4328 OSKext::loadKextWithIdentifier(
4329 OSString
* kextIdentifier
,
4330 Boolean allowDeferFlag
,
4331 Boolean delayAutounloadFlag
,
4332 OSKextExcludeLevel startOpt
,
4333 OSKextExcludeLevel startMatchingOpt
,
4334 OSArray
* personalityNames
)
4336 OSReturn result
= kOSReturnError
;
4337 OSReturn pingResult
= kOSReturnError
;
4338 OSKext
* theKext
= NULL
; // do not release
4339 OSDictionary
* loadRequest
= NULL
; // must release
4340 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4342 IORecursiveLockLock(sKextLock
);
4344 if (!kextIdentifier
) {
4345 result
= kOSKextReturnInvalidArgument
;
4349 OSKext::recordIdentifierRequest(kextIdentifier
);
4351 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
4353 if (!allowDeferFlag
) {
4354 OSKextLog(/* kext */ NULL
,
4355 kOSKextLogErrorLevel
|
4357 "Can't load kext %s - not found.",
4358 kextIdentifier
->getCStringNoCopy());
4362 if (!sKernelRequestsEnabled
) {
4364 kOSKextLogErrorLevel
|
4366 "Can't load kext %s - requests to user space are disabled.",
4367 kextIdentifier
->getCStringNoCopy());
4368 result
= kOSKextReturnDisabled
;
4372 /* Create a new request unless one is already sitting
4373 * in sKernelRequests for this bundle identifier
4375 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4376 if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4377 result
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
,
4379 if (result
!= kOSReturnSuccess
) {
4382 if (!_OSKextSetRequestArgument(loadRequest
,
4383 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
4385 result
= kOSKextReturnNoMemory
;
4388 if (!sKernelRequests
->setObject(loadRequest
)) {
4389 result
= kOSKextReturnNoMemory
;
4393 if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4394 result
= kOSKextReturnNoMemory
;
4399 kOSKextLogDebugLevel
|
4401 "Kext %s not found; queued load request to user space.",
4402 kextIdentifier
->getCStringNoCopy());
4405 pingResult
= OSKext::pingKextd();
4406 if (pingResult
== kOSKextReturnDisabled
) {
4407 OSKextLog(/* kext */ NULL
,
4408 ((sPrelinkBoot
) ? kOSKextLogDebugLevel
: kOSKextLogErrorLevel
) |
4410 "Kext %s might not load - kextd is currently unavailable.",
4411 kextIdentifier
->getCStringNoCopy());
4414 result
= kOSKextReturnDeferred
;
4418 result
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
);
4420 if (result
!= kOSReturnSuccess
) {
4422 kOSKextLogErrorLevel
|
4424 "Failed to load kext %s (error 0x%x).",
4425 kextIdentifier
->getCStringNoCopy(), (int)result
);
4427 OSKext::removeKext(theKext
,
4428 /* terminateService/removePersonalities */ true);
4432 if (delayAutounloadFlag
) {
4434 kOSKextLogProgressLevel
|
4435 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4436 "Setting delayed autounload for %s.",
4437 kextIdentifier
->getCStringNoCopy());
4438 theKext
->flags
.delayAutounload
= 1;
4442 OSSafeReleaseNULL(loadRequest
);
4443 OSSafeReleaseNULL(kextIdentifierSymbol
);
4445 IORecursiveLockUnlock(sKextLock
);
4450 /*********************************************************************
4451 *********************************************************************/
4454 OSKext::recordIdentifierRequest(
4455 OSString
* kextIdentifier
)
4457 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4460 if (!sAllKextLoadIdentifiers
|| !kextIdentifier
) {
4464 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4465 if (!kextIdentifierSymbol
) {
4466 // xxx - this is really a basic alloc failure
4471 IORecursiveLockLock(sKextLock
);
4472 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4473 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4476 // xxx - need to find a way to associate this whole func w/the kext
4477 OSKextLog(/* kext */ NULL
,
4478 // xxx - check level
4479 kOSKextLogStepLevel
|
4480 kOSKextLogArchiveFlag
,
4481 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4482 kextIdentifier
->getCStringNoCopy());
4485 IORecursiveLockUnlock(sKextLock
);
4490 OSKextLog(/* kext */ NULL
,
4491 kOSKextLogErrorLevel
|
4492 kOSKextLogArchiveFlag
,
4493 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4494 kextIdentifier
->getCStringNoCopy());
4496 OSSafeReleaseNULL(kextIdentifierSymbol
);
4500 /*********************************************************************
4501 *********************************************************************/
4504 OSKextExcludeLevel startOpt
,
4505 OSKextExcludeLevel startMatchingOpt
,
4506 OSArray
* personalityNames
)
4508 OSReturn result
= kOSReturnError
;
4509 kern_return_t kxldResult
;
4510 OSKextExcludeLevel dependenciesStartOpt
= startOpt
;
4511 OSKextExcludeLevel dependenciesStartMatchingOpt
= startMatchingOpt
;
4512 unsigned int i
, count
;
4513 Boolean alreadyLoaded
= false;
4514 OSKext
* lastLoadedKext
= NULL
;
4516 if (isInExcludeList()) {
4518 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
|
4520 "Kext %s is in exclude list, not loadable",
4521 getIdentifierCString());
4523 result
= kOSKextReturnNotLoadable
;
4528 alreadyLoaded
= true;
4529 result
= kOSReturnSuccess
;
4532 kOSKextLogDebugLevel
|
4533 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4534 "Kext %s is already loaded.",
4535 getIdentifierCString());
4540 if (current_task() != kernel_task
) {
4541 int macCheckResult
= 0;
4542 kauth_cred_t cred
= NULL
;
4544 cred
= kauth_cred_get_with_ref();
4545 macCheckResult
= mac_kext_check_load(cred
, getIdentifierCString());
4546 kauth_cred_unref(&cred
);
4548 if (macCheckResult
!= 0) {
4549 result
= kOSReturnError
;
4551 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4552 "Failed to load kext %s (MAC policy error 0x%x).",
4553 getIdentifierCString(), macCheckResult
);
4559 if (!sLoadEnabled
) {
4561 kOSKextLogErrorLevel
|
4563 "Kext loading is disabled (attempt to load kext %s).",
4564 getIdentifierCString());
4565 result
= kOSKextReturnDisabled
;
4569 /* If we've pushed the next available load tag to the invalid value,
4570 * we can't load any more kexts.
4572 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4574 kOSKextLogErrorLevel
|
4576 "Can't load kext %s - no more load tags to assign.",
4577 getIdentifierCString());
4578 result
= kOSKextReturnNoResources
;
4582 /* This is a bit of a hack, because we shouldn't be handling
4583 * personalities within the load function.
4585 if (!declaresExecutable()) {
4586 result
= kOSReturnSuccess
;
4590 /* Are we in safe boot?
4592 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4594 kOSKextLogErrorLevel
|
4596 "Can't load kext %s - not loadable during safe boot.",
4597 getIdentifierCString());
4598 result
= kOSKextReturnBootLevel
;
4603 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4605 getIdentifierCString());
4607 if (!sKxldContext
) {
4608 kxldResult
= kxld_create_context(&sKxldContext
, &kern_allocate
,
4609 &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,
4610 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
4613 kOSKextLogErrorLevel
|
4614 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4615 "Can't load kext %s - failed to create link context.",
4616 getIdentifierCString());
4617 result
= kOSKextReturnNoMemory
;
4622 /* We only need to resolve dependencies once for the whole graph, but
4623 * resolveDependencies will just return if there's no work to do, so it's
4624 * safe to call it more than once.
4626 if (!resolveDependencies()) {
4627 // xxx - check resolveDependencies() for log msg
4629 kOSKextLogErrorLevel
|
4630 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4631 "Can't load kext %s - failed to resolve library dependencies.",
4632 getIdentifierCString());
4633 result
= kOSKextReturnDependencies
;
4637 /* If we are excluding just the kext being loaded now (and not its
4638 * dependencies), drop the exclusion level to none so dependencies
4639 * start and/or add their personalities.
4641 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4642 dependenciesStartOpt
= kOSKextExcludeNone
;
4645 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4646 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4649 /* Load the dependencies, recursively.
4651 count
= getNumDependencies();
4652 for (i
= 0; i
< count
; i
++) {
4653 OSKext
* dependency
= OSDynamicCast(OSKext
,
4654 dependencies
->getObject(i
));
4655 if (dependency
== NULL
) {
4657 kOSKextLogErrorLevel
|
4658 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4659 "Internal error loading kext %s; dependency disappeared.",
4660 getIdentifierCString());
4661 result
= kOSKextReturnInternalError
;
4665 /* Dependencies must be started accorting to the opt,
4666 * but not given the personality names of the main kext.
4668 result
= dependency
->load(dependenciesStartOpt
,
4669 dependenciesStartMatchingOpt
,
4670 /* personalityNames */ NULL
);
4671 if (result
!= KERN_SUCCESS
) {
4673 kOSKextLogErrorLevel
|
4674 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4675 "Dependency %s of kext %s failed to load.",
4676 dependency
->getIdentifierCString(),
4677 getIdentifierCString());
4679 OSKext::removeKext(dependency
,
4680 /* terminateService/removePersonalities */ true);
4681 result
= kOSKextReturnDependencyLoadError
;
4687 result
= loadExecutable();
4688 if (result
!= KERN_SUCCESS
) {
4692 pendingPgoHead
.next
= &pendingPgoHead
;
4693 pendingPgoHead
.prev
= &pendingPgoHead
;
4695 uuid_generate(instance_uuid
);
4696 account
= IONew(OSKextAccount
, 1);
4698 result
= KERN_MEMORY_ERROR
;
4701 bzero(account
, sizeof(*account
));
4702 account
->loadTag
= kmod_info
->id
;
4703 account
->site
.flags
= VM_TAG_KMOD
;
4704 account
->kext
= this;
4706 flags
.loaded
= true;
4708 /* Add the kext to the list of loaded kexts and update the kmod_info
4709 * struct to point to that of the last loaded kext (which is the way
4710 * it's always been done, though I'd rather do them in order now).
4712 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
4713 sLoadedKexts
->setObject(this);
4715 /* Keep the kernel itself out of the kmod list.
4717 if (lastLoadedKext
->isKernel()) {
4718 lastLoadedKext
= NULL
;
4721 if (lastLoadedKext
) {
4722 kmod_info
->next
= lastLoadedKext
->kmod_info
;
4725 notifyKextLoadObservers(this, kmod_info
);
4727 /* Make the global kmod list point at the just-loaded kext. Note that the
4728 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4729 * although we do report it in kextstat these days by using the newer
4730 * OSArray of loaded kexts, which does contain it.
4732 * (The OSKext object representing the kernel doesn't even have a kmod_info
4733 * struct, though I suppose we could stick a pointer to it from the
4734 * static struct in OSRuntime.cpp.)
4738 /* Save the list of loaded kexts in case we panic.
4740 OSKext::saveLoadedKextPanicList();
4742 if (isExecutable()) {
4743 OSKext::updateLoadedKextSummaries();
4744 savePanicString(/* isLoading */ true);
4747 registerWithDTrace();
4749 jettisonLinkeditSegment();
4750 #endif /* CONFIG_DTRACE */
4752 #if !VM_MAPPED_KEXTS
4753 /* If there is a page (or more) worth of padding after the end
4754 * of the last data section but before the end of the data segment
4755 * then free it in the same manner the LinkeditSegment is freed
4757 jettisonDATASegmentPadding();
4762 if (isExecutable() && !flags
.started
) {
4763 if (startOpt
== kOSKextExcludeNone
) {
4765 if (result
!= kOSReturnSuccess
) {
4767 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4768 "Kext %s start failed (result 0x%x).",
4769 getIdentifierCString(), result
);
4770 result
= kOSKextReturnStartStopError
;
4775 /* If not excluding matching, send the personalities to the kernel.
4776 * This never affects the result of the load operation.
4777 * This is a bit of a hack, because we shouldn't be handling
4778 * personalities within the load function.
4780 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
4781 result
= sendPersonalitiesToCatalog(true, personalityNames
);
4786 /* More hack! If the kext doesn't declare an executable, even if we
4787 * "loaded" it, we have to remove any personalities naming it, or we'll
4788 * never see the registry go quiet. Errors here do not count for the
4789 * load operation itself.
4791 * Note that in every other regard it's perfectly ok for a kext to
4792 * not declare an executable and serve only as a package for personalities
4793 * naming another kext, so we do have to allow such kexts to be "loaded"
4794 * so that those other personalities get added & matched.
4796 if (!declaresExecutable()) {
4798 kOSKextLogStepLevel
| kOSKextLogLoadFlag
,
4799 "Kext %s has no executable; removing any personalities naming it.",
4800 getIdentifierCString());
4801 removePersonalitiesFromCatalog();
4804 if (result
!= kOSReturnSuccess
) {
4806 kOSKextLogErrorLevel
|
4808 "Kext %s failed to load (0x%x).",
4809 getIdentifierCString(), (int)result
);
4810 } else if (!alreadyLoaded
) {
4812 kOSKextLogProgressLevel
|
4815 getIdentifierCString());
4817 queueKextNotification(kKextRequestPredicateLoadNotification
,
4818 OSDynamicCast(OSString
, bundleID
));
4823 /*********************************************************************
4825 *********************************************************************/
4826 static char * strdup(const char * string
)
4828 char * result
= NULL
;
4835 size
= 1 + strlen(string
);
4836 result
= (char *)kalloc_tag(size
, VM_KERN_MEMORY_OSKEXT
);
4841 memcpy(result
, string
, size
);
4847 /*********************************************************************
4849 *********************************************************************/
4852 OSKext::lookupSection(const char *segname
, const char *secname
)
4854 kernel_section_t
* found_section
= NULL
;
4855 kernel_mach_header_t
* mh
= NULL
;
4856 kernel_segment_command_t
* seg
= NULL
;
4857 kernel_section_t
* sec
= NULL
;
4859 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4861 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4863 if (0 != strcmp(seg
->segname
, segname
)) {
4867 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4869 if (0 == strcmp(sec
->sectname
, secname
)) {
4870 found_section
= sec
;
4877 return found_section
;
4880 /*********************************************************************
4882 *********************************************************************/
4885 OSKext::slidePrelinkedExecutable(bool doCoalesedSlides
)
4887 OSReturn result
= kOSKextReturnBadData
;
4888 kernel_mach_header_t
* mh
= NULL
;
4889 kernel_segment_command_t
* seg
= NULL
;
4890 kernel_segment_command_t
* linkeditSeg
= NULL
;
4891 kernel_section_t
* sec
= NULL
;
4892 char * linkeditBase
= NULL
;
4893 bool haveLinkeditBase
= false;
4894 char * relocBase
= NULL
;
4895 bool haveRelocBase
= false;
4896 struct dysymtab_command
* dysymtab
= NULL
;
4897 struct linkedit_data_command
* segmentSplitInfo
= NULL
;
4898 struct symtab_command
* symtab
= NULL
;
4899 kernel_nlist_t
* sym
= NULL
;
4900 struct relocation_info
* reloc
= NULL
;
4903 vm_offset_t new_kextsize
;
4905 if (linkedExecutable
== NULL
|| vm_kernel_slide
== 0) {
4906 result
= kOSReturnSuccess
;
4910 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4911 segmentSplitInfo
= (struct linkedit_data_command
*) getcommandfromheader(mh
, LC_SEGMENT_SPLIT_INFO
);
4913 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4917 seg
->vmaddr
+= vm_kernel_slide
;
4919 #if KASLR_KEXT_DEBUG
4920 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
4922 (unsigned long)VM_KERNEL_UNSLIDE(seg
->vmaddr
),
4923 (unsigned long)seg
->vmaddr
);
4926 if (!haveRelocBase
) {
4927 relocBase
= (char *) seg
->vmaddr
;
4928 haveRelocBase
= true;
4930 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
4931 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
4932 haveLinkeditBase
= true;
4935 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4936 sec
->addr
+= vm_kernel_slide
;
4938 #if KASLR_KEXT_DEBUG
4939 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
4941 (unsigned long)VM_KERNEL_UNSLIDE(sec
->addr
),
4942 (unsigned long)sec
->addr
);
4947 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
4949 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
4951 if (symtab
!= NULL
&& doCoalesedSlides
== false) {
4952 /* Some pseudo-kexts have symbol tables without segments.
4954 if (symtab
->nsyms
> 0 && haveLinkeditBase
) {
4955 sym
= (kernel_nlist_t
*) (linkeditBase
+ symtab
->symoff
);
4956 for (i
= 0; i
< symtab
->nsyms
; i
++) {
4957 if (sym
[i
].n_type
& N_STAB
) {
4960 sym
[i
].n_value
+= vm_kernel_slide
;
4962 #if KASLR_KEXT_DEBUG
4963 #define MAX_SYMS_TO_LOG 5
4964 if ( i
< MAX_SYMS_TO_LOG
) {
4965 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
4966 (unsigned long)VM_KERNEL_UNSLIDE(sym
[i
].n_value
),
4967 (unsigned long)sym
[i
].n_value
);
4974 if (dysymtab
!= NULL
&& doCoalesedSlides
== false) {
4975 if (dysymtab
->nextrel
> 0) {
4977 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4979 "Sliding kext %s: External relocations found.",
4980 getIdentifierCString());
4984 if (dysymtab
->nlocrel
> 0) {
4985 if (!haveLinkeditBase
) {
4987 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4989 "Sliding kext %s: No linkedit segment.",
4990 getIdentifierCString());
4994 if (!haveRelocBase
) {
4996 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4999 "Sliding kext %s: No writable segments.",
5001 "Sliding kext %s: No segments.",
5003 getIdentifierCString());
5007 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
5008 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
5010 for (i
= 0; i
< dysymtab
->nlocrel
; i
++) {
5011 if ( reloc
[i
].r_extern
!= 0
5012 || reloc
[i
].r_type
!= 0
5013 || reloc
[i
].r_length
!= (sizeof(void *) == 8 ? 3 : 2)
5016 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5018 "Sliding kext %s: Unexpected relocation found.",
5019 getIdentifierCString());
5022 if (reloc
[i
].r_pcrel
!= 0) {
5025 *((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)) += vm_kernel_slide
;
5027 #if KASLR_KEXT_DEBUG
5028 #define MAX_DYSYMS_TO_LOG 5
5029 if ( i
< MAX_DYSYMS_TO_LOG
) {
5030 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
5031 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
))),
5032 (unsigned long)*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)));
5037 /* We should free these relocations, not just delete the reference to them.
5038 * <rdar://problem/10535549> Free relocations from PIE kexts.
5040 * For now, we do not free LINKEDIT for kexts with split segments.
5042 new_kextsize
= round_page(kmod_info
->size
- reloc_size
);
5043 if (((kmod_info
->size
- new_kextsize
) > PAGE_SIZE
) && (!segmentSplitInfo
)) {
5044 vm_offset_t endofkext
= kmod_info
->address
+ kmod_info
->size
;
5045 vm_offset_t new_endofkext
= kmod_info
->address
+ new_kextsize
;
5046 vm_offset_t endofrelocInfo
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
);
5047 int bytes_remaining
= endofkext
- endofrelocInfo
;
5048 OSData
* new_osdata
= NULL
;
5050 /* fix up symbol offsets if they are after the dsymtab local relocs */
5052 if (dysymtab
->locreloff
< symtab
->symoff
){
5053 symtab
->symoff
-= reloc_size
;
5055 if (dysymtab
->locreloff
< symtab
->stroff
) {
5056 symtab
->stroff
-= reloc_size
;
5059 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
5060 dysymtab
->extreloff
-= reloc_size
;
5063 /* move data behind reloc info down to new offset */
5064 if (endofrelocInfo
< endofkext
) {
5065 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
5068 /* Create a new OSData for the smaller kext object and reflect
5069 * new linkedit segment size.
5071 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
5072 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
5074 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
5076 /* Fix up kmod info and linkedExecutable.
5078 kmod_info
->size
= new_kextsize
;
5080 new_osdata
->setDeallocFunction(osdata_kext_free
);
5082 new_osdata
->setDeallocFunction(osdata_phys_free
);
5084 linkedExecutable
->setDeallocFunction(NULL
);
5085 linkedExecutable
->release();
5086 linkedExecutable
= new_osdata
;
5089 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
5091 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
5095 dysymtab
->nlocrel
= 0;
5096 dysymtab
->locreloff
= 0;
5100 result
= kOSReturnSuccess
;
5105 /*********************************************************************
5106 * called only by load()
5107 *********************************************************************/
5109 OSKext::loadExecutable()
5111 OSReturn result
= kOSReturnError
;
5112 kern_return_t kxldResult
;
5113 KXLDDependency
* kxlddeps
= NULL
; // must kfree
5114 uint32_t num_kxlddeps
= 0;
5115 OSArray
* linkDependencies
= NULL
; // must release
5116 uint32_t numDirectDependencies
= 0;
5117 uint32_t num_kmod_refs
= 0;
5118 struct mach_header
** kxldHeaderPtr
= NULL
; // do not free
5119 struct mach_header
* kxld_header
= NULL
; // xxx - need to free here?
5120 OSData
* theExecutable
= NULL
; // do not release
5121 OSString
* versString
= NULL
; // do not release
5122 const char * versCString
= NULL
; // do not free
5123 const char * string
= NULL
; // do not free
5126 /* We need the version string for a variety of bits below.
5128 versString
= OSDynamicCast(OSString
,
5129 getPropertyForHostArch(kCFBundleVersionKey
));
5133 versCString
= versString
->getCStringNoCopy();
5135 if (isKernelComponent()) {
5136 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
5138 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
5140 kOSKextLogErrorLevel
|
5142 "Kernel component %s has incorrect version %s; "
5144 getIdentifierCString(),
5145 versCString
, KERNEL6_VERSION
);
5146 result
= kOSKextReturnInternalError
;
5148 } else if (strcmp(versCString
, osrelease
)) {
5150 kOSKextLogErrorLevel
|
5152 "Kernel component %s has incorrect version %s; "
5154 getIdentifierCString(),
5155 versCString
, osrelease
);
5156 result
= kOSKextReturnInternalError
;
5162 if (isPrelinked()) {
5166 /* <rdar://problem/21444003> all callers must be entitled */
5167 if (FALSE
== IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management")) {
5169 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5170 "Not entitled to link kext '%s'",
5171 getIdentifierCString());
5172 result
= kOSKextReturnNotPrivileged
;
5176 theExecutable
= getExecutable();
5177 if (!theExecutable
) {
5178 if (declaresExecutable()) {
5180 kOSKextLogErrorLevel
|
5182 "Can't load kext %s - executable is missing.",
5183 getIdentifierCString());
5184 result
= kOSKextReturnValidation
;
5190 if (isInterface()) {
5191 OSData
*executableCopy
= OSData::withData(theExecutable
);
5192 setLinkedExecutable(executableCopy
);
5193 executableCopy
->release();
5197 numDirectDependencies
= getNumDependencies();
5199 if (flags
.hasBleedthrough
) {
5200 linkDependencies
= dependencies
;
5201 linkDependencies
->retain();
5203 linkDependencies
= OSArray::withArray(dependencies
);
5204 if (!linkDependencies
) {
5206 kOSKextLogErrorLevel
|
5207 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5208 "Can't allocate link dependencies to load kext %s.",
5209 getIdentifierCString());
5213 for (i
= 0; i
< numDirectDependencies
; ++i
) {
5214 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
5215 dependencies
->getObject(i
));
5216 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
5220 num_kxlddeps
= linkDependencies
->getCount();
5221 if (!num_kxlddeps
) {
5223 kOSKextLogErrorLevel
|
5224 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
5225 "Can't load kext %s - it has no library dependencies.",
5226 getIdentifierCString());
5230 kxlddeps
= (KXLDDependency
*)kalloc_tag(num_kxlddeps
* sizeof(*kxlddeps
), VM_KERN_MEMORY_OSKEXT
);
5233 kOSKextLogErrorLevel
|
5234 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5235 "Can't allocate link context to load kext %s.",
5236 getIdentifierCString());
5239 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
5241 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5242 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
5244 if (dependency
->isInterface()) {
5245 OSKext
*interfaceTargetKext
= NULL
;
5246 OSData
* interfaceTarget
= NULL
;
5248 if (dependency
->isKernelComponent()) {
5249 interfaceTargetKext
= sKernelKext
;
5250 interfaceTarget
= sKernelKext
->linkedExecutable
;
5252 interfaceTargetKext
= OSDynamicCast(OSKext
,
5253 dependency
->dependencies
->getObject(0));
5255 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
5258 if (!interfaceTarget
) {
5263 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5264 * it will be useful to have them in the debugger.
5265 * strdup() failing isn't critical right here so we don't check that.
5267 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
5268 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
5269 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
5271 kxlddeps
[i
].interface
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5272 kxlddeps
[i
].interface_size
= dependency
->linkedExecutable
->getLength();
5273 kxlddeps
[i
].interface_name
= strdup(dependency
->getIdentifierCString());
5275 kxlddeps
[i
].kext
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5276 kxlddeps
[i
].kext_size
= dependency
->linkedExecutable
->getLength();
5277 kxlddeps
[i
].kext_name
= strdup(dependency
->getIdentifierCString());
5280 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
5283 kxldHeaderPtr
= &kxld_header
;
5287 kOSKextLogExplicitLevel
|
5288 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5289 "Kext %s - calling kxld_link_file:\n"
5290 " kxld_context: %p\n"
5291 " executable: %p executable_length: %d\n"
5293 " kxld_dependencies: %p num_dependencies: %d\n"
5294 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5295 getIdentifierCString(), sKxldContext
,
5296 theExecutable
->getBytesNoCopy(), theExecutable
->getLength(),
5297 this, kxlddeps
, num_kxlddeps
,
5298 kxldHeaderPtr
, &kmod_info
);
5301 /* After this call, the linkedExecutable instance variable
5304 kxldResult
= kxld_link_file(sKxldContext
,
5305 (u_char
*)theExecutable
->getBytesNoCopy(),
5306 theExecutable
->getLength(),
5307 getIdentifierCString(), this, kxlddeps
, num_kxlddeps
,
5308 (u_char
**)kxldHeaderPtr
, (kxld_addr_t
*)&kmod_info
);
5310 if (kxldResult
!= KERN_SUCCESS
) {
5311 // xxx - add kxldResult here?
5313 kOSKextLogErrorLevel
|
5315 "Can't load kext %s - link failed.",
5316 getIdentifierCString());
5317 result
= kOSKextReturnLinkError
;
5321 /* We've written data & instructions into kernel memory, so flush the data
5322 * cache and invalidate the instruction cache.
5323 * I/D caches are coherent on x86
5325 #if !defined(__i386__) && !defined(__x86_64__)
5326 flush_dcache(kmod_info
->address
, kmod_info
->size
, false);
5327 invalidate_icache(kmod_info
->address
, kmod_info
->size
, false);
5331 if (isInterface()) {
5333 /* Whip up a fake kmod_info entry for the interface kext.
5335 kmod_info
= (kmod_info_t
*)kalloc_tag(sizeof(kmod_info_t
), VM_KERN_MEMORY_OSKEXT
);
5337 result
= KERN_MEMORY_ERROR
;
5341 /* A pseudokext has almost nothing in its kmod_info struct.
5343 bzero(kmod_info
, sizeof(kmod_info_t
));
5345 kmod_info
->info_version
= KMOD_INFO_VERSION
;
5347 /* An interface kext doesn't have a linkedExecutable, so save a
5348 * copy of the UUID out of the original executable via copyUUID()
5349 * while we still have the original executable.
5351 interfaceUUID
= copyUUID();
5354 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5355 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5357 /* Stamp the bundle ID and version from the OSKext over anything
5358 * resident inside the kmod_info.
5360 string
= getIdentifierCString();
5361 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5363 string
= versCString
;
5364 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5366 /* Add the dependencies' kmod_info structs as kmod_references.
5368 num_kmod_refs
= getNumDependencies();
5369 if (num_kmod_refs
) {
5370 kmod_info
->reference_list
= (kmod_reference_t
*)kalloc_tag(
5371 num_kmod_refs
* sizeof(kmod_reference_t
), VM_KERN_MEMORY_OSKEXT
);
5372 if (!kmod_info
->reference_list
) {
5373 result
= KERN_MEMORY_ERROR
;
5376 bzero(kmod_info
->reference_list
,
5377 num_kmod_refs
* sizeof(kmod_reference_t
));
5378 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5379 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5380 OSKext
* refKext
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
));
5381 ref
->info
= refKext
->kmod_info
;
5382 ref
->info
->reference_count
++;
5384 if (refIndex
+ 1 < num_kmod_refs
) {
5385 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5390 if (!isInterface() && linkedExecutable
) {
5392 kOSKextLogProgressLevel
|
5394 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5396 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5397 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5398 (unsigned)kmod_info
->id
);
5401 /* if prelinked, VM protections are already set */
5402 result
= setVMAttributes(!isPrelinked(), true);
5403 if (result
!= KERN_SUCCESS
) {
5407 result
= kOSReturnSuccess
;
5410 OSSafeReleaseNULL(linkDependencies
);
5412 /* Clear up locally allocated dependency info.
5414 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5417 if (kxlddeps
[i
].kext_name
) {
5418 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5419 kfree(kxlddeps
[i
].kext_name
, size
);
5421 if (kxlddeps
[i
].interface_name
) {
5422 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5423 kfree(kxlddeps
[i
].interface_name
, size
);
5426 if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5428 /* We no longer need the unrelocated executable (which the linker
5429 * has altered anyhow).
5431 setExecutable(NULL
);
5433 if (result
!= kOSReturnSuccess
) {
5435 kOSKextLogErrorLevel
|
5437 "Failed to load executable for kext %s.",
5438 getIdentifierCString());
5440 if (kmod_info
&& kmod_info
->reference_list
) {
5441 kfree(kmod_info
->reference_list
,
5442 num_kmod_refs
* sizeof(kmod_reference_t
));
5444 if (isInterface()) {
5445 kfree(kmod_info
, sizeof(kmod_info_t
));
5448 if (linkedExecutable
) {
5449 linkedExecutable
->release();
5450 linkedExecutable
= NULL
;
5457 /*********************************************************************
5458 * The linkedit segment is used by the kext linker for dependency
5459 * resolution, and by dtrace for probe initialization. We can free it
5460 * for non-library kexts, since no kexts depend on non-library kexts
5461 * by definition, once dtrace has been initialized.
5462 *********************************************************************/
5464 OSKext::jettisonLinkeditSegment(void)
5466 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5467 kernel_segment_command_t
* linkedit
= NULL
;
5469 vm_size_t linkeditsize
, kextsize
;
5470 OSData
* data
= NULL
;
5473 /* We can free symbol tables for all embedded kexts because we don't
5474 * support runtime kext linking.
5476 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5478 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5483 /* Find the linkedit segment. If it's not the last segment, then freeing
5484 * it will fragment the kext into multiple VM regions, which OSKext is not
5485 * designed to handle, so we'll have to skip it.
5487 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5492 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5493 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
))
5498 /* Create a new OSData for the smaller kext object.
5500 linkeditsize
= round_page(linkedit
->vmsize
);
5501 kextsize
= kmod_info
->size
- linkeditsize
;
5502 start
= linkedit
->vmaddr
;
5504 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5509 /* Fix the kmod info and linkedExecutable.
5511 kmod_info
->size
= kextsize
;
5514 data
->setDeallocFunction(osdata_kext_free
);
5516 data
->setDeallocFunction(osdata_phys_free
);
5518 linkedExecutable
->setDeallocFunction(NULL
);
5519 linkedExecutable
->release();
5520 linkedExecutable
= data
;
5521 flags
.jettisonLinkeditSeg
= 1;
5523 /* Free the linkedit segment.
5526 kext_free(start
, linkeditsize
);
5528 ml_static_mfree(start
, linkeditsize
);
5535 /*********************************************************************
5536 * If there are whole pages that are unused betweem the last section
5537 * of the DATA segment and the end of the DATA segment then we can free
5539 *********************************************************************/
5541 OSKext::jettisonDATASegmentPadding(void)
5543 kernel_mach_header_t
* mh
;
5544 kernel_segment_command_t
* dataSeg
;
5545 kernel_section_t
* sec
, * lastSec
;
5546 vm_offset_t dataSegEnd
, lastSecEnd
;
5549 mh
= (kernel_mach_header_t
*)kmod_info
->address
;
5551 dataSeg
= getsegbynamefromheader(mh
, SEG_DATA
);
5552 if (dataSeg
== NULL
) {
5557 sec
= firstsect(dataSeg
);
5558 while (sec
!= NULL
) {
5560 sec
= nextsect(dataSeg
, sec
);
5563 if (lastSec
== NULL
) {
5567 if ((dataSeg
->vmaddr
!= round_page(dataSeg
->vmaddr
)) ||
5568 (dataSeg
->vmsize
!= round_page(dataSeg
->vmsize
))) {
5572 dataSegEnd
= dataSeg
->vmaddr
+ dataSeg
->vmsize
;
5573 lastSecEnd
= round_page(lastSec
->addr
+ lastSec
->size
);
5575 if (dataSegEnd
<= lastSecEnd
) {
5579 padSize
= dataSegEnd
- lastSecEnd
;
5581 if (padSize
>= PAGE_SIZE
) {
5583 kext_free(lastSecEnd
, padSize
);
5585 ml_static_mfree(lastSecEnd
, padSize
);
5590 /*********************************************************************
5591 *********************************************************************/
5593 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5595 if (linkedExecutable
) {
5596 panic("Attempt to set linked executable on kext "
5597 "that already has one (%s).\n",
5598 getIdentifierCString());
5600 linkedExecutable
= anExecutable
;
5601 linkedExecutable
->retain();
5606 /*********************************************************************
5607 * Go through all loaded kexts and tell them to register with dtrace.
5608 * The instance method only registers if necessary.
5609 *********************************************************************/
5612 OSKext::registerKextsWithDTrace(void)
5614 uint32_t count
= sLoadedKexts
->getCount();
5617 IORecursiveLockLock(sKextLock
);
5619 for (i
= 0; i
< count
; i
++) {
5620 OSKext
* thisKext
= NULL
; // do not release
5622 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5623 if (!thisKext
|| !thisKext
->isExecutable()) {
5627 thisKext
->registerWithDTrace();
5630 IORecursiveLockUnlock(sKextLock
);
5636 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5637 extern int (*dtrace_modunload
)(struct kmod_info
*);
5640 /*********************************************************************
5641 *********************************************************************/
5643 OSKext::registerWithDTrace(void)
5645 /* Register kext with dtrace. A dtrace_modload failure should not
5646 * prevent a kext from loading, so we ignore the return code.
5648 if (!flags
.dtraceInitialized
&& (dtrace_modload
!= NULL
)) {
5649 uint32_t modflag
= 0;
5650 OSObject
* forceInit
= getPropertyForHostArch("OSBundleForceDTraceInit");
5651 if (forceInit
== kOSBooleanTrue
) {
5652 modflag
|= KMOD_DTRACE_FORCE_INIT
;
5655 (void)(*dtrace_modload
)(kmod_info
, modflag
);
5656 flags
.dtraceInitialized
= true;
5657 jettisonLinkeditSegment();
5661 /*********************************************************************
5662 *********************************************************************/
5664 OSKext::unregisterWithDTrace(void)
5666 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5667 * prevent a kext from loading, so we ignore the return code.
5669 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
5670 (void)(*dtrace_modunload
)(kmod_info
);
5671 flags
.dtraceInitialized
= false;
5675 #endif /* CONFIG_DTRACE */
5678 /*********************************************************************
5679 * called only by loadExecutable()
5680 *********************************************************************/
5681 #if !VM_MAPPED_KEXTS
5682 #error Unrecognized architecture
5684 static inline kern_return_t
5687 vm_map_offset_t start
,
5688 vm_map_offset_t end
,
5692 if (start
== end
) { // 10538581
5693 return(KERN_SUCCESS
);
5695 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
5698 static inline kern_return_t
5701 vm_map_offset_t start
,
5702 vm_map_offset_t end
,
5703 vm_prot_t access_type
,
5704 boolean_t user_wire
)
5706 return vm_map_wire(map
, start
, end
, access_type
| VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_KEXT
), user_wire
);
5711 OSKext::setVMAttributes(bool protect
, bool wire
)
5713 vm_map_t kext_map
= NULL
;
5714 kernel_segment_command_t
* seg
= NULL
;
5715 vm_map_offset_t start
= 0;
5716 vm_map_offset_t end
= 0;
5717 OSReturn result
= kOSReturnError
;
5719 if (isInterface() || !declaresExecutable()) {
5720 result
= kOSReturnSuccess
;
5724 /* Get the kext's vm map */
5725 kext_map
= kext_get_vm_map(kmod_info
);
5727 result
= KERN_MEMORY_ERROR
;
5731 #if !VM_MAPPED_KEXTS
5732 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
5733 /* This is a split kext in a prelinked kernelcache; we'll let the
5734 * platform code take care of protecting it. It is already wired.
5736 /* TODO: Should this still allow protections for the first segment
5737 * to go through, in the event that we have a mix of split and
5740 result
= KERN_SUCCESS
;
5745 /* Protect the headers as read-only; they do not need to be wired */
5746 result
= (protect
) ? OSKext_protect(kext_map
, kmod_info
->address
,
5747 kmod_info
->address
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
)
5749 if (result
!= KERN_SUCCESS
) {
5753 /* Set the VM protections and wire down each of the segments */
5754 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5758 start
= round_page(seg
->vmaddr
);
5759 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
5762 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
5763 if (result
!= KERN_SUCCESS
) {
5765 kOSKextLogErrorLevel
|
5767 "Kext %s failed to set maximum VM protections "
5768 "for segment %s - 0x%x.",
5769 getIdentifierCString(), seg
->segname
, (int)result
);
5773 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5774 if (result
!= KERN_SUCCESS
) {
5776 kOSKextLogErrorLevel
|
5778 "Kext %s failed to set initial VM protections "
5779 "for segment %s - 0x%x.",
5780 getIdentifierCString(), seg
->segname
, (int)result
);
5785 if (segmentShouldBeWired(seg
) && wire
) {
5786 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5787 if (result
!= KERN_SUCCESS
) {
5792 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5799 /*********************************************************************
5800 *********************************************************************/
5802 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
5804 return (sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
)));
5807 /*********************************************************************
5808 *********************************************************************/
5810 OSKext::validateKextMapping(bool startFlag
)
5812 OSReturn result
= kOSReturnError
;
5813 const char * whichOp
= startFlag
? "start" : "stop";
5814 kern_return_t kern_result
= 0;
5815 vm_map_t kext_map
= NULL
;
5816 kernel_segment_command_t
* seg
= NULL
;
5817 mach_vm_address_t address
= 0;
5818 mach_vm_size_t size
= 0;
5820 mach_msg_type_number_t count
;
5821 vm_region_submap_short_info_data_64_t info
;
5823 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
5824 bzero(&info
, sizeof(info
));
5826 // xxx - do we need a distinct OSReturn value for these or is "bad data"
5827 // xxx - sufficient?
5829 /* Verify that the kmod_info and start/stop pointers are non-NULL.
5833 kOSKextLogErrorLevel
|
5835 "Kext %s - NULL kmod_info pointer.",
5836 getIdentifierCString());
5837 result
= kOSKextReturnBadData
;
5842 address
= (mach_vm_address_t
)kmod_info
->start
;
5844 address
= (mach_vm_address_t
)kmod_info
->stop
;
5849 kOSKextLogErrorLevel
|
5851 "Kext %s - NULL module %s pointer.",
5852 getIdentifierCString(), whichOp
);
5853 result
= kOSKextReturnBadData
;
5857 kext_map
= kext_get_vm_map(kmod_info
);
5858 depth
= (kernel_map
== kext_map
) ? 1 : 2;
5860 /* Verify that the start/stop function lies within the kext's address range.
5862 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
5863 /* This will likely be how we deal with split kexts; walk the segments to
5864 * check that the function lies inside one of the segments of this kext.
5866 for (seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5868 seg
= nextsegfromheader((kernel_mach_header_t
*)kmod_info
->address
, seg
)) {
5869 if ((address
>= seg
->vmaddr
) && address
< (seg
->vmaddr
+ seg
->vmsize
)) {
5876 kOSKextLogErrorLevel
|
5878 "Kext %s module %s pointer is outside of kext range "
5879 "(%s %p - kext starts at %p).",
5880 getIdentifierCString(),
5883 (void *)VM_KERNEL_UNSLIDE(address
),
5884 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
));
5885 result
= kOSKextReturnBadData
;
5891 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
5892 kmod_info
->address
+ kmod_info
->size
<= address
)
5895 kOSKextLogErrorLevel
|
5897 "Kext %s module %s pointer is outside of kext range "
5898 "(%s %p - kext at %p-%p).",
5899 getIdentifierCString(),
5902 (void *)VM_KERNEL_UNSLIDE(address
),
5903 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5904 (void *)(VM_KERNEL_UNSLIDE(kmod_info
->address
) + kmod_info
->size
));
5905 result
= kOSKextReturnBadData
;
5910 /* Only do these checks before calling the start function;
5911 * If anything goes wrong with the mapping while the kext is running,
5912 * we'll likely have panicked well before any attempt to stop the kext.
5916 /* Verify that the start/stop function is executable.
5918 kern_result
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
,
5919 (vm_region_recurse_info_t
)&info
, &count
);
5920 if (kern_result
!= KERN_SUCCESS
) {
5922 kOSKextLogErrorLevel
|
5924 "Kext %s - bad %s pointer %p.",
5925 getIdentifierCString(),
5926 whichOp
, (void *)VM_KERNEL_UNSLIDE(address
));
5927 result
= kOSKextReturnBadData
;
5932 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
5934 kOSKextLogErrorLevel
|
5936 "Kext %s - memory region containing module %s function "
5937 "is not executable.",
5938 getIdentifierCString(), whichOp
);
5939 result
= kOSKextReturnBadData
;
5944 /* Verify that the kext's segments are backed by physical memory.
5946 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5948 if (!verifySegmentMapping(seg
)) {
5949 result
= kOSKextReturnBadData
;
5953 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5958 result
= kOSReturnSuccess
;
5963 /*********************************************************************
5964 *********************************************************************/
5966 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
5968 mach_vm_address_t address
= 0;
5970 if (!segmentShouldBeWired(seg
)) return true;
5972 for (address
= seg
->vmaddr
;
5973 address
< round_page(seg
->vmaddr
+ seg
->vmsize
);
5974 address
+= PAGE_SIZE
)
5976 if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) {
5978 kOSKextLogErrorLevel
|
5980 "Kext %s - page %p is not backed by physical memory.",
5981 getIdentifierCString(),
5990 /*********************************************************************
5991 *********************************************************************/
5993 OSKextLogKextInfo(OSKext
*aKext
, uint64_t address
, uint64_t size
, firehose_tracepoint_code_t code
)
5997 firehose_tracepoint_id_u trace_id
;
5998 struct firehose_trace_uuid_info_s uuid_info_s
;
5999 firehose_trace_uuid_info_t uuid_info
= &uuid_info_s
;
6000 size_t uuid_info_len
= sizeof(struct firehose_trace_uuid_info_s
);
6003 stamp
= firehose_tracepoint_time(firehose_activity_flags_default
);
6004 trace_id
.ftid_value
= FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata
, _firehose_tracepoint_type_metadata_kext
, (firehose_tracepoint_flags_t
)0, code
);
6006 uuid_data
= aKext
->copyUUID();
6008 memcpy(uuid_info
->ftui_uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_info
->ftui_uuid
));
6009 OSSafeReleaseNULL(uuid_data
);
6012 uuid_info
->ftui_size
= size
;
6013 uuid_info
->ftui_address
= VM_KERNEL_UNSLIDE(address
);
6015 firehose_trace_metadata(firehose_stream_metadata
, trace_id
, stamp
, uuid_info
, uuid_info_len
);
6019 /*********************************************************************
6020 *********************************************************************/
6022 OSKext::start(bool startDependenciesFlag
)
6024 OSReturn result
= kOSReturnError
;
6025 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
6026 unsigned int i
, count
;
6027 void * kmodStartData
= NULL
;
6029 if (isStarted() || isInterface() || isKernelComponent()) {
6030 result
= kOSReturnSuccess
;
6036 kOSKextLogErrorLevel
|
6038 "Attempt to start nonloaded kext %s.",
6039 getIdentifierCString());
6040 result
= kOSKextReturnInvalidArgument
;
6044 if (!sLoadEnabled
) {
6046 kOSKextLogErrorLevel
|
6048 "Kext loading is disabled (attempt to start kext %s).",
6049 getIdentifierCString());
6050 result
= kOSKextReturnDisabled
;
6054 result
= validateKextMapping(/* start? */ true);
6055 if (result
!= kOSReturnSuccess
) {
6059 startfunc
= kmod_info
->start
;
6061 count
= getNumDependencies();
6062 for (i
= 0; i
< count
; i
++) {
6063 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
6064 if (dependency
== NULL
) {
6066 kOSKextLogErrorLevel
|
6068 "Kext %s start - internal error, dependency disappeared.",
6069 getIdentifierCString());
6072 if (!dependency
->isStarted()) {
6073 if (startDependenciesFlag
) {
6074 OSReturn dependencyResult
=
6075 dependency
->start(startDependenciesFlag
);
6076 if (dependencyResult
!= KERN_SUCCESS
) {
6078 kOSKextLogErrorLevel
|
6080 "Kext %s start - dependency %s failed to start (error 0x%x).",
6081 getIdentifierCString(),
6082 dependency
->getIdentifierCString(),
6088 kOSKextLogErrorLevel
|
6090 "Not starting %s - dependency %s not started yet.",
6091 getIdentifierCString(),
6092 dependency
->getIdentifierCString());
6093 result
= kOSKextReturnStartStopError
; // xxx - make new return?
6100 kOSKextLogDetailLevel
|
6102 "Kext %s calling module start function.",
6103 getIdentifierCString());
6107 // Drop a log message so logd can grab the needed information to decode this kext
6108 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_load
);
6110 #if !CONFIG_STATIC_CPPINIT
6111 result
= OSRuntimeInitializeCPP(kmod_info
, NULL
);
6112 if (result
== KERN_SUCCESS
) {
6116 kmodStartData
= GetAppleTEXTHashForKext(this, this->infoDict
);
6119 if (kmodStartData
) {
6121 kOSKextLogErrorLevel
|
6122 kOSKextLogGeneralFlag
,
6123 "Kext %s calling module start function. kmodStartData %p. arch %s",
6124 getIdentifierCString(), kmodStartData
, ARCHNAME
);
6127 #endif // CONFIG_KEC_FIPS
6128 result
= startfunc(kmod_info
, kmodStartData
);
6130 #if !CONFIG_STATIC_CPPINIT
6131 if (result
!= KERN_SUCCESS
) {
6132 (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6139 /* On success overlap the setting of started/starting. On failure just
6142 if (result
== KERN_SUCCESS
) {
6145 // xxx - log start error from kernel?
6147 kOSKextLogProgressLevel
|
6149 "Kext %s is now started.",
6150 getIdentifierCString());
6152 invokeOrCancelRequestCallbacks(
6153 /* result not actually used */ kOSKextReturnStartStopError
,
6154 /* invokeFlag */ false);
6156 kOSKextLogProgressLevel
|
6158 "Kext %s did not start (return code 0x%x).",
6159 getIdentifierCString(), result
);
6166 /*********************************************************************
6167 *********************************************************************/
6169 bool OSKext::canUnloadKextWithIdentifier(
6170 OSString
* kextIdentifier
,
6171 bool checkClassesFlag
)
6173 bool result
= false;
6174 OSKext
* aKext
= NULL
; // do not release
6176 IORecursiveLockLock(sKextLock
);
6178 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
6181 goto finish
; // can't unload what's not loaded
6184 if (aKext
->isLoaded()) {
6185 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
6188 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
6196 IORecursiveLockUnlock(sKextLock
);
6200 /*********************************************************************
6201 *********************************************************************/
6205 OSReturn result
= kOSReturnError
;
6206 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
6208 if (!isStarted() || isInterface()) {
6209 result
= kOSReturnSuccess
;
6215 kOSKextLogErrorLevel
|
6217 "Attempt to stop nonloaded kext %s.",
6218 getIdentifierCString());
6219 result
= kOSKextReturnInvalidArgument
;
6223 /* Refuse to stop if we have clients or instances. It is up to
6224 * the caller to make sure those aren't true.
6226 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6228 kOSKextLogErrorLevel
|
6230 "Kext %s - C++ instances; can't stop.",
6231 getIdentifierCString());
6232 result
= kOSKextReturnInUse
;
6236 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6239 kOSKextLogErrorLevel
|
6241 "Kext %s - has references (linkage or tracking object); "
6243 getIdentifierCString());
6244 result
= kOSKextReturnInUse
;
6248 /* Note: If validateKextMapping fails on the stop & unload path,
6249 * we are in serious trouble and a kernel panic is likely whether
6250 * we stop & unload the kext or not.
6252 result
= validateKextMapping(/* start? */ false);
6253 if (result
!= kOSReturnSuccess
) {
6257 stopfunc
= kmod_info
->stop
;
6260 kOSKextLogDetailLevel
|
6262 "Kext %s calling module stop function.",
6263 getIdentifierCString());
6267 result
= stopfunc(kmod_info
, /* userData */ NULL
);
6268 #if !CONFIG_STATIC_CPPINIT
6269 if (result
== KERN_SUCCESS
) {
6270 result
= OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6276 if (result
== KERN_SUCCESS
) {
6280 kOSKextLogDetailLevel
|
6282 "Kext %s is now stopped and ready to unload.",
6283 getIdentifierCString());
6286 kOSKextLogErrorLevel
|
6288 "Kext %s did not stop (return code 0x%x).",
6289 getIdentifierCString(), result
);
6290 result
= kOSKextReturnStartStopError
;
6295 // Drop a log message so logd can update this kext's metadata
6296 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_unload
);
6300 /*********************************************************************
6301 *********************************************************************/
6303 OSKext::unload(void)
6305 OSReturn result
= kOSReturnError
;
6307 uint32_t num_kmod_refs
= 0;
6308 OSKextAccount
* freeAccount
;
6310 if (!sUnloadEnabled
) {
6312 kOSKextLogErrorLevel
|
6314 "Kext unloading is disabled (%s).",
6315 this->getIdentifierCString());
6317 result
= kOSKextReturnDisabled
;
6321 /* Refuse to unload if we have clients or instances. It is up to
6322 * the caller to make sure those aren't true.
6324 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6325 // xxx - Don't log under errors? this is more of an info thing
6327 kOSKextLogErrorLevel
|
6328 kOSKextLogKextBookkeepingFlag
,
6329 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6330 getIdentifierCString());
6331 result
= kOSKextReturnInUse
;
6335 if (hasOSMetaClassInstances()) {
6337 kOSKextLogErrorLevel
|
6338 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6339 "Can't unload kext %s; classes have instances:",
6340 getIdentifierCString());
6341 reportOSMetaClassInstances(kOSKextLogErrorLevel
|
6342 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
);
6343 result
= kOSKextReturnInUse
;
6348 result
= kOSReturnSuccess
;
6352 if (isKernelComponent()) {
6353 result
= kOSKextReturnInvalidArgument
;
6357 /* Note that the kext is unloading before running any code that
6358 * might be in the kext (request callbacks, module stop function).
6359 * We will deny certain requests made against a kext in the process
6362 flags
.unloading
= 1;
6364 /* Update the string describing the last kext to unload in case we panic.
6366 savePanicString(/* isLoading */ false);
6370 if (result
!= KERN_SUCCESS
) {
6372 kOSKextLogErrorLevel
|
6374 "Kext %s can't unload - module stop returned 0x%x.",
6375 getIdentifierCString(), (unsigned)result
);
6376 result
= kOSKextReturnStartStopError
;
6382 kOSKextLogProgressLevel
|
6384 "Kext %s unloading.",
6385 getIdentifierCString());
6388 struct list_head
*p
;
6389 struct list_head
*prev
;
6390 struct list_head
*next
;
6391 for (p
= pendingPgoHead
.next
; p
!= &pendingPgoHead
; p
= next
) {
6392 OSKextGrabPgoStruct
*s
= container_of(p
, OSKextGrabPgoStruct
, list_head
);
6393 s
->err
= OSKextGrabPgoDataLocked(this, s
->metadata
, instance_uuid
, s
->pSize
, s
->pBuffer
, s
->bufferSize
);
6400 IORecursiveLockWakeup(sKextLock
, s
, false);
6405 /* Even if we don't call the stop function, we want to be sure we
6406 * have no OSMetaClass references before unloading the kext executable
6407 * from memory. OSMetaClasses may have pointers into the kext executable
6408 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6411 metaClasses
->flushCollection();
6414 /* Remove the kext from the list of loaded kexts, patch the gap
6415 * in the kmod_info_t linked list, and reset "kmod" to point to the
6416 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6418 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
6419 if (index
!= (unsigned int)-1) {
6421 sLoadedKexts
->removeObject(index
);
6423 OSKext
* nextKext
= OSDynamicCast(OSKext
,
6424 sLoadedKexts
->getObject(index
));
6428 OSKext
* gapKext
= OSDynamicCast(OSKext
,
6429 sLoadedKexts
->getObject(index
- 1));
6431 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
6433 } else /* index == 0 */ {
6434 nextKext
->kmod_info
->next
= NULL
;
6438 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
6439 if (lastKext
&& !lastKext
->isKernel()) {
6440 kmod
= lastKext
->kmod_info
;
6442 kmod
= NULL
; // clear the global kmod variable
6446 /* Clear out the kmod references that we're keeping for compatibility
6447 * with current panic backtrace code & kgmacros.
6448 * xxx - will want to update those bits sometime and remove this.
6450 num_kmod_refs
= getNumDependencies();
6451 if (num_kmod_refs
&& kmod_info
&& kmod_info
->reference_list
) {
6452 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
6453 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
6454 ref
->info
->reference_count
--;
6456 kfree(kmod_info
->reference_list
,
6457 num_kmod_refs
* sizeof(kmod_reference_t
));
6461 unregisterWithDTrace();
6462 #endif /* CONFIG_DTRACE */
6464 notifyKextUnloadObservers(this);
6467 IOSimpleLockLock(sKextAccountsLock
);
6468 account
->kext
= NULL
;
6469 if (account
->site
.tag
) account
->site
.flags
|= VM_TAG_UNLOAD
;
6470 else freeAccount
= account
;
6471 IOSimpleLockUnlock(sKextAccountsLock
);
6472 if (freeAccount
) IODelete(freeAccount
, OSKextAccount
, 1);
6474 /* Unwire and free the linked executable.
6476 if (linkedExecutable
) {
6478 if (!isInterface()) {
6479 kernel_segment_command_t
*seg
= NULL
;
6480 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6484 kOSKextLogErrorLevel
|
6486 "Failed to free kext %s; couldn't find the kext map.",
6487 getIdentifierCString());
6488 result
= kOSKextReturnInternalError
;
6493 kOSKextLogProgressLevel
|
6495 "Kext %s unwiring and unmapping linked executable.",
6496 getIdentifierCString());
6498 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6500 if (segmentShouldBeWired(seg
)) {
6501 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6502 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6503 if (result
!= KERN_SUCCESS
) {
6505 kOSKextLogErrorLevel
|
6507 "Failed to unwire kext %s.",
6508 getIdentifierCString());
6509 result
= kOSKextReturnInternalError
;
6514 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6518 OSSafeReleaseNULL(linkedExecutable
);
6521 /* An interface kext has a fake kmod_info that was allocated,
6522 * so we have to free it.
6524 if (isInterface()) {
6525 kfree(kmod_info
, sizeof(kmod_info_t
));
6530 flags
.loaded
= false;
6531 flushDependencies();
6533 /* save a copy of the bundle ID for us to check when deciding to
6534 * rebuild the kernel cache file. If a kext was already in the kernel
6535 * cache and unloaded then later loaded we do not need to rebuild the
6536 * kernel cache. 9055303
6538 if (isPrelinked()) {
6539 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6540 IORecursiveLockLock(sKextLock
);
6541 if (sUnloadedPrelinkedKexts
) {
6542 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6544 IORecursiveLockUnlock(sKextLock
);
6549 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6550 "Kext %s unloaded.", getIdentifierCString());
6552 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6553 OSDynamicCast(OSString
, bundleID
));
6556 OSKext::saveLoadedKextPanicList();
6557 OSKext::updateLoadedKextSummaries();
6559 flags
.unloading
= 0;
6563 /*********************************************************************
6564 * Assumes sKextLock is held.
6565 *********************************************************************/
6568 OSKext::queueKextNotification(
6569 const char * notificationName
,
6570 OSString
* kextIdentifier
)
6572 OSReturn result
= kOSReturnError
;
6573 OSDictionary
* loadRequest
= NULL
; // must release
6575 if (!kextIdentifier
) {
6576 result
= kOSKextReturnInvalidArgument
;
6580 /* Create a new request unless one is already sitting
6581 * in sKernelRequests for this bundle identifier
6583 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6584 if (result
!= kOSReturnSuccess
) {
6587 if (!_OSKextSetRequestArgument(loadRequest
,
6588 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6590 result
= kOSKextReturnNoMemory
;
6593 if (!sKernelRequests
->setObject(loadRequest
)) {
6594 result
= kOSKextReturnNoMemory
;
6598 /* We might want to only queue the notification if kextd is active,
6599 * but that wouldn't work for embedded. Note that we don't care if
6600 * the ping immediately succeeds here so don't do anything with the
6601 * result of this call.
6603 OSKext::pingKextd();
6605 result
= kOSReturnSuccess
;
6608 OSSafeReleaseNULL(loadRequest
);
6613 /*********************************************************************
6614 *********************************************************************/
6616 _OSKextConsiderDestroyingLinkContext(
6617 __unused thread_call_param_t p0
,
6618 __unused thread_call_param_t p1
)
6620 /* Take multiple locks in the correct order.
6622 IORecursiveLockLock(sKextLock
);
6623 IORecursiveLockLock(sKextInnerLock
);
6625 /* The first time we destroy the kxldContext is in the first
6626 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6627 * before calling this function. Thereafter any call to this function
6628 * will actually destroy the context.
6630 if (sConsiderUnloadsCalled
&& sKxldContext
) {
6631 kxld_destroy_context(sKxldContext
);
6632 sKxldContext
= NULL
;
6635 /* Free the thread_call that was allocated to execute this function.
6637 if (sDestroyLinkContextThread
) {
6638 if (!thread_call_free(sDestroyLinkContextThread
)) {
6639 OSKextLog(/* kext */ NULL
,
6640 kOSKextLogErrorLevel
|
6641 kOSKextLogGeneralFlag
,
6642 "thread_call_free() failed for kext link context.");
6644 sDestroyLinkContextThread
= 0;
6647 IORecursiveLockUnlock(sKextInnerLock
);
6648 IORecursiveLockUnlock(sKextLock
);
6653 /*********************************************************************
6654 * Destroying the kxldContext requires checking variables under both
6655 * sKextInnerLock and sKextLock, so we do it on a separate thread
6656 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6657 * call relationship.
6659 * This function must be invoked with sKextInnerLock held.
6660 * Do not call any function that takes sKextLock here!
6661 *********************************************************************/
6664 OSKext::considerDestroyingLinkContext(void)
6666 IORecursiveLockLock(sKextInnerLock
);
6668 /* If we have already queued a thread to destroy the link context,
6669 * don't bother resetting; that thread will take care of it.
6671 if (sDestroyLinkContextThread
) {
6675 /* The function to be invoked in the thread will deallocate
6676 * this thread_call, so don't share it around.
6678 sDestroyLinkContextThread
= thread_call_allocate(
6679 &_OSKextConsiderDestroyingLinkContext
, 0);
6680 if (!sDestroyLinkContextThread
) {
6681 OSKextLog(/* kext */ NULL
,
6682 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
| kOSKextLogLinkFlag
,
6683 "Can't create thread to destroy kext link context.");
6687 thread_call_enter(sDestroyLinkContextThread
);
6690 IORecursiveLockUnlock(sKextInnerLock
);
6695 #pragma mark Autounload
6697 /*********************************************************************
6698 * This is a static method because the kext will be deallocated if it
6700 *********************************************************************/
6703 OSKext::autounloadKext(OSKext
* aKext
)
6705 OSReturn result
= kOSKextReturnInUse
;
6707 /* Check for external references to this kext (usu. dependents),
6708 * instances of defined classes (or classes derived from them),
6709 * outstanding requests.
6711 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
6712 !aKext
->flags
.autounloadEnabled
||
6713 aKext
->isKernelComponent()) {
6718 /* Skip a delay-autounload kext, once.
6720 if (aKext
->flags
.delayAutounload
) {
6722 kOSKextLogProgressLevel
|
6723 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6724 "Kext %s has delayed autounload set; skipping and clearing flag.",
6725 aKext
->getIdentifierCString());
6726 aKext
->flags
.delayAutounload
= 0;
6730 if (aKext
->hasOSMetaClassInstances() ||
6731 aKext
->countRequestCallbacks()) {
6735 result
= OSKext::removeKext(aKext
);
6741 /*********************************************************************
6742 *********************************************************************/
6744 _OSKextConsiderUnloads(
6745 __unused thread_call_param_t p0
,
6746 __unused thread_call_param_t p1
)
6748 bool didUnload
= false;
6749 unsigned int count
, i
;
6751 /* Take multiple locks in the correct order
6752 * (note also sKextSummaries lock further down).
6754 IORecursiveLockLock(sKextLock
);
6755 IORecursiveLockLock(sKextInnerLock
);
6757 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6759 /* If the system is powering down, don't try to unload anything.
6765 OSKextLog(/* kext */ NULL
,
6766 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6767 "Checking for unused kexts to autounload.");
6770 * Remove any request callbacks marked as stale,
6771 * and mark as stale any currently in flight.
6773 count
= sRequestCallbackRecords
->getCount();
6777 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
6778 sRequestCallbackRecords
->getObject(i
));
6779 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
6780 callbackRecord
->getObject(kKextRequestStaleKey
));
6782 if (stale
== kOSBooleanTrue
) {
6783 OSKext::invokeRequestCallback(callbackRecord
,
6784 kOSKextReturnTimeout
);
6786 callbackRecord
->setObject(kKextRequestStaleKey
,
6793 * Make multiple passes through the array of loaded kexts until
6794 * we don't unload any. This handles unwinding of dependency
6795 * chains. We have to go *backwards* through the array because
6796 * kexts are removed from it when unloaded, and we cannot make
6797 * a copy or we'll mess up the retain counts we rely on to
6798 * check whether a kext will unload. If only we could have
6799 * nonretaining collections like CF has....
6804 count
= sLoadedKexts
->getCount();
6808 OSKext
* thisKext
= OSDynamicCast(OSKext
,
6809 sLoadedKexts
->getObject(i
));
6810 didUnload
|= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
6813 } while (didUnload
);
6816 sConsiderUnloadsPending
= false;
6817 sConsiderUnloadsExecuted
= true;
6819 (void) OSKext::considerRebuildOfPrelinkedKernel();
6821 IORecursiveLockUnlock(sKextInnerLock
);
6822 IORecursiveLockUnlock(sKextLock
);
6827 /*********************************************************************
6828 * Do not call any function that takes sKextLock here!
6829 *********************************************************************/
6830 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
6834 IORecursiveLockLock(sKextInnerLock
);
6836 if (!sUnloadCallout
) {
6837 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, 0);
6840 /* we only reset delay value for unloading if we already have something
6841 * pending. rescheduleOnlyFlag should not start the count down.
6843 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
6847 thread_call_cancel(sUnloadCallout
);
6848 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
6849 clock_interval_to_deadline(sConsiderUnloadDelay
,
6850 1000 * 1000 * 1000, &when
);
6852 OSKextLog(/* kext */ NULL
,
6853 kOSKextLogProgressLevel
|
6855 "%scheduling %sscan for unused kexts in %lu seconds.",
6856 sConsiderUnloadsPending
? "Res" : "S",
6857 sConsiderUnloadsCalled
? "" : "initial ",
6858 (unsigned long)sConsiderUnloadDelay
);
6860 sConsiderUnloadsPending
= true;
6861 thread_call_enter_delayed(sUnloadCallout
, when
);
6865 /* The kxld context should be reused throughout boot. We mark the end of
6866 * period as the first time considerUnloads() is called, and we destroy
6867 * the first kxld context in that function. Afterwards, it will be
6868 * destroyed in flushNonloadedKexts.
6870 if (!sConsiderUnloadsCalled
) {
6871 sConsiderUnloadsCalled
= true;
6872 OSKext::considerDestroyingLinkContext();
6875 IORecursiveLockUnlock(sKextInnerLock
);
6879 /*********************************************************************
6880 * Do not call any function that takes sKextLock here!
6881 *********************************************************************/
6884 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
);
6885 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
)
6887 IORecursiveLockLock(sKextInnerLock
);
6889 /* If the system is going to sleep, cancel the reaper thread timer,
6890 * and note that we're in a sleep state in case it just fired but hasn't
6891 * taken the lock yet. If we are coming back from sleep, just
6892 * clear the sleep flag; IOService's normal operation will cause
6893 * unloads to be considered soon enough.
6895 if (messageType
== kIOMessageSystemWillSleep
) {
6896 if (sUnloadCallout
) {
6897 thread_call_cancel(sUnloadCallout
);
6899 sSystemSleep
= true;
6900 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
6901 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
6902 sSystemSleep
= false;
6903 clock_get_uptime(&sLastWakeTime
);
6905 IORecursiveLockUnlock(sKextInnerLock
);
6907 return kIOReturnSuccess
;
6914 #pragma mark Prelinked Kernel
6916 /*********************************************************************
6917 * Do not access sConsiderUnloads... variables other than
6918 * sConsiderUnloadsExecuted in this function. They are guarded by a
6920 *********************************************************************/
6923 OSKext::considerRebuildOfPrelinkedKernel(void)
6925 static bool requestedPrelink
= false;
6926 OSReturn checkResult
= kOSReturnError
;
6927 OSDictionary
* prelinkRequest
= NULL
; // must release
6928 OSCollectionIterator
* kextIterator
= NULL
; // must release
6929 const OSSymbol
* thisID
= NULL
; // do not release
6930 bool doRebuild
= false;
6931 AbsoluteTime my_abstime
;
6935 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
6936 if (requestedPrelink
|| !sPrelinkBoot
) {
6940 /* no direct return from this point */
6941 IORecursiveLockLock(sKextLock
);
6943 /* We need to wait for kextd to get up and running with unloads already done
6944 * and any new startup kexts loaded.
6946 if (!sConsiderUnloadsExecuted
||
6947 !sDeferredLoadSucceeded
) {
6951 /* we really only care about boot / system start up related kexts so bail
6952 * if we're here after REBUILD_MAX_TIME.
6954 if (!_OSKextInPrelinkRebuildWindow()) {
6955 OSKextLog(/* kext */ NULL
,
6956 kOSKextLogArchiveFlag
,
6957 "%s prebuild rebuild has expired",
6959 requestedPrelink
= true;
6963 /* we do not want to trigger a rebuild if we get here too close to waking
6964 * up. (see radar 10233768)
6966 IORecursiveLockLock(sKextInnerLock
);
6968 clock_get_uptime(&my_abstime
);
6969 delta_secs
= MINIMUM_WAKEUP_SECONDS
+ 1;
6970 if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) {
6971 SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
);
6972 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
6973 delta_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
6975 IORecursiveLockUnlock(sKextInnerLock
);
6977 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
6978 /* too close to time of last wake from sleep */
6981 requestedPrelink
= true;
6983 /* Now it's time to see if we have a reason to rebuild. We may have done
6984 * some loads and unloads but the kernel cache didn't actually change.
6985 * We will rebuild if any kext is not marked prelinked AND is not in our
6986 * list of prelinked kexts that got unloaded. (see radar 9055303)
6988 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
6989 if (!kextIterator
) {
6993 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
6994 OSKext
* thisKext
; // do not release
6996 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
6997 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
7001 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
7004 /* kext is loaded and was not in current kernel cache so let's rebuild
7007 OSKextLog(/* kext */ NULL
,
7008 kOSKextLogArchiveFlag
,
7009 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
7010 thisKext
->bundleID
->getCStringNoCopy());
7013 sUnloadedPrelinkedKexts
->flushCollection();
7019 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
7021 if (checkResult
!= kOSReturnSuccess
) {
7025 if (!sKernelRequests
->setObject(prelinkRequest
)) {
7029 OSKext::pingKextd();
7032 IORecursiveLockUnlock(sKextLock
);
7033 OSSafeReleaseNULL(prelinkRequest
);
7034 OSSafeReleaseNULL(kextIterator
);
7040 #pragma mark Dependencies
7042 /*********************************************************************
7043 *********************************************************************/
7045 OSKext::resolveDependencies(
7046 OSArray
* loopStack
)
7048 bool result
= false;
7049 OSArray
* localLoopStack
= NULL
; // must release
7050 bool addedToLoopStack
= false;
7051 OSDictionary
* libraries
= NULL
; // do not release
7052 OSCollectionIterator
* libraryIterator
= NULL
; // must release
7053 OSString
* libraryID
= NULL
; // do not release
7054 OSString
* infoString
= NULL
; // do not release
7055 OSString
* readableString
= NULL
; // do not release
7056 OSKext
* libraryKext
= NULL
; // do not release
7057 bool hasRawKernelDependency
= false;
7058 bool hasKernelDependency
= false;
7059 bool hasKPIDependency
= false;
7060 bool hasPrivateKPIDependency
= false;
7063 /* A kernel component will automatically have this flag set,
7064 * and a loaded kext should also have it set (as should all its
7065 * loaded dependencies).
7067 if (flags
.hasAllDependencies
) {
7072 /* Check for loops in the dependency graph.
7075 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
7077 kOSKextLogErrorLevel
|
7078 kOSKextLogDependenciesFlag
,
7079 "Kext %s has a dependency loop; can't resolve dependencies.",
7080 getIdentifierCString());
7085 kOSKextLogStepLevel
|
7086 kOSKextLogDependenciesFlag
,
7087 "Kext %s resolving dependencies.",
7088 getIdentifierCString());
7090 loopStack
= OSArray::withCapacity(6); // any small capacity will do
7093 kOSKextLogErrorLevel
|
7094 kOSKextLogDependenciesFlag
,
7095 "Kext %s can't create bookkeeping stack to resolve dependencies.",
7096 getIdentifierCString());
7099 localLoopStack
= loopStack
;
7101 if (!loopStack
->setObject(this)) {
7103 kOSKextLogErrorLevel
|
7104 kOSKextLogDependenciesFlag
,
7105 "Kext %s - internal error resolving dependencies.",
7106 getIdentifierCString());
7109 addedToLoopStack
= true;
7111 /* Purge any existing kexts in the dependency list and start over.
7113 flushDependencies();
7116 kOSKextLogErrorLevel
|
7117 kOSKextLogDependenciesFlag
,
7118 "Kext %s - internal error resolving dependencies.",
7119 getIdentifierCString());
7122 libraries
= OSDynamicCast(OSDictionary
,
7123 getPropertyForHostArch(kOSBundleLibrariesKey
));
7124 if (libraries
== NULL
|| libraries
->getCount() == 0) {
7126 kOSKextLogErrorLevel
|
7127 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7128 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7129 getIdentifierCString(), kOSBundleLibrariesKey
);
7133 /* Make a new array to hold the dependencies (flush freed the old one).
7135 dependencies
= OSArray::withCapacity(libraries
->getCount());
7136 if (!dependencies
) {
7138 kOSKextLogErrorLevel
|
7139 kOSKextLogDependenciesFlag
,
7140 "Kext %s - can't allocate dependencies array.",
7141 getIdentifierCString());
7145 // xxx - compat: We used to add an implicit dependency on kernel 6.0
7146 // xxx - compat: if none were declared.
7148 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
7149 if (!libraryIterator
) {
7151 kOSKextLogErrorLevel
|
7152 kOSKextLogDependenciesFlag
,
7153 "Kext %s - can't allocate dependencies iterator.",
7154 getIdentifierCString());
7158 while ((libraryID
= OSDynamicCast(OSString
,
7159 libraryIterator
->getNextObject()))) {
7161 const char * library_id
= libraryID
->getCStringNoCopy();
7163 OSString
* libraryVersion
= OSDynamicCast(OSString
,
7164 libraries
->getObject(libraryID
));
7165 if (libraryVersion
== NULL
) {
7167 kOSKextLogErrorLevel
|
7168 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7169 "Kext %s - illegal type in OSBundleLibraries.",
7170 getIdentifierCString());
7174 OSKextVersion libraryVers
=
7175 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
7176 if (libraryVers
== -1) {
7178 kOSKextLogErrorLevel
|
7179 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7180 "Kext %s - invalid library version %s.",
7181 getIdentifierCString(),
7182 libraryVersion
->getCStringNoCopy());
7186 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
7187 if (libraryKext
== NULL
) {
7189 kOSKextLogErrorLevel
|
7190 kOSKextLogDependenciesFlag
,
7191 "Kext %s - library kext %s not found.",
7192 getIdentifierCString(), library_id
);
7196 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
7198 kOSKextLogErrorLevel
|
7199 kOSKextLogDependenciesFlag
,
7200 "Kext %s - library kext %s not compatible "
7201 "with requested version %s.",
7202 getIdentifierCString(), library_id
,
7203 libraryVersion
->getCStringNoCopy());
7207 /* If a nonprelinked library somehow got into the mix for a
7208 * prelinked kext, at any point in the chain, we must fail
7209 * because the prelinked relocs for the library will be all wrong.
7211 if (this->isPrelinked() &&
7212 libraryKext
->declaresExecutable() &&
7213 !libraryKext
->isPrelinked()) {
7216 kOSKextLogErrorLevel
|
7217 kOSKextLogDependenciesFlag
,
7218 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7219 getIdentifierCString(), library_id
,
7220 libraryVersion
->getCStringNoCopy());
7224 if (!libraryKext
->resolveDependencies(loopStack
)) {
7228 /* Add the library directly only if it has an executable to link.
7229 * Otherwise it's just used to collect other dependencies, so put
7230 * *its* dependencies on the list for this kext.
7232 // xxx - We are losing info here; would like to make fake entries or
7233 // xxx - keep these in the dependency graph for loaded kexts.
7234 // xxx - I really want to make kernel components not a special case!
7235 if (libraryKext
->declaresExecutable() ||
7236 libraryKext
->isInterface()) {
7238 if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) {
7239 dependencies
->setObject(libraryKext
);
7242 kOSKextLogDetailLevel
|
7243 kOSKextLogDependenciesFlag
,
7244 "Kext %s added dependency %s.",
7245 getIdentifierCString(),
7246 libraryKext
->getIdentifierCString());
7249 int numLibDependencies
= libraryKext
->getNumDependencies();
7250 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
7253 if (numLibDependencies
) {
7254 // xxx - this msg level should be 1 lower than the per-kext one
7256 kOSKextLogDetailLevel
|
7257 kOSKextLogDependenciesFlag
,
7258 "Kext %s pulling %d dependencies from codeless library %s.",
7259 getIdentifierCString(),
7261 libraryKext
->getIdentifierCString());
7263 for (index
= 0; index
< numLibDependencies
; index
++) {
7264 OSKext
* thisLibDependency
= OSDynamicCast(OSKext
,
7265 libraryDependencies
->getObject(index
));
7266 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) {
7267 dependencies
->setObject(thisLibDependency
);
7269 kOSKextLogDetailLevel
|
7270 kOSKextLogDependenciesFlag
,
7271 "Kext %s added dependency %s from codeless library %s.",
7272 getIdentifierCString(),
7273 thisLibDependency
->getIdentifierCString(),
7274 libraryKext
->getIdentifierCString());
7279 if ((strlen(library_id
) == strlen(KERNEL_LIB
)) &&
7280 0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) {
7282 hasRawKernelDependency
= true;
7283 } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) {
7284 hasKernelDependency
= true;
7285 } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) {
7286 hasKPIDependency
= true;
7287 if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) {
7288 hasPrivateKPIDependency
= true;
7293 if (hasRawKernelDependency
) {
7295 kOSKextLogErrorLevel
|
7296 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7297 "Error - kext %s declares a dependency on %s, which is not permitted.",
7298 getIdentifierCString(), KERNEL_LIB
);
7302 if (hasKernelDependency
) {
7304 kOSKextLogErrorLevel
|
7305 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7306 "Error - kext %s declares %s dependencies. "
7307 "Only %s* dependencies are supported for 64-bit kexts.",
7308 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7311 if (!hasKPIDependency
) {
7313 kOSKextLogWarningLevel
|
7314 kOSKextLogDependenciesFlag
,
7315 "Warning - kext %s declares no %s* dependencies. "
7316 "If it uses any KPIs, the link may fail with undefined symbols.",
7317 getIdentifierCString(), KPI_LIB_PREFIX
);
7319 #else /* __LP64__ */
7320 // xxx - will change to flatly disallow "kernel" dependencies at some point
7321 // xxx - is it invalid to do both "com.apple.kernel" and any
7322 // xxx - "com.apple.kernel.*"?
7324 if (hasKernelDependency
&& hasKPIDependency
) {
7326 kOSKextLogWarningLevel
|
7327 kOSKextLogDependenciesFlag
,
7328 "Warning - kext %s has immediate dependencies on both "
7329 "%s* and %s* components; use only one style.",
7330 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7333 if (!hasKernelDependency
&& !hasKPIDependency
) {
7334 // xxx - do we want to use validation flag for these too?
7336 kOSKextLogWarningLevel
|
7337 kOSKextLogDependenciesFlag
,
7338 "Warning - %s declares no kernel dependencies; using %s.",
7339 getIdentifierCString(), KERNEL6_LIB
);
7340 OSKext
* kernelKext
= OSDynamicCast(OSKext
,
7341 sKextsByID
->getObject(KERNEL6_LIB
));
7343 dependencies
->setObject(kernelKext
);
7346 kOSKextLogErrorLevel
|
7347 kOSKextLogDependenciesFlag
,
7348 "Error - Library %s not found for %s.",
7349 KERNEL6_LIB
, getIdentifierCString());
7353 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7354 * its indirect dependencies to simulate old-style linking. XXX - Should
7355 * check for duplicates.
7357 if (!hasKPIDependency
) {
7360 flags
.hasBleedthrough
= true;
7362 count
= getNumDependencies();
7364 /* We add to the dependencies array in this loop, but do not iterate
7365 * past its original count.
7367 for (i
= 0; i
< count
; i
++) {
7368 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
7369 dependencies
->getObject(i
));
7370 dependencyKext
->addBleedthroughDependencies(dependencies
);
7373 #endif /* __LP64__ */
7375 if (hasPrivateKPIDependency
) {
7376 bool hasApplePrefix
= false;
7377 bool infoCopyrightIsValid
= false;
7378 bool readableCopyrightIsValid
= false;
7380 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
7383 infoString
= OSDynamicCast(OSString
,
7384 getPropertyForHostArch("CFBundleGetInfoString"));
7386 infoCopyrightIsValid
=
7387 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
7390 readableString
= OSDynamicCast(OSString
,
7391 getPropertyForHostArch("NSHumanReadableCopyright"));
7392 if (readableString
) {
7393 readableCopyrightIsValid
=
7394 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
7397 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
7399 kOSKextLogErrorLevel
|
7400 kOSKextLogDependenciesFlag
,
7401 "Error - kext %s declares a dependency on %s. "
7402 "Only Apple kexts may declare a dependency on %s.",
7403 getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
);
7409 flags
.hasAllDependencies
= 1;
7413 if (addedToLoopStack
) {
7414 count
= loopStack
->getCount();
7415 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
7416 loopStack
->removeObject(count
- 1);
7419 kOSKextLogErrorLevel
|
7420 kOSKextLogDependenciesFlag
,
7421 "Kext %s - internal error resolving dependencies.",
7422 getIdentifierCString());
7426 if (result
&& localLoopStack
) {
7428 kOSKextLogStepLevel
|
7429 kOSKextLogDependenciesFlag
,
7430 "Kext %s successfully resolved dependencies.",
7431 getIdentifierCString());
7434 OSSafeReleaseNULL(localLoopStack
);
7435 OSSafeReleaseNULL(libraryIterator
);
7440 /*********************************************************************
7441 *********************************************************************/
7443 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
7445 bool result
= false;
7446 unsigned int dependencyIndex
, dependencyCount
;
7448 dependencyCount
= getNumDependencies();
7450 for (dependencyIndex
= 0;
7451 dependencyIndex
< dependencyCount
;
7452 dependencyIndex
++) {
7454 OSKext
* dependency
= OSDynamicCast(OSKext
,
7455 dependencies
->getObject(dependencyIndex
));
7458 kOSKextLogErrorLevel
|
7459 kOSKextLogDependenciesFlag
,
7460 "Kext %s - internal error propagating compatibility dependencies.",
7461 getIdentifierCString());
7464 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7465 anArray
->setObject(dependency
);
7467 dependency
->addBleedthroughDependencies(anArray
);
7476 /*********************************************************************
7477 *********************************************************************/
7479 OSKext::flushDependencies(bool forceFlag
)
7481 bool result
= false;
7483 /* Only clear the dependencies if the kext isn't loaded;
7484 * we need the info for loaded kexts to track references.
7486 if (!isLoaded() || forceFlag
) {
7488 // xxx - check level
7490 kOSKextLogProgressLevel
|
7491 kOSKextLogDependenciesFlag
,
7492 "Kext %s flushing dependencies.",
7493 getIdentifierCString());
7494 OSSafeReleaseNULL(dependencies
);
7497 if (!isKernelComponent()) {
7498 flags
.hasAllDependencies
= 0;
7506 /*********************************************************************
7507 *********************************************************************/
7509 OSKext::getNumDependencies(void)
7511 if (!dependencies
) {
7514 return dependencies
->getCount();
7517 /*********************************************************************
7518 *********************************************************************/
7520 OSKext::getDependencies(void)
7522 return dependencies
;
7526 #pragma mark OSMetaClass Support
7528 /*********************************************************************
7529 *********************************************************************/
7532 OSMetaClass
* aClass
,
7533 uint32_t numClasses
)
7535 OSReturn result
= kOSMetaClassNoInsKModSet
;
7538 metaClasses
= OSSet::withCapacity(numClasses
);
7544 if (metaClasses
->containsObject(aClass
)) {
7546 kOSKextLogWarningLevel
|
7548 "Notice - kext %s has already registered class %s.",
7549 getIdentifierCString(),
7550 aClass
->getClassName());
7551 result
= kOSReturnSuccess
;
7555 if (!metaClasses
->setObject(aClass
)) {
7559 kOSKextLogDetailLevel
|
7561 "Kext %s registered class %s.",
7562 getIdentifierCString(),
7563 aClass
->getClassName());
7566 if (!flags
.autounloadEnabled
) {
7567 const OSMetaClass
* metaScan
= NULL
; // do not release
7569 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7570 if (metaScan
== OSTypeID(IOService
)) {
7573 kOSKextLogProgressLevel
|
7575 "Kext %s has IOService subclass %s; enabling autounload.",
7576 getIdentifierCString(),
7577 aClass
->getClassName());
7579 flags
.autounloadEnabled
= 1;
7585 notifyAddClassObservers(this, aClass
, flags
);
7587 result
= kOSReturnSuccess
;
7590 if (result
!= kOSReturnSuccess
) {
7592 kOSKextLogErrorLevel
|
7594 "Kext %s failed to register class %s.",
7595 getIdentifierCString(),
7596 aClass
->getClassName());
7602 /*********************************************************************
7603 *********************************************************************/
7605 OSKext::removeClass(
7606 OSMetaClass
* aClass
)
7608 OSReturn result
= kOSMetaClassNoKModSet
;
7614 if (!metaClasses
->containsObject(aClass
)) {
7616 kOSKextLogWarningLevel
|
7618 "Notice - kext %s asked to unregister unknown class %s.",
7619 getIdentifierCString(),
7620 aClass
->getClassName());
7621 result
= kOSReturnSuccess
;
7626 kOSKextLogDetailLevel
|
7628 "Kext %s unregistering class %s.",
7629 getIdentifierCString(),
7630 aClass
->getClassName());
7632 metaClasses
->removeObject(aClass
);
7634 notifyRemoveClassObservers(this, aClass
, flags
);
7636 result
= kOSReturnSuccess
;
7639 if (result
!= kOSReturnSuccess
) {
7641 kOSKextLogErrorLevel
|
7643 "Failed to unregister kext %s class %s.",
7644 getIdentifierCString(),
7645 aClass
->getClassName());
7650 /*********************************************************************
7651 *********************************************************************/
7653 OSKext::getMetaClasses(void)
7658 /*********************************************************************
7659 *********************************************************************/
7661 OSKext::hasOSMetaClassInstances(void)
7663 bool result
= false;
7664 OSCollectionIterator
* classIterator
= NULL
; // must release
7665 OSMetaClass
* checkClass
= NULL
; // do not release
7671 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7672 if (!classIterator
) {
7673 // xxx - log alloc failure?
7676 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7677 if (checkClass
->getInstanceCount()) {
7685 OSSafeReleaseNULL(classIterator
);
7689 /*********************************************************************
7690 *********************************************************************/
7693 OSKext::reportOSMetaClassInstances(
7694 const char * kextIdentifier
,
7695 OSKextLogSpec msgLogSpec
)
7697 OSKext
* theKext
= NULL
; // must release
7699 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
7704 theKext
->reportOSMetaClassInstances(msgLogSpec
);
7706 OSSafeReleaseNULL(theKext
);
7710 /*********************************************************************
7711 *********************************************************************/
7713 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
7715 OSCollectionIterator
* classIterator
= NULL
; // must release
7716 OSMetaClass
* checkClass
= NULL
; // do not release
7722 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7723 if (!classIterator
) {
7726 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7727 if (checkClass
->getInstanceCount()) {
7730 " Kext %s class %s has %d instance%s.",
7731 getIdentifierCString(),
7732 checkClass
->getClassName(),
7733 checkClass
->getInstanceCount(),
7734 checkClass
->getInstanceCount() == 1 ? "" : "s");
7739 OSSafeReleaseNULL(classIterator
);
7744 #pragma mark User-Space Requests
7746 /*********************************************************************
7747 * XXX - this function is a big ugly mess
7748 *********************************************************************/
7751 OSKext::handleRequest(
7752 host_priv_t hostPriv
,
7753 OSKextLogSpec clientLogFilter
,
7754 char * requestBuffer
,
7755 uint32_t requestLength
,
7756 char ** responseOut
,
7757 uint32_t * responseLengthOut
,
7759 uint32_t * logInfoLengthOut
)
7761 OSReturn result
= kOSReturnError
;
7762 kern_return_t kmem_result
= KERN_FAILURE
;
7764 char * response
= NULL
; // returned by reference
7765 uint32_t responseLength
= 0;
7767 OSObject
* parsedXML
= NULL
; // must release
7768 OSDictionary
* requestDict
= NULL
; // do not release
7769 OSString
* errorString
= NULL
; // must release
7771 OSObject
* responseObject
= NULL
; // must release
7773 OSSerialize
* serializer
= NULL
; // must release
7775 OSArray
* logInfoArray
= NULL
; // must release
7777 OSString
* predicate
= NULL
; // do not release
7778 OSString
* kextIdentifier
= NULL
; // do not release
7779 OSArray
* kextIdentifiers
= NULL
; // do not release
7780 OSKext
* theKext
= NULL
; // do not release
7781 OSBoolean
* boolArg
= NULL
; // do not release
7783 IORecursiveLockLock(sKextLock
);
7786 *responseOut
= NULL
;
7787 *responseLengthOut
= 0;
7791 *logInfoLengthOut
= 0;
7794 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
7796 /* XML must be nul-terminated.
7798 if (requestBuffer
[requestLength
- 1] != '\0') {
7799 OSKextLog(/* kext */ NULL
,
7800 kOSKextLogErrorLevel
|
7802 "Invalid request from user space (not nul-terminated).");
7803 result
= kOSKextReturnBadData
;
7806 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
7808 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
7811 const char * errorCString
= "(unknown error)";
7813 if (errorString
&& errorString
->getCStringNoCopy()) {
7814 errorCString
= errorString
->getCStringNoCopy();
7815 } else if (parsedXML
) {
7816 errorCString
= "not a dictionary";
7818 OSKextLog(/* kext */ NULL
,
7819 kOSKextLogErrorLevel
|
7821 "Error unserializing request from user space: %s.",
7823 result
= kOSKextReturnSerialization
;
7827 predicate
= _OSKextGetRequestPredicate(requestDict
);
7829 OSKextLog(/* kext */ NULL
,
7830 kOSKextLogErrorLevel
|
7832 "Recieved kext request from user space with no predicate.");
7833 result
= kOSKextReturnInvalidArgument
;
7837 OSKextLog(/* kext */ NULL
,
7838 kOSKextLogDebugLevel
|
7840 "Received '%s' request from user space.",
7841 predicate
->getCStringNoCopy());
7843 result
= kOSKextReturnNotPrivileged
;
7844 if (hostPriv
== HOST_PRIV_NULL
) {
7845 /* must be root to use these kext requests */
7846 if (predicate
->isEqualTo(kKextRequestPredicateUnload
) ||
7847 predicate
->isEqualTo(kKextRequestPredicateStart
) ||
7848 predicate
->isEqualTo(kKextRequestPredicateStop
) ||
7849 predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
) ||
7850 predicate
->isEqualTo(kKextRequestPredicateSendResource
) ) {
7851 OSKextLog(/* kext */ NULL
,
7852 kOSKextLogErrorLevel
|
7854 "Access Failure - must be root user.");
7859 /* Get common args in anticipation of use.
7861 kextIdentifier
= OSDynamicCast(OSString
, _OSKextGetRequestArgument(
7862 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7863 kextIdentifiers
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument(
7864 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7865 if (kextIdentifier
) {
7866 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
7868 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
7869 requestDict
, kKextRequestArgumentValueKey
));
7871 result
= kOSKextReturnInvalidArgument
;
7873 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
7874 if (!kextIdentifier
) {
7875 OSKextLog(/* kext */ NULL
,
7876 kOSKextLogErrorLevel
|
7878 "Invalid arguments to kext start request.");
7879 } else if (!theKext
) {
7880 OSKextLog(/* kext */ NULL
,
7881 kOSKextLogErrorLevel
|
7883 "Kext %s not found for start request.",
7884 kextIdentifier
->getCStringNoCopy());
7885 result
= kOSKextReturnNotFound
;
7887 result
= theKext
->start();
7890 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
7891 if (!kextIdentifier
) {
7892 OSKextLog(/* kext */ NULL
,
7893 kOSKextLogErrorLevel
|
7895 "Invalid arguments to kext stop request.");
7896 } else if (!theKext
) {
7897 OSKextLog(/* kext */ NULL
,
7898 kOSKextLogErrorLevel
|
7900 "Kext %s not found for stop request.",
7901 kextIdentifier
->getCStringNoCopy());
7902 result
= kOSKextReturnNotFound
;
7904 result
= theKext
->stop();
7907 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
7908 if (!kextIdentifier
) {
7909 OSKextLog(/* kext */ NULL
,
7910 kOSKextLogErrorLevel
|
7912 "Invalid arguments to kext unload request.");
7913 } else if (!theKext
) {
7914 OSKextLog(/* kext */ NULL
,
7915 kOSKextLogErrorLevel
|
7917 "Kext %s not found for unload request.",
7918 kextIdentifier
->getCStringNoCopy());
7919 result
= kOSKextReturnNotFound
;
7921 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
7922 _OSKextGetRequestArgument(requestDict
,
7923 kKextRequestArgumentTerminateIOServicesKey
));
7924 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
7927 } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
7928 result
= OSKext::dispatchResource(requestDict
);
7930 } else if (predicate
->isEqualTo(kKextRequestPredicateGetUUIDByAddress
)) {
7932 OSNumber
*lookupNum
= NULL
;
7933 lookupNum
= OSDynamicCast(OSNumber
,
7934 _OSKextGetRequestArgument(requestDict
,
7935 kKextRequestArgumentLookupAddressKey
));
7937 responseObject
= OSKext::copyKextUUIDForAddress(lookupNum
);
7938 if (responseObject
) {
7939 result
= kOSReturnSuccess
;
7944 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
) ||
7945 predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
7946 OSBoolean
* delayAutounloadBool
= NULL
;
7947 OSObject
* infoKeysRaw
= NULL
;
7948 OSArray
* infoKeys
= NULL
;
7949 uint32_t infoKeysCount
= 0;
7951 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
7952 _OSKextGetRequestArgument(requestDict
,
7953 kKextRequestArgumentDelayAutounloadKey
));
7955 /* If asked to delay autounload, reset the timer if it's currently set.
7956 * (That is, don't schedule an unload if one isn't already pending.
7958 if (delayAutounloadBool
== kOSBooleanTrue
) {
7959 OSKext::considerUnloads(/* rescheduleOnly? */ true);
7962 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
7963 kKextRequestArgumentInfoKeysKey
);
7964 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
7965 if (infoKeysRaw
&& !infoKeys
) {
7966 OSKextLog(/* kext */ NULL
,
7967 kOSKextLogErrorLevel
|
7969 "Invalid arguments to kext info request.");
7974 infoKeysCount
= infoKeys
->getCount();
7975 for (uint32_t i
= 0; i
< infoKeysCount
; i
++) {
7976 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) {
7977 OSKextLog(/* kext */ NULL
,
7978 kOSKextLogErrorLevel
|
7980 "Invalid arguments to kext info request.");
7986 if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
7987 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
7989 else if (predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
7990 responseObject
= OSKext::copyLoadedKextInfoByUUID(kextIdentifiers
, infoKeys
);
7992 if (!responseObject
) {
7993 result
= kOSKextReturnInternalError
;
7995 OSKextLog(/* kext */ NULL
,
7996 kOSKextLogDebugLevel
|
7998 "Returning loaded kext info.");
7999 result
= kOSReturnSuccess
;
8001 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) {
8003 /* Hand the current sKernelRequests array to the caller
8004 * (who must release it), and make a new one.
8006 responseObject
= sKernelRequests
;
8007 sKernelRequests
= OSArray::withCapacity(0);
8008 sPostedKextLoadIdentifiers
->flushCollection();
8009 OSKextLog(/* kext */ NULL
,
8010 kOSKextLogDebugLevel
|
8012 "Returning kernel requests.");
8013 result
= kOSReturnSuccess
;
8015 } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) {
8017 /* Return the set of all requested bundle identifiers */
8018 responseObject
= sAllKextLoadIdentifiers
;
8019 responseObject
->retain();
8020 OSKextLog(/* kext */ NULL
,
8021 kOSKextLogDebugLevel
|
8023 "Returning load requests.");
8024 result
= kOSReturnSuccess
;
8027 OSKextLog(/* kext */ NULL
,
8028 kOSKextLogDebugLevel
|
8030 "Received '%s' invalid request from user space.",
8031 predicate
->getCStringNoCopy());
8036 * Now we have handle the request, or not. Gather up the response & logging
8037 * info to ship to user space.
8040 /* Note: Nothing in OSKext is supposed to retain requestDict,
8041 * but you never know....
8043 if (requestDict
->getRetainCount() > 1) {
8044 OSKextLog(/* kext */ NULL
,
8045 kOSKextLogWarningLevel
|
8047 "Request from user space still retained by a kext; "
8048 "probable memory leak.");
8051 if (responseOut
&& responseObject
) {
8052 serializer
= OSSerialize::withCapacity(0);
8054 result
= kOSKextReturnNoMemory
;
8058 if (!responseObject
->serialize(serializer
)) {
8059 OSKextLog(/* kext */ NULL
,
8060 kOSKextLogGeneralFlag
| kOSKextLogErrorLevel
,
8061 "Failed to serialize response to request from user space.");
8062 result
= kOSKextReturnSerialization
;
8066 response
= (char *)serializer
->text();
8067 responseLength
= serializer
->getLength();
8070 if (responseOut
&& response
) {
8073 /* This kmem_alloc sets the return value of the function.
8075 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
,
8076 round_page(responseLength
), VM_KERN_MEMORY_OSKEXT
);
8077 if (kmem_result
!= KERN_SUCCESS
) {
8078 OSKextLog(/* kext */ NULL
,
8079 kOSKextLogErrorLevel
|
8081 "Failed to copy response to request from user space.");
8082 result
= kmem_result
;
8085 /* 11981737 - clear uninitialized data in last page */
8086 bzero((void *)(buffer
+ responseLength
),
8087 (round_page(responseLength
) - responseLength
));
8088 memcpy(buffer
, response
, responseLength
);
8089 *responseOut
= buffer
;
8090 *responseLengthOut
= responseLength
;
8096 /* Gather up the collected log messages for user space. Any messages
8097 * messages past this call will not make it up as log messages but
8098 * will be in the system log. Note that we ignore the return of the
8099 * serialize; it has no bearing on the operation at hand even if we
8100 * fail to get the log messages.
8102 logInfoArray
= OSKext::clearUserSpaceLogFilter();
8104 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
8105 (void)OSKext::serializeLogInfo(logInfoArray
,
8106 logInfoOut
, logInfoLengthOut
);
8109 IORecursiveLockUnlock(sKextLock
);
8111 OSSafeReleaseNULL(parsedXML
);
8112 OSSafeReleaseNULL(errorString
);
8113 OSSafeReleaseNULL(responseObject
);
8114 OSSafeReleaseNULL(serializer
);
8115 OSSafeReleaseNULL(logInfoArray
);
8121 // #include <InstrProfiling.h>
8124 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin
,
8125 const char *DataEnd
,
8126 const char *CountersBegin
,
8127 const char *CountersEnd
,
8128 const char *NamesBegin
,
8129 const char *NamesEnd
);
8130 int __llvm_profile_write_buffer_internal(char *Buffer
,
8131 const char *DataBegin
,
8132 const char *DataEnd
,
8133 const char *CountersBegin
,
8134 const char *CountersEnd
,
8135 const char *NamesBegin
,
8136 const char *NamesEnd
);
8141 void OSKextPgoMetadataPut(char *pBuffer
,
8144 uint32_t *num_pairs
,
8148 size_t strlen_key
= strlen(key
);
8149 size_t strlen_value
= strlen(value
);
8150 size_t len
= strlen(key
) + 1 + strlen(value
) + 1;
8151 char *pos
= pBuffer
+ *position
;
8153 if (pBuffer
&& bufferSize
&& *position
<= bufferSize
) {
8154 memcpy(pos
, key
, strlen_key
); pos
+= strlen_key
;
8156 memcpy(pos
, value
, strlen_value
); pos
+= strlen_value
;
8166 void OSKextPgoMetadataPutMax(size_t *position
, const char *key
, size_t value_max
)
8168 *position
+= strlen(key
) + 1 + value_max
+ 1;
8173 void OSKextPgoMetadataPutAll(OSKext
*kext
,
8174 uuid_t instance_uuid
,
8178 uint32_t *num_pairs
)
8180 _static_assert_1_arg(sizeof(clock_sec_t
) % 2 == 0);
8181 //log_10 2^16 ≈ 4.82
8182 const size_t max_secs_string_size
= 5 * sizeof(clock_sec_t
)/2;
8183 const size_t max_timestamp_string_size
= max_secs_string_size
+ 1 + 6;
8186 OSKextPgoMetadataPutMax(position
, "INSTANCE", 36);
8187 OSKextPgoMetadataPutMax(position
, "UUID", 36);
8188 OSKextPgoMetadataPutMax(position
, "TIMESTAMP", max_timestamp_string_size
);
8190 uuid_string_t instance_uuid_string
;
8191 uuid_unparse(instance_uuid
, instance_uuid_string
);
8192 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8193 "INSTANCE", instance_uuid_string
);
8197 uuid_string_t uuid_string
;
8198 uuid_data
= kext
->copyUUID();
8200 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
8201 OSSafeReleaseNULL(uuid_data
);
8202 uuid_unparse(uuid
, uuid_string
);
8203 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8204 "UUID", uuid_string
);
8209 clock_get_calendar_microtime(&secs
, &usecs
);
8210 assert(usecs
< 1000000);
8211 char timestamp
[max_timestamp_string_size
+ 1];
8212 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t
));
8213 snprintf(timestamp
, sizeof(timestamp
), "%lu.%06d", (unsigned long)secs
, (int)usecs
);
8214 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8215 "TIMESTAMP", timestamp
);
8218 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8219 "NAME", kext
->getIdentifierCString());
8221 char versionCString
[kOSKextVersionMaxLength
];
8222 OSKextVersionGetString(kext
->getVersion(), versionCString
, kOSKextVersionMaxLength
);
8223 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8224 "VERSION", versionCString
);
8229 size_t OSKextPgoMetadataSize(OSKext
*kext
)
8231 size_t position
= 0;
8232 uuid_t fakeuuid
= {};
8233 OSKextPgoMetadataPutAll(kext
, fakeuuid
, NULL
, &position
, 0, NULL
);
8238 int OSKextGrabPgoDataLocked(OSKext
*kext
,
8240 uuid_t instance_uuid
,
8243 uint64_t bufferSize
)
8248 kernel_section_t
*sect_prf_data
= NULL
;
8249 kernel_section_t
*sect_prf_name
= NULL
;
8250 kernel_section_t
*sect_prf_cnts
= NULL
;
8252 size_t metadata_size
= 0;
8254 sect_prf_data
= kext
->lookupSection("__DATA", "__llvm_prf_data");
8255 sect_prf_name
= kext
->lookupSection("__DATA", "__llvm_prf_name");
8256 sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8258 if (!sect_prf_data
|| !sect_prf_name
|| !sect_prf_cnts
) {
8263 size
= __llvm_profile_get_size_for_buffer_internal(
8264 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8265 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8266 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8269 metadata_size
= OSKextPgoMetadataSize(kext
);
8270 size
+= metadata_size
;
8271 size
+= sizeof(pgo_metadata_footer
);
8279 if (pBuffer
&& bufferSize
) {
8280 if (bufferSize
< size
) {
8285 err
= __llvm_profile_write_buffer_internal(
8287 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8288 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8289 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8297 char *end_of_buffer
= pBuffer
+ size
;
8298 struct pgo_metadata_footer
*footerp
= (struct pgo_metadata_footer
*) (end_of_buffer
- sizeof(struct pgo_metadata_footer
));
8299 char *metadata_buffer
= end_of_buffer
- (sizeof(struct pgo_metadata_footer
) + metadata_size
);
8301 size_t metadata_position
= 0;
8302 uint32_t num_pairs
= 0;
8303 OSKextPgoMetadataPutAll(kext
, instance_uuid
, metadata_buffer
, &metadata_position
, metadata_size
, &num_pairs
);
8304 while (metadata_position
< metadata_size
) {
8305 metadata_buffer
[metadata_position
++] = 0;
8308 struct pgo_metadata_footer footer
;
8309 footer
.magic
= htonl(0x6d657461);
8310 footer
.number_of_pairs
= htonl( num_pairs
);
8311 footer
.offset_to_pairs
= htonl( sizeof(struct pgo_metadata_footer
) + metadata_size
);
8312 memcpy(footerp
, &footer
, sizeof(footer
));
8323 OSKextGrabPgoData(uuid_t uuid
,
8326 uint64_t bufferSize
,
8327 int wait_for_unload
,
8331 OSKext
*kext
= NULL
;
8334 IORecursiveLockLock(sKextLock
);
8336 kext
= OSKext::lookupKextWithUUID(uuid
);
8342 if (wait_for_unload
) {
8343 OSKextGrabPgoStruct s
;
8345 s
.metadata
= metadata
;
8347 s
.pBuffer
= pBuffer
;
8348 s
.bufferSize
= bufferSize
;
8351 struct list_head
*prev
= &kext
->pendingPgoHead
;
8352 struct list_head
*next
= kext
->pendingPgoHead
.next
;
8354 s
.list_head
.prev
= prev
;
8355 s
.list_head
.next
= next
;
8357 prev
->next
= &s
.list_head
;
8358 next
->prev
= &s
.list_head
;
8363 IORecursiveLockSleep(sKextLock
, &s
, THREAD_ABORTSAFE
);
8365 prev
= s
.list_head
.prev
;
8366 next
= s
.list_head
.next
;
8374 err
= OSKextGrabPgoDataLocked(kext
, metadata
, kext
->instance_uuid
, pSize
, pBuffer
, bufferSize
);
8382 IORecursiveLockUnlock(sKextLock
);
8388 OSKextResetPgoCountersLock()
8390 IORecursiveLockLock(sKextLock
);
8394 OSKextResetPgoCountersUnlock()
8396 IORecursiveLockUnlock(sKextLock
);
8400 extern unsigned int not_in_kdp
;
8403 OSKextResetPgoCounters()
8405 assert(!not_in_kdp
);
8406 uint32_t count
= sLoadedKexts
->getCount();
8407 for (uint32_t i
= 0; i
< count
; i
++) {
8408 OSKext
*kext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8409 kernel_section_t
*sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8410 if (!sect_prf_cnts
) {
8413 memset((void*)sect_prf_cnts
->addr
, 0, sect_prf_cnts
->size
);
8418 OSKext::copyLoadedKextInfoByUUID(
8419 OSArray
* kextIdentifiers
,
8422 OSDictionary
* result
= NULL
;
8423 OSDictionary
* kextInfo
= NULL
; // must release
8425 uint32_t idCount
= 0;
8426 uint32_t idIndex
= 0;
8428 IORecursiveLockLock(sKextLock
);
8431 /* Is the calling process allowed to query kext info? */
8432 if (current_task() != kernel_task
) {
8433 int macCheckResult
= 0;
8434 kauth_cred_t cred
= NULL
;
8436 cred
= kauth_cred_get_with_ref();
8437 macCheckResult
= mac_kext_check_query(cred
);
8438 kauth_cred_unref(&cred
);
8440 if (macCheckResult
!= 0) {
8441 OSKextLog(/* kext */ NULL
,
8442 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8443 "Failed to query kext info (MAC policy error 0x%x).",
8450 /* Empty list of UUIDs is equivalent to no list (get all).
8452 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8453 kextIdentifiers
= NULL
;
8454 } else if (kextIdentifiers
) {
8455 idCount
= kextIdentifiers
->getCount();
8460 if (infoKeys
&& !infoKeys
->getCount()) {
8464 count
= sLoadedKexts
->getCount();
8465 result
= OSDictionary::withCapacity(count
);
8470 for (i
= 0; i
< count
; i
++) {
8471 OSKext
*thisKext
= NULL
; // do not release
8472 Boolean includeThis
= true;
8473 uuid_t thisKextUUID
;
8475 uuid_string_t uuid_key
;
8478 kextInfo
->release();
8482 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8487 uuid_data
= thisKext
->copyUUID();
8492 memcpy(&thisKextUUID
, uuid_data
->getBytesNoCopy(), sizeof(thisKextUUID
));
8493 OSSafeReleaseNULL(uuid_data
);
8495 uuid_unparse(thisKextUUID
, uuid_key
);
8497 /* Skip current kext if we have a list of UUIDs and
8498 * it isn't in the list.
8500 if (kextIdentifiers
) {
8501 includeThis
= false;
8503 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8504 const OSString
* wantedUUID
= OSDynamicCast(OSString
,
8505 kextIdentifiers
->getObject(idIndex
));
8508 uuid_parse(wantedUUID
->getCStringNoCopy(), uuid
);
8510 if (0 == uuid_compare(uuid
, thisKextUUID
)) {
8522 kextInfo
= thisKext
->copyInfo(infoKeys
);
8524 result
->setObject(uuid_key
, kextInfo
);
8529 IORecursiveLockUnlock(sKextLock
);
8531 if (kextInfo
) kextInfo
->release();
8536 /*********************************************************************
8537 *********************************************************************/
8540 OSKext::copyLoadedKextInfo(
8541 OSArray
* kextIdentifiers
,
8544 OSDictionary
* result
= NULL
;
8545 OSDictionary
* kextInfo
= NULL
; // must release
8547 uint32_t idCount
= 0;
8548 uint32_t idIndex
= 0;
8550 IORecursiveLockLock(sKextLock
);
8553 /* Is the calling process allowed to query kext info? */
8554 if (current_task() != kernel_task
) {
8555 int macCheckResult
= 0;
8556 kauth_cred_t cred
= NULL
;
8558 cred
= kauth_cred_get_with_ref();
8559 macCheckResult
= mac_kext_check_query(cred
);
8560 kauth_cred_unref(&cred
);
8562 if (macCheckResult
!= 0) {
8563 OSKextLog(/* kext */ NULL
,
8564 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8565 "Failed to query kext info (MAC policy error 0x%x).",
8572 /* Empty list of bundle ids is equivalent to no list (get all).
8574 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8575 kextIdentifiers
= NULL
;
8576 } else if (kextIdentifiers
) {
8577 idCount
= kextIdentifiers
->getCount();
8582 if (infoKeys
&& !infoKeys
->getCount()) {
8586 count
= sLoadedKexts
->getCount();
8587 result
= OSDictionary::withCapacity(count
);
8593 OSKextLog(/* kext */ NULL
,
8594 kOSKextLogErrorLevel
|
8595 kOSKextLogGeneralFlag
,
8596 "kaslr: vm_kernel_slide 0x%lx \n",
8598 OSKextLog(/* kext */ NULL
,
8599 kOSKextLogErrorLevel
|
8600 kOSKextLogGeneralFlag
,
8601 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
8602 vm_kernel_stext
, vm_kernel_etext
);
8603 OSKextLog(/* kext */ NULL
,
8604 kOSKextLogErrorLevel
|
8605 kOSKextLogGeneralFlag
,
8606 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
8607 vm_kernel_base
, vm_kernel_top
);
8608 OSKextLog(/* kext */ NULL
,
8609 kOSKextLogErrorLevel
|
8610 kOSKextLogGeneralFlag
,
8611 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
8612 vm_kext_base
, vm_kext_top
);
8613 OSKextLog(/* kext */ NULL
,
8614 kOSKextLogErrorLevel
|
8615 kOSKextLogGeneralFlag
,
8616 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
8617 vm_prelink_stext
, vm_prelink_etext
);
8618 OSKextLog(/* kext */ NULL
,
8619 kOSKextLogErrorLevel
|
8620 kOSKextLogGeneralFlag
,
8621 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
8622 vm_prelink_sinfo
, vm_prelink_einfo
);
8623 OSKextLog(/* kext */ NULL
,
8624 kOSKextLogErrorLevel
|
8625 kOSKextLogGeneralFlag
,
8626 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
8627 vm_slinkedit
, vm_elinkedit
);
8630 for (i
= 0; i
< count
; i
++) {
8631 OSKext
* thisKext
= NULL
; // do not release
8632 Boolean includeThis
= true;
8635 kextInfo
->release();
8638 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8643 /* Skip current kext if we have a list of bundle IDs and
8644 * it isn't in the list.
8646 if (kextIdentifiers
) {
8647 const OSString
* thisKextID
= thisKext
->getIdentifier();
8649 includeThis
= false;
8651 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8652 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
8653 kextIdentifiers
->getObject(idIndex
));
8654 if (thisKextID
->isEqualTo(thisRequestID
)) {
8665 kextInfo
= thisKext
->copyInfo(infoKeys
);
8667 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
8672 IORecursiveLockUnlock(sKextLock
);
8674 if (kextInfo
) kextInfo
->release();
8679 /*********************************************************************
8680 * Any info that needs to do allocations must goto finish on alloc
8681 * failure. Info that is just a lookup should just not set the object
8682 * if the info does not exist.
8683 *********************************************************************/
8684 #define _OSKextLoadInfoDictCapacity (12)
8687 OSKext::copyInfo(OSArray
* infoKeys
)
8689 OSDictionary
* result
= NULL
;
8690 bool success
= false;
8691 OSData
* headerData
= NULL
; // must release
8692 OSData
* logData
= NULL
; // must release
8693 OSNumber
* cpuTypeNumber
= NULL
; // must release
8694 OSNumber
* cpuSubtypeNumber
= NULL
; // must release
8695 OSString
* versionString
= NULL
; // do not release
8696 uint32_t executablePathCStringSize
= 0;
8697 char * executablePathCString
= NULL
; // must release
8698 OSString
* executablePathString
= NULL
; // must release
8699 OSData
* uuid
= NULL
; // must release
8700 OSNumber
* scratchNumber
= NULL
; // must release
8701 OSArray
* dependencyLoadTags
= NULL
; // must release
8702 OSCollectionIterator
* metaClassIterator
= NULL
; // must release
8703 OSArray
* metaClassInfo
= NULL
; // must release
8704 OSDictionary
* metaClassDict
= NULL
; // must release
8705 OSMetaClass
* thisMetaClass
= NULL
; // do not release
8706 OSString
* metaClassName
= NULL
; // must release
8707 OSString
* superclassName
= NULL
; // must release
8710 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
8716 /* Empty keys means no keys, but NULL is quicker to check.
8718 if (infoKeys
&& !infoKeys
->getCount()) {
8722 /* Headers, CPU type, and CPU subtype.
8725 _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) ||
8726 _OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
) ||
8727 _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) ||
8728 _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
))
8731 if (linkedExecutable
&& !isInterface()) {
8733 kernel_mach_header_t
*kext_mach_hdr
= (kernel_mach_header_t
*)
8734 linkedExecutable
->getBytesNoCopy();
8737 // do not return macho header info on shipping iOS - 19095897
8738 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) {
8739 kernel_mach_header_t
* temp_kext_mach_hdr
;
8740 struct load_command
* lcp
;
8742 headerData
= OSData::withBytes(kext_mach_hdr
,
8743 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
8748 // unslide any vmaddrs we return to userspace - 10726716
8749 temp_kext_mach_hdr
= (kernel_mach_header_t
*)
8750 headerData
->getBytesNoCopy();
8751 if (temp_kext_mach_hdr
== NULL
) {
8755 lcp
= (struct load_command
*) (temp_kext_mach_hdr
+ 1);
8756 for (i
= 0; i
< temp_kext_mach_hdr
->ncmds
; i
++) {
8757 if (lcp
->cmd
== LC_SEGMENT_KERNEL
) {
8758 kernel_segment_command_t
* segp
;
8759 kernel_section_t
* secp
;
8761 segp
= (kernel_segment_command_t
*) lcp
;
8762 // 10543468 - if we jettisoned __LINKEDIT clear size info
8763 if (flags
.jettisonLinkeditSeg
) {
8764 if (strncmp(segp
->segname
, SEG_LINKEDIT
, sizeof(segp
->segname
)) == 0) {
8771 OSKextLog(/* kext */ NULL
,
8772 kOSKextLogErrorLevel
|
8773 kOSKextLogGeneralFlag
,
8774 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
8775 __FUNCTION__
, segp
->segname
, segp
->vmaddr
,
8776 VM_KERNEL_UNSLIDE(segp
->vmaddr
),
8777 segp
->vmsize
, segp
->nsects
);
8778 if ( (VM_KERNEL_IS_SLID(segp
->vmaddr
) == false) &&
8779 (VM_KERNEL_IS_KEXT(segp
->vmaddr
) == false) &&
8780 (VM_KERNEL_IS_PRELINKTEXT(segp
->vmaddr
) == false) &&
8781 (VM_KERNEL_IS_PRELINKINFO(segp
->vmaddr
) == false) &&
8782 (VM_KERNEL_IS_KEXT_LINKEDIT(segp
->vmaddr
) == false) ) {
8783 OSKextLog(/* kext */ NULL
,
8784 kOSKextLogErrorLevel
|
8785 kOSKextLogGeneralFlag
,
8786 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
8787 __FUNCTION__
, segp
->vmaddr
, vm_kext_base
, vm_kext_top
);
8790 segp
->vmaddr
= VM_KERNEL_UNSLIDE(segp
->vmaddr
);
8792 for (secp
= firstsect(segp
); secp
!= NULL
; secp
= nextsect(segp
, secp
)) {
8793 secp
->addr
= VM_KERNEL_UNSLIDE(secp
->addr
);
8796 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
8798 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
8800 #endif // SECURE_KERNEL
8802 if (_OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
)) {
8803 osLogDataHeaderRef
*header
;
8804 char headerBytes
[offsetof(osLogDataHeaderRef
, sections
) + NUM_OS_LOG_SECTIONS
* sizeof(header
->sections
[0])];
8806 void *os_log_data
= NULL
;
8807 void *cstring_data
= NULL
;
8808 unsigned long os_log_size
= 0;
8809 unsigned long cstring_size
= 0;
8810 uint32_t os_log_offset
= 0;
8811 uint32_t cstring_offset
= 0;
8814 os_log_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__os_log", &os_log_size
);
8815 os_log_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__os_log");
8816 cstring_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__cstring", &cstring_size
);
8817 cstring_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__cstring");
8819 header
= (osLogDataHeaderRef
*) headerBytes
;
8820 header
->version
= OS_LOG_HDR_VERSION
;
8821 header
->sect_count
= NUM_OS_LOG_SECTIONS
;
8822 header
->sections
[OS_LOG_SECT_IDX
].sect_offset
= os_log_offset
;
8823 header
->sections
[OS_LOG_SECT_IDX
].sect_size
= (uint32_t) os_log_size
;
8824 header
->sections
[CSTRING_SECT_IDX
].sect_offset
= cstring_offset
;
8825 header
->sections
[CSTRING_SECT_IDX
].sect_size
= (uint32_t) cstring_size
;
8828 logData
= OSData::withBytes(header
, (u_int
) (sizeof(osLogDataHeaderRef
)));
8832 res
= logData
->appendBytes(&(header
->sections
[0]), (u_int
)(header
->sect_count
* sizeof(header
->sections
[0])));
8837 res
= logData
->appendBytes(os_log_data
, (u_int
)header
->sections
[OS_LOG_SECT_IDX
].sect_size
);
8843 res
= logData
->appendBytes(cstring_data
, (u_int
)header
->sections
[CSTRING_SECT_IDX
].sect_size
);
8848 result
->setObject(kOSBundleLogStringsKey
, logData
);
8851 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) {
8852 cpuTypeNumber
= OSNumber::withNumber(
8853 (uint64_t) kext_mach_hdr
->cputype
,
8854 8 * sizeof(kext_mach_hdr
->cputype
));
8855 if (!cpuTypeNumber
) {
8858 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
8861 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
8862 cpuSubtypeNumber
= OSNumber::withNumber(
8863 (uint64_t) kext_mach_hdr
->cpusubtype
,
8864 8 * sizeof(kext_mach_hdr
->cpusubtype
));
8865 if (!cpuSubtypeNumber
) {
8868 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
8873 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
8875 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
8879 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
8880 versionString
= OSDynamicCast(OSString
,
8881 getPropertyForHostArch(kCFBundleVersionKey
));
8882 if (versionString
) {
8883 result
->setObject(kCFBundleVersionKey
, versionString
);
8887 /* OSBundleCompatibleVersion.
8889 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
8890 versionString
= OSDynamicCast(OSString
,
8891 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
8892 if (versionString
) {
8893 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
8899 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
8901 result
->setObject(kOSBundlePathKey
, path
);
8906 /* OSBundleExecutablePath.
8908 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
8909 if (path
&& executableRelPath
) {
8911 uint32_t pathLength
= path
->getLength(); // gets incremented below
8913 // +1 for slash, +1 for \0
8914 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
8916 executablePathCString
= (char *)kalloc_tag((executablePathCStringSize
) *
8917 sizeof(char), VM_KERN_MEMORY_OSKEXT
); // +1 for \0
8918 if (!executablePathCString
) {
8921 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
8922 executablePathCStringSize
);
8923 executablePathCString
[pathLength
++] = '/';
8924 executablePathCString
[pathLength
++] = '\0';
8925 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
8926 executablePathCStringSize
);
8928 executablePathString
= OSString::withCString(executablePathCString
);
8930 if (!executablePathString
) {
8934 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
8938 /* UUID, if the kext has one.
8940 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
8943 result
->setObject(kOSBundleUUIDKey
, uuid
);
8948 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
8950 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSKernelResourceKey
)) {
8951 result
->setObject(kOSKernelResourceKey
,
8952 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
8955 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
8956 result
->setObject(kOSBundleIsInterfaceKey
,
8957 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
8960 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
8961 result
->setObject(kOSBundlePrelinkedKey
,
8962 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
8965 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
8966 result
->setObject(kOSBundleStartedKey
,
8967 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
8972 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
8973 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
8974 /* numBits */ 8 * sizeof(loadTag
));
8975 if (!scratchNumber
) {
8978 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
8979 OSSafeReleaseNULL(scratchNumber
);
8982 /* LoadAddress, LoadSize.
8985 _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) ||
8986 _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) ||
8987 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
) ||
8988 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
) ||
8989 _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
))
8991 if (isInterface() || linkedExecutable
) {
8992 /* These go to userspace via serialization, so we don't want any doubts
8995 uint64_t loadAddress
= 0;
8996 uint32_t loadSize
= 0;
8997 uint32_t wiredSize
= 0;
8998 uint64_t execLoadAddress
= 0;
8999 uint32_t execLoadSize
= 0;
9001 /* Interfaces always report 0 load address & size.
9002 * Just the way they roll.
9004 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
9005 * xxx - shouldn't have one!
9007 if (linkedExecutable
/* && !isInterface() */) {
9008 kernel_mach_header_t
*mh
= NULL
;
9009 kernel_segment_command_t
*seg
= NULL
;
9011 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
9012 mh
= (kernel_mach_header_t
*)loadAddress
;
9013 loadAddress
= VM_KERNEL_UNSLIDE(loadAddress
);
9014 loadSize
= linkedExecutable
->getLength();
9016 /* Walk through the kext, looking for the first executable
9017 * segment in case we were asked for its size/address.
9019 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
9020 if (seg
->initprot
& VM_PROT_EXECUTE
) {
9021 execLoadAddress
= VM_KERNEL_UNSLIDE(seg
->vmaddr
);
9022 execLoadSize
= seg
->vmsize
;
9027 /* If we have a kmod_info struct, calculated the wired size
9028 * from that. Otherwise it's the full load size.
9031 wiredSize
= loadSize
- kmod_info
->hdr_size
;
9033 wiredSize
= loadSize
;
9037 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
9038 scratchNumber
= OSNumber::withNumber(
9039 (unsigned long long)(loadAddress
),
9040 /* numBits */ 8 * sizeof(loadAddress
));
9041 if (!scratchNumber
) {
9044 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
9045 OSSafeReleaseNULL(scratchNumber
);
9047 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
)) {
9048 scratchNumber
= OSNumber::withNumber(
9049 (unsigned long long)(execLoadAddress
),
9050 /* numBits */ 8 * sizeof(execLoadAddress
));
9051 if (!scratchNumber
) {
9054 result
->setObject(kOSBundleExecLoadAddressKey
, scratchNumber
);
9055 OSSafeReleaseNULL(scratchNumber
);
9057 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
9058 scratchNumber
= OSNumber::withNumber(
9059 (unsigned long long)(loadSize
),
9060 /* numBits */ 8 * sizeof(loadSize
));
9061 if (!scratchNumber
) {
9064 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
9065 OSSafeReleaseNULL(scratchNumber
);
9067 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
)) {
9068 scratchNumber
= OSNumber::withNumber(
9069 (unsigned long long)(execLoadSize
),
9070 /* numBits */ 8 * sizeof(execLoadSize
));
9071 if (!scratchNumber
) {
9074 result
->setObject(kOSBundleExecLoadSizeKey
, scratchNumber
);
9075 OSSafeReleaseNULL(scratchNumber
);
9077 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
9078 scratchNumber
= OSNumber::withNumber(
9079 (unsigned long long)(wiredSize
),
9080 /* numBits */ 8 * sizeof(wiredSize
));
9081 if (!scratchNumber
) {
9084 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
9085 OSSafeReleaseNULL(scratchNumber
);
9090 /* OSBundleDependencies. In descending order for
9091 * easy compatibility with kextstat(8).
9093 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
9094 if ((count
= getNumDependencies())) {
9095 dependencyLoadTags
= OSArray::withCapacity(count
);
9096 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
9100 OSKext
* dependency
= OSDynamicCast(OSKext
,
9101 dependencies
->getObject(i
));
9103 OSSafeReleaseNULL(scratchNumber
);
9108 scratchNumber
= OSNumber::withNumber(
9109 (unsigned long long)dependency
->getLoadTag(),
9110 /* numBits*/ 8 * sizeof(loadTag
));
9111 if (!scratchNumber
) {
9114 dependencyLoadTags
->setObject(scratchNumber
);
9119 OSSafeReleaseNULL(scratchNumber
);
9121 /* OSBundleMetaClasses.
9123 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) {
9124 if (metaClasses
&& metaClasses
->getCount()) {
9125 metaClassIterator
= OSCollectionIterator::withCollection(metaClasses
);
9126 metaClassInfo
= OSArray::withCapacity(metaClasses
->getCount());
9127 if (!metaClassIterator
|| !metaClassInfo
) {
9130 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
9132 while ( (thisMetaClass
= OSDynamicCast(OSMetaClass
,
9133 metaClassIterator
->getNextObject())) ) {
9135 OSSafeReleaseNULL(metaClassDict
);
9136 OSSafeReleaseNULL(scratchNumber
);
9137 OSSafeReleaseNULL(metaClassName
);
9138 OSSafeReleaseNULL(superclassName
);
9140 metaClassDict
= OSDictionary::withCapacity(3);
9141 if (!metaClassDict
) {
9145 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
9146 if (thisMetaClass
->getSuperClass()) {
9147 superclassName
= OSString::withCString(
9148 thisMetaClass
->getSuperClass()->getClassName());
9150 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
9151 8 * sizeof(unsigned int));
9153 /* Bail if any of the essentials is missing. The root class lacks a superclass,
9156 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
9160 metaClassInfo
->setObject(metaClassDict
);
9161 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
9162 if (superclassName
) {
9163 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
9165 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
9170 /* OSBundleRetainCount.
9172 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
9173 OSSafeReleaseNULL(scratchNumber
);
9175 int kextRetainCount
= getRetainCount() - 1;
9179 scratchNumber
= OSNumber::withNumber(
9180 (int)kextRetainCount
,
9181 /* numBits*/ 8 * sizeof(int));
9182 if (scratchNumber
) {
9183 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
9191 OSSafeReleaseNULL(headerData
);
9192 OSSafeReleaseNULL(logData
);
9193 OSSafeReleaseNULL(cpuTypeNumber
);
9194 OSSafeReleaseNULL(cpuSubtypeNumber
);
9195 OSSafeReleaseNULL(executablePathString
);
9196 if (executablePathCString
) kfree(executablePathCString
, executablePathCStringSize
);
9197 OSSafeReleaseNULL(uuid
);
9198 OSSafeReleaseNULL(scratchNumber
);
9199 OSSafeReleaseNULL(dependencyLoadTags
);
9200 OSSafeReleaseNULL(metaClassIterator
);
9201 OSSafeReleaseNULL(metaClassInfo
);
9202 OSSafeReleaseNULL(metaClassDict
);
9203 OSSafeReleaseNULL(metaClassName
);
9204 OSSafeReleaseNULL(superclassName
);
9206 OSSafeReleaseNULL(result
);
9211 /*********************************************************************
9212 *********************************************************************/
9215 OSKext::requestResource(
9216 const char * kextIdentifierCString
,
9217 const char * resourceNameCString
,
9218 OSKextRequestResourceCallback callback
,
9220 OSKextRequestTag
* requestTagOut
)
9222 OSReturn result
= kOSReturnError
;
9223 OSKext
* callbackKext
= NULL
; // must release (looked up)
9225 OSKextRequestTag requestTag
= -1;
9226 OSNumber
* requestTagNum
= NULL
; // must release
9228 OSDictionary
* requestDict
= NULL
; // must release
9229 OSString
* kextIdentifier
= NULL
; // must release
9230 OSString
* resourceName
= NULL
; // must release
9232 OSDictionary
* callbackRecord
= NULL
; // must release
9233 OSData
* callbackWrapper
= NULL
; // must release
9235 OSData
* contextWrapper
= NULL
; // must release
9237 IORecursiveLockLock(sKextLock
);
9239 if (requestTagOut
) {
9240 *requestTagOut
= kOSKextRequestTagInvalid
;
9243 /* If requests to user space are disabled, don't go any further */
9244 if (!sKernelRequestsEnabled
) {
9245 OSKextLog(/* kext */ NULL
,
9246 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9247 "Can't request resource %s for %s - requests to user space are disabled.",
9248 resourceNameCString
,
9249 kextIdentifierCString
);
9250 result
= kOSKextReturnDisabled
;
9254 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
9255 result
= kOSKextReturnInvalidArgument
;
9259 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9260 if (!callbackKext
) {
9261 OSKextLog(/* kext */ NULL
,
9262 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9263 "Resource request has bad callback address.");
9264 result
= kOSKextReturnInvalidArgument
;
9267 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9268 OSKextLog(/* kext */ NULL
,
9269 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9270 "Resource request callback is in a kext that is not started.");
9271 result
= kOSKextReturnInvalidArgument
;
9275 /* Do not allow any new requests to be made on a kext that is unloading.
9277 if (callbackKext
->flags
.stopping
) {
9278 result
= kOSKextReturnStopping
;
9282 /* If we're wrapped the next available request tag around to the negative
9283 * numbers, we can't service any more requests.
9285 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
9286 OSKextLog(/* kext */ NULL
,
9287 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9288 "No more request tags available; restart required.");
9289 result
= kOSKextReturnNoResources
;
9292 requestTag
= sNextRequestTag
++;
9294 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
9296 if (result
!= kOSReturnSuccess
) {
9300 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
9301 resourceName
= OSString::withCString(resourceNameCString
);
9302 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9303 8 * sizeof(requestTag
));
9304 if (!kextIdentifier
||
9307 !_OSKextSetRequestArgument(requestDict
,
9308 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
9309 !_OSKextSetRequestArgument(requestDict
,
9310 kKextRequestArgumentNameKey
, resourceName
) ||
9311 !_OSKextSetRequestArgument(requestDict
,
9312 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
9314 result
= kOSKextReturnNoMemory
;
9318 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
9319 if (!callbackRecord
) {
9320 result
= kOSKextReturnNoMemory
;
9323 // we validate callback address at call time
9324 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
9326 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
9328 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9329 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
9331 result
= kOSKextReturnNoMemory
;
9336 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9337 kKextRequestArgumentContextKey
, contextWrapper
)) {
9339 result
= kOSKextReturnNoMemory
;
9344 /* Only post the requests after all the other potential failure points
9347 if (!sKernelRequests
->setObject(requestDict
) ||
9348 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
9350 result
= kOSKextReturnNoMemory
;
9354 OSKext::pingKextd();
9356 result
= kOSReturnSuccess
;
9357 if (requestTagOut
) {
9358 *requestTagOut
= requestTag
;
9363 /* If we didn't succeed, yank the request & callback
9364 * from their holding arrays.
9366 if (result
!= kOSReturnSuccess
) {
9369 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
9370 if (index
!= (unsigned int)-1) {
9371 sKernelRequests
->removeObject(index
);
9373 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
9374 if (index
!= (unsigned int)-1) {
9375 sRequestCallbackRecords
->removeObject(index
);
9379 OSKext::considerUnloads(/* rescheduleOnly? */ true);
9381 IORecursiveLockUnlock(sKextLock
);
9383 if (callbackKext
) callbackKext
->release();
9384 if (requestTagNum
) requestTagNum
->release();
9386 if (requestDict
) requestDict
->release();
9387 if (kextIdentifier
) kextIdentifier
->release();
9388 if (resourceName
) resourceName
->release();
9390 if (callbackRecord
) callbackRecord
->release();
9391 if (callbackWrapper
) callbackWrapper
->release();
9392 if (contextWrapper
) contextWrapper
->release();
9397 /*********************************************************************
9398 * Assumes sKextLock is held.
9399 *********************************************************************/
9402 OSKext::dequeueCallbackForRequestTag(
9403 OSKextRequestTag requestTag
,
9404 OSDictionary
** callbackRecordOut
)
9406 OSReturn result
= kOSReturnError
;
9407 OSNumber
* requestTagNum
= NULL
; // must release
9409 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9410 8 * sizeof(requestTag
));
9411 if (!requestTagNum
) {
9415 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
9419 OSSafeReleaseNULL(requestTagNum
);
9424 /*********************************************************************
9425 * Assumes sKextLock is held.
9426 *********************************************************************/
9429 OSKext::dequeueCallbackForRequestTag(
9430 OSNumber
* requestTagNum
,
9431 OSDictionary
** callbackRecordOut
)
9433 OSReturn result
= kOSKextReturnInvalidArgument
;
9434 OSDictionary
* callbackRecord
= NULL
; // retain if matched!
9435 OSNumber
* callbackTagNum
= NULL
; // do not release
9436 unsigned int count
, i
;
9438 result
= kOSReturnError
;
9439 count
= sRequestCallbackRecords
->getCount();
9440 for (i
= 0; i
< count
; i
++) {
9441 callbackRecord
= OSDynamicCast(OSDictionary
,
9442 sRequestCallbackRecords
->getObject(i
));
9443 if (!callbackRecord
) {
9447 /* If we don't find a tag, we basically have a leak here. Maybe
9448 * we should just remove it.
9450 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
9451 callbackRecord
, kKextRequestArgumentRequestTagKey
));
9452 if (!callbackTagNum
) {
9456 /* We could be even more paranoid and check that all the incoming
9457 * args match what's in the callback record.
9459 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
9460 if (callbackRecordOut
) {
9461 *callbackRecordOut
= callbackRecord
;
9462 callbackRecord
->retain();
9464 sRequestCallbackRecords
->removeObject(i
);
9465 result
= kOSReturnSuccess
;
9469 result
= kOSKextReturnNotFound
;
9475 /*********************************************************************
9476 * Assumes sKextLock is held.
9477 *********************************************************************/
9480 OSKext::dispatchResource(OSDictionary
* requestDict
)
9482 OSReturn result
= kOSReturnError
;
9483 OSDictionary
* callbackRecord
= NULL
; // must release
9484 OSNumber
* requestTag
= NULL
; // do not release
9485 OSNumber
* requestResult
= NULL
; // do not release
9486 OSData
* dataObj
= NULL
; // do not release
9487 uint32_t dataLength
= 0;
9488 const void * dataPtr
= NULL
; // do not free
9489 OSData
* callbackWrapper
= NULL
; // do not release
9490 OSKextRequestResourceCallback callback
= NULL
;
9491 OSData
* contextWrapper
= NULL
; // do not release
9492 void * context
= NULL
; // do not free
9493 OSKext
* callbackKext
= NULL
; // must release (looked up)
9495 /* Get the args from the request. Right now we need the tag
9496 * to look up the callback record, and the result for invoking the callback.
9498 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9499 kKextRequestArgumentRequestTagKey
));
9500 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9501 kKextRequestArgumentResultKey
));
9502 if (!requestTag
|| !requestResult
) {
9503 result
= kOSKextReturnInvalidArgument
;
9507 /* Look for a callback record matching this request's tag.
9509 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
9510 if (result
!= kOSReturnSuccess
) {
9515 * Get the context pointer of the callback record (if there is one).
9517 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
9518 kKextRequestArgumentContextKey
));
9519 context
= _OSKextExtractPointer(contextWrapper
);
9520 if (contextWrapper
&& !context
) {
9524 callbackWrapper
= OSDynamicCast(OSData
,
9525 _OSKextGetRequestArgument(callbackRecord
,
9526 kKextRequestArgumentCallbackKey
));
9527 callback
= (OSKextRequestResourceCallback
)
9528 _OSKextExtractPointer(callbackWrapper
);
9533 /* Check for a data obj. We might not have one and that's ok, that means
9534 * we didn't find the requested resource, and we still have to tell the
9535 * caller that via the callback.
9537 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
9538 kKextRequestArgumentValueKey
));
9540 dataPtr
= dataObj
->getBytesNoCopy();
9541 dataLength
= dataObj
->getLength();
9544 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9545 if (!callbackKext
) {
9546 OSKextLog(/* kext */ NULL
,
9547 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9548 "Can't invoke callback for resource request; ");
9551 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9552 OSKextLog(/* kext */ NULL
,
9553 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9554 "Can't invoke kext resource callback; ");
9558 (void)callback(requestTag
->unsigned32BitValue(),
9559 (OSReturn
)requestResult
->unsigned32BitValue(),
9560 dataPtr
, dataLength
, context
);
9562 result
= kOSReturnSuccess
;
9565 if (callbackKext
) callbackKext
->release();
9566 if (callbackRecord
) callbackRecord
->release();
9571 /*********************************************************************
9572 *********************************************************************/
9575 OSKext::invokeRequestCallback(
9576 OSDictionary
* callbackRecord
,
9577 OSReturn callbackResult
)
9579 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
9580 OSNumber
* resultNum
= NULL
; // must release
9586 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
9587 8 * sizeof(callbackResult
));
9592 /* Insert the result into the callback record and dispatch it as if it
9593 * were the reply coming down from user space.
9595 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
9598 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
9599 /* This removes the pending callback record.
9601 OSKext::dispatchResource(callbackRecord
);
9605 if (resultNum
) resultNum
->release();
9609 /*********************************************************************
9610 * Assumes sKextLock is held.
9611 *********************************************************************/
9614 OSKext::cancelRequest(
9615 OSKextRequestTag requestTag
,
9618 OSReturn result
= kOSKextReturnNoMemory
;
9619 OSDictionary
* callbackRecord
= NULL
; // must release
9620 OSData
* contextWrapper
= NULL
; // do not release
9622 IORecursiveLockLock(sKextLock
);
9623 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
9625 IORecursiveLockUnlock(sKextLock
);
9627 if (result
== kOSReturnSuccess
&& contextOut
) {
9628 contextWrapper
= OSDynamicCast(OSData
,
9629 _OSKextGetRequestArgument(callbackRecord
,
9630 kKextRequestArgumentContextKey
));
9631 *contextOut
= _OSKextExtractPointer(contextWrapper
);
9634 if (callbackRecord
) callbackRecord
->release();
9639 /*********************************************************************
9640 * Assumes sKextLock is held.
9641 *********************************************************************/
9643 OSKext::invokeOrCancelRequestCallbacks(
9644 OSReturn callbackResult
,
9647 unsigned int count
, i
;
9649 count
= sRequestCallbackRecords
->getCount();
9656 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9657 sRequestCallbackRecords
->getObject(i
));
9662 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9663 _OSKextGetRequestArgument(request
,
9664 kKextRequestArgumentCallbackKey
));
9666 if (!callbackWrapper
) {
9667 sRequestCallbackRecords
->removeObject(i
);
9671 vm_address_t callbackAddress
= (vm_address_t
)
9672 _OSKextExtractPointer(callbackWrapper
);
9674 if ((kmod_info
->address
<= callbackAddress
) &&
9675 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9678 /* This removes the callback record.
9680 invokeRequestCallback(request
, callbackResult
);
9682 sRequestCallbackRecords
->removeObject(i
);
9691 /*********************************************************************
9692 * Assumes sKextLock is held.
9693 *********************************************************************/
9695 OSKext::countRequestCallbacks(void)
9697 uint32_t result
= 0;
9698 unsigned int count
, i
;
9700 count
= sRequestCallbackRecords
->getCount();
9707 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9708 sRequestCallbackRecords
->getObject(i
));
9713 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9714 _OSKextGetRequestArgument(request
,
9715 kKextRequestArgumentCallbackKey
));
9717 if (!callbackWrapper
) {
9721 vm_address_t callbackAddress
= (vm_address_t
)
9722 _OSKextExtractPointer(callbackWrapper
);
9724 if ((kmod_info
->address
<= callbackAddress
) &&
9725 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9735 /*********************************************************************
9736 *********************************************************************/
9737 static OSReturn
_OSKextCreateRequest(
9738 const char * predicate
,
9739 OSDictionary
** requestP
)
9741 OSReturn result
= kOSKextReturnNoMemory
;
9742 OSDictionary
* request
= NULL
; // must release on error
9744 request
= OSDictionary::withCapacity(2);
9748 result
= _OSDictionarySetCStringValue(request
,
9749 kKextRequestPredicateKey
, predicate
);
9750 if (result
!= kOSReturnSuccess
) {
9753 result
= kOSReturnSuccess
;
9756 if (result
!= kOSReturnSuccess
) {
9757 if (request
) request
->release();
9759 *requestP
= request
;
9765 /*********************************************************************
9766 *********************************************************************/
9767 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
9769 return OSDynamicCast(OSString
,
9770 requestDict
->getObject(kKextRequestPredicateKey
));
9773 /*********************************************************************
9774 *********************************************************************/
9775 static OSObject
* _OSKextGetRequestArgument(
9776 OSDictionary
* requestDict
,
9777 const char * argName
)
9779 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9780 requestDict
->getObject(kKextRequestArgumentsKey
));
9782 return args
->getObject(argName
);
9787 /*********************************************************************
9788 *********************************************************************/
9789 static bool _OSKextSetRequestArgument(
9790 OSDictionary
* requestDict
,
9791 const char * argName
,
9794 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9795 requestDict
->getObject(kKextRequestArgumentsKey
));
9797 args
= OSDictionary::withCapacity(2);
9801 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
9805 return args
->setObject(argName
, value
);
9811 /*********************************************************************
9812 *********************************************************************/
9813 static void * _OSKextExtractPointer(OSData
* wrapper
)
9815 void * result
= NULL
;
9816 const void * resultPtr
= NULL
;
9821 resultPtr
= wrapper
->getBytesNoCopy();
9822 result
= *(void **)resultPtr
;
9827 /*********************************************************************
9828 *********************************************************************/
9829 static OSReturn
_OSDictionarySetCStringValue(
9830 OSDictionary
* dict
,
9832 const char * cValue
)
9834 OSReturn result
= kOSKextReturnNoMemory
;
9835 const OSSymbol
* key
= NULL
; // must release
9836 OSString
* value
= NULL
; // must release
9838 key
= OSSymbol::withCString(cKey
);
9839 value
= OSString::withCString(cValue
);
9840 if (!key
|| !value
) {
9843 if (dict
->setObject(key
, value
)) {
9844 result
= kOSReturnSuccess
;
9848 if (key
) key
->release();
9849 if (value
) value
->release();
9854 /*********************************************************************
9855 *********************************************************************/
9856 static bool _OSArrayContainsCString(
9858 const char * cString
)
9860 bool result
= false;
9861 const OSSymbol
* symbol
= NULL
;
9864 if (!array
|| !cString
) {
9868 symbol
= OSSymbol::withCStringNoCopy(cString
);
9873 count
= array
->getCount();
9874 for (i
= 0; i
< count
; i
++) {
9875 OSObject
* thisObject
= array
->getObject(i
);
9876 if (symbol
->isEqualTo(thisObject
)) {
9883 if (symbol
) symbol
->release();
9887 /*********************************************************************
9888 * We really only care about boot / system start up related kexts.
9889 * We return true if we're less than REBUILD_MAX_TIME since start up,
9890 * otherwise return false.
9891 *********************************************************************/
9892 bool _OSKextInPrelinkRebuildWindow(void)
9894 static bool outside_the_window
= false;
9895 AbsoluteTime my_abstime
;
9899 if (outside_the_window
) {
9902 clock_get_uptime(&my_abstime
);
9903 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
9904 my_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
9905 if (my_secs
> REBUILD_MAX_TIME
) {
9906 outside_the_window
= true;
9912 /*********************************************************************
9913 *********************************************************************/
9914 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
9916 int unLoadedCount
, i
;
9917 bool result
= false;
9919 IORecursiveLockLock(sKextLock
);
9921 if (sUnloadedPrelinkedKexts
== NULL
) {
9924 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
9925 if (unLoadedCount
== 0) {
9929 for (i
= 0; i
< unLoadedCount
; i
++) {
9930 const OSSymbol
* myBundleID
; // do not release
9932 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
9933 if (!myBundleID
) continue;
9934 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
9940 IORecursiveLockUnlock(sKextLock
);
9945 #pragma mark Personalities (IOKit Drivers)
9947 /*********************************************************************
9948 *********************************************************************/
9951 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
9953 OSArray
* result
= NULL
; // returned
9954 OSCollectionIterator
* kextIterator
= NULL
; // must release
9955 OSArray
* personalities
= NULL
; // must release
9956 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
9958 OSString
* kextID
= NULL
; // do not release
9959 OSKext
* theKext
= NULL
; // do not release
9961 IORecursiveLockLock(sKextLock
);
9963 /* Let's conservatively guess that any given kext has around 3
9964 * personalities for now.
9966 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
9971 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
9972 if (!kextIterator
) {
9976 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
9977 if (personalitiesIterator
) {
9978 personalitiesIterator
->release();
9979 personalitiesIterator
= NULL
;
9981 if (personalities
) {
9982 personalities
->release();
9983 personalities
= NULL
;
9986 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
9987 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
9988 personalities
= theKext
->copyPersonalitiesArray();
9989 if (!personalities
) {
9992 result
->merge(personalities
);
9994 // xxx - check for better place to put this log msg
9996 kOSKextLogWarningLevel
|
9998 "Kext %s is not loadable during safe boot; "
9999 "omitting its personalities.",
10000 theKext
->getIdentifierCString());
10006 IORecursiveLockUnlock(sKextLock
);
10008 if (kextIterator
) kextIterator
->release();
10009 if (personalitiesIterator
) personalitiesIterator
->release();
10010 if (personalities
) personalities
->release();
10015 /*********************************************************************
10016 *********************************************************************/
10019 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
10021 int numPersonalities
= 0;
10023 OSKextLog(/* kext */ NULL
,
10024 kOSKextLogStepLevel
|
10025 kOSKextLogLoadFlag
,
10026 "Sending all eligible registered kexts' personalities "
10027 "to the IOCatalogue %s.",
10028 startMatching
? "and starting matching" : "but not starting matching");
10030 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
10031 /* filterSafeBootFlag */ true);
10033 if (personalities
) {
10034 gIOCatalogue
->addDrivers(personalities
, startMatching
);
10035 numPersonalities
= personalities
->getCount();
10036 personalities
->release();
10039 OSKextLog(/* kext */ NULL
,
10040 kOSKextLogStepLevel
|
10041 kOSKextLogLoadFlag
,
10042 "%d kext personalit%s sent to the IOCatalogue; %s.",
10043 numPersonalities
, numPersonalities
> 0 ? "ies" : "y",
10044 startMatching
? "matching started" : "matching not started");
10048 /*********************************************************************
10049 * Do not make a deep copy, just convert the IOKitPersonalities dict
10050 * to an array for sending to the IOCatalogue.
10051 *********************************************************************/
10053 OSKext::copyPersonalitiesArray(void)
10055 OSArray
* result
= NULL
;
10056 OSDictionary
* personalities
= NULL
; // do not release
10057 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
10059 OSString
* personalityName
= NULL
; // do not release
10060 OSString
* personalityBundleIdentifier
= NULL
; // do not release
10062 personalities
= OSDynamicCast(OSDictionary
,
10063 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10064 if (!personalities
) {
10068 result
= OSArray::withCapacity(personalities
->getCount());
10073 personalitiesIterator
=
10074 OSCollectionIterator::withCollection(personalities
);
10075 if (!personalitiesIterator
) {
10078 while ((personalityName
= OSDynamicCast(OSString
,
10079 personalitiesIterator
->getNextObject()))) {
10081 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10082 personalities
->getObject(personalityName
));
10085 * If the personality doesn't have a CFBundleIdentifier, or if it
10086 * differs from the kext's, insert the kext's ID so we can find it.
10087 * The publisher ID is used to remove personalities from bundles
10090 personalityBundleIdentifier
= OSDynamicCast(OSString
,
10091 personality
->getObject(kCFBundleIdentifierKey
));
10093 if (!personalityBundleIdentifier
) {
10094 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
10095 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
10096 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
10099 result
->setObject(personality
);
10103 if (personalitiesIterator
) personalitiesIterator
->release();
10108 /*********************************************************************
10109 Might want to change this to a bool return?
10110 *********************************************************************/
10112 OSKext::sendPersonalitiesToCatalog(
10113 bool startMatching
,
10114 OSArray
* personalityNames
)
10116 OSReturn result
= kOSReturnSuccess
;
10117 OSArray
* personalitiesToSend
= NULL
; // must release
10118 OSDictionary
* kextPersonalities
= NULL
; // do not release
10121 if (!sLoadEnabled
) {
10123 kOSKextLogErrorLevel
|
10124 kOSKextLogLoadFlag
,
10125 "Kext loading is disabled (attempt to start matching for kext %s).",
10126 getIdentifierCString());
10127 result
= kOSKextReturnDisabled
;
10131 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
10133 kOSKextLogErrorLevel
|
10134 kOSKextLogLoadFlag
,
10135 "Kext %s is not loadable during safe boot; "
10136 "not sending personalities to the IOCatalogue.",
10137 getIdentifierCString());
10138 result
= kOSKextReturnNotLoadable
;
10142 if (!personalityNames
|| !personalityNames
->getCount()) {
10143 personalitiesToSend
= copyPersonalitiesArray();
10145 kextPersonalities
= OSDynamicCast(OSDictionary
,
10146 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10147 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
10151 personalitiesToSend
= OSArray::withCapacity(0);
10152 if (!personalitiesToSend
) {
10153 result
= kOSKextReturnNoMemory
;
10156 count
= personalityNames
->getCount();
10157 for (i
= 0; i
< count
; i
++) {
10158 OSString
* name
= OSDynamicCast(OSString
,
10159 personalityNames
->getObject(i
));
10163 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10164 kextPersonalities
->getObject(name
));
10166 personalitiesToSend
->setObject(personality
);
10170 if (personalitiesToSend
) {
10171 unsigned numPersonalities
= personalitiesToSend
->getCount();
10173 kOSKextLogStepLevel
|
10174 kOSKextLogLoadFlag
,
10175 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
10176 getIdentifierCString(),
10178 numPersonalities
> 1 ? "ies" : "y",
10179 startMatching
? " and starting matching" : " but not starting matching");
10180 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
10183 if (personalitiesToSend
) {
10184 personalitiesToSend
->release();
10189 /*********************************************************************
10190 * xxx - We should allow removing the kext's declared personalities,
10191 * xxx - even with other bundle identifiers.
10192 *********************************************************************/
10194 OSKext::removePersonalitiesFromCatalog(void)
10196 OSDictionary
* personality
= NULL
; // do not release
10198 personality
= OSDictionary::withCapacity(1);
10199 if (!personality
) {
10202 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
10205 kOSKextLogStepLevel
|
10206 kOSKextLogLoadFlag
,
10207 "Kext %s removing all personalities naming it from the IOCatalogue.",
10208 getIdentifierCString());
10210 /* Have the IOCatalog remove all personalities matching this kext's
10211 * bundle ID and trigger matching anew.
10213 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
10216 if (personality
) personality
->release();
10223 #pragma mark Logging
10225 /*********************************************************************
10226 * Do not call any function that takes sKextLock here!
10227 *********************************************************************/
10230 OSKext::setUserSpaceLogFilter(
10231 OSKextLogSpec newUserLogFilter
,
10234 OSKextLogSpec result
;
10235 bool allocError
= false;
10237 /* Do not call any function that takes sKextLoggingLock during
10238 * this critical block. That means do logging after.
10240 IOLockLock(sKextLoggingLock
);
10242 result
= sUserSpaceKextLogFilter
;
10243 sUserSpaceKextLogFilter
= newUserLogFilter
;
10245 if (newUserLogFilter
&& captureFlag
&&
10246 !sUserSpaceLogSpecArray
&& !sUserSpaceLogMessageArray
) {
10248 // xxx - do some measurements for a good initial capacity?
10249 sUserSpaceLogSpecArray
= OSArray::withCapacity(0);
10250 sUserSpaceLogMessageArray
= OSArray::withCapacity(0);
10252 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
10253 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10254 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10259 IOLockUnlock(sKextLoggingLock
);
10261 /* If the config flag itself is changing, log the state change
10262 * going both ways, before setting up the user-space log arrays,
10263 * so that this is only logged in the kernel.
10265 if (result
!= newUserLogFilter
) {
10266 OSKextLog(/* kext */ NULL
,
10267 kOSKextLogDebugLevel
|
10268 kOSKextLogGeneralFlag
,
10269 "User-space log flags changed from 0x%x to 0x%x.",
10270 result
, newUserLogFilter
);
10273 OSKextLog(/* kext */ NULL
,
10274 kOSKextLogErrorLevel
|
10275 kOSKextLogGeneralFlag
,
10276 "Failed to allocate user-space log message arrays.");
10282 /*********************************************************************
10283 * Do not call any function that takes sKextLock here!
10284 *********************************************************************/
10287 OSKext::clearUserSpaceLogFilter(void)
10289 OSArray
* result
= NULL
;
10290 OSKextLogSpec oldLogFilter
;
10291 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
10293 /* Do not call any function that takes sKextLoggingLock during
10294 * this critical block. That means do logging after.
10296 IOLockLock(sKextLoggingLock
);
10298 result
= OSArray::withCapacity(2);
10300 result
->setObject(sUserSpaceLogSpecArray
);
10301 result
->setObject(sUserSpaceLogMessageArray
);
10303 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10304 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10306 oldLogFilter
= sUserSpaceKextLogFilter
;
10307 sUserSpaceKextLogFilter
= newLogFilter
;
10309 IOLockUnlock(sKextLoggingLock
);
10311 /* If the config flag itself is changing, log the state change
10312 * going both ways, after tearing down the user-space log
10313 * arrays, so this is only logged within the kernel.
10315 if (oldLogFilter
!= newLogFilter
) {
10316 OSKextLog(/* kext */ NULL
,
10317 kOSKextLogDebugLevel
|
10318 kOSKextLogGeneralFlag
,
10319 "User-space log flags changed from 0x%x to 0x%x.",
10320 oldLogFilter
, newLogFilter
);
10327 /*********************************************************************
10328 * Do not call any function that takes sKextLock here!
10329 *********************************************************************/
10332 OSKext::getUserSpaceLogFilter(void)
10334 OSKextLogSpec result
;
10336 IOLockLock(sKextLoggingLock
);
10337 result
= sUserSpaceKextLogFilter
;
10338 IOLockUnlock(sKextLoggingLock
);
10343 /*********************************************************************
10344 * This function is called by OSMetaClass during kernel C++ setup.
10345 * Be careful what you access here; assume only OSKext::initialize()
10348 * Do not call any function that takes sKextLock here!
10349 *********************************************************************/
10350 #define VTRESET "\033[0m"
10352 #define VTBOLD "\033[1m"
10353 #define VTUNDER "\033[4m"
10355 #define VTRED "\033[31m"
10356 #define VTGREEN "\033[32m"
10357 #define VTYELLOW "\033[33m"
10358 #define VTBLUE "\033[34m"
10359 #define VTMAGENTA "\033[35m"
10360 #define VTCYAN "\033[36m"
10362 inline const char * colorForFlags(OSKextLogSpec flags
)
10364 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
10366 switch (logLevel
) {
10367 case kOSKextLogErrorLevel
:
10368 return VTRED VTBOLD
;
10369 case kOSKextLogWarningLevel
:
10371 case kOSKextLogBasicLevel
:
10372 return VTYELLOW VTUNDER
;
10373 case kOSKextLogProgressLevel
:
10375 case kOSKextLogStepLevel
:
10377 case kOSKextLogDetailLevel
:
10379 case kOSKextLogDebugLevel
:
10382 return ""; // white
10386 inline bool logSpecMatch(
10387 OSKextLogSpec msgLogSpec
,
10388 OSKextLogSpec logFilter
)
10390 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
10391 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
10392 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
10394 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
10395 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
10396 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
10398 /* Explicit messages always get logged.
10400 if (msgLevel
== kOSKextLogExplicitLevel
) {
10404 /* Warnings and errors are logged regardless of the flags.
10406 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
10410 /* A verbose message that isn't for a logging-enabled kext and isn't global
10411 * does *not* get logged.
10413 if (!msgKextGlobal
&& !filterKextGlobal
) {
10417 /* Warnings and errors are logged regardless of the flags.
10418 * All other messages must fit the flags and
10419 * have a level at or below the filter.
10422 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
10433 OSKextLogSpec msgLogSpec
,
10434 const char * format
, ...)
10438 va_start(argList
, format
);
10439 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
10446 OSKextLogSpec msgLogSpec
,
10447 const char * format
,
10448 va_list srcArgList
)
10450 extern int disableConsoleOutput
;
10452 bool logForKernel
= false;
10453 bool logForUser
= false;
10455 char stackBuffer
[120];
10456 uint32_t length
= 0;
10457 char * allocBuffer
= NULL
; // must kfree
10458 OSNumber
* logSpecNum
= NULL
; // must release
10459 OSString
* logString
= NULL
; // must release
10460 char * buffer
= stackBuffer
; // do not free
10462 IOLockLock(sKextLoggingLock
);
10464 /* Set the kext/global bit in the message spec if we have no
10465 * kext or if the kext requests logging.
10467 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
10468 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
10471 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
10472 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10473 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
10476 if (! (logForKernel
|| logForUser
) ) {
10480 /* No goto from here until past va_end()!
10482 va_copy(argList
, srcArgList
);
10483 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
10486 if (length
+ 1 >= sizeof(stackBuffer
)) {
10487 allocBuffer
= (char *)kalloc_tag((length
+ 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT
);
10488 if (!allocBuffer
) {
10492 /* No goto from here until past va_end()!
10494 va_copy(argList
, srcArgList
);
10495 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
10498 buffer
= allocBuffer
;
10501 /* If user space wants the log message, queue it up.
10503 if (logForUser
&& sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10504 logSpecNum
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
));
10505 logString
= OSString::withCString(buffer
);
10506 if (logSpecNum
&& logString
) {
10507 sUserSpaceLogSpecArray
->setObject(logSpecNum
);
10508 sUserSpaceLogMessageArray
->setObject(logString
);
10512 /* Always log messages from the kernel according to the kernel's
10515 if (logForKernel
) {
10517 /* If we are in console mode and have a custom log filter,
10518 * colorize the log message.
10520 if (!disableConsoleOutput
&& sBootArgLogFilterFound
) {
10521 const char * color
= ""; // do not free
10522 color
= colorForFlags(msgLogSpec
);
10523 printf("%s%s%s\n", colorForFlags(msgLogSpec
),
10524 buffer
, color
[0] ? VTRESET
: "");
10526 printf("%s\n", buffer
);
10531 IOLockUnlock(sKextLoggingLock
);
10534 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
10536 OSSafeReleaseNULL(logString
);
10537 OSSafeReleaseNULL(logSpecNum
);
10541 #if KASLR_IOREG_DEBUG
10543 #define IOLOG_INDENT( the_indention ) \
10546 for ( i = 0; i < (the_indention); i++ ) { \
10551 extern vm_offset_t vm_kernel_stext
;
10552 extern vm_offset_t vm_kernel_etext
;
10553 extern mach_vm_offset_t kext_alloc_base
;
10554 extern mach_vm_offset_t kext_alloc_max
;
10556 bool ScanForAddrInObject(OSObject
* theObject
,
10559 bool ScanForAddrInObject(OSObject
* theObject
,
10562 const OSMetaClass
* myTypeID
;
10563 OSCollectionIterator
* myIter
;
10565 OSObject
* myValue
;
10566 bool myResult
= false;
10568 if ( theObject
== NULL
) {
10569 IOLog("%s: theObject is NULL \n",
10574 myTypeID
= OSTypeIDInst(theObject
);
10576 if ( myTypeID
== OSTypeID(OSDictionary
) ) {
10577 OSDictionary
* myDictionary
;
10579 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
10580 myIter
= OSCollectionIterator::withCollection( myDictionary
);
10581 if ( myIter
== NULL
)
10585 while ( (myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject())) ) {
10588 myValue
= myDictionary
->getObject(myKey
);
10589 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10590 if (myTempResult
) {
10591 // if we ever get a true result return true
10593 IOLOG_INDENT(indent
);
10594 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
10599 else if ( myTypeID
== OSTypeID(OSArray
) ) {
10602 myArray
= OSDynamicCast(OSArray
, theObject
);
10603 myIter
= OSCollectionIterator::withCollection(myArray
);
10604 if ( myIter
== NULL
)
10608 while ( (myValue
= myIter
->getNextObject()) ) {
10610 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10611 if (myTempResult
) {
10612 // if we ever get a true result return true
10614 IOLOG_INDENT(indent
);
10615 IOLog("OSArray: \n");
10620 else if ( myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
) ) {
10622 // should we look for addresses in strings?
10624 else if ( myTypeID
== OSTypeID(OSData
) ) {
10627 unsigned int myLen
;
10628 OSData
* myDataObj
;
10630 myDataObj
= OSDynamicCast(OSData
, theObject
);
10631 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
10632 myLen
= myDataObj
->getLength();
10634 if (myPtrPtr
&& myLen
&& myLen
> 7) {
10636 int myPtrCount
= (myLen
/ sizeof(void *));
10638 for (i
= 0; i
< myPtrCount
; i
++) {
10639 UInt64 numberValue
= (UInt64
) *(myPtrPtr
);
10641 if ( kext_alloc_max
!= 0 &&
10642 numberValue
>= kext_alloc_base
&&
10643 numberValue
< kext_alloc_max
) {
10645 OSKext
* myKext
= NULL
; // must release (looked up)
10646 // IOLog("found OSData %p in kext map %p to %p \n",
10648 // (void *) kext_alloc_base,
10649 // (void *) kext_alloc_max);
10651 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) *(myPtrPtr
) );
10653 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
10655 myKext
->getIdentifierCString());
10660 if ( vm_kernel_etext
!= 0 &&
10661 numberValue
>= vm_kernel_stext
&&
10662 numberValue
< vm_kernel_etext
) {
10663 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
10665 (void *) vm_kernel_stext
,
10666 (void *) vm_kernel_etext
);
10673 else if ( myTypeID
== OSTypeID(OSBoolean
) ) {
10675 // do nothing here...
10677 else if ( myTypeID
== OSTypeID(OSNumber
) ) {
10679 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
10681 UInt64 numberValue
= number
->unsigned64BitValue();
10683 if ( kext_alloc_max
!= 0 &&
10684 numberValue
>= kext_alloc_base
&&
10685 numberValue
< kext_alloc_max
) {
10687 OSKext
* myKext
= NULL
; // must release (looked up)
10688 IOLog("found OSNumber in kext map %p to %p \n",
10689 (void *) kext_alloc_base
,
10690 (void *) kext_alloc_max
);
10691 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10693 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) numberValue
);
10695 IOLog("found in kext \"%s\" \n",
10696 myKext
->getIdentifierCString());
10702 if ( vm_kernel_etext
!= 0 &&
10703 numberValue
>= vm_kernel_stext
&&
10704 numberValue
< vm_kernel_etext
) {
10705 IOLog("found OSNumber in kernel text segment %p to %p \n",
10706 (void *) vm_kernel_stext
,
10707 (void *) vm_kernel_etext
);
10708 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10714 const OSMetaClass
* myMetaClass
= NULL
;
10716 myMetaClass
= theObject
->getMetaClass();
10717 if ( myMetaClass
) {
10718 IOLog("class %s \n", myMetaClass
->getClassName() );
10721 IOLog("Unknown object \n" );
10728 #endif // KASLR_KEXT_DEBUG
10730 }; /* extern "C" */
10733 #pragma mark Backtrace Dump & kmod_get_info() support
10735 /*********************************************************************
10736 * This function must be safe to call in panic context.
10737 *********************************************************************/
10740 OSKext::printKextsInBacktrace(
10741 vm_offset_t
* addr
,
10743 int (* printf_func
)(const char *fmt
, ...),
10747 addr64_t summary_page
= 0;
10748 addr64_t last_summary_page
= 0;
10749 bool found_kmod
= false;
10753 if (!sKextSummariesLock
) return;
10754 IOLockLock(sKextSummariesLock
);
10757 if (!gLoadedKextSummaries
) {
10758 (*printf_func
)(" can't perform kext scan: no kext summary");
10762 summary_page
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
);
10763 last_summary_page
= round_page(summary_page
+ sLoadedKextSummariesAllocSize
);
10764 for (; summary_page
< last_summary_page
; summary_page
+= PAGE_SIZE
) {
10765 if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) {
10766 (*printf_func
)(" can't perform kext scan: "
10767 "missing kext summary page %p", summary_page
);
10772 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10773 OSKextLoadedKextSummary
* summary
;
10775 summary
= gLoadedKextSummaries
->summaries
+ i
;
10776 if (!summary
->address
) {
10780 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
10785 (*printf_func
)(" Kernel Extensions in backtrace:\n");
10789 printSummary(summary
, printf_func
, doUnslide
);
10794 IOLockUnlock(sKextSummariesLock
);
10800 /*********************************************************************
10801 * This function must be safe to call in panic context.
10802 *********************************************************************/
10805 OSKext::summaryIsInBacktrace(
10806 OSKextLoadedKextSummary
* summary
,
10807 vm_offset_t
* addr
,
10812 for (i
= 0; i
< cnt
; i
++) {
10813 vm_offset_t kscan_addr
= addr
[i
];
10814 if ((kscan_addr
>= summary
->address
) &&
10815 (kscan_addr
< (summary
->address
+ summary
->size
)))
10825 * Get the kext summary object for the kext where 'addr' lies. Must be called with
10826 * sKextSummariesLock held.
10828 OSKextLoadedKextSummary
*
10829 OSKext::summaryForAddress(const uintptr_t addr
)
10831 for (unsigned i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10833 OSKextLoadedKextSummary
*summary
= &gLoadedKextSummaries
->summaries
[i
];
10834 if (!summary
->address
) {
10838 #if VM_MAPPED_KEXTS
10839 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not
10840 * support split kexts, but we also may unmap the kexts, which can
10841 * race with the above codepath (see OSKext::unload). As such,
10842 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
10844 if ((addr
>= summary
->address
) && (addr
< (summary
->address
+ summary
->size
))) {
10848 kernel_mach_header_t
*mh
= (kernel_mach_header_t
*)summary
->address
;
10849 kernel_segment_command_t
*seg
;
10851 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
10852 if ((addr
>= seg
->vmaddr
) && (addr
< (seg
->vmaddr
+ seg
->vmsize
))) {
10859 /* addr did not map to any kext */
10865 OSKext::kextForAddress(const void *addr
)
10867 void *image
= NULL
;
10869 if (((vm_offset_t
)(uintptr_t)addr
>= vm_kernel_stext
) &&
10870 ((vm_offset_t
)(uintptr_t)addr
< vm_kernel_etext
)) {
10871 return (void *)&_mh_execute_header
;
10874 if (!sKextSummariesLock
) {
10877 IOLockLock(sKextSummariesLock
);
10878 OSKextLoadedKextSummary
*summary
= OSKext::summaryForAddress((uintptr_t)addr
);
10880 image
= (void *)summary
->address
;
10882 IOLockUnlock(sKextSummariesLock
);
10887 /*********************************************************************
10888 * scan list of loaded kext summaries looking for a load address match and if
10889 * found return the UUID C string. If not found then set empty string.
10890 *********************************************************************/
10891 static void findSummaryUUID(
10893 uuid_string_t uuid
);
10895 static void findSummaryUUID(
10897 uuid_string_t uuid
)
10901 uuid
[0] = 0x00; // default to no UUID
10903 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10904 OSKextLoadedKextSummary
* summary
;
10906 summary
= gLoadedKextSummaries
->summaries
+ i
;
10908 if (summary
->loadTag
== tag_ID
) {
10909 (void) uuid_unparse(summary
->uuid
, uuid
);
10916 /*********************************************************************
10917 * This function must be safe to call in panic context.
10918 *********************************************************************/
10919 void OSKext::printSummary(
10920 OSKextLoadedKextSummary
* summary
,
10921 int (* printf_func
)(const char *fmt
, ...),
10924 kmod_reference_t
* kmod_ref
= NULL
;
10925 uuid_string_t uuid
;
10926 char version
[kOSKextVersionMaxLength
];
10929 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
10930 strlcpy(version
, "unknown version", sizeof(version
));
10932 (void) uuid_unparse(summary
->uuid
, uuid
);
10935 tmpAddr
= VM_KERNEL_UNSLIDE(summary
->address
);
10938 tmpAddr
= summary
->address
;
10940 (*printf_func
)(" %s(%s)[%s]@0x%llx->0x%llx\n",
10941 summary
->name
, version
, uuid
,
10942 tmpAddr
, tmpAddr
+ summary
->size
- 1);
10944 /* print dependency info */
10945 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
10947 kmod_ref
= kmod_ref
->next
) {
10948 kmod_info_t
* rinfo
;
10950 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) {
10951 (*printf_func
)(" kmod dependency scan stopped "
10952 "due to missing dependency page: %p\n",
10953 doUnslide
? (void *)VM_KERNEL_UNSLIDE(kmod_ref
) : kmod_ref
);
10956 rinfo
= kmod_ref
->info
;
10958 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) {
10959 (*printf_func
)(" kmod dependency scan stopped "
10960 "due to missing kmod page: %p\n",
10961 doUnslide
? (void *)VM_KERNEL_UNSLIDE(rinfo
) : rinfo
);
10965 if (!rinfo
->address
) {
10966 continue; // skip fake entries for built-ins
10969 /* locate UUID in gLoadedKextSummaries */
10970 findSummaryUUID(rinfo
->id
, uuid
);
10973 tmpAddr
= VM_KERNEL_UNSLIDE(rinfo
->address
);
10976 tmpAddr
= rinfo
->address
;
10978 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
10979 rinfo
->name
, rinfo
->version
, uuid
, tmpAddr
);
10985 /*******************************************************************************
10986 * substitute() looks at an input string (a pointer within a larger buffer)
10987 * for a match to a substring, and on match it writes the marker & substitution
10988 * character to an output string, updating the scan (from) and
10989 * output (to) indexes as appropriate.
10990 *******************************************************************************/
10991 static int substitute(
10992 const char * scan_string
,
10994 uint32_t * to_index
,
10995 uint32_t * from_index
,
10996 const char * substring
,
10998 char substitution
);
11000 /* string_out must be at least KMOD_MAX_NAME bytes.
11004 const char * scan_string
,
11006 uint32_t * to_index
,
11007 uint32_t * from_index
,
11008 const char * substring
,
11012 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
11014 /* On a substring match, append the marker (if there is one) and then
11015 * the substitution character, updating the output (to) index accordingly.
11016 * Then update the input (from) length by the length of the substring
11017 * that got replaced.
11019 if (!strncmp(scan_string
, substring
, substring_length
)) {
11021 string_out
[(*to_index
)++] = marker
;
11023 string_out
[(*to_index
)++] = substitution
;
11024 (*from_index
) += substring_length
;
11030 /*******************************************************************************
11031 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
11032 * KMOD_MAX_NAME characters and performs various substitutions of common
11033 * prefixes & substrings as defined by tables in kext_panic_report.h.
11034 *******************************************************************************/
11035 static void compactIdentifier(
11036 const char * identifier
,
11037 char * identifier_out
,
11038 char ** identifier_out_end
);
11042 const char * identifier
,
11043 char * identifier_out
,
11044 char ** identifier_out_end
)
11046 uint32_t from_index
, to_index
;
11047 uint32_t scan_from_index
= 0;
11048 uint32_t scan_to_index
= 0;
11049 subs_entry_t
* subs_entry
= NULL
;
11052 from_index
= to_index
= 0;
11053 identifier_out
[0] = '\0';
11055 /* Replace certain identifier prefixes with shorter @+character sequences.
11056 * Check the return value of substitute() so we only replace the prefix.
11058 for (subs_entry
= &kext_identifier_prefix_subs
[0];
11059 subs_entry
->substring
&& !did_sub
;
11062 did_sub
= substitute(identifier
, identifier_out
,
11063 &scan_to_index
, &scan_from_index
,
11064 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
11068 /* Now scan through the identifier looking for the common substrings
11069 * and replacing them with shorter !+character sequences via substitute().
11071 for (/* see above */;
11072 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
11075 const char * scan_string
= &identifier
[scan_from_index
];
11079 if (scan_from_index
) {
11080 for (subs_entry
= &kext_identifier_substring_subs
[0];
11081 subs_entry
->substring
&& !did_sub
;
11084 did_sub
= substitute(scan_string
, identifier_out
,
11085 &scan_to_index
, &scan_from_index
,
11086 subs_entry
->substring
, '!', subs_entry
->substitute
);
11090 /* If we didn't substitute, copy the input character to the output.
11093 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
11097 identifier_out
[scan_to_index
] = '\0';
11098 if (identifier_out_end
) {
11099 *identifier_out_end
= &identifier_out
[scan_to_index
];
11105 /*******************************************************************************
11106 * assemble_identifier_and_version() adds to a string buffer a compacted
11107 * bundle identifier followed by a version string.
11108 *******************************************************************************/
11110 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
11112 static int assemble_identifier_and_version(
11113 kmod_info_t
* kmod_info
,
11114 char * identPlusVers
,
11118 assemble_identifier_and_version(
11119 kmod_info_t
* kmod_info
,
11120 char * identPlusVers
,
11125 compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
);
11126 result
= strnlen(identPlusVers
, KMOD_MAX_NAME
- 1);
11127 identPlusVers
[result
++] = '\t'; // increment for real char
11128 identPlusVers
[result
] = '\0'; // don't increment for nul char
11129 result
= strlcat(identPlusVers
, kmod_info
->version
, bufSize
);
11130 if (result
>= bufSize
) {
11131 identPlusVers
[bufSize
- 1] = '\0';
11132 result
= bufSize
- 1;
11138 /*******************************************************************************
11139 * Assumes sKextLock is held.
11140 *******************************************************************************/
11143 OSKext::saveLoadedKextPanicListTyped(
11144 const char * prefix
,
11148 uint32_t list_size
)
11151 unsigned int count
, i
;
11153 count
= sLoadedKexts
->getCount();
11160 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
11161 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
11163 uint32_t identPlusVersLength
;
11165 char identPlusVers
[2*KMOD_MAX_NAME
];
11168 printf("OSKext::saveLoadedKextPanicListTyped - "
11169 "NULL kext in loaded kext list; continuing\n");
11174 printf("OSKext::saveLoadedKextPanicListTyped - "
11175 "Kext type cast failed in loaded kext list; continuing\n");
11179 /* Skip all built-in kexts.
11181 if (theKext
->isKernelComponent()) {
11185 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
11187 /* Filter for kmod name (bundle identifier).
11189 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
11190 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
11194 /* Filter for libraries (kexts that have a compatible version).
11196 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
11197 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
11203 !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) {
11205 printf("kext scan stopped due to missing kmod_info page: %p\n",
11210 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
11212 sizeof(identPlusVers
));
11213 if (!identPlusVersLength
) {
11214 printf("error saving loaded kext info\n");
11218 /* make sure everything fits and we null terminate.
11220 tempLen
= strlcat(paniclist
, identPlusVers
, list_size
);
11221 if (tempLen
>= list_size
) {
11222 // panic list is full, keep it and null terminate
11223 paniclist
[list_size
- 1] = 0x00;
11227 tempLen
= strlcat(paniclist
, "\n", list_size
);
11228 if (tempLen
>= list_size
) {
11229 // panic list is full, keep it and null terminate
11230 paniclist
[list_size
- 1] = 0x00;
11242 /*********************************************************************
11243 *********************************************************************/
11246 OSKext::saveLoadedKextPanicList(void)
11248 char * newlist
= NULL
;
11249 uint32_t newlist_size
= 0;
11251 newlist_size
= KEXT_PANICLIST_SIZE
;
11252 newlist
= (char *)kalloc_tag(newlist_size
, VM_KERN_MEMORY_OSKEXT
);
11255 OSKextLog(/* kext */ NULL
,
11256 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
11257 "Couldn't allocate kext panic log buffer.");
11263 // non-"com.apple." kexts
11264 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
11265 /* libs? */ -1, newlist
, newlist_size
) != 0) {
11269 // "com.apple." nonlibrary kexts
11270 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11271 /* libs? */ 0, newlist
, newlist_size
) != 0) {
11275 // "com.apple." library kexts
11276 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11277 /* libs? */ 1, newlist
, newlist_size
) != 0) {
11282 if (loaded_kext_paniclist
) {
11283 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
11285 loaded_kext_paniclist
= newlist
;
11287 loaded_kext_paniclist_size
= newlist_size
;
11291 kfree(newlist
, newlist_size
);
11296 /*********************************************************************
11297 * Assumes sKextLock is held.
11298 *********************************************************************/
11300 OSKext::savePanicString(bool isLoading
)
11305 return; // do not goto finish here b/c of lock
11308 len
= assemble_identifier_and_version( kmod_info
,
11309 (isLoading
) ? last_loaded_str_buf
: last_unloaded_str_buf
,
11310 (isLoading
) ? sizeof(last_loaded_str_buf
) : sizeof(last_unloaded_str_buf
) );
11312 printf("error saving unloaded kext info\n");
11317 last_loaded_strlen
= len
;
11318 last_loaded_address
= (void *)kmod_info
->address
;
11319 last_loaded_size
= kmod_info
->size
;
11320 clock_get_uptime(&last_loaded_timestamp
);
11322 last_unloaded_strlen
= len
;
11323 last_unloaded_address
= (void *)kmod_info
->address
;
11324 last_unloaded_size
= kmod_info
->size
;
11325 clock_get_uptime(&last_unloaded_timestamp
);
11332 /*********************************************************************
11333 *********************************************************************/
11336 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
11338 if (last_loaded_strlen
) {
11339 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
11340 AbsoluteTime_to_scalar(&last_loaded_timestamp
),
11341 last_loaded_strlen
, last_loaded_str_buf
,
11342 last_loaded_address
, last_loaded_size
);
11345 if (last_unloaded_strlen
) {
11346 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
11347 AbsoluteTime_to_scalar(&last_unloaded_timestamp
),
11348 last_unloaded_strlen
, last_unloaded_str_buf
,
11349 last_unloaded_address
, last_unloaded_size
);
11352 printf_func("loaded kexts:\n");
11353 if (loaded_kext_paniclist
&&
11354 pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) &&
11355 loaded_kext_paniclist
[0]) {
11357 printf_func("%.*s",
11358 strnlen(loaded_kext_paniclist
, loaded_kext_paniclist_size
),
11359 loaded_kext_paniclist
);
11361 printf_func("(none)\n");
11366 /*********************************************************************
11367 * Assumes sKextLock is held.
11368 *********************************************************************/
11371 OSKext::updateLoadedKextSummaries(void)
11373 kern_return_t result
= KERN_FAILURE
;
11374 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
11375 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
11377 vm_map_offset_t start
, end
;
11378 size_t summarySize
= 0;
11383 OSKextActiveAccount
* accountingList
;
11384 OSKextActiveAccount
* prevAccountingList
;
11385 uint32_t idx
, accountingListAlloc
, accountingListCount
, prevAccountingListCount
;
11387 prevAccountingList
= NULL
;
11388 prevAccountingListCount
= 0;
11390 #if DEVELOPMENT || DEBUG
11391 if (IORecursiveLockHaveLock(sKextLock
) == false) {
11392 panic("sKextLock must be held");
11396 IOLockLock(sKextSummariesLock
);
11398 count
= sLoadedKexts
->getCount();
11399 for (i
= 0, maxKexts
= 0; i
< count
; ++i
) {
11400 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11401 maxKexts
+= (aKext
&& aKext
->isExecutable());
11404 if (!maxKexts
) goto finish
;
11405 if (maxKexts
< kOSKextTypicalLoadCount
) maxKexts
= kOSKextTypicalLoadCount
;
11407 /* Calculate the size needed for the new summary headers.
11410 size
= sizeof(*gLoadedKextSummaries
);
11411 size
+= maxKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
11412 size
= round_page(size
);
11414 if (gLoadedKextSummaries
== NULL
|| sLoadedKextSummariesAllocSize
< size
) {
11415 if (gLoadedKextSummaries
) {
11416 kmem_free(kernel_map
, (vm_offset_t
)gLoadedKextSummaries
, sLoadedKextSummariesAllocSize
);
11417 gLoadedKextSummaries
= NULL
;
11418 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11419 sLoadedKextSummariesAllocSize
= 0;
11421 result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&summaryHeaderAlloc
, size
, VM_KERN_MEMORY_OSKEXT
);
11422 if (result
!= KERN_SUCCESS
) goto finish
;
11423 summaryHeader
= summaryHeaderAlloc
;
11424 summarySize
= size
;
11427 summaryHeader
= gLoadedKextSummaries
;
11428 summarySize
= sLoadedKextSummariesAllocSize
;
11430 start
= (vm_map_offset_t
) summaryHeader
;
11431 end
= start
+ summarySize
;
11432 result
= vm_map_protect(kernel_map
,
11437 if (result
!= KERN_SUCCESS
) goto finish
;
11440 /* Populate the summary header.
11443 bzero(summaryHeader
, summarySize
);
11444 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
11445 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
11447 /* Populate each kext summary.
11450 count
= sLoadedKexts
->getCount();
11451 accountingListAlloc
= 0;
11452 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11453 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11454 if (!aKext
|| !aKext
->isExecutable()) {
11458 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
11459 summaryHeader
->numSummaries
++;
11460 accountingListAlloc
++;
11463 accountingList
= IONew(typeof(accountingList
[0]), accountingListAlloc
);
11464 accountingListCount
= 0;
11465 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11466 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11467 if (!aKext
|| !aKext
->isExecutable()) {
11471 OSKextActiveAccount activeAccount
;
11472 aKext
->updateActiveAccount(&activeAccount
);
11473 // order by address
11474 for (idx
= 0; idx
< accountingListCount
; idx
++)
11476 if (activeAccount
.address
< accountingList
[idx
].address
) break;
11478 bcopy(&accountingList
[idx
], &accountingList
[idx
+ 1], (accountingListCount
- idx
) * sizeof(accountingList
[0]));
11479 accountingList
[idx
] = activeAccount
;
11480 accountingListCount
++;
11482 assert(accountingListCount
== accountingListAlloc
);
11483 /* Write protect the buffer and move it into place.
11486 start
= (vm_map_offset_t
) summaryHeader
;
11487 end
= start
+ summarySize
;
11489 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_READ
, FALSE
);
11490 if (result
!= KERN_SUCCESS
)
11493 gLoadedKextSummaries
= summaryHeader
;
11494 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11495 sLoadedKextSummariesAllocSize
= summarySize
;
11496 summaryHeaderAlloc
= NULL
;
11498 /* Call the magic breakpoint function through a static function pointer so
11499 * the compiler can't optimize the function away.
11501 if (sLoadedKextSummariesUpdated
) (*sLoadedKextSummariesUpdated
)();
11503 IOSimpleLockLock(sKextAccountsLock
);
11504 prevAccountingList
= sKextAccounts
;
11505 prevAccountingListCount
= sKextAccountsCount
;
11506 sKextAccounts
= accountingList
;
11507 sKextAccountsCount
= accountingListCount
;
11508 IOSimpleLockUnlock(sKextAccountsLock
);
11511 IOLockUnlock(sKextSummariesLock
);
11513 /* If we had to allocate a new buffer but failed to generate the summaries,
11516 if (summaryHeaderAlloc
) {
11517 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
11519 if (prevAccountingList
) {
11520 IODelete(prevAccountingList
, typeof(accountingList
[0]), prevAccountingListCount
);
11526 /*********************************************************************
11527 *********************************************************************/
11529 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
11533 strlcpy(summary
->name
, getIdentifierCString(),
11534 sizeof(summary
->name
));
11538 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
11539 OSSafeReleaseNULL(uuid
);
11542 summary
->address
= kmod_info
->address
;
11543 summary
->size
= kmod_info
->size
;
11544 summary
->version
= getVersion();
11545 summary
->loadTag
= kmod_info
->id
;
11546 summary
->flags
= 0;
11547 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
11552 /*********************************************************************
11553 *********************************************************************/
11556 OSKext::updateActiveAccount(OSKextActiveAccount
*accountp
)
11558 kernel_mach_header_t
*hdr
= NULL
;
11559 kernel_segment_command_t
*seg
= NULL
;
11561 hdr
= (kernel_mach_header_t
*)kmod_info
->address
;
11563 if (getcommandfromheader(hdr
, LC_SEGMENT_SPLIT_INFO
)) {
11564 /* If this kext supports split segments, use the first
11565 * executable segment as the range for instructions
11566 * (and thus for backtracing.
11568 for (seg
= firstsegfromheader(hdr
); seg
!= NULL
; seg
= nextsegfromheader(hdr
, seg
)) {
11569 if (seg
->initprot
& VM_PROT_EXECUTE
) {
11575 bzero(accountp
, sizeof(*accountp
));
11577 accountp
->address
= seg
->vmaddr
;
11578 if (accountp
->address
) {
11579 accountp
->address_end
= seg
->vmaddr
+ seg
->vmsize
;
11582 /* For non-split kexts and for kexts without executable
11583 * segments, just use the kmod_info range (as the kext
11584 * is either all in one range or should not show up in
11585 * instruction backtraces).
11587 accountp
->address
= kmod_info
->address
;
11588 if (accountp
->address
) {
11589 accountp
->address_end
= kmod_info
->address
+ kmod_info
->size
;
11592 accountp
->account
= this->account
;
11595 extern "C" const vm_allocation_site_t
*
11596 OSKextGetAllocationSiteForCaller(uintptr_t address
)
11598 OSKextActiveAccount
* active
;
11599 vm_allocation_site_t
* site
;
11603 IOSimpleLockLock(sKextAccountsLock
);
11605 // bsearch sKextAccounts list
11606 for (baseIdx
= 0, lim
= sKextAccountsCount
; lim
; lim
>>= 1)
11608 active
= &sKextAccounts
[baseIdx
+ (lim
>> 1)];
11609 if ((address
>= active
->address
) && (address
< active
->address_end
))
11611 site
= &active
->account
->site
;
11612 if (!site
->tag
) vm_tag_alloc_locked(site
);
11615 else if (address
> active
->address
)
11618 baseIdx
+= (lim
>> 1) + 1;
11623 IOSimpleLockUnlock(sKextAccountsLock
);
11628 extern "C" uint32_t
11629 OSKextGetKmodIDForSite(vm_allocation_site_t
* site
, char * name
, vm_size_t namelen
)
11631 OSKextAccount
* account
= (typeof(account
)) site
;
11632 const char * kname
;
11636 if (account
->kext
) kname
= account
->kext
->getIdentifierCString();
11638 strlcpy(name
, kname
, namelen
);
11641 return (account
->loadTag
);
11645 OSKextFreeSite(vm_allocation_site_t
* site
)
11647 OSKextAccount
* freeAccount
= (typeof(freeAccount
)) site
;
11648 IODelete(freeAccount
, OSKextAccount
, 1);
11651 /*********************************************************************
11652 *********************************************************************/
11654 #if CONFIG_KEC_FIPS
11657 #pragma mark Kernel External Components for FIPS compliance
11660 /*********************************************************************
11661 * Kernel External Components for FIPS compliance (KEC_FIPS)
11662 *********************************************************************/
11664 GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
)
11666 AppleTEXTHash_t my_ath
= {2, 0, NULL
};
11667 AppleTEXTHash_t
* my_athp
= NULL
; // do not release
11668 OSData
* segmentHash
= NULL
; // do not release
11670 if (theKext
== NULL
|| theInfoDict
== NULL
) {
11674 // Get the part of the plist associate with kAppleTextHashesKey and let
11675 // the crypto library do further parsing (slice/architecture)
11676 segmentHash
= OSDynamicCast(OSData
, theInfoDict
->getObject(kAppleTextHashesKey
));
11677 // Support for ATH v1 while rolling out ATH v2 without revision locking submissions
11678 // Remove this when v2 PLIST are supported
11679 if (segmentHash
== NULL
) {
11680 // If this fails, we may be dealing with a v1 PLIST
11681 OSDictionary
* textHashDict
= NULL
; // do not release
11682 textHashDict
= OSDynamicCast(OSDictionary
, theInfoDict
->getObject(kAppleTextHashesKey
));
11683 if (textHashDict
== NULL
) {
11686 my_ath
.ath_version
=1;
11687 segmentHash
= OSDynamicCast(OSData
,textHashDict
->getObject(ARCHNAME
));
11688 } // end of v2 rollout
11690 if (segmentHash
== NULL
) {
11694 // KEC_FIPS type kexts never unload so we don't have to clean up our
11696 if (kmem_alloc(kernel_map
, (vm_offset_t
*) &my_athp
,
11697 sizeof(AppleTEXTHash_t
), VM_KERN_MEMORY_OSKEXT
) != KERN_SUCCESS
) {
11701 memcpy(my_athp
, &my_ath
, sizeof(my_ath
));
11702 my_athp
->ath_length
= segmentHash
->getLength();
11703 if (my_athp
->ath_length
> 0) {
11704 my_athp
->ath_hash
= (void *)segmentHash
->getBytesNoCopy();
11709 kOSKextLogErrorLevel
|
11710 kOSKextLogGeneralFlag
,
11711 "Kext %s ath_version %d ath_length %d ath_hash %p",
11712 theKext
->getIdentifierCString(),
11713 my_athp
->ath_version
,
11714 my_athp
->ath_length
,
11715 my_athp
->ath_hash
);
11718 return( (void *) my_athp
);
11721 #endif // CONFIG_KEC_FIPS
11723 #if CONFIG_IMAGEBOOT
11724 int OSKextGetUUIDForName(const char *name
, uuid_t uuid
)
11726 OSKext
*kext
= OSKext::lookupKextWithIdentifier(name
);
11731 OSData
*uuid_data
= kext
->copyUUID();
11733 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_t
));
11734 OSSafeReleaseNULL(uuid_data
);