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 <os/firehose_buffer_private.h>
36 #include <vm/vm_kern.h>
37 #include <kextd/kextd_mach.h>
38 #include <libkern/kernel_mach_header.h>
39 #include <libkern/kext_panic_report.h>
40 #include <libkern/kext_request_keys.h>
41 #include <libkern/mkext.h>
42 #include <libkern/prelink.h>
43 #include <libkern/version.h>
44 #include <libkern/zlib.h>
45 #include <mach/host_special_ports.h>
46 #include <mach/mach_vm.h>
47 #include <mach/mach_time.h>
48 #include <sys/sysctl.h>
49 #include <uuid/uuid.h>
50 // 04/18/11 - gab: <rdar://problem/9236163>
51 #include <sys/random.h>
56 #include <sys/kauth.h>
57 #include <security/mac_framework.h>
61 #include <libkern/OSKextLibPrivate.h>
62 #include <libkern/c++/OSKext.h>
63 #include <libkern/c++/OSLib.h>
65 #include <IOKit/IOLib.h>
66 #include <IOKit/IOCatalogue.h>
67 #include <IOKit/IORegistryEntry.h>
68 #include <IOKit/IOService.h>
70 #include <IOKit/IOStatisticsPrivate.h>
71 #include <IOKit/IOBSD.h>
74 #pragma mark External & Internal Function Protos
76 /*********************************************************************
77 *********************************************************************/
79 extern int IODTGetLoaderInfo(const char * key
, void ** infoAddr
, int * infoSize
);
80 extern void IODTFreeLoaderInfo(const char * key
, void * infoAddr
, int infoSize
);
81 extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t
* segment
);
82 extern void OSRuntimeUnloadCPP(kmod_info_t
* ki
, void * data
);
84 extern ppnum_t
pmap_find_phys(pmap_t pmap
, addr64_t va
); /* osfmk/machine/pmap.h */
87 static OSReturn
_OSKextCreateRequest(
88 const char * predicate
,
89 OSDictionary
** requestP
);
90 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
);
91 static OSObject
* _OSKextGetRequestArgument(
92 OSDictionary
* requestDict
,
93 const char * argName
);
94 static bool _OSKextSetRequestArgument(
95 OSDictionary
* requestDict
,
98 static void * _OSKextExtractPointer(OSData
* wrapper
);
99 static OSReturn
_OSDictionarySetCStringValue(
103 static bool _OSKextInPrelinkRebuildWindow(void);
104 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol
* theBundleID
);
106 // We really should add containsObject() & containsCString to OSCollection & subclasses.
107 // So few pad slots, though....
108 static bool _OSArrayContainsCString(OSArray
* array
, const char * cString
);
111 static void * GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
);
112 #endif // CONFIG_KEC_FIPS
114 /* Prelinked arm kexts do not have VM entries because the method we use to
115 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
116 * not work on ARM. To get around that, we must free prelinked kext
117 * executables with ml_static_mfree() instead of kext_free().
119 #if __i386__ || __x86_64__
120 #define VM_MAPPED_KEXTS 1
121 #define KASLR_KEXT_DEBUG 0
122 #define KASLR_IOREG_DEBUG 0
124 #error Unsupported architecture
128 #pragma mark Constants & Macros
130 /*********************************************************************
132 *********************************************************************/
134 /* Use this number to create containers.
136 #define kOSKextTypicalLoadCount (150)
138 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
139 * A loaded kext will no dependents or external retains will have 2 retains.
141 #define kOSKextMinRetainCount (1)
142 #define kOSKextMinLoadedRetainCount (2)
145 * Strings and substrings used in dependency resolution.
147 #define APPLE_KEXT_PREFIX "com.apple."
148 #define KERNEL_LIB "com.apple.kernel"
150 #define PRIVATE_KPI "com.apple.kpi.private"
152 /* Version for compatbility pseudokexts (com.apple.kernel.*),
153 * compatible back to v6.0.
155 #define KERNEL6_LIB "com.apple.kernel.6.0"
156 #define KERNEL6_VERSION "7.9.9"
158 #define KERNEL_LIB_PREFIX "com.apple.kernel."
159 #define KPI_LIB_PREFIX "com.apple.kpi."
161 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0)
163 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
164 #define MINIMUM_WAKEUP_SECONDS (30)
166 /*********************************************************************
167 * infoDict keys for internally-stored data. Saves on ivar slots for
168 * objects we don't keep around past boot time or during active load.
169 *********************************************************************/
171 /* A usable, uncompressed file is stored under this key.
173 #define _kOSKextExecutableKey "_OSKextExecutable"
175 /* An indirect reference to the executable file from an mkext
176 * is stored under this key.
178 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference"
180 /* If the file is contained in a larger buffer laid down by the booter or
181 * sent from user space, the OSKext stores that OSData under this key so that
182 * references are properly tracked. This is always an mkext, right now.
184 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
186 #define OS_LOG_HDR_VERSION 1
187 #define NUM_OS_LOG_SECTIONS 2
189 #define OS_LOG_SECT_IDX 0
190 #define CSTRING_SECT_IDX 1
193 #pragma mark Typedefs
195 /*********************************************************************
197 *********************************************************************/
199 /*********************************************************************
200 * osLogDataHeaderRef describes the header information of an OSData
201 * object that is returned when querying for kOSBundleLogStringsKey.
202 * We currently return information regarding 2 sections - os_log and
203 * cstring. In the case that the os_log section doesn't exist, we just
204 * return an offset and length of 0 for that section.
205 *********************************************************************/
206 typedef struct osLogDataHeader
{
210 uint32_t sect_offset
;
213 } osLogDataHeaderRef
;
215 /*********************************************************************
216 * MkextEntryRef describes the contents of an OSData object
217 * referencing a file entry from an mkext so that we can uncompress
218 * (if necessary) and extract it on demand.
220 * It contains the mkextVersion in case we ever wind up supporting
221 * multiple mkext formats. Mkext format 1 is officially retired as of
223 *********************************************************************/
224 typedef struct MkextEntryRef
{
225 mkext_basic_header
* mkext
; // beginning of whole mkext file
226 void * fileinfo
; // mkext2_file_entry or equiv; see mkext.h
230 #pragma mark Global and static Module Variables
232 /*********************************************************************
233 * Global & static variables, used to keep track of kexts.
234 *********************************************************************/
236 static bool sPrelinkBoot
= false;
237 static bool sSafeBoot
= false;
238 static bool sKeepSymbols
= false;
240 /*********************************************************************
241 * sKextLock is the principal lock for OSKext, and guards all static
242 * and global variables not owned by other locks (declared further
243 * below). It must be taken by any entry-point method or function,
244 * including internal functions called on scheduled threads.
246 * sKextLock and sKextInnerLock are recursive due to multiple functions
247 * that are called both externally and internally. The other locks are
250 * Which locks are taken depends on what they protect, but if more than
251 * one must be taken, they must always be locked in this order
252 * (and unlocked in reverse order) to prevent deadlocks:
256 * 3. sKextSummariesLock
257 * 4. sKextLoggingLock
259 static IORecursiveLock
* sKextLock
= NULL
;
261 static OSDictionary
* sKextsByID
= NULL
;
262 static OSDictionary
* sExcludeListByID
= NULL
;
263 static OSArray
* sLoadedKexts
= NULL
;
264 static OSArray
* sUnloadedPrelinkedKexts
= NULL
;
266 // Requests to kextd waiting to be picked up.
267 static OSArray
* sKernelRequests
= NULL
;
268 // Identifier of kext load requests in sKernelRequests
269 static OSSet
* sPostedKextLoadIdentifiers
= NULL
;
270 static OSArray
* sRequestCallbackRecords
= NULL
;
272 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
273 static OSSet
* sAllKextLoadIdentifiers
= NULL
;
274 static KXLDContext
* sKxldContext
= NULL
;
275 static uint32_t sNextLoadTag
= 0;
276 static uint32_t sNextRequestTag
= 0;
278 static bool sUserLoadsActive
= false;
279 static bool sKextdActive
= false;
280 static bool sDeferredLoadSucceeded
= false;
281 static bool sConsiderUnloadsExecuted
= false;
284 static bool sKernelRequestsEnabled
= false;
286 static bool sKernelRequestsEnabled
= true;
288 static bool sLoadEnabled
= true;
289 static bool sUnloadEnabled
= true;
291 /*********************************************************************
292 * Stuff for the OSKext representing the kernel itself.
294 static OSKext
* sKernelKext
= NULL
;
296 /* Set up a fake kmod_info struct for the kernel.
297 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
298 * before OSKext is initialized; that call only needs the name
299 * and address to be set correctly.
301 * We don't do much else with the kerne's kmod_info; we never
302 * put it into the kmod list, never adjust the reference count,
303 * and never have kernel components reference it.
304 * For that matter, we don't do much with kmod_info structs
305 * at all anymore! We just keep them filled in for gdb and
306 * binary compability.
308 kmod_info_t g_kernel_kmod_info
= {
310 /* info_version */ KMOD_INFO_VERSION
,
311 /* id */ 0, // loadTag: kernel is always 0
312 /* name */ kOSKextKernelIdentifier
, // bundle identifier
313 /* version */ "0", // filled in in OSKext::initialize()
314 /* reference_count */ -1, // never adjusted; kernel never unloads
315 /* reference_list */ NULL
,
317 /* size */ 0, // filled in in OSKext::initialize()
324 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
325 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
326 // misc_protos.h, db_low_trace.c, kgmacros
327 // 'kmod' is a holdover from the old kmod system, we can't rename it.
328 kmod_info_t
* kmod
= NULL
;
330 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
333 static char * loaded_kext_paniclist
= NULL
;
334 static uint32_t loaded_kext_paniclist_size
= 0;
336 AbsoluteTime last_loaded_timestamp
;
337 static char last_loaded_str_buf
[2*KMOD_MAX_NAME
];
338 static u_long last_loaded_strlen
= 0;
339 static void * last_loaded_address
= NULL
;
340 static u_long last_loaded_size
= 0;
342 AbsoluteTime last_unloaded_timestamp
;
343 static char last_unloaded_str_buf
[2*KMOD_MAX_NAME
];
344 static u_long last_unloaded_strlen
= 0;
345 static void * last_unloaded_address
= NULL
;
346 static u_long last_unloaded_size
= 0;
348 /*********************************************************************
349 * sKextInnerLock protects against cross-calls with IOService and
350 * IOCatalogue, and owns the variables declared immediately below.
352 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
354 * When both sKextLock and sKextInnerLock need to be taken,
355 * always lock sKextLock first and unlock it second. Never take both
356 * locks in an entry point to OSKext; if you need to do so, you must
357 * spawn an independent thread to avoid potential deadlocks for threads
358 * calling into OSKext.
360 static IORecursiveLock
* sKextInnerLock
= NULL
;
362 static bool sAutounloadEnabled
= true;
363 static bool sConsiderUnloadsCalled
= false;
364 static bool sConsiderUnloadsPending
= false;
366 static unsigned int sConsiderUnloadDelay
= 60; // seconds
367 static thread_call_t sUnloadCallout
= 0;
368 static thread_call_t sDestroyLinkContextThread
= 0; // one-shot, one-at-a-time thread
369 static bool sSystemSleep
= false; // true when system going to sleep
370 static AbsoluteTime sLastWakeTime
; // last time we woke up
372 /*********************************************************************
373 * Backtraces can be printed at various times so we need a tight lock
374 * on data used for that. sKextSummariesLock protects the variables
375 * declared immediately below.
377 * gLoadedKextSummaries is accessed by other modules, but only during
378 * a panic so the lock isn't needed then.
380 * gLoadedKextSummaries has the "used" attribute in order to ensure
381 * that it remains visible even when we are performing extremely
382 * aggressive optimizations, as it is needed to allow the debugger
383 * to automatically parse the list of loaded kexts.
385 static IOLock
* sKextSummariesLock
= NULL
;
386 extern "C" lck_spin_t vm_allocation_sites_lock
;
387 static IOSimpleLock
* sKextAccountsLock
= &vm_allocation_sites_lock
;
389 void (*sLoadedKextSummariesUpdated
)(void) = OSKextLoadedKextSummariesUpdated
;
390 OSKextLoadedKextSummaryHeader
* gLoadedKextSummaries
__attribute__((used
)) = NULL
;
391 uint64_t gLoadedKextSummariesTimestamp
__attribute__((used
)) = 0;
392 static size_t sLoadedKextSummariesAllocSize
= 0;
394 static OSKextActiveAccount
* sKextAccounts
;
395 static uint32_t sKextAccountsCount
;
398 /*********************************************************************
399 * sKextLoggingLock protects the logging variables declared immediately below.
401 static IOLock
* sKextLoggingLock
= NULL
;
403 static const OSKextLogSpec kDefaultKernelLogFilter
= kOSKextLogBasicLevel
|
404 kOSKextLogVerboseFlagsMask
;
405 static OSKextLogSpec sKernelLogFilter
= kDefaultKernelLogFilter
;
406 static bool sBootArgLogFilterFound
= false;
407 SYSCTL_UINT(_debug
, OID_AUTO
, kextlog
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &sKernelLogFilter
,
408 0, "kernel kext logging");
410 static OSKextLogSpec sUserSpaceKextLogFilter
= kOSKextLogSilentFilter
;
411 static OSArray
* sUserSpaceLogSpecArray
= NULL
;
412 static OSArray
* sUserSpaceLogMessageArray
= NULL
;
415 * End scope for sKextInnerLock-protected variables.
416 *********************************************************************/
419 /*********************************************************************
420 helper function used for collecting PGO data upon unload of a kext
423 static int OSKextGrabPgoDataLocked(OSKext
*kext
,
425 uuid_t instance_uuid
,
428 uint64_t bufferSize
);
430 /**********************************************************************/
435 #pragma mark OSData callbacks (need to move to OSData)
437 /*********************************************************************
438 * C functions used for callbacks.
439 *********************************************************************/
441 void osdata_kmem_free(void * ptr
, unsigned int length
) {
442 kmem_free(kernel_map
, (vm_address_t
)ptr
, length
);
446 void osdata_phys_free(void * ptr
, unsigned int length
) {
447 ml_static_mfree((vm_offset_t
)ptr
, length
);
451 void osdata_vm_deallocate(void * ptr
, unsigned int length
)
453 (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
);
457 void osdata_kext_free(void * ptr
, unsigned int length
)
459 (void)kext_free((vm_offset_t
)ptr
, length
);
465 #pragma mark KXLD Allocation Callback
467 /*********************************************************************
468 * KXLD Allocation Callback
469 *********************************************************************/
473 KXLDAllocateFlags
* flags
,
476 vm_address_t result
= 0; // returned
477 kern_return_t mach_result
= KERN_FAILURE
;
478 bool success
= false;
479 OSKext
* theKext
= (OSKext
*)user_data
;
480 u_long roundSize
= round_page(size
);
481 OSData
* linkBuffer
= NULL
; // must release
483 mach_result
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
);
484 if (mach_result
!= KERN_SUCCESS
) {
486 kOSKextLogErrorLevel
|
487 kOSKextLogGeneralFlag
,
488 "Can't allocate kernel memory to link %s.",
489 theKext
->getIdentifierCString());
493 /* Create an OSData wrapper for the allocated buffer.
495 linkBuffer
= OSData::withBytesNoCopy((void *)result
, roundSize
);
498 kOSKextLogErrorLevel
|
499 kOSKextLogGeneralFlag
,
500 "Can't allocate linked executable wrapper for %s.",
501 theKext
->getIdentifierCString());
504 linkBuffer
->setDeallocFunction(osdata_kext_free
);
506 kOSKextLogProgressLevel
|
507 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
508 "Allocated link buffer for kext %s at %p (%lu bytes).",
509 theKext
->getIdentifierCString(),
510 (void *)result
, (unsigned long)roundSize
);
512 theKext
->setLinkedExecutable(linkBuffer
);
514 *flags
= kKxldAllocateWritable
;
518 if (!success
&& result
) {
519 kext_free(result
, roundSize
);
523 OSSafeReleaseNULL(linkBuffer
);
525 return (kxld_addr_t
)result
;
528 /*********************************************************************
529 *********************************************************************/
532 KXLDLogSubsystem subsystem
,
538 OSKext
*theKext
= (OSKext
*) user_data
;
539 OSKextLogSpec logSpec
= 0;
542 case kKxldLogLinking
:
543 logSpec
|= kOSKextLogLinkFlag
;
545 case kKxldLogPatching
:
546 logSpec
|= kOSKextLogPatchFlag
;
551 case kKxldLogExplicit
:
552 logSpec
|= kOSKextLogExplicitLevel
;
555 logSpec
|= kOSKextLogErrorLevel
;
558 logSpec
|= kOSKextLogWarningLevel
;
561 logSpec
|= kOSKextLogProgressLevel
;
564 logSpec
|= kOSKextLogDetailLevel
;
567 logSpec
|= kOSKextLogDebugLevel
;
571 OSKextVLog(theKext
, logSpec
, format
, argList
);
575 #pragma mark IOStatistics defines
580 #define notifyKextLoadObservers(kext, kmod_info) \
582 IOStatistics::onKextLoad(kext, kmod_info); \
585 #define notifyKextUnloadObservers(kext) \
587 IOStatistics::onKextUnload(kext); \
590 #define notifyAddClassObservers(kext, addedClass, flags) \
592 IOStatistics::onClassAdded(kext, addedClass); \
595 #define notifyRemoveClassObservers(kext, removedClass, flags) \
597 IOStatistics::onClassRemoved(kext, removedClass); \
602 #define notifyKextLoadObservers(kext, kmod_info)
603 #define notifyKextUnloadObservers(kext)
604 #define notifyAddClassObservers(kext, addedClass, flags)
605 #define notifyRemoveClassObservers(kext, removedClass, flags)
607 #endif /* IOKITSTATS */
610 #pragma mark Module Config (Startup & Shutdown)
612 /*********************************************************************
613 * Module Config (Class Definition & Class Methods)
614 *********************************************************************/
615 #define super OSObject
616 OSDefineMetaClassAndStructors(OSKext
, OSObject
)
618 /*********************************************************************
619 *********************************************************************/
622 OSKext::initialize(void)
624 OSData
* kernelExecutable
= NULL
; // do not release
625 u_char
* kernelStart
= NULL
; // do not free
626 size_t kernelLength
= 0;
627 OSString
* scratchString
= NULL
; // must release
628 IORegistryEntry
* registryRoot
= NULL
; // do not release
629 OSNumber
* kernelCPUType
= NULL
; // must release
630 OSNumber
* kernelCPUSubtype
= NULL
; // must release
631 OSKextLogSpec bootLogFilter
= kOSKextLogSilentFilter
;
632 bool setResult
= false;
633 uint64_t * timestamp
= 0;
634 char bootArgBuffer
[16]; // for PE_parse_boot_argn w/strings
636 /* This must be the first thing allocated. Everything else grabs this lock.
638 sKextLock
= IORecursiveLockAlloc();
639 sKextInnerLock
= IORecursiveLockAlloc();
640 sKextSummariesLock
= IOLockAlloc();
641 sKextLoggingLock
= IOLockAlloc();
643 assert(sKextInnerLock
);
644 assert(sKextSummariesLock
);
645 assert(sKextLoggingLock
);
647 sKextsByID
= OSDictionary::withCapacity(kOSKextTypicalLoadCount
);
648 sLoadedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
);
649 sUnloadedPrelinkedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
/ 10);
650 sKernelRequests
= OSArray::withCapacity(0);
651 sPostedKextLoadIdentifiers
= OSSet::withCapacity(0);
652 sAllKextLoadIdentifiers
= OSSet::withCapacity(kOSKextTypicalLoadCount
);
653 sRequestCallbackRecords
= OSArray::withCapacity(0);
654 assert(sKextsByID
&& sLoadedKexts
&& sKernelRequests
&&
655 sPostedKextLoadIdentifiers
&& sAllKextLoadIdentifiers
&&
656 sRequestCallbackRecords
&& sUnloadedPrelinkedKexts
);
658 /* Read the log flag boot-args and set the log flags.
660 if (PE_parse_boot_argn("kextlog", &bootLogFilter
, sizeof(bootLogFilter
))) {
661 sBootArgLogFilterFound
= true;
662 sKernelLogFilter
= bootLogFilter
;
663 // log this if any flags are set
664 OSKextLog(/* kext */ NULL
,
665 kOSKextLogBasicLevel
|
667 "Kernel kext log filter 0x%x per kextlog boot arg.",
668 (unsigned)sKernelLogFilter
);
671 sSafeBoot
= PE_parse_boot_argn("-x", bootArgBuffer
,
672 sizeof(bootArgBuffer
)) ? true : false;
675 OSKextLog(/* kext */ NULL
,
676 kOSKextLogWarningLevel
|
677 kOSKextLogGeneralFlag
,
678 "SAFE BOOT DETECTED - "
679 "only valid OSBundleRequired kexts will be loaded.");
682 PE_parse_boot_argn("keepsyms", &sKeepSymbols
, sizeof(sKeepSymbols
));
684 /* Set up an OSKext instance to represent the kernel itself.
686 sKernelKext
= new OSKext
;
689 kernelStart
= (u_char
*)&_mh_execute_header
;
690 kernelLength
= getlastaddr() - (vm_offset_t
)kernelStart
;
691 kernelExecutable
= OSData::withBytesNoCopy(
692 kernelStart
, kernelLength
);
693 assert(kernelExecutable
);
696 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %llu (0x%016lx) \n",
697 (unsigned long)kernelStart
,
698 (unsigned long)getlastaddr(),
700 vm_kernel_slide
, vm_kernel_slide
);
703 sKernelKext
->loadTag
= sNextLoadTag
++; // the kernel is load tag 0
704 sKernelKext
->bundleID
= OSSymbol::withCString(kOSKextKernelIdentifier
);
706 sKernelKext
->version
= OSKextParseVersionString(osrelease
);
707 sKernelKext
->compatibleVersion
= sKernelKext
->version
;
708 sKernelKext
->linkedExecutable
= kernelExecutable
;
710 sKernelKext
->flags
.hasAllDependencies
= 1;
711 sKernelKext
->flags
.kernelComponent
= 1;
712 sKernelKext
->flags
.prelinked
= 0;
713 sKernelKext
->flags
.loaded
= 1;
714 sKernelKext
->flags
.started
= 1;
715 sKernelKext
->flags
.CPPInitialized
= 0;
716 sKernelKext
->flags
.jettisonLinkeditSeg
= 0;
718 sKernelKext
->kmod_info
= &g_kernel_kmod_info
;
719 strlcpy(g_kernel_kmod_info
.version
, osrelease
,
720 sizeof(g_kernel_kmod_info
.version
));
721 g_kernel_kmod_info
.size
= kernelLength
;
722 g_kernel_kmod_info
.id
= sKernelKext
->loadTag
;
724 /* Cons up an info dict, so we don't have to have special-case
727 sKernelKext
->infoDict
= OSDictionary::withCapacity(5);
728 assert(sKernelKext
->infoDict
);
729 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
,
730 sKernelKext
->bundleID
);
732 setResult
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
,
736 scratchString
= OSString::withCStringNoCopy(osrelease
);
737 assert(scratchString
);
738 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
,
741 OSSafeReleaseNULL(scratchString
);
743 scratchString
= OSString::withCStringNoCopy("mach_kernel");
744 assert(scratchString
);
745 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
,
748 OSSafeReleaseNULL(scratchString
);
750 /* Add the kernel kext to the bookkeeping dictionaries. Note that
751 * the kernel kext doesn't have a kmod_info struct. copyInfo()
752 * gathers info from other places anyhow.
754 setResult
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
);
756 setResult
= sLoadedKexts
->setObject(sKernelKext
);
758 sKernelKext
->release();
760 registryRoot
= IORegistryEntry::getRegistryRoot();
761 kernelCPUType
= OSNumber::withNumber(
762 (long long unsigned int)_mh_execute_header
.cputype
,
763 8 * sizeof(_mh_execute_header
.cputype
));
764 kernelCPUSubtype
= OSNumber::withNumber(
765 (long long unsigned int)_mh_execute_header
.cpusubtype
,
766 8 * sizeof(_mh_execute_header
.cpusubtype
));
767 assert(registryRoot
&& kernelCPUSubtype
&& kernelCPUType
);
769 registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
);
770 registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
);
772 OSSafeReleaseNULL(kernelCPUType
);
773 OSSafeReleaseNULL(kernelCPUSubtype
);
775 timestamp
= __OSAbsoluteTimePtr(&last_loaded_timestamp
);
777 timestamp
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
);
779 timestamp
= __OSAbsoluteTimePtr(&sLastWakeTime
);
782 OSKextLog(/* kext */ NULL
,
783 kOSKextLogProgressLevel
|
784 kOSKextLogGeneralFlag
,
785 "Kext system initialized.");
787 notifyKextLoadObservers(sKernelKext
, sKernelKext
->kmod_info
);
792 /*********************************************************************
793 * This could be in OSKextLib.cpp but we need to hold a lock
794 * while removing all the segments and sKextLock will do.
795 *********************************************************************/
798 OSKext::removeKextBootstrap(void)
800 OSReturn result
= kOSReturnError
;
802 static bool alreadyDone
= false;
804 const char * dt_kernel_header_name
= "Kernel-__HEADER";
805 const char * dt_kernel_symtab_name
= "Kernel-__SYMTAB";
806 kernel_mach_header_t
* dt_mach_header
= NULL
;
807 int dt_mach_header_size
= 0;
808 struct symtab_command
* dt_symtab
= NULL
;
809 int dt_symtab_size
= 0;
812 kernel_segment_command_t
* seg_to_remove
= NULL
;
815 /* This must be the very first thing done by this function.
817 IORecursiveLockLock(sKextLock
);
819 /* If we already did this, it's a success.
822 result
= kOSReturnSuccess
;
826 OSKextLog(/* kext */ NULL
,
827 kOSKextLogProgressLevel
|
828 kOSKextLogGeneralFlag
,
829 "Jettisoning kext bootstrap segments.");
832 * Dispose of unnecessary stuff that the booter didn't need to load.
834 dt_result
= IODTGetLoaderInfo(dt_kernel_header_name
,
835 (void **)&dt_mach_header
, &dt_mach_header_size
);
836 if (dt_result
== 0 && dt_mach_header
) {
837 IODTFreeLoaderInfo(dt_kernel_header_name
, (void *)dt_mach_header
,
838 round_page_32(dt_mach_header_size
));
840 dt_result
= IODTGetLoaderInfo(dt_kernel_symtab_name
,
841 (void **)&dt_symtab
, &dt_symtab_size
);
842 if (dt_result
== 0 && dt_symtab
) {
843 IODTFreeLoaderInfo(dt_kernel_symtab_name
, (void *)dt_symtab
,
844 round_page_32(dt_symtab_size
));
848 * KLD bootstrap segment.
850 // xxx - should rename KLD segment
851 seg_to_remove
= getsegbyname("__KLD");
853 OSRuntimeUnloadCPPForSegment(seg_to_remove
);
856 #if __i386__ || __x86_64__
857 /* On x86, use the mapping data from the segment load command to
858 * unload KLD directly.
859 * This may invalidate any assumptions about "avail_start"
860 * defining the lower bound for valid physical addresses.
862 if (seg_to_remove
&& seg_to_remove
->vmaddr
&& seg_to_remove
->vmsize
) {
863 // 04/18/11 - gab: <rdar://problem/9236163>
864 // overwrite memory occupied by KLD segment with random data before
866 read_frandom((void *) seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
867 ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
873 seg_to_remove
= NULL
;
876 * Prelinked kernel's symtab (if there is one).
878 kernel_section_t
* sect
;
879 sect
= getsectbyname("__PRELINK", "__symtab");
880 if (sect
&& sect
->addr
&& sect
->size
) {
881 ml_static_mfree(sect
->addr
, sect
->size
);
884 seg_to_remove
= (kernel_segment_command_t
*)getsegbyname("__LINKEDIT");
886 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
887 * pageable, unless keepsyms is set. To do that, we have to copy it from
888 * its booter-allocated memory, free the booter memory, reallocate proper
889 * managed memory, then copy the segment back in.
893 kern_return_t mem_result
;
894 void *seg_copy
= NULL
;
895 void *seg_data
= NULL
;
896 vm_map_offset_t seg_offset
= 0;
897 vm_map_offset_t seg_copy_offset
= 0;
898 vm_map_size_t seg_length
= 0;
900 seg_data
= (void *) seg_to_remove
->vmaddr
;
901 seg_offset
= (vm_map_offset_t
) seg_to_remove
->vmaddr
;
902 seg_length
= (vm_map_size_t
) seg_to_remove
->vmsize
;
904 /* Allocate space for the LINKEDIT copy.
906 mem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*) &seg_copy
,
907 seg_length
, VM_KERN_MEMORY_KEXT
);
908 if (mem_result
!= KERN_SUCCESS
) {
909 OSKextLog(/* kext */ NULL
,
910 kOSKextLogErrorLevel
|
911 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
912 "Can't copy __LINKEDIT segment for VM reassign.");
915 seg_copy_offset
= (vm_map_offset_t
) seg_copy
;
919 memcpy(seg_copy
, seg_data
, seg_length
);
921 /* Dump the booter memory.
923 ml_static_mfree(seg_offset
, seg_length
);
925 /* Set up the VM region.
927 mem_result
= vm_map_enter_mem_object(
930 seg_length
, /* mask */ 0,
931 VM_FLAGS_FIXED
| VM_FLAGS_OVERWRITE
,
933 (vm_object_offset_t
) 0,
935 /* cur_protection */ VM_PROT_READ
| VM_PROT_WRITE
,
936 /* max_protection */ VM_PROT_ALL
,
937 /* inheritance */ VM_INHERIT_DEFAULT
);
938 if ((mem_result
!= KERN_SUCCESS
) ||
939 (seg_offset
!= (vm_map_offset_t
) seg_data
))
941 OSKextLog(/* kext */ NULL
,
942 kOSKextLogErrorLevel
|
943 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
944 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
945 seg_data
, seg_length
, mem_result
);
951 memcpy(seg_data
, seg_copy
, seg_length
);
955 kmem_free(kernel_map
, seg_copy_offset
, seg_length
);
957 #else /* we are not CONFIG_KXLD */
958 #error CONFIG_KXLD is expected for this arch
961 * Dump the LINKEDIT segment, unless keepsyms is set.
964 dt_segment_name
= "Kernel-__LINKEDIT";
965 if (0 == IODTGetLoaderInfo(dt_segment_name
,
966 &segment_paddress
, &segment_size
)) {
968 vm_offset_t vmaddr
= ml_static_ptovirt((vm_offset_t
)segment_paddress
);
969 bzero((void*)vmaddr
, segment_size
);
971 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
975 OSKextLog(/* kext */ NULL
,
976 kOSKextLogBasicLevel
|
977 kOSKextLogGeneralFlag
,
978 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
980 #endif /* CONFIG_KXLD */
982 seg_to_remove
= NULL
;
985 result
= kOSReturnSuccess
;
989 /* This must be the very last thing done before returning.
991 IORecursiveLockUnlock(sKextLock
);
996 /*********************************************************************
997 *********************************************************************/
999 OSKext::flushNonloadedKexts(
1000 Boolean flushPrelinkedKexts
)
1002 OSSet
* prelinkedKexts
= NULL
; // must release
1003 OSCollectionIterator
* kextIterator
= NULL
; // must release
1004 OSCollectionIterator
* prelinkIterator
= NULL
; // must release
1005 const OSSymbol
* thisID
= NULL
; // do not release
1006 OSKext
* thisKext
= NULL
; // do not release
1009 IORecursiveLockLock(sKextLock
);
1011 OSKextLog(/* kext */ NULL
,
1012 kOSKextLogProgressLevel
|
1013 kOSKextLogKextBookkeepingFlag
,
1014 "Flushing nonloaded kexts and other unused data.");
1016 OSKext::considerDestroyingLinkContext();
1018 /* If we aren't flushing unused prelinked kexts, we have to put them
1019 * aside while we flush everything else so make a container for them.
1021 if (!flushPrelinkedKexts
) {
1022 prelinkedKexts
= OSSet::withCapacity(0);
1023 if (!prelinkedKexts
) {
1028 /* Set aside prelinked kexts (in-use or not) and break
1029 * any lingering inter-kext references for nonloaded kexts
1030 * so they have min. retain counts.
1032 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1033 if (!kextIterator
) {
1037 while ((thisID
= OSDynamicCast(OSSymbol
,
1038 kextIterator
->getNextObject()))) {
1040 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1043 if (prelinkedKexts
&& thisKext
->isPrelinked()) {
1044 prelinkedKexts
->setObject(thisKext
);
1046 thisKext
->flushDependencies(/* forceIfLoaded */ false);
1050 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1052 sKextsByID
->flushCollection();
1054 /* Now put the loaded kexts back into the ID dictionary.
1056 count
= sLoadedKexts
->getCount();
1057 for (i
= 0; i
< count
; i
++) {
1058 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
1059 sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
);
1062 /* Finally, put back the prelinked kexts if we saved any.
1064 if (prelinkedKexts
) {
1065 prelinkIterator
= OSCollectionIterator::withCollection(prelinkedKexts
);
1066 if (!prelinkIterator
) {
1070 while ((thisKext
= OSDynamicCast(OSKext
,
1071 prelinkIterator
->getNextObject()))) {
1073 sKextsByID
->setObject(thisKext
->getIdentifierCString(),
1079 IORecursiveLockUnlock(sKextLock
);
1081 OSSafeReleaseNULL(prelinkedKexts
);
1082 OSSafeReleaseNULL(kextIterator
);
1083 OSSafeReleaseNULL(prelinkIterator
);
1088 /*********************************************************************
1089 *********************************************************************/
1092 OSKext::setKextdActive(Boolean active
)
1094 IORecursiveLockLock(sKextLock
);
1095 sKextdActive
= active
;
1096 if (sKernelRequests
->getCount()) {
1097 OSKext::pingKextd();
1099 IORecursiveLockUnlock(sKextLock
);
1104 /*********************************************************************
1105 * OSKextLib.cpp might need access to this someday but for now it's
1107 *********************************************************************/
1109 extern void ipc_port_release_send(ipc_port_t
);
1114 OSKext::pingKextd(void)
1116 OSReturn result
= kOSReturnError
;
1118 mach_port_t kextd_port
= IPC_PORT_NULL
;
1120 if (!sKextdActive
) {
1121 result
= kOSKextReturnDisabled
; // basically unavailable
1125 result
= host_get_kextd_port(host_priv_self(), &kextd_port
);
1126 if (result
!= KERN_SUCCESS
|| !IPC_PORT_VALID(kextd_port
)) {
1127 OSKextLog(/* kext */ NULL
,
1128 kOSKextLogErrorLevel
|
1130 "Can't get kextd port.");
1134 result
= kextd_ping(kextd_port
);
1135 if (result
!= KERN_SUCCESS
) {
1136 OSKextLog(/* kext */ NULL
,
1137 kOSKextLogErrorLevel
|
1139 "kextd ping failed (0x%x).", (int)result
);
1144 if (IPC_PORT_VALID(kextd_port
)) {
1145 ipc_port_release_send(kextd_port
);
1152 /*********************************************************************
1153 *********************************************************************/
1156 OSKext::setDeferredLoadSucceeded(Boolean succeeded
)
1158 IORecursiveLockLock(sKextLock
);
1159 sDeferredLoadSucceeded
= succeeded
;
1160 IORecursiveLockUnlock(sKextLock
);
1165 /*********************************************************************
1166 * Called from IOSystemShutdownNotification.
1167 *********************************************************************/
1170 OSKext::willShutdown(void)
1173 OSReturn checkResult
= kOSReturnError
;
1175 OSDictionary
* exitRequest
= NULL
; // must release
1177 IORecursiveLockLock(sKextLock
);
1179 OSKext::setLoadEnabled(false);
1180 OSKext::setUnloadEnabled(false);
1181 OSKext::setAutounloadsEnabled(false);
1182 OSKext::setKernelRequestsEnabled(false);
1185 OSKextLog(/* kext */ NULL
,
1186 kOSKextLogProgressLevel
|
1187 kOSKextLogGeneralFlag
,
1188 "System shutdown; requesting immediate kextd exit.");
1190 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
,
1192 if (checkResult
!= kOSReturnSuccess
) {
1195 if (!sKernelRequests
->setObject(exitRequest
)) {
1199 OSKext::pingKextd();
1204 IORecursiveLockUnlock(sKextLock
);
1206 OSSafeReleaseNULL(exitRequest
);
1210 /*********************************************************************
1211 *********************************************************************/
1214 OSKext::getLoadEnabled(void)
1218 IORecursiveLockLock(sKextLock
);
1219 result
= sLoadEnabled
;
1220 IORecursiveLockUnlock(sKextLock
);
1224 /*********************************************************************
1225 *********************************************************************/
1228 OSKext::setLoadEnabled(bool flag
)
1232 IORecursiveLockLock(sKextLock
);
1233 result
= sLoadEnabled
;
1234 sLoadEnabled
= (flag
? true : false);
1236 if (sLoadEnabled
!= result
) {
1237 OSKextLog(/* kext */ NULL
,
1238 kOSKextLogBasicLevel
|
1240 "Kext loading now %sabled.", sLoadEnabled
? "en" : "dis");
1243 IORecursiveLockUnlock(sKextLock
);
1248 /*********************************************************************
1249 *********************************************************************/
1252 OSKext::getUnloadEnabled(void)
1256 IORecursiveLockLock(sKextLock
);
1257 result
= sUnloadEnabled
;
1258 IORecursiveLockUnlock(sKextLock
);
1262 /*********************************************************************
1263 *********************************************************************/
1266 OSKext::setUnloadEnabled(bool flag
)
1270 IORecursiveLockLock(sKextLock
);
1271 result
= sUnloadEnabled
;
1272 sUnloadEnabled
= (flag
? true : false);
1273 IORecursiveLockUnlock(sKextLock
);
1275 if (sUnloadEnabled
!= result
) {
1276 OSKextLog(/* kext */ NULL
,
1277 kOSKextLogBasicLevel
|
1278 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1279 "Kext unloading now %sabled.", sUnloadEnabled
? "en" : "dis");
1285 /*********************************************************************
1286 * Do not call any function that takes sKextLock here!
1287 *********************************************************************/
1290 OSKext::getAutounloadEnabled(void)
1294 IORecursiveLockLock(sKextInnerLock
);
1295 result
= sAutounloadEnabled
? true : false;
1296 IORecursiveLockUnlock(sKextInnerLock
);
1300 /*********************************************************************
1301 * Do not call any function that takes sKextLock here!
1302 *********************************************************************/
1305 OSKext::setAutounloadsEnabled(bool flag
)
1309 IORecursiveLockLock(sKextInnerLock
);
1311 result
= sAutounloadEnabled
;
1312 sAutounloadEnabled
= (flag
? true : false);
1313 if (!sAutounloadEnabled
&& sUnloadCallout
) {
1314 thread_call_cancel(sUnloadCallout
);
1317 if (sAutounloadEnabled
!= result
) {
1318 OSKextLog(/* kext */ NULL
,
1319 kOSKextLogBasicLevel
|
1320 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1321 "Kext autounloading now %sabled.",
1322 sAutounloadEnabled
? "en" : "dis");
1325 IORecursiveLockUnlock(sKextInnerLock
);
1330 /*********************************************************************
1331 *********************************************************************/
1332 /* instance method operating on OSKext field */
1334 OSKext::setAutounloadEnabled(bool flag
)
1336 bool result
= flags
.autounloadEnabled
? true : false;
1337 flags
.autounloadEnabled
= flag
? 1 : 0;
1339 if (result
!= (flag
? true : false)) {
1341 kOSKextLogProgressLevel
|
1342 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
1343 "Autounloading for kext %s now %sabled.",
1344 getIdentifierCString(),
1345 flags
.autounloadEnabled
? "en" : "dis");
1350 /*********************************************************************
1351 *********************************************************************/
1354 OSKext::setKernelRequestsEnabled(bool flag
)
1358 IORecursiveLockLock(sKextLock
);
1359 result
= sKernelRequestsEnabled
;
1360 sKernelRequestsEnabled
= flag
? true : false;
1362 if (sKernelRequestsEnabled
!= result
) {
1363 OSKextLog(/* kext */ NULL
,
1364 kOSKextLogBasicLevel
|
1365 kOSKextLogGeneralFlag
,
1366 "Kernel requests now %sabled.",
1367 sKernelRequestsEnabled
? "en" : "dis");
1369 IORecursiveLockUnlock(sKextLock
);
1373 /*********************************************************************
1374 *********************************************************************/
1377 OSKext::getKernelRequestsEnabled(void)
1381 IORecursiveLockLock(sKextLock
);
1382 result
= sKernelRequestsEnabled
;
1383 IORecursiveLockUnlock(sKextLock
);
1388 #pragma mark Kext Life Cycle
1390 /*********************************************************************
1391 *********************************************************************/
1393 OSKext::withPrelinkedInfoDict(
1394 OSDictionary
* anInfoDict
,
1395 bool doCoalesedSlides
)
1397 OSKext
* newKext
= new OSKext
;
1399 if (newKext
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
, doCoalesedSlides
)) {
1407 /*********************************************************************
1408 *********************************************************************/
1410 OSKext::initWithPrelinkedInfoDict(
1411 OSDictionary
* anInfoDict
,
1412 bool doCoalesedSlides
)
1414 bool result
= false;
1415 OSString
* kextPath
= NULL
; // do not release
1416 OSNumber
* addressNum
= NULL
; // reused; do not release
1417 OSNumber
* lengthNum
= NULL
; // reused; do not release
1418 void * data
= NULL
; // do not free
1419 void * srcData
= NULL
; // do not free
1420 OSData
* prelinkedExecutable
= NULL
; // must release
1421 uint32_t length
= 0; // reused
1423 if (!super::init()) {
1427 /* Get the path. Don't look for an arch-specific path property.
1429 kextPath
= OSDynamicCast(OSString
,
1430 anInfoDict
->getObject(kPrelinkBundlePathKey
));
1432 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
1435 #if KASLR_KEXT_DEBUG
1436 IOLog("kaslr: doCoalesedSlides %d kext %s \n", doCoalesedSlides
, getIdentifierCString());
1439 /* Also get the executable's bundle-relative path if present.
1440 * Don't look for an arch-specific path property.
1442 executableRelPath
= OSDynamicCast(OSString
,
1443 anInfoDict
->getObject(kPrelinkExecutableRelativePathKey
));
1444 if (executableRelPath
) {
1445 executableRelPath
->retain();
1448 /* Don't need the paths to be in the info dictionary any more.
1450 anInfoDict
->removeObject(kPrelinkBundlePathKey
);
1451 anInfoDict
->removeObject(kPrelinkExecutableRelativePathKey
);
1453 /* Create an OSData wrapper around the linked executable.
1455 addressNum
= OSDynamicCast(OSNumber
,
1456 anInfoDict
->getObject(kPrelinkExecutableLoadKey
));
1458 lengthNum
= OSDynamicCast(OSNumber
,
1459 anInfoDict
->getObject(kPrelinkExecutableSizeKey
));
1462 kOSKextLogErrorLevel
|
1463 kOSKextLogArchiveFlag
,
1464 "Kext %s can't find prelinked kext executable size.",
1465 getIdentifierCString());
1469 data
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1470 length
= (uint32_t) (lengthNum
->unsigned32BitValue());
1472 #if KASLR_KEXT_DEBUG
1473 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1474 (unsigned long)VM_KERNEL_UNSLIDE(data
),
1475 (unsigned long)data
,
1479 anInfoDict
->removeObject(kPrelinkExecutableLoadKey
);
1480 anInfoDict
->removeObject(kPrelinkExecutableSizeKey
);
1482 /* If the kext's load address differs from its source address, allocate
1483 * space in the kext map at the load address and copy the kext over.
1485 addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
));
1487 srcData
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1489 #if KASLR_KEXT_DEBUG
1490 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1491 (unsigned long)VM_KERNEL_UNSLIDE(srcData
),
1492 (unsigned long)srcData
);
1495 if (data
!= srcData
) {
1497 kern_return_t alloc_result
;
1499 alloc_result
= kext_alloc((vm_offset_t
*)&data
, length
, /* fixed */ TRUE
);
1500 if (alloc_result
!= KERN_SUCCESS
) {
1502 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1503 "Failed to allocate space for prelinked kext %s.",
1504 getIdentifierCString());
1507 memcpy(data
, srcData
, length
);
1510 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1511 "Error: prelinked kext %s - source and load addresses "
1512 "differ on ILP32 architecture.",
1513 getIdentifierCString());
1515 #endif /* __LP64__ */
1518 anInfoDict
->removeObject(kPrelinkExecutableSourceKey
);
1521 prelinkedExecutable
= OSData::withBytesNoCopy(data
, length
);
1522 if (!prelinkedExecutable
) {
1524 kOSKextLogErrorLevel
|
1525 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
1526 "Kext %s failed to create executable wrapper.",
1527 getIdentifierCString());
1532 prelinkedExecutable
->setDeallocFunction(osdata_kext_free
);
1534 prelinkedExecutable
->setDeallocFunction(osdata_phys_free
);
1536 setLinkedExecutable(prelinkedExecutable
);
1537 addressNum
= OSDynamicCast(OSNumber
,
1538 anInfoDict
->getObject(kPrelinkKmodInfoKey
));
1541 kOSKextLogErrorLevel
|
1542 kOSKextLogArchiveFlag
,
1543 "Kext %s can't find prelinked kext kmod_info address.",
1544 getIdentifierCString());
1548 if (addressNum
->unsigned64BitValue() != 0) {
1549 kmod_info
= (kmod_info_t
*) (intptr_t) (addressNum
->unsigned64BitValue() + vm_kernel_slide
);
1550 kmod_info
->address
+= vm_kernel_slide
;
1551 #if KASLR_KEXT_DEBUG
1552 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1553 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
),
1554 (unsigned long)kmod_info
);
1555 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1556 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
1557 (unsigned long)kmod_info
->address
);
1561 anInfoDict
->removeObject(kPrelinkKmodInfoKey
);
1564 /* If the plist has a UUID for an interface, save that off.
1566 if (isInterface()) {
1567 interfaceUUID
= OSDynamicCast(OSData
,
1568 anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
));
1569 if (interfaceUUID
) {
1570 interfaceUUID
->retain();
1571 anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
);
1575 result
= slidePrelinkedExecutable(doCoalesedSlides
);
1576 if (result
!= kOSReturnSuccess
) {
1580 if (doCoalesedSlides
== false) {
1581 /* set VM protections now, wire later at kext load */
1582 result
= setVMAttributes(true, false);
1583 if (result
!= KERN_SUCCESS
) {
1588 flags
.prelinked
= true;
1590 /* If we created a kext from prelink info,
1591 * we must be booting from a prelinked kernel.
1593 sPrelinkBoot
= true;
1595 result
= registerIdentifier();
1598 OSSafeReleaseNULL(prelinkedExecutable
);
1603 /*********************************************************************
1604 *********************************************************************/
1606 void OSKext::setAllVMAttributes(void)
1608 OSCollectionIterator
* kextIterator
= NULL
; // must release
1609 const OSSymbol
* thisID
= NULL
; // do not release
1611 IORecursiveLockLock(sKextLock
);
1613 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1614 if (!kextIterator
) {
1618 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
1619 OSKext
* thisKext
; // do not release
1621 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1622 if (!thisKext
|| thisKext
->isInterface() || !thisKext
->declaresExecutable()) {
1626 /* set VM protections now, wire later at kext load */
1627 thisKext
->setVMAttributes(true, false);
1631 IORecursiveLockUnlock(sKextLock
);
1632 OSSafeReleaseNULL(kextIterator
);
1637 /*********************************************************************
1638 *********************************************************************/
1640 OSKext::withBooterData(
1641 OSString
* deviceTreeName
,
1642 OSData
* booterData
)
1644 OSKext
* newKext
= new OSKext
;
1646 if (newKext
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) {
1654 /*********************************************************************
1655 *********************************************************************/
1656 typedef struct _BooterKextFileInfo
{
1657 uint32_t infoDictPhysAddr
;
1658 uint32_t infoDictLength
;
1659 uint32_t executablePhysAddr
;
1660 uint32_t executableLength
;
1661 uint32_t bundlePathPhysAddr
;
1662 uint32_t bundlePathLength
;
1663 } _BooterKextFileInfo
;
1666 OSKext::initWithBooterData(
1667 OSString
* deviceTreeName
,
1668 OSData
* booterData
)
1670 bool result
= false;
1671 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not free
1672 char * infoDictAddr
= NULL
; // do not free
1673 void * executableAddr
= NULL
; // do not free
1674 char * bundlePathAddr
= NULL
; // do not free
1676 OSObject
* parsedXML
= NULL
; // must release
1677 OSDictionary
* theInfoDict
= NULL
; // do not release
1678 OSString
* kextPath
= NULL
; // must release
1679 OSString
* errorString
= NULL
; // must release
1680 OSData
* executable
= NULL
; // must release
1682 if (!super::init()) {
1686 kextFileInfo
= (_BooterKextFileInfo
*)booterData
->getBytesNoCopy();
1687 if (!kextFileInfo
) {
1689 kOSKextLogErrorLevel
|
1690 kOSKextLogGeneralFlag
,
1691 "No booter-provided data for kext device tree entry %s.",
1692 deviceTreeName
->getCStringNoCopy());
1696 /* The info plist must exist or we can't read the kext.
1698 if (!kextFileInfo
->infoDictPhysAddr
|| !kextFileInfo
->infoDictLength
) {
1700 kOSKextLogErrorLevel
|
1701 kOSKextLogGeneralFlag
,
1702 "No kext info dictionary for booter device tree entry %s.",
1703 deviceTreeName
->getCStringNoCopy());
1707 infoDictAddr
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
1708 if (!infoDictAddr
) {
1710 kOSKextLogErrorLevel
|
1711 kOSKextLogGeneralFlag
,
1712 "Can't translate physical address 0x%x of kext info dictionary "
1713 "for device tree entry %s.",
1714 (int)kextFileInfo
->infoDictPhysAddr
,
1715 deviceTreeName
->getCStringNoCopy());
1719 parsedXML
= OSUnserializeXML(infoDictAddr
, &errorString
);
1721 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
1724 const char * errorCString
= "(unknown error)";
1726 if (errorString
&& errorString
->getCStringNoCopy()) {
1727 errorCString
= errorString
->getCStringNoCopy();
1728 } else if (parsedXML
) {
1729 errorCString
= "not a dictionary";
1732 kOSKextLogErrorLevel
|
1733 kOSKextLogGeneralFlag
,
1734 "Error unserializing info dictionary for device tree entry %s: %s.",
1735 deviceTreeName
->getCStringNoCopy(), errorCString
);
1739 /* A bundle path is not mandatory.
1741 if (kextFileInfo
->bundlePathPhysAddr
&& kextFileInfo
->bundlePathLength
) {
1742 bundlePathAddr
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
);
1743 if (!bundlePathAddr
) {
1745 kOSKextLogErrorLevel
|
1746 kOSKextLogGeneralFlag
,
1747 "Can't translate physical address 0x%x of kext bundle path "
1748 "for device tree entry %s.",
1749 (int)kextFileInfo
->bundlePathPhysAddr
,
1750 deviceTreeName
->getCStringNoCopy());
1753 bundlePathAddr
[kextFileInfo
->bundlePathLength
-1] = '\0'; // just in case!
1755 kextPath
= OSString::withCString(bundlePathAddr
);
1758 kOSKextLogErrorLevel
|
1759 kOSKextLogGeneralFlag
,
1760 "Failed to create wrapper for device tree entry %s kext path %s.",
1761 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
);
1766 if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) {
1770 /* An executable is not mandatory.
1772 if (kextFileInfo
->executablePhysAddr
&& kextFileInfo
->executableLength
) {
1773 executableAddr
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
);
1774 if (!executableAddr
) {
1776 kOSKextLogErrorLevel
|
1777 kOSKextLogGeneralFlag
,
1778 "Can't translate physical address 0x%x of kext executable "
1779 "for device tree entry %s.",
1780 (int)kextFileInfo
->executablePhysAddr
,
1781 deviceTreeName
->getCStringNoCopy());
1785 executable
= OSData::withBytesNoCopy(executableAddr
,
1786 kextFileInfo
->executableLength
);
1789 kOSKextLogErrorLevel
|
1790 kOSKextLogGeneralFlag
,
1791 "Failed to create executable wrapper for device tree entry %s.",
1792 deviceTreeName
->getCStringNoCopy());
1796 /* A kext with an executable needs to retain the whole booterData
1797 * object to keep the executable in memory.
1799 if (!setExecutable(executable
, booterData
)) {
1801 kOSKextLogErrorLevel
|
1802 kOSKextLogGeneralFlag
,
1803 "Failed to set kext executable for device tree entry %s.",
1804 deviceTreeName
->getCStringNoCopy());
1809 result
= registerIdentifier();
1812 OSSafeReleaseNULL(parsedXML
);
1813 OSSafeReleaseNULL(kextPath
);
1814 OSSafeReleaseNULL(errorString
);
1815 OSSafeReleaseNULL(executable
);
1820 /*********************************************************************
1821 *********************************************************************/
1823 OSKext::registerIdentifier(void)
1825 bool result
= false;
1826 OSKext
* existingKext
= NULL
; // do not release
1827 bool existingIsLoaded
= false;
1828 bool existingIsPrelinked
= false;
1829 OSKextVersion newVersion
= -1;
1830 OSKextVersion existingVersion
= -1;
1831 char newVersionCString
[kOSKextVersionMaxLength
];
1832 char existingVersionCString
[kOSKextVersionMaxLength
];
1833 OSData
* newUUID
= NULL
; // must release
1834 OSData
* existingUUID
= NULL
; // must release
1836 IORecursiveLockLock(sKextLock
);
1838 /* Get the new kext's version for checks & log messages.
1840 newVersion
= getVersion();
1841 OSKextVersionGetString(newVersion
, newVersionCString
,
1842 kOSKextVersionMaxLength
);
1844 /* If we don't have an existing kext with this identifier,
1845 * just record the new kext and we're done!
1847 existingKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
));
1848 if (!existingKext
) {
1849 sKextsByID
->setObject(bundleID
, this);
1854 /* Get the existing kext's version for checks & log messages.
1856 existingVersion
= existingKext
->getVersion();
1857 OSKextVersionGetString(existingVersion
,
1858 existingVersionCString
, kOSKextVersionMaxLength
);
1860 existingIsLoaded
= existingKext
->isLoaded();
1861 existingIsPrelinked
= existingKext
->isPrelinked();
1863 /* If we have a kext with this identifier that's already loaded/prelinked,
1864 * we can't use the new one, but let's be really thorough and check how
1865 * the two are related for a precise diagnostic log message.
1867 * Note that user space can't find out about nonloaded prelinked kexts,
1868 * so in this case we log a message when new & existing are equivalent
1869 * at the step rather than warning level, because we are always going
1870 * be getting a copy of the kext in the user load request mkext.
1872 if (existingIsLoaded
|| existingIsPrelinked
) {
1873 bool sameVersion
= (newVersion
== existingVersion
);
1874 bool sameExecutable
= true; // assume true unless we have UUIDs
1876 /* Only get the UUID if the existing kext is loaded. Doing so
1877 * might have to uncompress an mkext executable and we shouldn't
1878 * take that hit when neither kext is loaded.
1880 newUUID
= copyUUID();
1881 existingUUID
= existingKext
->copyUUID();
1883 /* I'm entirely too paranoid about checking equivalence of executables,
1884 * but I remember nasty problems with it in the past.
1886 * - If we have UUIDs for both kexts, compare them.
1887 * - If only one kext has a UUID, they're definitely different.
1889 if (newUUID
&& existingUUID
) {
1890 sameExecutable
= newUUID
->isEqualTo(existingUUID
);
1891 } else if (newUUID
|| existingUUID
) {
1892 sameExecutable
= false;
1895 if (!newUUID
&& !existingUUID
) {
1897 /* If there are no UUIDs, we can't really tell that the executables
1898 * are *different* without a lot of work; the loaded kext's
1899 * unrelocated executable is no longer around (and we never had it
1900 * in-kernel for a prelinked kext). We certainly don't want to do
1901 * a whole fake link for the new kext just to compare, either.
1904 OSKextVersionGetString(version
, newVersionCString
,
1905 sizeof(newVersionCString
));
1907 kOSKextLogWarningLevel
|
1908 kOSKextLogKextBookkeepingFlag
,
1909 "Notice - new kext %s, v%s matches %s kext "
1910 "but can't determine if executables are the same (no UUIDs).",
1911 getIdentifierCString(),
1913 (existingIsLoaded
? "loaded" : "prelinked"));
1916 if (sameVersion
&& sameExecutable
) {
1918 (existingIsLoaded
? kOSKextLogWarningLevel
: kOSKextLogStepLevel
) |
1919 kOSKextLogKextBookkeepingFlag
,
1920 "Refusing new kext %s, v%s: a %s copy is already present "
1921 "(same version and executable).",
1922 getIdentifierCString(), newVersionCString
,
1923 (existingIsLoaded
? "loaded" : "prelinked"));
1926 /* This condition is significant so log it under warnings.
1929 kOSKextLogWarningLevel
|
1930 kOSKextLogKextBookkeepingFlag
,
1931 "Refusing new kext %s, v%s: already have %s v%s.",
1932 getIdentifierCString(),
1934 (existingIsLoaded
? "loaded" : "prelinked"),
1935 existingVersionCString
);
1937 /* This condition is significant so log it under warnings.
1940 kOSKextLogWarningLevel
| kOSKextLogKextBookkeepingFlag
,
1941 "Refusing new kext %s, v%s: a %s copy with a different "
1942 "executable UUID is already present.",
1943 getIdentifierCString(), newVersionCString
,
1944 (existingIsLoaded
? "loaded" : "prelinked"));
1948 } /* if (existingIsLoaded || existingIsPrelinked) */
1950 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
1951 * user loads are happening or if we're still in early boot. User agents are
1952 * supposed to resolve dependencies topside and include only the exact
1953 * kexts needed; so we always accept the new kext (in fact we should never
1954 * see an older unloaded copy hanging around).
1956 if (sUserLoadsActive
) {
1957 sKextsByID
->setObject(bundleID
, this);
1961 kOSKextLogStepLevel
|
1962 kOSKextLogKextBookkeepingFlag
,
1963 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
1964 getIdentifierCString(),
1965 existingVersionCString
,
1971 /* During early boot, the kext with the highest version always wins out.
1972 * Prelinked kernels will never hit this, but mkexts and booter-read
1973 * kexts might have duplicates.
1975 if (newVersion
> existingVersion
) {
1976 sKextsByID
->setObject(bundleID
, this);
1980 kOSKextLogStepLevel
|
1981 kOSKextLogKextBookkeepingFlag
,
1982 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
1983 existingVersionCString
,
1984 getIdentifierCString(),
1989 kOSKextLogStepLevel
|
1990 kOSKextLogKextBookkeepingFlag
,
1991 "Kext %s is already registered with a higher/same version (v%s); "
1992 "dropping newly-added (v%s).",
1993 getIdentifierCString(),
1994 existingVersionCString
,
1998 /* result has been set appropriately by now. */
2002 IORecursiveLockUnlock(sKextLock
);
2006 kOSKextLogStepLevel
|
2007 kOSKextLogKextBookkeepingFlag
,
2008 "Kext %s, v%s registered and available for loading.",
2009 getIdentifierCString(), newVersionCString
);
2012 OSSafeReleaseNULL(newUUID
);
2013 OSSafeReleaseNULL(existingUUID
);
2018 /*********************************************************************
2019 * Does the bare minimum validation to look up a kext.
2020 * All other validation is done on the spot as needed.
2021 **********************************************************************/
2023 OSKext::setInfoDictionaryAndPath(
2024 OSDictionary
* aDictionary
,
2027 bool result
= false;
2028 OSString
* bundleIDString
= NULL
; // do not release
2029 OSString
* versionString
= NULL
; // do not release
2030 OSString
* compatibleVersionString
= NULL
; // do not release
2031 const char * versionCString
= NULL
; // do not free
2032 const char * compatibleVersionCString
= NULL
; // do not free
2033 OSBoolean
* scratchBool
= NULL
; // do not release
2034 OSDictionary
* scratchDict
= NULL
; // do not release
2037 panic("Attempt to set info dictionary on a kext "
2038 "that already has one (%s).",
2039 getIdentifierCString());
2042 if (!aDictionary
|| !OSDynamicCast(OSDictionary
, aDictionary
)) {
2046 infoDict
= aDictionary
;
2049 /* Check right away if the info dictionary has any log flags.
2051 scratchBool
= OSDynamicCast(OSBoolean
,
2052 getPropertyForHostArch(kOSBundleEnableKextLoggingKey
));
2053 if (scratchBool
== kOSBooleanTrue
) {
2054 flags
.loggingEnabled
= 1;
2057 /* The very next thing to get is the bundle identifier. Unlike
2058 * in user space, a kext with no bundle identifier gets axed
2061 bundleIDString
= OSDynamicCast(OSString
,
2062 getPropertyForHostArch(kCFBundleIdentifierKey
));
2063 if (!bundleIDString
) {
2065 kOSKextLogErrorLevel
|
2066 kOSKextLogValidationFlag
,
2067 "CFBundleIdentifier missing/invalid type in kext %s.",
2068 aPath
? aPath
->getCStringNoCopy() : "(unknown)");
2071 bundleID
= OSSymbol::withString(bundleIDString
);
2074 kOSKextLogErrorLevel
|
2075 kOSKextLogValidationFlag
,
2076 "Can't copy bundle identifier as symbol for kext %s.",
2077 bundleIDString
->getCStringNoCopy());
2081 /* Save the path if we got one (it should always be available but it's
2082 * just something nice to have for bookkeeping).
2090 * Minimal validation to initialize. We'll do other validation on the spot.
2092 if (bundleID
->getLength() >= KMOD_MAX_NAME
) {
2094 kOSKextLogErrorLevel
|
2095 kOSKextLogValidationFlag
,
2096 "Kext %s error - CFBundleIdentifier over max length %d.",
2097 getIdentifierCString(), KMOD_MAX_NAME
- 1);
2101 version
= compatibleVersion
= -1;
2103 versionString
= OSDynamicCast(OSString
,
2104 getPropertyForHostArch(kCFBundleVersionKey
));
2105 if (!versionString
) {
2107 kOSKextLogErrorLevel
|
2108 kOSKextLogValidationFlag
,
2109 "Kext %s error - CFBundleVersion missing/invalid type.",
2110 getIdentifierCString());
2113 versionCString
= versionString
->getCStringNoCopy();
2114 version
= OSKextParseVersionString(versionCString
);
2117 kOSKextLogErrorLevel
|
2118 kOSKextLogValidationFlag
,
2119 "Kext %s error - CFBundleVersion bad value '%s'.",
2120 getIdentifierCString(), versionCString
);
2124 compatibleVersion
= -1; // set to illegal value for kexts that don't have
2126 compatibleVersionString
= OSDynamicCast(OSString
,
2127 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
2128 if (compatibleVersionString
) {
2129 compatibleVersionCString
= compatibleVersionString
->getCStringNoCopy();
2130 compatibleVersion
= OSKextParseVersionString(compatibleVersionCString
);
2131 if (compatibleVersion
< 0) {
2133 kOSKextLogErrorLevel
|
2134 kOSKextLogValidationFlag
,
2135 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2136 getIdentifierCString(), compatibleVersionCString
);
2140 if (compatibleVersion
> version
) {
2142 kOSKextLogErrorLevel
|
2143 kOSKextLogValidationFlag
,
2144 "Kext %s error - %s %s > %s %s (must be <=).",
2145 getIdentifierCString(),
2146 kOSBundleCompatibleVersionKey
, compatibleVersionCString
,
2147 kCFBundleVersionKey
, versionCString
);
2152 /* Check to see if this kext is in exclude list */
2153 if ( isInExcludeList() ) {
2155 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
2156 "Kext %s is in exclude list, not loadable",
2157 getIdentifierCString());
2161 /* Set flags for later use if the infoDict gets flushed. We only
2162 * check for true values, not false ones(!)
2164 scratchBool
= OSDynamicCast(OSBoolean
,
2165 getPropertyForHostArch(kOSBundleIsInterfaceKey
));
2166 if (scratchBool
== kOSBooleanTrue
) {
2167 flags
.interface
= 1;
2170 scratchBool
= OSDynamicCast(OSBoolean
,
2171 getPropertyForHostArch(kOSKernelResourceKey
));
2172 if (scratchBool
== kOSBooleanTrue
) {
2173 flags
.kernelComponent
= 1;
2174 flags
.interface
= 1; // xxx - hm. the kernel itself isn't an interface...
2177 /* A kernel component has one implicit dependency on the kernel.
2179 flags
.hasAllDependencies
= 1;
2182 /* Make sure common string values in personalities are uniqued to OSSymbols.
2184 scratchDict
= OSDynamicCast(OSDictionary
,
2185 getPropertyForHostArch(kIOKitPersonalitiesKey
));
2187 uniquePersonalityProperties(scratchDict
);
2197 /*********************************************************************
2198 * Not used for prelinked kernel boot as there is no unrelocated
2200 *********************************************************************/
2202 OSKext::setExecutable(
2203 OSData
* anExecutable
,
2204 OSData
* externalData
,
2205 bool externalDataIsMkext
)
2207 bool result
= false;
2208 const char * executableKey
= NULL
; // do not free
2210 if (!anExecutable
) {
2211 infoDict
->removeObject(_kOSKextExecutableKey
);
2212 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
2213 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
2218 if (infoDict
->getObject(_kOSKextExecutableKey
) ||
2219 infoDict
->getObject(_kOSKextMkextExecutableReferenceKey
)) {
2221 panic("Attempt to set an executable on a kext "
2222 "that already has one (%s).",
2223 getIdentifierCString());
2227 if (externalDataIsMkext
) {
2228 executableKey
= _kOSKextMkextExecutableReferenceKey
;
2230 executableKey
= _kOSKextExecutableKey
;
2234 infoDict
->setObject(executableKey
, anExecutable
);
2236 infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
);
2246 /*********************************************************************
2247 *********************************************************************/
2249 uniqueStringPlistProperty(OSDictionary
* dict
, const char * key
)
2251 OSString
* stringValue
= NULL
; // do not release
2252 const OSSymbol
* symbolValue
= NULL
; // must release
2254 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2259 symbolValue
= OSSymbol::withString(stringValue
);
2264 dict
->setObject(key
, symbolValue
);
2267 if (symbolValue
) symbolValue
->release();
2272 /*********************************************************************
2273 *********************************************************************/
2275 uniqueStringPlistProperty(OSDictionary
* dict
, const OSString
* key
)
2277 OSString
* stringValue
= NULL
; // do not release
2278 const OSSymbol
* symbolValue
= NULL
; // must release
2280 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2285 symbolValue
= OSSymbol::withString(stringValue
);
2290 dict
->setObject(key
, symbolValue
);
2293 if (symbolValue
) symbolValue
->release();
2298 /*********************************************************************
2299 * Replace common personality property values with uniqued instances
2300 * to save on wired memory.
2301 *********************************************************************/
2304 OSKext::uniquePersonalityProperties(OSDictionary
* personalityDict
)
2306 /* Properties every personality has.
2308 uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKey
);
2309 uniqueStringPlistProperty(personalityDict
, kIOProviderClassKey
);
2310 uniqueStringPlistProperty(personalityDict
, gIOClassKey
);
2312 /* Other commonly used properties.
2314 uniqueStringPlistProperty(personalityDict
, gIOMatchCategoryKey
);
2315 uniqueStringPlistProperty(personalityDict
, gIOResourceMatchKey
);
2316 uniqueStringPlistProperty(personalityDict
, gIOUserClientClassKey
);
2318 uniqueStringPlistProperty(personalityDict
, "HIDDefaultBehavior");
2319 uniqueStringPlistProperty(personalityDict
, "HIDPointerAccelerationType");
2320 uniqueStringPlistProperty(personalityDict
, "HIDRemoteControlType");
2321 uniqueStringPlistProperty(personalityDict
, "HIDScrollAccelerationType");
2322 uniqueStringPlistProperty(personalityDict
, "IOPersonalityPublisher");
2323 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect");
2324 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect Location");
2325 uniqueStringPlistProperty(personalityDict
, "Vendor");
2326 uniqueStringPlistProperty(personalityDict
, "Vendor Identification");
2327 uniqueStringPlistProperty(personalityDict
, "Vendor Name");
2328 uniqueStringPlistProperty(personalityDict
, "bConfigurationValue");
2329 uniqueStringPlistProperty(personalityDict
, "bInterfaceNumber");
2330 uniqueStringPlistProperty(personalityDict
, "idProduct");
2335 /*********************************************************************
2336 *********************************************************************/
2341 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2344 OSSafeReleaseNULL(infoDict
);
2345 OSSafeReleaseNULL(bundleID
);
2346 OSSafeReleaseNULL(path
);
2347 OSSafeReleaseNULL(executableRelPath
);
2348 OSSafeReleaseNULL(dependencies
);
2349 OSSafeReleaseNULL(linkedExecutable
);
2350 OSSafeReleaseNULL(metaClasses
);
2351 OSSafeReleaseNULL(interfaceUUID
);
2353 if (isInterface() && kmod_info
) {
2354 kfree(kmod_info
, sizeof(kmod_info_t
));
2362 #pragma mark Mkext files
2364 /*********************************************************************
2365 *********************************************************************/
2367 OSKext::readMkextArchive(OSData
* mkextData
,
2368 uint32_t * checksumPtr
)
2370 OSReturn result
= kOSKextReturnBadData
;
2371 uint32_t mkextLength
= 0;
2372 mkext_header
* mkextHeader
= 0; // do not free
2373 uint32_t mkextVersion
= 0;
2375 /* Note default return of kOSKextReturnBadData above.
2377 mkextLength
= mkextData
->getLength();
2378 if (mkextLength
< sizeof(mkext_basic_header
)) {
2379 OSKextLog(/* kext */ NULL
,
2380 kOSKextLogErrorLevel
|
2381 kOSKextLogArchiveFlag
,
2382 "Mkext archive too small to be valid.");
2386 mkextHeader
= (mkext_header
*)mkextData
->getBytesNoCopy();
2388 if (MKEXT_GET_MAGIC(mkextHeader
) != MKEXT_MAGIC
||
2389 MKEXT_GET_SIGNATURE(mkextHeader
) != MKEXT_SIGN
) {
2390 OSKextLog(/* kext */ NULL
,
2391 kOSKextLogErrorLevel
|
2392 kOSKextLogArchiveFlag
,
2393 "Mkext archive has invalid magic or signature.");
2397 if (MKEXT_GET_LENGTH(mkextHeader
) != mkextLength
) {
2398 OSKextLog(/* kext */ NULL
,
2399 kOSKextLogErrorLevel
|
2400 kOSKextLogArchiveFlag
,
2401 "Mkext archive recorded length doesn't match actual file length.");
2405 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2407 if (mkextVersion
== MKEXT_VERS_2
) {
2408 result
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
);
2410 OSKextLog(/* kext */ NULL
,
2411 kOSKextLogErrorLevel
|
2412 kOSKextLogArchiveFlag
,
2413 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
);
2414 result
= kOSKextReturnUnsupported
;
2421 /*********************************************************************
2422 * Assumes magic, signature, version, length have been checked.
2423 * xxx - need to add further bounds checking for each file entry
2425 * Should keep track of all kexts created so far, and if we hit a
2426 * fatal error halfway through, remove those kexts. If we've dropped
2427 * an older version that had already been read, whoops! Might want to
2428 * add a level of buffering?
2429 *********************************************************************/
2432 OSKext::readMkext2Archive(
2434 OSDictionary
** mkextPlistOut
,
2435 uint32_t * checksumPtr
)
2437 OSReturn result
= kOSReturnError
;
2438 uint32_t mkextLength
;
2439 mkext2_header
* mkextHeader
= NULL
; // do not free
2440 void * mkextEnd
= NULL
; // do not free
2441 uint32_t mkextVersion
;
2442 uint8_t * crc_address
= NULL
;
2444 uint32_t mkextPlistOffset
;
2445 uint32_t mkextPlistCompressedSize
;
2446 char * mkextPlistEnd
= NULL
; // do not free
2447 uint32_t mkextPlistFullSize
;
2448 OSString
* errorString
= NULL
; // must release
2449 OSData
* mkextPlistUncompressedData
= NULL
; // must release
2450 const char * mkextPlistDataBuffer
= NULL
; // do not free
2451 OSObject
* parsedXML
= NULL
; // must release
2452 OSDictionary
* mkextPlist
= NULL
; // do not release
2453 OSArray
* mkextInfoDictArray
= NULL
; // do not release
2456 mkextLength
= mkextData
->getLength();
2457 mkextHeader
= (mkext2_header
*)mkextData
->getBytesNoCopy();
2458 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2459 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2461 crc_address
= (u_int8_t
*)&mkextHeader
->version
;
2462 checksum
= mkext_adler32(crc_address
,
2463 (uintptr_t)mkextHeader
+
2464 MKEXT_GET_LENGTH(mkextHeader
) - (uintptr_t)crc_address
);
2466 if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) {
2467 OSKextLog(/* kext */ NULL
,
2468 kOSKextLogErrorLevel
|
2469 kOSKextLogArchiveFlag
,
2470 "Mkext archive has bad checksum.");
2471 result
= kOSKextReturnBadData
;
2476 *checksumPtr
= checksum
;
2479 /* Check that the CPU type & subtype match that of the running kernel. */
2480 if (MKEXT_GET_CPUTYPE(mkextHeader
) == (UInt32
)CPU_TYPE_ANY
) {
2481 OSKextLog(/* kext */ NULL
,
2482 kOSKextLogErrorLevel
|
2483 kOSKextLogArchiveFlag
,
2484 "Mkext archive must have a specific CPU type.");
2485 result
= kOSKextReturnBadData
;
2488 if ((UInt32
)_mh_execute_header
.cputype
!=
2489 MKEXT_GET_CPUTYPE(mkextHeader
)) {
2491 OSKextLog(/* kext */ NULL
,
2492 kOSKextLogErrorLevel
|
2493 kOSKextLogArchiveFlag
,
2494 "Mkext archive does not match the running kernel's CPU type.");
2495 result
= kOSKextReturnArchNotFound
;
2500 mkextPlistOffset
= MKEXT2_GET_PLIST(mkextHeader
);
2501 mkextPlistCompressedSize
= MKEXT2_GET_PLIST_COMPSIZE(mkextHeader
);
2502 mkextPlistEnd
= (char *)mkextHeader
+ mkextPlistOffset
+
2503 mkextPlistCompressedSize
;
2504 if (mkextPlistEnd
> mkextEnd
) {
2505 OSKextLog(/* kext */ NULL
,
2506 kOSKextLogErrorLevel
|
2507 kOSKextLogArchiveFlag
,
2508 "Mkext archive file overrun.");
2509 result
= kOSKextReturnBadData
;
2512 mkextPlistFullSize
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
);
2513 if (mkextPlistCompressedSize
) {
2514 mkextPlistUncompressedData
= sKernelKext
->extractMkext2FileData(
2515 (UInt8
*)mkextHeader
+ mkextPlistOffset
,
2517 mkextPlistCompressedSize
, mkextPlistFullSize
);
2518 if (!mkextPlistUncompressedData
) {
2521 mkextPlistDataBuffer
= (const char *)
2522 mkextPlistUncompressedData
->getBytesNoCopy();
2524 mkextPlistDataBuffer
= (const char *)mkextHeader
+ mkextPlistOffset
;
2527 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2529 parsedXML
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
);
2531 mkextPlist
= OSDynamicCast(OSDictionary
, parsedXML
);
2534 const char * errorCString
= "(unknown error)";
2536 if (errorString
&& errorString
->getCStringNoCopy()) {
2537 errorCString
= errorString
->getCStringNoCopy();
2538 } else if (parsedXML
) {
2539 errorCString
= "not a dictionary";
2541 OSKextLog(/* kext */ NULL
,
2542 kOSKextLogErrorLevel
|
2543 kOSKextLogArchiveFlag
,
2544 "Error unserializing mkext plist: %s.", errorCString
);
2548 /* If the caller needs the plist, hand it back and retain it.
2549 * (This function releases it at the end.)
2551 if (mkextPlistOut
) {
2552 *mkextPlistOut
= mkextPlist
;
2553 (*mkextPlistOut
)->retain();
2556 mkextInfoDictArray
= OSDynamicCast(OSArray
,
2557 mkextPlist
->getObject(kMKEXTInfoDictionariesKey
));
2558 if (!mkextInfoDictArray
) {
2559 OSKextLog(/* kext */ NULL
,
2560 kOSKextLogErrorLevel
|
2561 kOSKextLogArchiveFlag
,
2562 "Mkext archive contains no kext info dictionaries.");
2566 count
= mkextInfoDictArray
->getCount();
2567 for (i
= 0; i
< count
; i
++) {
2568 OSDictionary
* infoDict
;
2571 infoDict
= OSDynamicCast(OSDictionary
,
2572 mkextInfoDictArray
->getObject(i
));
2574 /* Create the kext for the entry, then release it, because the
2575 * kext system keeps them around until explicitly removed.
2576 * Any creation/registration failures are already logged for us.
2579 OSKext
* newKext
= OSKext::withMkext2Info(infoDict
, mkextData
);
2580 OSSafeReleaseNULL(newKext
);
2584 /* Even if we didn't keep any kexts from the mkext, we may have a load
2585 * request to process, so we are successful (no errors occurred).
2587 result
= kOSReturnSuccess
;
2591 OSSafeReleaseNULL(parsedXML
);
2592 OSSafeReleaseNULL(mkextPlistUncompressedData
);
2593 OSSafeReleaseNULL(errorString
);
2598 /*********************************************************************
2599 *********************************************************************/
2602 OSKext::withMkext2Info(
2603 OSDictionary
* anInfoDict
,
2606 OSKext
* newKext
= new OSKext
;
2608 if (newKext
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) {
2616 /*********************************************************************
2617 *********************************************************************/
2619 OSKext::initWithMkext2Info(
2620 OSDictionary
* anInfoDict
,
2623 bool result
= false;
2624 OSString
* kextPath
= NULL
; // do not release
2625 OSNumber
* executableOffsetNum
= NULL
; // do not release
2626 OSCollectionIterator
* iterator
= NULL
; // must release
2627 OSData
* executable
= NULL
; // must release
2629 if (anInfoDict
== NULL
|| !super::init()) {
2633 /* Get the path. Don't look for an arch-specific path property.
2635 kextPath
= OSDynamicCast(OSString
,
2636 anInfoDict
->getObject(kMKEXTBundlePathKey
));
2638 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
2642 /* If we have a path to the executable, save it.
2644 executableRelPath
= OSDynamicCast(OSString
,
2645 anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
));
2646 if (executableRelPath
) {
2647 executableRelPath
->retain();
2650 /* Don't need the paths to be in the info dictionary any more.
2652 anInfoDict
->removeObject(kMKEXTBundlePathKey
);
2653 anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
);
2655 executableOffsetNum
= OSDynamicCast(OSNumber
,
2656 infoDict
->getObject(kMKEXTExecutableKey
));
2657 if (executableOffsetNum
) {
2658 executable
= createMkext2FileEntry(mkextData
,
2659 executableOffsetNum
, "executable");
2660 infoDict
->removeObject(kMKEXTExecutableKey
);
2664 if (!setExecutable(executable
, mkextData
, true)) {
2669 result
= registerIdentifier();
2673 OSSafeReleaseNULL(executable
);
2674 OSSafeReleaseNULL(iterator
);
2678 /*********************************************************************
2679 *********************************************************************/
2681 OSKext::createMkext2FileEntry(
2683 OSNumber
* offsetNum
,
2686 OSData
* result
= NULL
;
2687 MkextEntryRef entryRef
;
2688 uint8_t * mkextBuffer
= (uint8_t *)mkextData
->getBytesNoCopy();
2689 uint32_t entryOffset
= offsetNum
->unsigned32BitValue();
2691 result
= OSData::withCapacity(sizeof(entryRef
));
2696 entryRef
.mkext
= (mkext_basic_header
*)mkextBuffer
;
2697 entryRef
.fileinfo
= mkextBuffer
+ entryOffset
;
2698 if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) {
2699 OSSafeReleaseNULL(result
);
2706 kOSKextLogErrorLevel
|
2707 kOSKextLogArchiveFlag
,
2708 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2709 name
, getIdentifierCString());
2714 /*********************************************************************
2715 *********************************************************************/
2717 static void * z_alloc(void *, u_int items
, u_int size
);
2718 static void z_free(void *, void *ptr
);
2720 typedef struct z_mem
{
2721 uint32_t alloc_size
;
2726 * Space allocation and freeing routines for use by zlib routines.
2729 z_alloc(void * notused __unused
, u_int num_items
, u_int size
)
2731 void * result
= NULL
;
2732 z_mem
* zmem
= NULL
;
2734 uint64_t total
= ((uint64_t)num_items
) * ((uint64_t)size
);
2735 //Check for overflow due to multiplication
2736 if (total
> UINT32_MAX
){
2737 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
2738 notused
, num_items
, size
, num_items
, size
);
2741 uint64_t allocSize64
= total
+ ((uint64_t)sizeof(zmem
));
2742 //Check for overflow due to addition
2743 if (allocSize64
> UINT32_MAX
){
2744 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
2745 notused
, num_items
, size
, (uint32_t)total
, sizeof(zmem
));
2747 uint32_t allocSize
= (uint32_t)allocSize64
;
2749 zmem
= (z_mem
*)kalloc_tag(allocSize
, VM_KERN_MEMORY_OSKEXT
);
2753 zmem
->alloc_size
= allocSize
;
2754 result
= (void *)&(zmem
->data
);
2760 z_free(void * notused __unused
, void * ptr
)
2762 uint32_t * skipper
= (uint32_t *)ptr
- 1;
2763 z_mem
* zmem
= (z_mem
*)skipper
;
2764 kfree((void *)zmem
, zmem
->alloc_size
);
2770 OSKext::extractMkext2FileData(
2773 uint32_t compressedSize
,
2776 OSData
* result
= NULL
;
2778 OSData
* uncompressedData
= NULL
; // release on error
2780 uint8_t * uncompressedDataBuffer
= 0; // do not free
2781 unsigned long uncompressedSize
;
2783 bool zstream_inited
= false;
2786 /* If the file isn't compressed, we want to make a copy
2787 * so that we don't have the tie to the larger mkext file buffer any more.
2789 if (!compressedSize
) {
2790 uncompressedData
= OSData::withBytes(data
, fullSize
);
2791 // xxx - no check for failure?
2792 result
= uncompressedData
;
2796 if (KERN_SUCCESS
!= kmem_alloc(kernel_map
,
2797 (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
, VM_KERN_MEMORY_OSKEXT
)) {
2799 /* How's this for cheesy? The kernel is only asked to extract
2800 * kext plists so we tailor the log messages.
2804 kOSKextLogErrorLevel
|
2805 kOSKextLogArchiveFlag
,
2806 "Allocation failure extracting %s from mkext.", name
);
2809 kOSKextLogErrorLevel
|
2810 kOSKextLogArchiveFlag
,
2811 "Allocation failure extracting %s from mkext for kext %s.",
2812 name
, getIdentifierCString());
2817 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
);
2818 if (!uncompressedData
) {
2821 kOSKextLogErrorLevel
|
2822 kOSKextLogArchiveFlag
,
2823 "Allocation failure extracting %s from mkext.", name
);
2826 kOSKextLogErrorLevel
|
2827 kOSKextLogArchiveFlag
,
2828 "Allocation failure extracting %s from mkext for kext %s.",
2829 name
, getIdentifierCString());
2833 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
2837 kOSKextLogDetailLevel
|
2838 kOSKextLogArchiveFlag
,
2839 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2840 name
, compressedSize
, fullSize
);
2843 kOSKextLogDetailLevel
|
2844 kOSKextLogArchiveFlag
,
2845 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2846 getIdentifierCString(), name
, compressedSize
, fullSize
);
2849 bzero(&zstream
, sizeof(zstream
));
2850 zstream
.next_in
= (UInt8
*)data
;
2851 zstream
.avail_in
= compressedSize
;
2853 zstream
.next_out
= uncompressedDataBuffer
;
2854 zstream
.avail_out
= fullSize
;
2856 zstream
.zalloc
= z_alloc
;
2857 zstream
.zfree
= z_free
;
2859 zlib_result
= inflateInit(&zstream
);
2860 if (Z_OK
!= zlib_result
) {
2863 kOSKextLogErrorLevel
|
2864 kOSKextLogArchiveFlag
,
2865 "Mkext error; zlib inflateInit failed (%d) for %s.",
2869 kOSKextLogErrorLevel
|
2870 kOSKextLogArchiveFlag
,
2871 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2872 getIdentifierCString(), zlib_result
, name
);
2876 zstream_inited
= true;
2879 zlib_result
= inflate(&zstream
, Z_FINISH
);
2881 if (zlib_result
== Z_STREAM_END
|| zlib_result
== Z_OK
) {
2882 uncompressedSize
= zstream
.total_out
;
2886 kOSKextLogErrorLevel
|
2887 kOSKextLogArchiveFlag
,
2888 "Mkext error; zlib inflate failed (%d) for %s.",
2892 kOSKextLogErrorLevel
|
2893 kOSKextLogArchiveFlag
,
2894 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
2895 getIdentifierCString(), zlib_result
, name
);
2899 kOSKextLogErrorLevel
|
2900 kOSKextLogArchiveFlag
,
2901 "zlib error: %s.", zstream
.msg
);
2906 if (uncompressedSize
!= fullSize
) {
2909 kOSKextLogErrorLevel
|
2910 kOSKextLogArchiveFlag
,
2911 "Mkext error; zlib inflate discrepancy for %s, "
2912 "uncompressed size != original size.", name
);
2915 kOSKextLogErrorLevel
|
2916 kOSKextLogArchiveFlag
,
2917 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
2918 "uncompressed size != original size.",
2919 getIdentifierCString(), name
);
2924 result
= uncompressedData
;
2927 /* Don't bother checking return, nothing we can do on fail.
2929 if (zstream_inited
) inflateEnd(&zstream
);
2932 OSSafeReleaseNULL(uncompressedData
);
2938 /*********************************************************************
2939 *********************************************************************/
2942 OSKext::loadFromMkext(
2943 OSKextLogSpec clientLogFilter
,
2945 uint32_t mkextBufferLength
,
2947 uint32_t * logInfoLengthOut
)
2949 OSReturn result
= kOSReturnError
;
2950 OSReturn tempResult
= kOSReturnError
;
2952 OSData
* mkextData
= NULL
; // must release
2953 OSDictionary
* mkextPlist
= NULL
; // must release
2955 OSArray
* logInfoArray
= NULL
; // must release
2956 OSSerialize
* serializer
= NULL
; // must release
2958 OSString
* predicate
= NULL
; // do not release
2959 OSDictionary
* requestArgs
= NULL
; // do not release
2961 OSString
* kextIdentifier
= NULL
; // do not release
2962 OSNumber
* startKextExcludeNum
= NULL
; // do not release
2963 OSNumber
* startMatchingExcludeNum
= NULL
; // do not release
2964 OSBoolean
* delayAutounloadBool
= NULL
; // do not release
2965 OSArray
* personalityNames
= NULL
; // do not release
2967 /* Default values for these two options: regular autounload behavior,
2968 * load all kexts, send no personalities.
2970 Boolean delayAutounload
= false;
2971 OSKextExcludeLevel startKextExcludeLevel
= kOSKextExcludeNone
;
2972 OSKextExcludeLevel startMatchingExcludeLevel
= kOSKextExcludeAll
;
2974 IORecursiveLockLock(sKextLock
);
2978 *logInfoLengthOut
= 0;
2981 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
2983 OSKextLog(/* kext */ NULL
,
2984 kOSKextLogDebugLevel
|
2986 "Received kext load request from user space.");
2988 /* Regardless of processing, the fact that we have gotten here means some
2989 * user-space program is up and talking to us, so we'll switch our kext
2990 * registration to reflect that.
2992 if (!sUserLoadsActive
) {
2993 OSKextLog(/* kext */ NULL
,
2994 kOSKextLogProgressLevel
|
2995 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
2996 "Switching to late startup (user-space) kext loading policy.");
2998 sUserLoadsActive
= true;
3001 if (!sLoadEnabled
) {
3002 OSKextLog(/* kext */ NULL
,
3003 kOSKextLogErrorLevel
|
3005 "Kext loading is disabled.");
3006 result
= kOSKextReturnDisabled
;
3010 /* Note that we do not set a dealloc function on this OSData
3011 * object! No references to it can remain after the loadFromMkext()
3012 * call since we are in a MIG function, and will vm_deallocate()
3015 mkextData
= OSData::withBytesNoCopy(mkextBuffer
,
3018 OSKextLog(/* kext */ NULL
,
3019 kOSKextLogErrorLevel
|
3020 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3021 "Failed to create wrapper for kext load request.");
3022 result
= kOSKextReturnNoMemory
;
3026 result
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
);
3027 if (result
!= kOSReturnSuccess
) {
3028 OSKextLog(/* kext */ NULL
,
3029 kOSKextLogErrorLevel
|
3031 "Failed to read kext load request.");
3035 predicate
= _OSKextGetRequestPredicate(mkextPlist
);
3036 if (!predicate
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) {
3037 OSKextLog(/* kext */ NULL
,
3038 kOSKextLogErrorLevel
|
3040 "Received kext load request with no predicate; skipping.");
3041 result
= kOSKextReturnInvalidArgument
;
3045 requestArgs
= OSDynamicCast(OSDictionary
,
3046 mkextPlist
->getObject(kKextRequestArgumentsKey
));
3047 if (!requestArgs
|| !requestArgs
->getCount()) {
3048 OSKextLog(/* kext */ NULL
,
3049 kOSKextLogErrorLevel
|
3051 "Received kext load request with no arguments.");
3052 result
= kOSKextReturnInvalidArgument
;
3056 kextIdentifier
= OSDynamicCast(OSString
,
3057 requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
));
3058 if (!kextIdentifier
) {
3059 OSKextLog(/* kext */ NULL
,
3060 kOSKextLogErrorLevel
|
3062 "Received kext load request with no kext identifier.");
3063 result
= kOSKextReturnInvalidArgument
;
3067 startKextExcludeNum
= OSDynamicCast(OSNumber
,
3068 requestArgs
->getObject(kKextRequestArgumentStartExcludeKey
));
3069 startMatchingExcludeNum
= OSDynamicCast(OSNumber
,
3070 requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
));
3071 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
3072 requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
));
3073 personalityNames
= OSDynamicCast(OSArray
,
3074 requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
));
3076 if (delayAutounloadBool
) {
3077 delayAutounload
= delayAutounloadBool
->getValue();
3079 if (startKextExcludeNum
) {
3080 startKextExcludeLevel
= startKextExcludeNum
->unsigned8BitValue();
3082 if (startMatchingExcludeNum
) {
3083 startMatchingExcludeLevel
= startMatchingExcludeNum
->unsigned8BitValue();
3086 OSKextLog(/* kext */ NULL
,
3087 kOSKextLogProgressLevel
|
3089 "Received request from user space to load kext %s.",
3090 kextIdentifier
->getCStringNoCopy());
3092 /* Load the kext, with no deferral, since this is a load from outside
3094 * xxx - Would like a better way to handle the default values for the
3095 * xxx - start/match opt args.
3097 result
= OSKext::loadKextWithIdentifier(
3099 /* allowDefer */ false,
3101 startKextExcludeLevel
,
3102 startMatchingExcludeLevel
,
3104 if (result
!= kOSReturnSuccess
) {
3107 /* If the load came down from kextd, it will shortly inform IOCatalogue
3108 * for matching via a separate IOKit calldown.
3113 /* Gather up the collected log messages for user space. Any
3114 * error messages past this call will not make it up as log messages
3115 * but will be in the system log.
3117 logInfoArray
= OSKext::clearUserSpaceLogFilter();
3119 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
3120 tempResult
= OSKext::serializeLogInfo(logInfoArray
,
3121 logInfoOut
, logInfoLengthOut
);
3122 if (tempResult
!= kOSReturnSuccess
) {
3123 result
= tempResult
;
3127 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3129 /* Note: mkextDataObject will have been retained by every kext w/an
3130 * executable in it. That should all have been flushed out at the
3131 * and of the load operation, but you never know....
3133 if (mkextData
&& mkextData
->getRetainCount() > 1) {
3134 OSKextLog(/* kext */ NULL
,
3135 kOSKextLogErrorLevel
|
3136 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3137 "Kext load request buffer from user space still retained by a kext; "
3138 "probable memory leak.");
3141 IORecursiveLockUnlock(sKextLock
);
3143 OSSafeReleaseNULL(mkextData
);
3144 OSSafeReleaseNULL(mkextPlist
);
3145 OSSafeReleaseNULL(serializer
);
3146 OSSafeReleaseNULL(logInfoArray
);
3151 /*********************************************************************
3152 *********************************************************************/
3155 OSKext::serializeLogInfo(
3156 OSArray
* logInfoArray
,
3158 uint32_t * logInfoLengthOut
)
3160 OSReturn result
= kOSReturnError
;
3161 char * buffer
= NULL
;
3162 kern_return_t kmem_result
= KERN_FAILURE
;
3163 OSSerialize
* serializer
= NULL
; // must release; reused
3164 char * logInfo
= NULL
; // returned by reference
3165 uint32_t logInfoLength
= 0;
3167 if (!logInfoArray
|| !logInfoOut
|| !logInfoLengthOut
) {
3168 OSKextLog(/* kext */ NULL
,
3169 kOSKextLogErrorLevel
|
3171 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3172 /* Bad programmer. */
3173 result
= kOSKextReturnInvalidArgument
;
3177 serializer
= OSSerialize::withCapacity(0);
3179 OSKextLog(/* kext */ NULL
,
3180 kOSKextLogErrorLevel
|
3182 "Failed to create serializer on log info for request from user space.");
3183 /* Incidental error; we're going to (try to) allow the request
3184 * itself to succeed. */
3187 if (!logInfoArray
->serialize(serializer
)) {
3188 OSKextLog(/* kext */ NULL
,
3189 kOSKextLogErrorLevel
|
3191 "Failed to serialize log info for request from user space.");
3192 /* Incidental error; we're going to (try to) allow the request
3193 * itself to succeed. */
3195 logInfo
= serializer
->text();
3196 logInfoLength
= serializer
->getLength();
3198 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
, round_page(logInfoLength
), VM_KERN_MEMORY_OSKEXT
);
3199 if (kmem_result
!= KERN_SUCCESS
) {
3200 OSKextLog(/* kext */ NULL
,
3201 kOSKextLogErrorLevel
|
3203 "Failed to copy log info for request from user space.");
3204 /* Incidental error; we're going to (try to) allow the request
3207 /* 11981737 - clear uninitialized data in last page */
3208 bzero((void *)(buffer
+ logInfoLength
),
3209 (round_page(logInfoLength
) - logInfoLength
));
3210 memcpy(buffer
, logInfo
, logInfoLength
);
3211 *logInfoOut
= buffer
;
3212 *logInfoLengthOut
= logInfoLength
;
3216 result
= kOSReturnSuccess
;
3218 OSSafeReleaseNULL(serializer
);
3223 #pragma mark Instance Management Methods
3225 /*********************************************************************
3226 *********************************************************************/
3228 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
)
3230 OSKext
* foundKext
= NULL
;
3232 IORecursiveLockLock(sKextLock
);
3233 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3235 foundKext
->retain();
3237 IORecursiveLockUnlock(sKextLock
);
3242 /*********************************************************************
3243 *********************************************************************/
3245 OSKext::lookupKextWithIdentifier(OSString
* kextIdentifier
)
3247 return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy());
3250 /*********************************************************************
3251 *********************************************************************/
3253 OSKext::lookupKextWithLoadTag(uint32_t aTag
)
3255 OSKext
* foundKext
= NULL
; // returned
3258 IORecursiveLockLock(sKextLock
);
3260 count
= sLoadedKexts
->getCount();
3261 for (i
= 0; i
< count
; i
++) {
3262 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3263 if (thisKext
->getLoadTag() == aTag
) {
3264 foundKext
= thisKext
;
3265 foundKext
->retain();
3271 IORecursiveLockUnlock(sKextLock
);
3276 /*********************************************************************
3277 *********************************************************************/
3279 OSKext::lookupKextWithAddress(vm_address_t address
)
3281 OSKext
* foundKext
= NULL
; // returned
3284 IORecursiveLockLock(sKextLock
);
3286 count
= sLoadedKexts
->getCount();
3287 for (i
= 0; i
< count
; i
++) {
3288 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3289 if (thisKext
->linkedExecutable
) {
3290 vm_address_t kext_start
=
3291 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy();
3292 vm_address_t kext_end
= kext_start
+
3293 thisKext
->linkedExecutable
->getLength();
3294 if ((kext_start
<= address
) && (address
< kext_end
)) {
3295 foundKext
= thisKext
;
3296 foundKext
->retain();
3303 IORecursiveLockUnlock(sKextLock
);
3309 /*********************************************************************
3310 *********************************************************************/
3312 OSKext::lookupKextWithUUID(uuid_t wanted
)
3314 OSKext
* foundKext
= NULL
; // returned
3317 IORecursiveLockLock(sKextLock
);
3319 count
= sLoadedKexts
->getCount();
3321 for (i
= 0; i
< count
; i
++) {
3322 OSKext
* thisKext
= NULL
;
3324 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3329 OSData
*uuid_data
= thisKext
->copyUUID();
3335 memcpy(&uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
3336 uuid_data
->release();
3338 if (0 == uuid_compare(wanted
, uuid
)) {
3339 foundKext
= thisKext
;
3340 foundKext
->retain();
3347 IORecursiveLockUnlock(sKextLock
);
3355 /*********************************************************************
3356 *********************************************************************/
3358 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
)
3360 bool result
= false;
3361 OSKext
* foundKext
= NULL
; // returned
3363 IORecursiveLockLock(sKextLock
);
3365 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3366 if (foundKext
&& foundKext
->isLoaded()) {
3370 IORecursiveLockUnlock(sKextLock
);
3375 /*********************************************************************
3376 * xxx - should spawn a separate thread so a kext can safely have
3377 * xxx - itself unloaded.
3378 *********************************************************************/
3383 bool terminateServicesAndRemovePersonalitiesFlag
)
3386 OSReturn result
= kOSKextReturnInUse
;
3387 OSKext
* checkKext
= NULL
; // do not release
3389 int macCheckResult
= 0;
3390 kauth_cred_t cred
= NULL
;
3393 IORecursiveLockLock(sKextLock
);
3395 /* If the kext has no identifier, it failed to init
3396 * so isn't in sKextsByID and it isn't loaded.
3398 if (!aKext
->getIdentifier()) {
3399 result
= kOSReturnSuccess
;
3403 checkKext
= OSDynamicCast(OSKext
,
3404 sKextsByID
->getObject(aKext
->getIdentifier()));
3405 if (checkKext
!= aKext
) {
3406 result
= kOSKextReturnNotFound
;
3410 if (aKext
->isLoaded()) {
3412 if (current_task() != kernel_task
) {
3413 cred
= kauth_cred_get_with_ref();
3414 macCheckResult
= mac_kext_check_unload(cred
, aKext
->getIdentifierCString());
3415 kauth_cred_unref(&cred
);
3418 if (macCheckResult
!= 0) {
3419 result
= kOSReturnError
;
3421 kOSKextLogErrorLevel
|
3422 kOSKextLogKextBookkeepingFlag
,
3423 "Failed to remove kext %s (MAC policy error 0x%x).",
3424 aKext
->getIdentifierCString(), macCheckResult
);
3429 /* make sure there are no resource requests in flight - 17187548 */
3430 if (aKext
->countRequestCallbacks()) {
3434 /* If we are terminating, send the request to the IOCatalogue
3435 * (which will actually call us right back but that's ok we have
3436 * a recursive lock don't you know) but do not ask the IOCatalogue
3437 * to call back with an unload, we'll do that right here.
3439 if (terminateServicesAndRemovePersonalitiesFlag
) {
3440 result
= gIOCatalogue
->terminateDriversForModule(
3441 aKext
->getIdentifierCString(), /* unload */ false);
3442 if (result
!= kOSReturnSuccess
) {
3444 kOSKextLogErrorLevel
|
3445 kOSKextLogKextBookkeepingFlag
,
3446 "Can't remove kext %s; services failed to terminate - 0x%x.",
3447 aKext
->getIdentifierCString(), result
);
3452 result
= aKext
->unload();
3453 if (result
!= kOSReturnSuccess
) {
3458 /* Remove personalities as requested. This is a bit redundant for a loaded
3459 * kext as IOCatalogue::terminateDriversForModule() removes driver
3460 * personalities, but it doesn't restart matching, which we always want
3461 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3464 if (terminateServicesAndRemovePersonalitiesFlag
) {
3465 aKext
->removePersonalitiesFromCatalog();
3469 kOSKextLogProgressLevel
|
3470 kOSKextLogKextBookkeepingFlag
,
3471 "Removing kext %s.",
3472 aKext
->getIdentifierCString());
3474 sKextsByID
->removeObject(aKext
->getIdentifier());
3475 result
= kOSReturnSuccess
;
3478 IORecursiveLockUnlock(sKextLock
);
3482 /*********************************************************************
3483 *********************************************************************/
3486 OSKext::removeKextWithIdentifier(
3487 const char * kextIdentifier
,
3488 bool terminateServicesAndRemovePersonalitiesFlag
)
3490 OSReturn result
= kOSReturnError
;
3492 IORecursiveLockLock(sKextLock
);
3494 OSKext
* aKext
= OSDynamicCast(OSKext
,
3495 sKextsByID
->getObject(kextIdentifier
));
3497 result
= kOSKextReturnNotFound
;
3498 OSKextLog(/* kext */ NULL
,
3499 kOSKextLogErrorLevel
|
3500 kOSKextLogKextBookkeepingFlag
,
3501 "Can't remove kext %s - not found.",
3506 result
= OSKext::removeKext(aKext
,
3507 terminateServicesAndRemovePersonalitiesFlag
);
3510 IORecursiveLockUnlock(sKextLock
);
3515 /*********************************************************************
3516 *********************************************************************/
3519 OSKext::removeKextWithLoadTag(
3520 OSKextLoadTag loadTag
,
3521 bool terminateServicesAndRemovePersonalitiesFlag
)
3523 OSReturn result
= kOSReturnError
;
3524 OSKext
* foundKext
= NULL
;
3527 IORecursiveLockLock(sKextLock
);
3529 count
= sLoadedKexts
->getCount();
3530 for (i
= 0; i
< count
; i
++) {
3531 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3532 if (thisKext
->loadTag
== loadTag
) {
3533 foundKext
= thisKext
;
3539 result
= kOSKextReturnNotFound
;
3540 OSKextLog(/* kext */ NULL
,
3541 kOSKextLogErrorLevel
|
3542 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
3543 "Can't remove kext with load tag %d - not found.",
3548 result
= OSKext::removeKext(foundKext
,
3549 terminateServicesAndRemovePersonalitiesFlag
);
3552 IORecursiveLockUnlock(sKextLock
);
3557 /*********************************************************************
3558 *********************************************************************/
3560 OSKext::copyKexts(void)
3562 OSDictionary
* result
;
3564 IORecursiveLockLock(sKextLock
);
3565 result
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection());
3566 IORecursiveLockUnlock(sKextLock
);
3571 /*********************************************************************
3572 *********************************************************************/
3573 #define BOOTER_KEXT_PREFIX "Driver-"
3575 typedef struct _DeviceTreeBuffer
{
3578 } _DeviceTreeBuffer
;
3580 /*********************************************************************
3581 * Create a dictionary of excluded kexts from the given booter data.
3582 *********************************************************************/
3585 OSKext::createExcludeListFromBooterData(
3586 OSDictionary
* theDictionary
,
3587 OSCollectionIterator
* theIterator
)
3589 OSString
* deviceTreeName
= NULL
; // do not release
3590 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not release
3591 char * booterDataPtr
= NULL
; // do not release
3592 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not release
3593 char * infoDictAddr
= NULL
; // do not release
3594 OSObject
* parsedXML
= NULL
; // must release
3595 OSDictionary
* theInfoDict
= NULL
; // do not release
3597 theIterator
->reset();
3599 /* look for AppleKextExcludeList.kext */
3600 while ( (deviceTreeName
=
3601 OSDynamicCast(OSString
, theIterator
->getNextObject())) ) {
3603 const char * devTreeNameCString
;
3604 OSData
* deviceTreeEntry
;
3605 OSString
* myBundleID
; // do not release
3607 OSSafeReleaseNULL(parsedXML
);
3610 OSDynamicCast(OSData
, theDictionary
->getObject(deviceTreeName
));
3611 if (!deviceTreeEntry
) {
3615 /* Make sure it is a kext */
3616 devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
3617 if (strncmp(devTreeNameCString
, BOOTER_KEXT_PREFIX
,
3618 (sizeof(BOOTER_KEXT_PREFIX
) - 1)) != 0) {
3620 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3621 "\"%s\" not a kext",
3622 devTreeNameCString
);
3626 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
3627 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
3628 if (!deviceTreeBuffer
) {
3632 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
3633 if (!booterDataPtr
) {
3637 kextFileInfo
= (_BooterKextFileInfo
*) booterDataPtr
;
3638 if (!kextFileInfo
->infoDictPhysAddr
||
3639 !kextFileInfo
->infoDictLength
) {
3643 infoDictAddr
= (char *)
3644 ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
3645 if (!infoDictAddr
) {
3649 parsedXML
= OSUnserializeXML(infoDictAddr
);
3654 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
3660 OSDynamicCast(OSString
,
3661 theInfoDict
->getObject(kCFBundleIdentifierKey
));
3663 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3665 /* get copy of exclusion list dictionary */
3666 OSDictionary
* myTempDict
; // do not free
3668 myTempDict
= OSDynamicCast(
3670 theInfoDict
->getObject("OSKextExcludeList"));
3671 if ( NULL
== myTempDict
) {
3673 panic("Missing OSKextExcludeList dictionary\n");
3676 IORecursiveLockLock(sKextLock
);
3678 /* get rid of old exclusion list */
3679 if (sExcludeListByID
) {
3680 OSSafeReleaseNULL(sExcludeListByID
);
3682 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3683 IORecursiveLockUnlock(sKextLock
);
3688 } // while ( (deviceTreeName = ...) )
3690 OSSafeReleaseNULL(parsedXML
);
3694 /*********************************************************************
3695 * Create a dictionary of excluded kexts from the given prelink
3696 * info (kernelcache).
3697 *********************************************************************/
3700 OSKext::createExcludeListFromPrelinkInfo( OSArray
* theInfoArray
)
3702 OSDictionary
* myInfoDict
= NULL
; // do not release
3703 OSString
* myBundleID
; // do not release
3706 /* Find com.apple.driver.KextExcludeList. */
3707 for (i
= 0; i
< theInfoArray
->getCount(); i
++) {
3708 myInfoDict
= OSDynamicCast(OSDictionary
, theInfoArray
->getObject(i
));
3713 OSDynamicCast(OSString
,
3714 myInfoDict
->getObject(kCFBundleIdentifierKey
));
3716 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3717 // get copy of exclude list dictionary
3718 OSDictionary
* myTempDict
; // do not free
3719 myTempDict
= OSDynamicCast(OSDictionary
,
3720 myInfoDict
->getObject("OSKextExcludeList"));
3721 if ( NULL
== myTempDict
) {
3723 panic("Missing OSKextExcludeList dictionary\n");
3726 IORecursiveLockLock(sKextLock
);
3727 // get rid of old exclude list
3728 if (sExcludeListByID
) {
3729 OSSafeReleaseNULL(sExcludeListByID
);
3732 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3733 IORecursiveLockUnlock(sKextLock
);
3736 } // for (i = 0; i < theInfoArray->getCount()...
3742 #pragma mark Accessors
3744 /*********************************************************************
3745 *********************************************************************/
3747 OSKext::getIdentifier(void)
3752 /*********************************************************************
3753 * A kext must have a bundle identifier to even survive initialization;
3754 * this is guaranteed to exist past then.
3755 *********************************************************************/
3757 OSKext::getIdentifierCString(void)
3759 return bundleID
->getCStringNoCopy();
3762 /*********************************************************************
3763 *********************************************************************/
3765 OSKext::getVersion(void)
3770 /*********************************************************************
3771 *********************************************************************/
3773 OSKext::getCompatibleVersion(void)
3775 return compatibleVersion
;
3778 /*********************************************************************
3779 *********************************************************************/
3781 OSKext::isLibrary(void)
3783 return (getCompatibleVersion() > 0);
3786 /*********************************************************************
3787 *********************************************************************/
3789 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
)
3791 if ((compatibleVersion
> -1 && version
> -1) &&
3792 (compatibleVersion
<= version
&& aVersion
<= version
)) {
3798 /*********************************************************************
3799 *********************************************************************/
3801 OSKext::declaresExecutable(void)
3803 return (getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
);
3806 /*********************************************************************
3807 *********************************************************************/
3809 OSKext::getExecutable(void)
3811 OSData
* result
= NULL
;
3812 OSData
* extractedExecutable
= NULL
; // must release
3813 OSData
* mkextExecutableRef
= NULL
; // do not release
3815 result
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
));
3820 mkextExecutableRef
= OSDynamicCast(OSData
,
3821 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
));
3823 if (mkextExecutableRef
) {
3825 MkextEntryRef
* mkextEntryRef
= (MkextEntryRef
*)
3826 mkextExecutableRef
->getBytesNoCopy();
3827 uint32_t mkextVersion
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
);
3828 if (mkextVersion
== MKEXT_VERS_2
) {
3829 mkext2_file_entry
* fileinfo
=
3830 (mkext2_file_entry
*)mkextEntryRef
->fileinfo
;
3831 uint32_t compressedSize
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
);
3832 uint32_t fullSize
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
);
3833 extractedExecutable
= extractMkext2FileData(
3834 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable",
3835 compressedSize
, fullSize
);
3837 OSKextLog(this, kOSKextLogErrorLevel
|
3838 kOSKextLogArchiveFlag
,
3839 "Kext %s - unknown mkext version 0x%x for executable.",
3840 getIdentifierCString(), mkextVersion
);
3843 /* Regardless of success, remove the mkext executable,
3844 * and drop one reference on the mkext. (setExecutable() does not
3845 * replace, it removes, or panics if asked to replace.)
3847 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
3848 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
3850 if (extractedExecutable
&& extractedExecutable
->getLength()) {
3851 if (!setExecutable(extractedExecutable
)) {
3854 result
= extractedExecutable
;
3862 OSSafeReleaseNULL(extractedExecutable
);
3867 /*********************************************************************
3868 *********************************************************************/
3870 OSKext::isInterface(void)
3872 return flags
.interface
;
3875 /*********************************************************************
3876 *********************************************************************/
3878 OSKext::isKernel(void)
3880 return (this == sKernelKext
);
3883 /*********************************************************************
3884 *********************************************************************/
3886 OSKext::isKernelComponent(void)
3888 return flags
.kernelComponent
? true : false;
3891 /*********************************************************************
3892 *********************************************************************/
3894 OSKext::isExecutable(void)
3896 return (!isKernel() && !isInterface() && declaresExecutable());
3899 /*********************************************************************
3900 * We might want to check this recursively for all dependencies,
3901 * since a subtree of dependencies could get loaded before we hit
3902 * a dependency that isn't safe-boot-loadable.
3904 * xxx - Might want to return false if OSBundleEnableKextLogging or
3905 * OSBundleDebugLevel
3906 * or IOKitDebug is nonzero too (we used to do that, but I don't see
3907 * the point except it's usually development drivers, which might
3908 * cause panics on startup, that have those properties). Heh; could
3909 * use a "kx" boot-arg!
3910 *********************************************************************/
3912 OSKext::isLoadableInSafeBoot(void)
3914 bool result
= false;
3915 OSString
* required
= NULL
; // do not release
3922 required
= OSDynamicCast(OSString
,
3923 getPropertyForHostArch(kOSBundleRequiredKey
));
3927 if (required
->isEqualTo(kOSBundleRequiredRoot
) ||
3928 required
->isEqualTo(kOSBundleRequiredLocalRoot
) ||
3929 required
->isEqualTo(kOSBundleRequiredNetworkRoot
) ||
3930 required
->isEqualTo(kOSBundleRequiredSafeBoot
) ||
3931 required
->isEqualTo(kOSBundleRequiredConsole
)) {
3940 /*********************************************************************
3941 *********************************************************************/
3943 OSKext::isPrelinked(void)
3945 return flags
.prelinked
? true : false;
3948 /*********************************************************************
3949 *********************************************************************/
3950 bool OSKext::isLoaded(void)
3952 return flags
.loaded
? true : false;
3955 /*********************************************************************
3956 *********************************************************************/
3958 OSKext::isStarted(void)
3960 return flags
.started
? true : false;
3963 /*********************************************************************
3964 *********************************************************************/
3966 OSKext::isCPPInitialized(void)
3968 return flags
.CPPInitialized
;
3971 /*********************************************************************
3972 *********************************************************************/
3974 OSKext::setCPPInitialized(bool initialized
)
3976 flags
.CPPInitialized
= initialized
;
3979 /*********************************************************************
3980 *********************************************************************/
3982 OSKext::getLoadTag(void)
3987 /*********************************************************************
3988 *********************************************************************/
3989 void OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
)
3991 if (linkedExecutable
) {
3992 *loadSize
= linkedExecutable
->getLength();
3994 /* If we have a kmod_info struct, calculated the wired size
3995 * from that. Otherwise it's the full load size.
3998 *wiredSize
= *loadSize
- kmod_info
->hdr_size
;
4000 *wiredSize
= *loadSize
;
4009 /*********************************************************************
4010 *********************************************************************/
4012 OSKext::copyUUID(void)
4014 OSData
* result
= NULL
;
4015 OSData
* theExecutable
= NULL
; // do not release
4016 const kernel_mach_header_t
* header
= NULL
;
4017 const struct load_command
* load_cmd
= NULL
;
4018 const struct uuid_command
* uuid_cmd
= NULL
;
4021 /* An interface kext doesn't have a linked executable with an LC_UUID,
4022 * we create one when it's linked.
4024 if (interfaceUUID
) {
4025 result
= interfaceUUID
;
4030 /* For real kexts, try to get the UUID from the linked executable,
4031 * or if is hasn't been linked yet, the unrelocated executable.
4033 theExecutable
= linkedExecutable
;
4034 if (!theExecutable
) {
4035 theExecutable
= getExecutable();
4037 if (!theExecutable
) {
4041 header
= (const kernel_mach_header_t
*)theExecutable
->getBytesNoCopy();
4042 load_cmd
= (const struct load_command
*)&header
[1];
4044 if (header
->magic
!= MH_MAGIC_KERNEL
) {
4046 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4047 "%s: bad header %p",
4053 for (i
= 0; i
< header
->ncmds
; i
++) {
4054 if (load_cmd
->cmd
== LC_UUID
) {
4055 uuid_cmd
= (struct uuid_command
*)load_cmd
;
4056 result
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
));
4059 load_cmd
= (struct load_command
*)((caddr_t
)load_cmd
+ load_cmd
->cmdsize
);
4066 /*********************************************************************
4067 *********************************************************************/
4069 #if defined (__x86_64__)
4070 #define ARCHNAME "x86_64"
4072 #error architecture not supported
4075 #define ARCH_SEPARATOR_CHAR '_'
4077 static char * makeHostArchKey(const char * key
, uint32_t * keySizeOut
)
4079 char * result
= NULL
;
4080 uint32_t keyLength
= strlen(key
);
4083 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4085 keySize
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
);
4086 result
= (char *)kalloc_tag(keySize
, VM_KERN_MEMORY_OSKEXT
);
4090 strlcpy(result
, key
, keySize
);
4091 result
[keyLength
++] = ARCH_SEPARATOR_CHAR
;
4092 result
[keyLength
] = '\0';
4093 strlcat(result
, ARCHNAME
, keySize
);
4094 *keySizeOut
= keySize
;
4100 /*********************************************************************
4101 *********************************************************************/
4103 OSKext::getPropertyForHostArch(const char * key
)
4105 OSObject
* result
= NULL
; // do not release
4106 uint32_t hostArchKeySize
= 0;
4107 char * hostArchKey
= NULL
; // must kfree
4109 if (!key
|| !infoDict
) {
4113 /* Some properties are not allowed to be arch-variant:
4114 * - Any CFBundle... property.
4115 * - OSBundleIsInterface.
4116 * - OSKernelResource.
4118 if (STRING_HAS_PREFIX(key
, "OS") ||
4119 STRING_HAS_PREFIX(key
, "IO")) {
4121 hostArchKey
= makeHostArchKey(key
, &hostArchKeySize
);
4123 OSKextLog(/* kext (this isn't about a kext) */ NULL
,
4124 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4125 "Allocation failure.");
4128 result
= infoDict
->getObject(hostArchKey
);
4132 result
= infoDict
->getObject(key
);
4136 if (hostArchKey
) kfree(hostArchKey
, hostArchKeySize
);
4141 #pragma mark Load/Start/Stop/Unload
4144 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4146 /*********************************************************************
4147 * sExcludeListByID is a dictionary with keys / values of:
4148 * key = bundleID string of kext we will not allow to load
4149 * value = version string(s) of the kext that is to be denied loading.
4150 * The version strings can be comma delimited. For example if kext
4151 * com.foocompany.fookext has two versions that we want to deny
4152 * loading then the version strings might look like:
4154 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4155 * not load the kext.
4157 * Value may also be in the form of "LE 2.0.0" (version numbers
4158 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4159 * number less than 2.0.0 will not load)
4161 * NOTE - we cannot use the characters "<=" or "<" because we have code
4162 * that serializes plists and treats '<' as a special character.
4163 *********************************************************************/
4165 OSKext::isInExcludeList(void)
4167 OSString
* versionString
= NULL
; // do not release
4168 char * versionCString
= NULL
; // do not free
4170 boolean_t wantLessThan
= false;
4171 boolean_t wantLessThanEqualTo
= false;
4174 if (!sExcludeListByID
) {
4177 /* look up by bundleID in our exclude list and if found get version
4178 * string (or strings) that we will not allow to load
4180 versionString
= OSDynamicCast(OSString
, sExcludeListByID
->getObject(bundleID
));
4181 if (versionString
== NULL
|| versionString
->getLength() > (sizeof(myBuffer
) - 1)) {
4185 /* parse version strings */
4186 versionCString
= (char *) versionString
->getCStringNoCopy();
4188 /* look for "LT" or "LE" form of version string, must be in first two
4191 if (*versionCString
== 'L' && *(versionCString
+ 1) == 'T') {
4192 wantLessThan
= true;
4195 else if (*versionCString
== 'L' && *(versionCString
+ 1) == 'E') {
4196 wantLessThanEqualTo
= true;
4200 for (i
= 0; *versionCString
!= 0x00; versionCString
++) {
4201 /* skip whitespace */
4202 if (isWhiteSpace(*versionCString
)) {
4206 /* peek ahead for version string separator or null terminator */
4207 if (*(versionCString
+ 1) == ',' || *(versionCString
+ 1) == 0x00) {
4209 /* OK, we have a version string */
4210 myBuffer
[i
++] = *versionCString
;
4213 OSKextVersion excludeVers
;
4214 excludeVers
= OSKextParseVersionString(myBuffer
);
4216 if (wantLessThanEqualTo
) {
4217 if (version
<= excludeVers
) {
4221 else if (wantLessThan
) {
4222 if (version
< excludeVers
) {
4226 else if ( version
== excludeVers
) {
4230 /* reset for the next (if any) version string */
4232 wantLessThan
= false;
4233 wantLessThanEqualTo
= false;
4236 /* save valid version character */
4237 myBuffer
[i
++] = *versionCString
;
4239 /* make sure bogus version string doesn't overrun local buffer */
4240 if ( i
>= sizeof(myBuffer
) ) {
4249 /*********************************************************************
4250 *********************************************************************/
4253 OSKext::loadKextWithIdentifier(
4254 const char * kextIdentifierCString
,
4255 Boolean allowDeferFlag
,
4256 Boolean delayAutounloadFlag
,
4257 OSKextExcludeLevel startOpt
,
4258 OSKextExcludeLevel startMatchingOpt
,
4259 OSArray
* personalityNames
)
4261 OSReturn result
= kOSReturnError
;
4262 OSString
* kextIdentifier
= NULL
; // must release
4264 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
4265 if (!kextIdentifier
) {
4266 result
= kOSKextReturnNoMemory
;
4269 result
= OSKext::loadKextWithIdentifier(kextIdentifier
,
4270 allowDeferFlag
, delayAutounloadFlag
,
4271 startOpt
, startMatchingOpt
, personalityNames
);
4274 OSSafeReleaseNULL(kextIdentifier
);
4278 /*********************************************************************
4279 *********************************************************************/
4281 OSKext::loadKextWithIdentifier(
4282 OSString
* kextIdentifier
,
4283 Boolean allowDeferFlag
,
4284 Boolean delayAutounloadFlag
,
4285 OSKextExcludeLevel startOpt
,
4286 OSKextExcludeLevel startMatchingOpt
,
4287 OSArray
* personalityNames
)
4289 OSReturn result
= kOSReturnError
;
4290 OSReturn pingResult
= kOSReturnError
;
4291 OSKext
* theKext
= NULL
; // do not release
4292 OSDictionary
* loadRequest
= NULL
; // must release
4293 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4295 IORecursiveLockLock(sKextLock
);
4297 if (!kextIdentifier
) {
4298 result
= kOSKextReturnInvalidArgument
;
4302 OSKext::recordIdentifierRequest(kextIdentifier
);
4304 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
4306 if (!allowDeferFlag
) {
4307 OSKextLog(/* kext */ NULL
,
4308 kOSKextLogErrorLevel
|
4310 "Can't load kext %s - not found.",
4311 kextIdentifier
->getCStringNoCopy());
4315 if (!sKernelRequestsEnabled
) {
4317 kOSKextLogErrorLevel
|
4319 "Can't load kext %s - requests to user space are disabled.",
4320 kextIdentifier
->getCStringNoCopy());
4321 result
= kOSKextReturnDisabled
;
4325 /* Create a new request unless one is already sitting
4326 * in sKernelRequests for this bundle identifier
4328 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4329 if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4330 result
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
,
4332 if (result
!= kOSReturnSuccess
) {
4335 if (!_OSKextSetRequestArgument(loadRequest
,
4336 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
4338 result
= kOSKextReturnNoMemory
;
4341 if (!sKernelRequests
->setObject(loadRequest
)) {
4342 result
= kOSKextReturnNoMemory
;
4346 if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4347 result
= kOSKextReturnNoMemory
;
4352 kOSKextLogDebugLevel
|
4354 "Kext %s not found; queued load request to user space.",
4355 kextIdentifier
->getCStringNoCopy());
4358 pingResult
= OSKext::pingKextd();
4359 if (pingResult
== kOSKextReturnDisabled
) {
4360 OSKextLog(/* kext */ NULL
,
4361 ((sPrelinkBoot
) ? kOSKextLogDebugLevel
: kOSKextLogErrorLevel
) |
4363 "Kext %s might not load - kextd is currently unavailable.",
4364 kextIdentifier
->getCStringNoCopy());
4367 result
= kOSKextReturnDeferred
;
4371 result
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
);
4373 if (result
!= kOSReturnSuccess
) {
4375 kOSKextLogErrorLevel
|
4377 "Failed to load kext %s (error 0x%x).",
4378 kextIdentifier
->getCStringNoCopy(), (int)result
);
4380 OSKext::removeKext(theKext
,
4381 /* terminateService/removePersonalities */ true);
4385 if (delayAutounloadFlag
) {
4387 kOSKextLogProgressLevel
|
4388 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4389 "Setting delayed autounload for %s.",
4390 kextIdentifier
->getCStringNoCopy());
4391 theKext
->flags
.delayAutounload
= 1;
4395 OSSafeReleaseNULL(loadRequest
);
4396 OSSafeReleaseNULL(kextIdentifierSymbol
);
4398 IORecursiveLockUnlock(sKextLock
);
4403 /*********************************************************************
4404 *********************************************************************/
4407 OSKext::recordIdentifierRequest(
4408 OSString
* kextIdentifier
)
4410 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4413 if (!sAllKextLoadIdentifiers
|| !kextIdentifier
) {
4417 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4418 if (!kextIdentifierSymbol
) {
4419 // xxx - this is really a basic alloc failure
4424 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4425 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4428 // xxx - need to find a way to associate this whole func w/the kext
4429 OSKextLog(/* kext */ NULL
,
4430 // xxx - check level
4431 kOSKextLogStepLevel
|
4432 kOSKextLogArchiveFlag
,
4433 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4434 kextIdentifier
->getCStringNoCopy());
4440 OSKextLog(/* kext */ NULL
,
4441 kOSKextLogErrorLevel
|
4442 kOSKextLogArchiveFlag
,
4443 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4444 kextIdentifier
->getCStringNoCopy());
4446 OSSafeReleaseNULL(kextIdentifierSymbol
);
4450 /*********************************************************************
4451 *********************************************************************/
4454 OSKextExcludeLevel startOpt
,
4455 OSKextExcludeLevel startMatchingOpt
,
4456 OSArray
* personalityNames
)
4458 OSReturn result
= kOSReturnError
;
4459 kern_return_t kxldResult
;
4460 OSKextExcludeLevel dependenciesStartOpt
= startOpt
;
4461 OSKextExcludeLevel dependenciesStartMatchingOpt
= startMatchingOpt
;
4462 unsigned int i
, count
;
4463 Boolean alreadyLoaded
= false;
4464 OSKext
* lastLoadedKext
= NULL
;
4466 if (isInExcludeList()) {
4468 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
|
4470 "Kext %s is in exclude list, not loadable",
4471 getIdentifierCString());
4473 result
= kOSKextReturnNotLoadable
;
4478 alreadyLoaded
= true;
4479 result
= kOSReturnSuccess
;
4482 kOSKextLogDebugLevel
|
4483 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4484 "Kext %s is already loaded.",
4485 getIdentifierCString());
4490 if (current_task() != kernel_task
) {
4491 int macCheckResult
= 0;
4492 kauth_cred_t cred
= NULL
;
4494 cred
= kauth_cred_get_with_ref();
4495 macCheckResult
= mac_kext_check_load(cred
, getIdentifierCString());
4496 kauth_cred_unref(&cred
);
4498 if (macCheckResult
!= 0) {
4499 result
= kOSReturnError
;
4501 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4502 "Failed to load kext %s (MAC policy error 0x%x).",
4503 getIdentifierCString(), macCheckResult
);
4509 if (!sLoadEnabled
) {
4511 kOSKextLogErrorLevel
|
4513 "Kext loading is disabled (attempt to load kext %s).",
4514 getIdentifierCString());
4515 result
= kOSKextReturnDisabled
;
4519 /* If we've pushed the next available load tag to the invalid value,
4520 * we can't load any more kexts.
4522 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4524 kOSKextLogErrorLevel
|
4526 "Can't load kext %s - no more load tags to assign.",
4527 getIdentifierCString());
4528 result
= kOSKextReturnNoResources
;
4532 /* This is a bit of a hack, because we shouldn't be handling
4533 * personalities within the load function.
4535 if (!declaresExecutable()) {
4536 result
= kOSReturnSuccess
;
4540 /* Are we in safe boot?
4542 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4544 kOSKextLogErrorLevel
|
4546 "Can't load kext %s - not loadable during safe boot.",
4547 getIdentifierCString());
4548 result
= kOSKextReturnBootLevel
;
4553 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4555 getIdentifierCString());
4557 if (!sKxldContext
) {
4558 kxldResult
= kxld_create_context(&sKxldContext
, &kern_allocate
,
4559 &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,
4560 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
4563 kOSKextLogErrorLevel
|
4564 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4565 "Can't load kext %s - failed to create link context.",
4566 getIdentifierCString());
4567 result
= kOSKextReturnNoMemory
;
4572 /* We only need to resolve dependencies once for the whole graph, but
4573 * resolveDependencies will just return if there's no work to do, so it's
4574 * safe to call it more than once.
4576 if (!resolveDependencies()) {
4577 // xxx - check resolveDependencies() for log msg
4579 kOSKextLogErrorLevel
|
4580 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4581 "Can't load kext %s - failed to resolve library dependencies.",
4582 getIdentifierCString());
4583 result
= kOSKextReturnDependencies
;
4587 /* If we are excluding just the kext being loaded now (and not its
4588 * dependencies), drop the exclusion level to none so dependencies
4589 * start and/or add their personalities.
4591 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4592 dependenciesStartOpt
= kOSKextExcludeNone
;
4595 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4596 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4599 /* Load the dependencies, recursively.
4601 count
= getNumDependencies();
4602 for (i
= 0; i
< count
; i
++) {
4603 OSKext
* dependency
= OSDynamicCast(OSKext
,
4604 dependencies
->getObject(i
));
4605 if (dependency
== NULL
) {
4607 kOSKextLogErrorLevel
|
4608 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4609 "Internal error loading kext %s; dependency disappeared.",
4610 getIdentifierCString());
4611 result
= kOSKextReturnInternalError
;
4615 /* Dependencies must be started accorting to the opt,
4616 * but not given the personality names of the main kext.
4618 result
= dependency
->load(dependenciesStartOpt
,
4619 dependenciesStartMatchingOpt
,
4620 /* personalityNames */ NULL
);
4621 if (result
!= KERN_SUCCESS
) {
4623 kOSKextLogErrorLevel
|
4624 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4625 "Dependency %s of kext %s failed to load.",
4626 dependency
->getIdentifierCString(),
4627 getIdentifierCString());
4629 OSKext::removeKext(dependency
,
4630 /* terminateService/removePersonalities */ true);
4631 result
= kOSKextReturnDependencyLoadError
;
4637 result
= loadExecutable();
4638 if (result
!= KERN_SUCCESS
) {
4642 pendingPgoHead
.next
= &pendingPgoHead
;
4643 pendingPgoHead
.prev
= &pendingPgoHead
;
4645 uuid_generate(instance_uuid
);
4646 account
= IONew(OSKextAccount
, 1);
4648 result
= KERN_MEMORY_ERROR
;
4651 bzero(account
, sizeof(*account
));
4652 account
->loadTag
= kmod_info
->id
;
4653 account
->site
.flags
= VM_TAG_KMOD
;
4654 account
->kext
= this;
4656 flags
.loaded
= true;
4658 /* Add the kext to the list of loaded kexts and update the kmod_info
4659 * struct to point to that of the last loaded kext (which is the way
4660 * it's always been done, though I'd rather do them in order now).
4662 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
4663 sLoadedKexts
->setObject(this);
4665 /* Keep the kernel itself out of the kmod list.
4667 if (lastLoadedKext
->isKernel()) {
4668 lastLoadedKext
= NULL
;
4671 if (lastLoadedKext
) {
4672 kmod_info
->next
= lastLoadedKext
->kmod_info
;
4675 notifyKextLoadObservers(this, kmod_info
);
4677 /* Make the global kmod list point at the just-loaded kext. Note that the
4678 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4679 * although we do report it in kextstat these days by using the newer
4680 * OSArray of loaded kexts, which does contain it.
4682 * (The OSKext object representing the kernel doesn't even have a kmod_info
4683 * struct, though I suppose we could stick a pointer to it from the
4684 * static struct in OSRuntime.cpp.)
4688 /* Save the list of loaded kexts in case we panic.
4690 OSKext::saveLoadedKextPanicList();
4692 if (isExecutable()) {
4693 OSKext::updateLoadedKextSummaries();
4694 savePanicString(/* isLoading */ true);
4697 registerWithDTrace();
4699 jettisonLinkeditSegment();
4700 #endif /* CONFIG_DTRACE */
4702 #if !VM_MAPPED_KEXTS
4703 /* If there is a page (or more) worth of padding after the end
4704 * of the last data section but before the end of the data segment
4705 * then free it in the same manner the LinkeditSegment is freed
4707 jettisonDATASegmentPadding();
4712 if (isExecutable() && !flags
.started
) {
4713 if (startOpt
== kOSKextExcludeNone
) {
4715 if (result
!= kOSReturnSuccess
) {
4717 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4718 "Kext %s start failed (result 0x%x).",
4719 getIdentifierCString(), result
);
4720 result
= kOSKextReturnStartStopError
;
4725 /* If not excluding matching, send the personalities to the kernel.
4726 * This never affects the result of the load operation.
4727 * This is a bit of a hack, because we shouldn't be handling
4728 * personalities within the load function.
4730 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
4731 result
= sendPersonalitiesToCatalog(true, personalityNames
);
4736 /* More hack! If the kext doesn't declare an executable, even if we
4737 * "loaded" it, we have to remove any personalities naming it, or we'll
4738 * never see the registry go quiet. Errors here do not count for the
4739 * load operation itself.
4741 * Note that in every other regard it's perfectly ok for a kext to
4742 * not declare an executable and serve only as a package for personalities
4743 * naming another kext, so we do have to allow such kexts to be "loaded"
4744 * so that those other personalities get added & matched.
4746 if (!declaresExecutable()) {
4748 kOSKextLogStepLevel
| kOSKextLogLoadFlag
,
4749 "Kext %s has no executable; removing any personalities naming it.",
4750 getIdentifierCString());
4751 removePersonalitiesFromCatalog();
4754 if (result
!= kOSReturnSuccess
) {
4756 kOSKextLogErrorLevel
|
4758 "Kext %s failed to load (0x%x).",
4759 getIdentifierCString(), (int)result
);
4760 } else if (!alreadyLoaded
) {
4762 kOSKextLogProgressLevel
|
4765 getIdentifierCString());
4767 queueKextNotification(kKextRequestPredicateLoadNotification
,
4768 OSDynamicCast(OSString
, bundleID
));
4773 /*********************************************************************
4775 *********************************************************************/
4776 static char * strdup(const char * string
)
4778 char * result
= NULL
;
4785 size
= 1 + strlen(string
);
4786 result
= (char *)kalloc_tag(size
, VM_KERN_MEMORY_OSKEXT
);
4791 memcpy(result
, string
, size
);
4797 /*********************************************************************
4799 *********************************************************************/
4802 OSKext::lookupSection(const char *segname
, const char *secname
)
4804 kernel_section_t
* found_section
= NULL
;
4805 kernel_mach_header_t
* mh
= NULL
;
4806 kernel_segment_command_t
* seg
= NULL
;
4807 kernel_section_t
* sec
= NULL
;
4809 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4811 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4813 if (0 != strcmp(seg
->segname
, segname
)) {
4817 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4819 if (0 == strcmp(sec
->sectname
, secname
)) {
4820 found_section
= sec
;
4827 return found_section
;
4830 /*********************************************************************
4832 *********************************************************************/
4835 OSKext::slidePrelinkedExecutable(bool doCoalesedSlides
)
4837 OSReturn result
= kOSKextReturnBadData
;
4838 kernel_mach_header_t
* mh
= NULL
;
4839 kernel_segment_command_t
* seg
= NULL
;
4840 kernel_segment_command_t
* linkeditSeg
= NULL
;
4841 kernel_section_t
* sec
= NULL
;
4842 char * linkeditBase
= NULL
;
4843 bool haveLinkeditBase
= false;
4844 char * relocBase
= NULL
;
4845 bool haveRelocBase
= false;
4846 struct dysymtab_command
* dysymtab
= NULL
;
4847 struct linkedit_data_command
* segmentSplitInfo
= NULL
;
4848 struct symtab_command
* symtab
= NULL
;
4849 kernel_nlist_t
* sym
= NULL
;
4850 struct relocation_info
* reloc
= NULL
;
4853 vm_offset_t new_kextsize
;
4855 if (linkedExecutable
== NULL
|| vm_kernel_slide
== 0) {
4856 result
= kOSReturnSuccess
;
4860 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4861 segmentSplitInfo
= (struct linkedit_data_command
*) getcommandfromheader(mh
, LC_SEGMENT_SPLIT_INFO
);
4863 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4867 seg
->vmaddr
+= vm_kernel_slide
;
4869 #if KASLR_KEXT_DEBUG
4870 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
4872 (unsigned long)VM_KERNEL_UNSLIDE(seg
->vmaddr
),
4873 (unsigned long)seg
->vmaddr
);
4876 if (!haveRelocBase
) {
4877 relocBase
= (char *) seg
->vmaddr
;
4878 haveRelocBase
= true;
4880 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
4881 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
4882 haveLinkeditBase
= true;
4885 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4886 sec
->addr
+= vm_kernel_slide
;
4888 #if KASLR_KEXT_DEBUG
4889 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
4891 (unsigned long)VM_KERNEL_UNSLIDE(sec
->addr
),
4892 (unsigned long)sec
->addr
);
4897 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
4899 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
4901 if (symtab
!= NULL
&& doCoalesedSlides
== false) {
4902 /* Some pseudo-kexts have symbol tables without segments.
4904 if (symtab
->nsyms
> 0 && haveLinkeditBase
) {
4905 sym
= (kernel_nlist_t
*) (linkeditBase
+ symtab
->symoff
);
4906 for (i
= 0; i
< symtab
->nsyms
; i
++) {
4907 if (sym
[i
].n_type
& N_STAB
) {
4910 sym
[i
].n_value
+= vm_kernel_slide
;
4912 #if KASLR_KEXT_DEBUG
4913 #define MAX_SYMS_TO_LOG 5
4914 if ( i
< MAX_SYMS_TO_LOG
) {
4915 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
4916 (unsigned long)VM_KERNEL_UNSLIDE(sym
[i
].n_value
),
4917 (unsigned long)sym
[i
].n_value
);
4924 if (dysymtab
!= NULL
&& doCoalesedSlides
== false) {
4925 if (dysymtab
->nextrel
> 0) {
4927 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4929 "Sliding kext %s: External relocations found.",
4930 getIdentifierCString());
4934 if (dysymtab
->nlocrel
> 0) {
4935 if (!haveLinkeditBase
) {
4937 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4939 "Sliding kext %s: No linkedit segment.",
4940 getIdentifierCString());
4944 if (!haveRelocBase
) {
4946 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4949 "Sliding kext %s: No writable segments.",
4951 "Sliding kext %s: No segments.",
4953 getIdentifierCString());
4957 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
4958 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
4960 for (i
= 0; i
< dysymtab
->nlocrel
; i
++) {
4961 if ( reloc
[i
].r_extern
!= 0
4962 || reloc
[i
].r_type
!= 0
4963 || reloc
[i
].r_length
!= (sizeof(void *) == 8 ? 3 : 2)
4966 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4968 "Sliding kext %s: Unexpected relocation found.",
4969 getIdentifierCString());
4972 if (reloc
[i
].r_pcrel
!= 0) {
4975 *((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)) += vm_kernel_slide
;
4977 #if KASLR_KEXT_DEBUG
4978 #define MAX_DYSYMS_TO_LOG 5
4979 if ( i
< MAX_DYSYMS_TO_LOG
) {
4980 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
4981 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
))),
4982 (unsigned long)*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)));
4987 /* We should free these relocations, not just delete the reference to them.
4988 * <rdar://problem/10535549> Free relocations from PIE kexts.
4990 * For now, we do not free LINKEDIT for kexts with split segments.
4992 new_kextsize
= round_page(kmod_info
->size
- reloc_size
);
4993 if (((kmod_info
->size
- new_kextsize
) > PAGE_SIZE
) && (!segmentSplitInfo
)) {
4994 vm_offset_t endofkext
= kmod_info
->address
+ kmod_info
->size
;
4995 vm_offset_t new_endofkext
= kmod_info
->address
+ new_kextsize
;
4996 vm_offset_t endofrelocInfo
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
);
4997 int bytes_remaining
= endofkext
- endofrelocInfo
;
4998 OSData
* new_osdata
= NULL
;
5000 /* fix up symbol offsets if they are after the dsymtab local relocs */
5002 if (dysymtab
->locreloff
< symtab
->symoff
){
5003 symtab
->symoff
-= reloc_size
;
5005 if (dysymtab
->locreloff
< symtab
->stroff
) {
5006 symtab
->stroff
-= reloc_size
;
5009 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
5010 dysymtab
->extreloff
-= reloc_size
;
5013 /* move data behind reloc info down to new offset */
5014 if (endofrelocInfo
< endofkext
) {
5015 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
5018 /* Create a new OSData for the smaller kext object and reflect
5019 * new linkedit segment size.
5021 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
5022 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
5024 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
5026 /* Fix up kmod info and linkedExecutable.
5028 kmod_info
->size
= new_kextsize
;
5030 new_osdata
->setDeallocFunction(osdata_kext_free
);
5032 new_osdata
->setDeallocFunction(osdata_phys_free
);
5034 linkedExecutable
->setDeallocFunction(NULL
);
5035 linkedExecutable
->release();
5036 linkedExecutable
= new_osdata
;
5039 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
5041 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
5045 dysymtab
->nlocrel
= 0;
5046 dysymtab
->locreloff
= 0;
5050 result
= kOSReturnSuccess
;
5055 /*********************************************************************
5056 * called only by load()
5057 *********************************************************************/
5059 OSKext::loadExecutable()
5061 OSReturn result
= kOSReturnError
;
5062 kern_return_t kxldResult
;
5063 KXLDDependency
* kxlddeps
= NULL
; // must kfree
5064 uint32_t num_kxlddeps
= 0;
5065 OSArray
* linkDependencies
= NULL
; // must release
5066 uint32_t numDirectDependencies
= 0;
5067 uint32_t num_kmod_refs
= 0;
5068 struct mach_header
** kxldHeaderPtr
= NULL
; // do not free
5069 struct mach_header
* kxld_header
= NULL
; // xxx - need to free here?
5070 OSData
* theExecutable
= NULL
; // do not release
5071 OSString
* versString
= NULL
; // do not release
5072 const char * versCString
= NULL
; // do not free
5073 const char * string
= NULL
; // do not free
5076 /* We need the version string for a variety of bits below.
5078 versString
= OSDynamicCast(OSString
,
5079 getPropertyForHostArch(kCFBundleVersionKey
));
5083 versCString
= versString
->getCStringNoCopy();
5085 if (isKernelComponent()) {
5086 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
5088 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
5090 kOSKextLogErrorLevel
|
5092 "Kernel component %s has incorrect version %s; "
5094 getIdentifierCString(),
5095 versCString
, KERNEL6_VERSION
);
5096 result
= kOSKextReturnInternalError
;
5098 } else if (strcmp(versCString
, osrelease
)) {
5100 kOSKextLogErrorLevel
|
5102 "Kernel component %s has incorrect version %s; "
5104 getIdentifierCString(),
5105 versCString
, osrelease
);
5106 result
= kOSKextReturnInternalError
;
5112 if (isPrelinked()) {
5116 /* <rdar://problem/21444003> all callers must be entitled */
5117 if (FALSE
== IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management")) {
5119 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5120 "Not entitled to link kext '%s'",
5121 getIdentifierCString());
5122 result
= kOSKextReturnNotPrivileged
;
5126 theExecutable
= getExecutable();
5127 if (!theExecutable
) {
5128 if (declaresExecutable()) {
5130 kOSKextLogErrorLevel
|
5132 "Can't load kext %s - executable is missing.",
5133 getIdentifierCString());
5134 result
= kOSKextReturnValidation
;
5140 if (isInterface()) {
5141 OSData
*executableCopy
= OSData::withData(theExecutable
);
5142 setLinkedExecutable(executableCopy
);
5143 executableCopy
->release();
5147 numDirectDependencies
= getNumDependencies();
5149 if (flags
.hasBleedthrough
) {
5150 linkDependencies
= dependencies
;
5151 linkDependencies
->retain();
5153 linkDependencies
= OSArray::withArray(dependencies
);
5154 if (!linkDependencies
) {
5156 kOSKextLogErrorLevel
|
5157 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5158 "Can't allocate link dependencies to load kext %s.",
5159 getIdentifierCString());
5163 for (i
= 0; i
< numDirectDependencies
; ++i
) {
5164 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
5165 dependencies
->getObject(i
));
5166 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
5170 num_kxlddeps
= linkDependencies
->getCount();
5171 if (!num_kxlddeps
) {
5173 kOSKextLogErrorLevel
|
5174 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
5175 "Can't load kext %s - it has no library dependencies.",
5176 getIdentifierCString());
5180 kxlddeps
= (KXLDDependency
*)kalloc_tag(num_kxlddeps
* sizeof(*kxlddeps
), VM_KERN_MEMORY_OSKEXT
);
5183 kOSKextLogErrorLevel
|
5184 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5185 "Can't allocate link context to load kext %s.",
5186 getIdentifierCString());
5189 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
5191 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5192 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
5194 if (dependency
->isInterface()) {
5195 OSKext
*interfaceTargetKext
= NULL
;
5196 OSData
* interfaceTarget
= NULL
;
5198 if (dependency
->isKernelComponent()) {
5199 interfaceTargetKext
= sKernelKext
;
5200 interfaceTarget
= sKernelKext
->linkedExecutable
;
5202 interfaceTargetKext
= OSDynamicCast(OSKext
,
5203 dependency
->dependencies
->getObject(0));
5205 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
5208 if (!interfaceTarget
) {
5213 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5214 * it will be useful to have them in the debugger.
5215 * strdup() failing isn't critical right here so we don't check that.
5217 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
5218 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
5219 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
5221 kxlddeps
[i
].interface
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5222 kxlddeps
[i
].interface_size
= dependency
->linkedExecutable
->getLength();
5223 kxlddeps
[i
].interface_name
= strdup(dependency
->getIdentifierCString());
5225 kxlddeps
[i
].kext
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5226 kxlddeps
[i
].kext_size
= dependency
->linkedExecutable
->getLength();
5227 kxlddeps
[i
].kext_name
= strdup(dependency
->getIdentifierCString());
5230 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
5233 kxldHeaderPtr
= &kxld_header
;
5237 kOSKextLogExplicitLevel
|
5238 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5239 "Kext %s - calling kxld_link_file:\n"
5240 " kxld_context: %p\n"
5241 " executable: %p executable_length: %d\n"
5243 " kxld_dependencies: %p num_dependencies: %d\n"
5244 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5245 getIdentifierCString(), sKxldContext
,
5246 theExecutable
->getBytesNoCopy(), theExecutable
->getLength(),
5247 this, kxlddeps
, num_kxlddeps
,
5248 kxldHeaderPtr
, &kmod_info
);
5251 /* After this call, the linkedExecutable instance variable
5254 kxldResult
= kxld_link_file(sKxldContext
,
5255 (u_char
*)theExecutable
->getBytesNoCopy(),
5256 theExecutable
->getLength(),
5257 getIdentifierCString(), this, kxlddeps
, num_kxlddeps
,
5258 (u_char
**)kxldHeaderPtr
, (kxld_addr_t
*)&kmod_info
);
5260 if (kxldResult
!= KERN_SUCCESS
) {
5261 // xxx - add kxldResult here?
5263 kOSKextLogErrorLevel
|
5265 "Can't load kext %s - link failed.",
5266 getIdentifierCString());
5267 result
= kOSKextReturnLinkError
;
5271 /* We've written data & instructions into kernel memory, so flush the data
5272 * cache and invalidate the instruction cache.
5273 * I/D caches are coherent on x86
5275 #if !defined(__i386__) && !defined(__x86_64__)
5276 flush_dcache(kmod_info
->address
, kmod_info
->size
, false);
5277 invalidate_icache(kmod_info
->address
, kmod_info
->size
, false);
5281 if (isInterface()) {
5283 /* Whip up a fake kmod_info entry for the interface kext.
5285 kmod_info
= (kmod_info_t
*)kalloc_tag(sizeof(kmod_info_t
), VM_KERN_MEMORY_OSKEXT
);
5287 result
= KERN_MEMORY_ERROR
;
5291 /* A pseudokext has almost nothing in its kmod_info struct.
5293 bzero(kmod_info
, sizeof(kmod_info_t
));
5295 kmod_info
->info_version
= KMOD_INFO_VERSION
;
5297 /* An interface kext doesn't have a linkedExecutable, so save a
5298 * copy of the UUID out of the original executable via copyUUID()
5299 * while we still have the original executable.
5301 interfaceUUID
= copyUUID();
5304 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5305 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5307 /* Stamp the bundle ID and version from the OSKext over anything
5308 * resident inside the kmod_info.
5310 string
= getIdentifierCString();
5311 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5313 string
= versCString
;
5314 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5316 /* Add the dependencies' kmod_info structs as kmod_references.
5318 num_kmod_refs
= getNumDependencies();
5319 if (num_kmod_refs
) {
5320 kmod_info
->reference_list
= (kmod_reference_t
*)kalloc_tag(
5321 num_kmod_refs
* sizeof(kmod_reference_t
), VM_KERN_MEMORY_OSKEXT
);
5322 if (!kmod_info
->reference_list
) {
5323 result
= KERN_MEMORY_ERROR
;
5326 bzero(kmod_info
->reference_list
,
5327 num_kmod_refs
* sizeof(kmod_reference_t
));
5328 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5329 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5330 OSKext
* refKext
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
));
5331 ref
->info
= refKext
->kmod_info
;
5332 ref
->info
->reference_count
++;
5334 if (refIndex
+ 1 < num_kmod_refs
) {
5335 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5340 if (!isInterface() && linkedExecutable
) {
5342 kOSKextLogProgressLevel
|
5344 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5346 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5347 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5348 (unsigned)kmod_info
->id
);
5351 /* if prelinked, VM protections are already set */
5352 result
= setVMAttributes(!isPrelinked(), true);
5353 if (result
!= KERN_SUCCESS
) {
5357 result
= kOSReturnSuccess
;
5360 OSSafeReleaseNULL(linkDependencies
);
5362 /* Clear up locally allocated dependency info.
5364 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5367 if (kxlddeps
[i
].kext_name
) {
5368 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5369 kfree(kxlddeps
[i
].kext_name
, size
);
5371 if (kxlddeps
[i
].interface_name
) {
5372 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5373 kfree(kxlddeps
[i
].interface_name
, size
);
5376 if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5378 /* We no longer need the unrelocated executable (which the linker
5379 * has altered anyhow).
5381 setExecutable(NULL
);
5383 if (result
!= kOSReturnSuccess
) {
5385 kOSKextLogErrorLevel
|
5387 "Failed to load executable for kext %s.",
5388 getIdentifierCString());
5390 if (kmod_info
&& kmod_info
->reference_list
) {
5391 kfree(kmod_info
->reference_list
,
5392 num_kmod_refs
* sizeof(kmod_reference_t
));
5394 if (isInterface()) {
5395 kfree(kmod_info
, sizeof(kmod_info_t
));
5398 if (linkedExecutable
) {
5399 linkedExecutable
->release();
5400 linkedExecutable
= NULL
;
5407 /*********************************************************************
5408 * The linkedit segment is used by the kext linker for dependency
5409 * resolution, and by dtrace for probe initialization. We can free it
5410 * for non-library kexts, since no kexts depend on non-library kexts
5411 * by definition, once dtrace has been initialized.
5412 *********************************************************************/
5414 OSKext::jettisonLinkeditSegment(void)
5416 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5417 kernel_segment_command_t
* linkedit
= NULL
;
5419 vm_size_t linkeditsize
, kextsize
;
5420 OSData
* data
= NULL
;
5423 /* We can free symbol tables for all embedded kexts because we don't
5424 * support runtime kext linking.
5426 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5428 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5433 /* Find the linkedit segment. If it's not the last segment, then freeing
5434 * it will fragment the kext into multiple VM regions, which OSKext is not
5435 * designed to handle, so we'll have to skip it.
5437 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5442 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5443 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
))
5448 /* Create a new OSData for the smaller kext object.
5450 linkeditsize
= round_page(linkedit
->vmsize
);
5451 kextsize
= kmod_info
->size
- linkeditsize
;
5452 start
= linkedit
->vmaddr
;
5454 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5459 /* Fix the kmod info and linkedExecutable.
5461 kmod_info
->size
= kextsize
;
5464 data
->setDeallocFunction(osdata_kext_free
);
5466 data
->setDeallocFunction(osdata_phys_free
);
5468 linkedExecutable
->setDeallocFunction(NULL
);
5469 linkedExecutable
->release();
5470 linkedExecutable
= data
;
5471 flags
.jettisonLinkeditSeg
= 1;
5473 /* Free the linkedit segment.
5476 kext_free(start
, linkeditsize
);
5478 ml_static_mfree(start
, linkeditsize
);
5485 /*********************************************************************
5486 * If there are whole pages that are unused betweem the last section
5487 * of the DATA segment and the end of the DATA segment then we can free
5489 *********************************************************************/
5491 OSKext::jettisonDATASegmentPadding(void)
5493 kernel_mach_header_t
* mh
;
5494 kernel_segment_command_t
* dataSeg
;
5495 kernel_section_t
* sec
, * lastSec
;
5496 vm_offset_t dataSegEnd
, lastSecEnd
;
5499 mh
= (kernel_mach_header_t
*)kmod_info
->address
;
5501 dataSeg
= getsegbynamefromheader(mh
, SEG_DATA
);
5502 if (dataSeg
== NULL
) {
5507 sec
= firstsect(dataSeg
);
5508 while (sec
!= NULL
) {
5510 sec
= nextsect(dataSeg
, sec
);
5513 if (lastSec
== NULL
) {
5517 if ((dataSeg
->vmaddr
!= round_page(dataSeg
->vmaddr
)) ||
5518 (dataSeg
->vmsize
!= round_page(dataSeg
->vmsize
))) {
5522 dataSegEnd
= dataSeg
->vmaddr
+ dataSeg
->vmsize
;
5523 lastSecEnd
= round_page(lastSec
->addr
+ lastSec
->size
);
5525 if (dataSegEnd
<= lastSecEnd
) {
5529 padSize
= dataSegEnd
- lastSecEnd
;
5531 if (padSize
>= PAGE_SIZE
) {
5533 kext_free(lastSecEnd
, padSize
);
5535 ml_static_mfree(lastSecEnd
, padSize
);
5540 /*********************************************************************
5541 *********************************************************************/
5543 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5545 if (linkedExecutable
) {
5546 panic("Attempt to set linked executable on kext "
5547 "that already has one (%s).\n",
5548 getIdentifierCString());
5550 linkedExecutable
= anExecutable
;
5551 linkedExecutable
->retain();
5556 /*********************************************************************
5557 * Go through all loaded kexts and tell them to register with dtrace.
5558 * The instance method only registers if necessary.
5559 *********************************************************************/
5562 OSKext::registerKextsWithDTrace(void)
5564 uint32_t count
= sLoadedKexts
->getCount();
5567 IORecursiveLockLock(sKextLock
);
5569 for (i
= 0; i
< count
; i
++) {
5570 OSKext
* thisKext
= NULL
; // do not release
5572 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5573 if (!thisKext
|| !thisKext
->isExecutable()) {
5577 thisKext
->registerWithDTrace();
5580 IORecursiveLockUnlock(sKextLock
);
5586 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5587 extern int (*dtrace_modunload
)(struct kmod_info
*);
5590 /*********************************************************************
5591 *********************************************************************/
5593 OSKext::registerWithDTrace(void)
5595 /* Register kext with dtrace. A dtrace_modload failure should not
5596 * prevent a kext from loading, so we ignore the return code.
5598 if (!flags
.dtraceInitialized
&& (dtrace_modload
!= NULL
)) {
5599 uint32_t modflag
= 0;
5600 OSObject
* forceInit
= getPropertyForHostArch("OSBundleForceDTraceInit");
5601 if (forceInit
== kOSBooleanTrue
) {
5602 modflag
|= KMOD_DTRACE_FORCE_INIT
;
5605 (void)(*dtrace_modload
)(kmod_info
, modflag
);
5606 flags
.dtraceInitialized
= true;
5607 jettisonLinkeditSegment();
5611 /*********************************************************************
5612 *********************************************************************/
5614 OSKext::unregisterWithDTrace(void)
5616 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5617 * prevent a kext from loading, so we ignore the return code.
5619 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
5620 (void)(*dtrace_modunload
)(kmod_info
);
5621 flags
.dtraceInitialized
= false;
5625 #endif /* CONFIG_DTRACE */
5628 /*********************************************************************
5629 * called only by loadExecutable()
5630 *********************************************************************/
5631 #if !VM_MAPPED_KEXTS
5632 #error Unrecognized architecture
5634 static inline kern_return_t
5637 vm_map_offset_t start
,
5638 vm_map_offset_t end
,
5642 if (start
== end
) { // 10538581
5643 return(KERN_SUCCESS
);
5645 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
5648 static inline kern_return_t
5651 vm_map_offset_t start
,
5652 vm_map_offset_t end
,
5653 vm_prot_t access_type
,
5654 boolean_t user_wire
)
5656 return vm_map_wire(map
, start
, end
, access_type
| VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_KEXT
), user_wire
);
5661 OSKext::setVMAttributes(bool protect
, bool wire
)
5663 vm_map_t kext_map
= NULL
;
5664 kernel_segment_command_t
* seg
= NULL
;
5665 vm_map_offset_t start
= 0;
5666 vm_map_offset_t end
= 0;
5667 OSReturn result
= kOSReturnError
;
5669 if (isInterface() || !declaresExecutable()) {
5670 result
= kOSReturnSuccess
;
5674 /* Get the kext's vm map */
5675 kext_map
= kext_get_vm_map(kmod_info
);
5677 result
= KERN_MEMORY_ERROR
;
5681 #if !VM_MAPPED_KEXTS
5682 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
5683 /* This is a split kext in a prelinked kernelcache; we'll let the
5684 * platform code take care of protecting it. It is already wired.
5686 /* TODO: Should this still allow protections for the first segment
5687 * to go through, in the event that we have a mix of split and
5690 result
= KERN_SUCCESS
;
5695 /* Protect the headers as read-only; they do not need to be wired */
5696 result
= (protect
) ? OSKext_protect(kext_map
, kmod_info
->address
,
5697 kmod_info
->address
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
)
5699 if (result
!= KERN_SUCCESS
) {
5703 /* Set the VM protections and wire down each of the segments */
5704 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5708 start
= round_page(seg
->vmaddr
);
5709 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
5712 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
5713 if (result
!= KERN_SUCCESS
) {
5715 kOSKextLogErrorLevel
|
5717 "Kext %s failed to set maximum VM protections "
5718 "for segment %s - 0x%x.",
5719 getIdentifierCString(), seg
->segname
, (int)result
);
5723 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5724 if (result
!= KERN_SUCCESS
) {
5726 kOSKextLogErrorLevel
|
5728 "Kext %s failed to set initial VM protections "
5729 "for segment %s - 0x%x.",
5730 getIdentifierCString(), seg
->segname
, (int)result
);
5735 if (segmentShouldBeWired(seg
) && wire
) {
5736 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5737 if (result
!= KERN_SUCCESS
) {
5742 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5749 /*********************************************************************
5750 *********************************************************************/
5752 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
5754 return (sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
)));
5757 /*********************************************************************
5758 *********************************************************************/
5760 OSKext::validateKextMapping(bool startFlag
)
5762 OSReturn result
= kOSReturnError
;
5763 const char * whichOp
= startFlag
? "start" : "stop";
5764 kern_return_t kern_result
= 0;
5765 vm_map_t kext_map
= NULL
;
5766 kernel_segment_command_t
* seg
= NULL
;
5767 mach_vm_address_t address
= 0;
5768 mach_vm_size_t size
= 0;
5770 mach_msg_type_number_t count
;
5771 vm_region_submap_short_info_data_64_t info
;
5773 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
5774 bzero(&info
, sizeof(info
));
5776 // xxx - do we need a distinct OSReturn value for these or is "bad data"
5777 // xxx - sufficient?
5779 /* Verify that the kmod_info and start/stop pointers are non-NULL.
5783 kOSKextLogErrorLevel
|
5785 "Kext %s - NULL kmod_info pointer.",
5786 getIdentifierCString());
5787 result
= kOSKextReturnBadData
;
5792 address
= (mach_vm_address_t
)kmod_info
->start
;
5794 address
= (mach_vm_address_t
)kmod_info
->stop
;
5799 kOSKextLogErrorLevel
|
5801 "Kext %s - NULL module %s pointer.",
5802 getIdentifierCString(), whichOp
);
5803 result
= kOSKextReturnBadData
;
5807 kext_map
= kext_get_vm_map(kmod_info
);
5808 depth
= (kernel_map
== kext_map
) ? 1 : 2;
5810 /* Verify that the start/stop function lies within the kext's address range.
5812 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
5813 /* This will likely be how we deal with split kexts; walk the segments to
5814 * check that the function lies inside one of the segments of this kext.
5816 for (seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5818 seg
= nextsegfromheader((kernel_mach_header_t
*)kmod_info
->address
, seg
)) {
5819 if ((address
>= seg
->vmaddr
) && address
< (seg
->vmaddr
+ seg
->vmsize
)) {
5826 kOSKextLogErrorLevel
|
5828 "Kext %s module %s pointer is outside of kext range "
5829 "(%s %p - kext starts at %p).",
5830 getIdentifierCString(),
5833 (void *)VM_KERNEL_UNSLIDE(address
),
5834 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
));
5835 result
= kOSKextReturnBadData
;
5841 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
5842 kmod_info
->address
+ kmod_info
->size
<= address
)
5845 kOSKextLogErrorLevel
|
5847 "Kext %s module %s pointer is outside of kext range "
5848 "(%s %p - kext at %p-%p).",
5849 getIdentifierCString(),
5852 (void *)VM_KERNEL_UNSLIDE(address
),
5853 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5854 (void *)(VM_KERNEL_UNSLIDE(kmod_info
->address
) + kmod_info
->size
));
5855 result
= kOSKextReturnBadData
;
5860 /* Only do these checks before calling the start function;
5861 * If anything goes wrong with the mapping while the kext is running,
5862 * we'll likely have panicked well before any attempt to stop the kext.
5866 /* Verify that the start/stop function is executable.
5868 kern_result
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
,
5869 (vm_region_recurse_info_t
)&info
, &count
);
5870 if (kern_result
!= KERN_SUCCESS
) {
5872 kOSKextLogErrorLevel
|
5874 "Kext %s - bad %s pointer %p.",
5875 getIdentifierCString(),
5876 whichOp
, (void *)VM_KERNEL_UNSLIDE(address
));
5877 result
= kOSKextReturnBadData
;
5882 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
5884 kOSKextLogErrorLevel
|
5886 "Kext %s - memory region containing module %s function "
5887 "is not executable.",
5888 getIdentifierCString(), whichOp
);
5889 result
= kOSKextReturnBadData
;
5894 /* Verify that the kext's segments are backed by physical memory.
5896 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5898 if (!verifySegmentMapping(seg
)) {
5899 result
= kOSKextReturnBadData
;
5903 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5908 result
= kOSReturnSuccess
;
5913 /*********************************************************************
5914 *********************************************************************/
5916 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
5918 mach_vm_address_t address
= 0;
5920 if (!segmentShouldBeWired(seg
)) return true;
5922 for (address
= seg
->vmaddr
;
5923 address
< round_page(seg
->vmaddr
+ seg
->vmsize
);
5924 address
+= PAGE_SIZE
)
5926 if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) {
5928 kOSKextLogErrorLevel
|
5930 "Kext %s - page %p is not backed by physical memory.",
5931 getIdentifierCString(),
5940 /*********************************************************************
5941 *********************************************************************/
5943 OSKextLogKextInfo(OSKext
*aKext
, uint64_t address
, uint64_t size
, firehose_tracepoint_code_t code
)
5947 firehose_tracepoint_id_u trace_id
;
5948 struct firehose_trace_uuid_info_s uuid_info_s
;
5949 firehose_trace_uuid_info_t uuid_info
= &uuid_info_s
;
5950 size_t uuid_info_len
= sizeof(struct firehose_trace_uuid_info_s
);
5953 stamp
= firehose_tracepoint_time(firehose_activity_flags_default
);
5954 trace_id
.ftid_value
= FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata
, _firehose_tracepoint_type_metadata_kext
, (firehose_tracepoint_flags_t
)0, code
);
5956 uuid_data
= aKext
->copyUUID();
5958 memcpy(uuid_info
->ftui_uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_info
->ftui_uuid
));
5959 OSSafeReleaseNULL(uuid_data
);
5962 uuid_info
->ftui_size
= size
;
5963 uuid_info
->ftui_address
= VM_KERNEL_UNSLIDE(address
);
5965 firehose_trace_metadata(firehose_stream_metadata
, trace_id
, stamp
, uuid_info
, uuid_info_len
);
5969 /*********************************************************************
5970 *********************************************************************/
5972 OSKext::start(bool startDependenciesFlag
)
5974 OSReturn result
= kOSReturnError
;
5975 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
5976 unsigned int i
, count
;
5977 void * kmodStartData
= NULL
;
5979 if (isStarted() || isInterface() || isKernelComponent()) {
5980 result
= kOSReturnSuccess
;
5986 kOSKextLogErrorLevel
|
5988 "Attempt to start nonloaded kext %s.",
5989 getIdentifierCString());
5990 result
= kOSKextReturnInvalidArgument
;
5994 if (!sLoadEnabled
) {
5996 kOSKextLogErrorLevel
|
5998 "Kext loading is disabled (attempt to start kext %s).",
5999 getIdentifierCString());
6000 result
= kOSKextReturnDisabled
;
6004 result
= validateKextMapping(/* start? */ true);
6005 if (result
!= kOSReturnSuccess
) {
6009 startfunc
= kmod_info
->start
;
6011 count
= getNumDependencies();
6012 for (i
= 0; i
< count
; i
++) {
6013 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
6014 if (dependency
== NULL
) {
6016 kOSKextLogErrorLevel
|
6018 "Kext %s start - internal error, dependency disappeared.",
6019 getIdentifierCString());
6022 if (!dependency
->isStarted()) {
6023 if (startDependenciesFlag
) {
6024 OSReturn dependencyResult
=
6025 dependency
->start(startDependenciesFlag
);
6026 if (dependencyResult
!= KERN_SUCCESS
) {
6028 kOSKextLogErrorLevel
|
6030 "Kext %s start - dependency %s failed to start (error 0x%x).",
6031 getIdentifierCString(),
6032 dependency
->getIdentifierCString(),
6038 kOSKextLogErrorLevel
|
6040 "Not starting %s - dependency %s not started yet.",
6041 getIdentifierCString(),
6042 dependency
->getIdentifierCString());
6043 result
= kOSKextReturnStartStopError
; // xxx - make new return?
6050 kOSKextLogDetailLevel
|
6052 "Kext %s calling module start function.",
6053 getIdentifierCString());
6057 // Drop a log message so logd can grab the needed information to decode this kext
6058 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_load
);
6060 #if !CONFIG_STATIC_CPPINIT
6061 result
= OSRuntimeInitializeCPP(kmod_info
, NULL
);
6062 if (result
== KERN_SUCCESS
) {
6066 kmodStartData
= GetAppleTEXTHashForKext(this, this->infoDict
);
6069 if (kmodStartData
) {
6071 kOSKextLogErrorLevel
|
6072 kOSKextLogGeneralFlag
,
6073 "Kext %s calling module start function. kmodStartData %p. arch %s",
6074 getIdentifierCString(), kmodStartData
, ARCHNAME
);
6077 #endif // CONFIG_KEC_FIPS
6078 result
= startfunc(kmod_info
, kmodStartData
);
6080 #if !CONFIG_STATIC_CPPINIT
6081 if (result
!= KERN_SUCCESS
) {
6082 (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6089 /* On success overlap the setting of started/starting. On failure just
6092 if (result
== KERN_SUCCESS
) {
6095 // xxx - log start error from kernel?
6097 kOSKextLogProgressLevel
|
6099 "Kext %s is now started.",
6100 getIdentifierCString());
6102 invokeOrCancelRequestCallbacks(
6103 /* result not actually used */ kOSKextReturnStartStopError
,
6104 /* invokeFlag */ false);
6106 kOSKextLogProgressLevel
|
6108 "Kext %s did not start (return code 0x%x).",
6109 getIdentifierCString(), result
);
6116 /*********************************************************************
6117 *********************************************************************/
6119 bool OSKext::canUnloadKextWithIdentifier(
6120 OSString
* kextIdentifier
,
6121 bool checkClassesFlag
)
6123 bool result
= false;
6124 OSKext
* aKext
= NULL
; // do not release
6126 IORecursiveLockLock(sKextLock
);
6128 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
6131 goto finish
; // can't unload what's not loaded
6134 if (aKext
->isLoaded()) {
6135 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
6138 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
6146 IORecursiveLockUnlock(sKextLock
);
6150 /*********************************************************************
6151 *********************************************************************/
6155 OSReturn result
= kOSReturnError
;
6156 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
6158 if (!isStarted() || isInterface()) {
6159 result
= kOSReturnSuccess
;
6165 kOSKextLogErrorLevel
|
6167 "Attempt to stop nonloaded kext %s.",
6168 getIdentifierCString());
6169 result
= kOSKextReturnInvalidArgument
;
6173 /* Refuse to stop if we have clients or instances. It is up to
6174 * the caller to make sure those aren't true.
6176 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6178 kOSKextLogErrorLevel
|
6180 "Kext %s - C++ instances; can't stop.",
6181 getIdentifierCString());
6182 result
= kOSKextReturnInUse
;
6186 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6189 kOSKextLogErrorLevel
|
6191 "Kext %s - has references (linkage or tracking object); "
6193 getIdentifierCString());
6194 result
= kOSKextReturnInUse
;
6198 /* Note: If validateKextMapping fails on the stop & unload path,
6199 * we are in serious trouble and a kernel panic is likely whether
6200 * we stop & unload the kext or not.
6202 result
= validateKextMapping(/* start? */ false);
6203 if (result
!= kOSReturnSuccess
) {
6207 stopfunc
= kmod_info
->stop
;
6210 kOSKextLogDetailLevel
|
6212 "Kext %s calling module stop function.",
6213 getIdentifierCString());
6217 result
= stopfunc(kmod_info
, /* userData */ NULL
);
6218 #if !CONFIG_STATIC_CPPINIT
6219 if (result
== KERN_SUCCESS
) {
6220 result
= OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6226 if (result
== KERN_SUCCESS
) {
6230 kOSKextLogDetailLevel
|
6232 "Kext %s is now stopped and ready to unload.",
6233 getIdentifierCString());
6236 kOSKextLogErrorLevel
|
6238 "Kext %s did not stop (return code 0x%x).",
6239 getIdentifierCString(), result
);
6240 result
= kOSKextReturnStartStopError
;
6245 // Drop a log message so logd can update this kext's metadata
6246 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_unload
);
6250 /*********************************************************************
6251 *********************************************************************/
6253 OSKext::unload(void)
6255 OSReturn result
= kOSReturnError
;
6257 uint32_t num_kmod_refs
= 0;
6258 OSKextAccount
* freeAccount
;
6260 if (!sUnloadEnabled
) {
6262 kOSKextLogErrorLevel
|
6264 "Kext unloading is disabled (%s).",
6265 this->getIdentifierCString());
6267 result
= kOSKextReturnDisabled
;
6271 /* Refuse to unload if we have clients or instances. It is up to
6272 * the caller to make sure those aren't true.
6274 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6275 // xxx - Don't log under errors? this is more of an info thing
6277 kOSKextLogErrorLevel
|
6278 kOSKextLogKextBookkeepingFlag
,
6279 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6280 getIdentifierCString());
6281 result
= kOSKextReturnInUse
;
6285 if (hasOSMetaClassInstances()) {
6287 kOSKextLogErrorLevel
|
6288 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6289 "Can't unload kext %s; classes have instances:",
6290 getIdentifierCString());
6291 reportOSMetaClassInstances(kOSKextLogErrorLevel
|
6292 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
);
6293 result
= kOSKextReturnInUse
;
6298 result
= kOSReturnSuccess
;
6302 if (isKernelComponent()) {
6303 result
= kOSKextReturnInvalidArgument
;
6307 /* Note that the kext is unloading before running any code that
6308 * might be in the kext (request callbacks, module stop function).
6309 * We will deny certain requests made against a kext in the process
6312 flags
.unloading
= 1;
6314 /* Update the string describing the last kext to unload in case we panic.
6316 savePanicString(/* isLoading */ false);
6320 if (result
!= KERN_SUCCESS
) {
6322 kOSKextLogErrorLevel
|
6324 "Kext %s can't unload - module stop returned 0x%x.",
6325 getIdentifierCString(), (unsigned)result
);
6326 result
= kOSKextReturnStartStopError
;
6332 kOSKextLogProgressLevel
|
6334 "Kext %s unloading.",
6335 getIdentifierCString());
6338 struct list_head
*p
;
6339 struct list_head
*prev
;
6340 struct list_head
*next
;
6341 for (p
= pendingPgoHead
.next
; p
!= &pendingPgoHead
; p
= next
) {
6342 OSKextGrabPgoStruct
*s
= container_of(p
, OSKextGrabPgoStruct
, list_head
);
6343 s
->err
= OSKextGrabPgoDataLocked(this, s
->metadata
, instance_uuid
, s
->pSize
, s
->pBuffer
, s
->bufferSize
);
6350 IORecursiveLockWakeup(sKextLock
, s
, false);
6355 /* Even if we don't call the stop function, we want to be sure we
6356 * have no OSMetaClass references before unloading the kext executable
6357 * from memory. OSMetaClasses may have pointers into the kext executable
6358 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6361 metaClasses
->flushCollection();
6364 /* Remove the kext from the list of loaded kexts, patch the gap
6365 * in the kmod_info_t linked list, and reset "kmod" to point to the
6366 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6368 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
6369 if (index
!= (unsigned int)-1) {
6371 sLoadedKexts
->removeObject(index
);
6373 OSKext
* nextKext
= OSDynamicCast(OSKext
,
6374 sLoadedKexts
->getObject(index
));
6378 OSKext
* gapKext
= OSDynamicCast(OSKext
,
6379 sLoadedKexts
->getObject(index
- 1));
6381 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
6383 } else /* index == 0 */ {
6384 nextKext
->kmod_info
->next
= NULL
;
6388 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
6389 if (lastKext
&& !lastKext
->isKernel()) {
6390 kmod
= lastKext
->kmod_info
;
6392 kmod
= NULL
; // clear the global kmod variable
6396 /* Clear out the kmod references that we're keeping for compatibility
6397 * with current panic backtrace code & kgmacros.
6398 * xxx - will want to update those bits sometime and remove this.
6400 num_kmod_refs
= getNumDependencies();
6401 if (num_kmod_refs
&& kmod_info
&& kmod_info
->reference_list
) {
6402 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
6403 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
6404 ref
->info
->reference_count
--;
6406 kfree(kmod_info
->reference_list
,
6407 num_kmod_refs
* sizeof(kmod_reference_t
));
6411 unregisterWithDTrace();
6412 #endif /* CONFIG_DTRACE */
6414 notifyKextUnloadObservers(this);
6417 IOSimpleLockLock(sKextAccountsLock
);
6418 account
->kext
= NULL
;
6419 if (account
->site
.tag
) account
->site
.flags
|= VM_TAG_UNLOAD
;
6420 else freeAccount
= account
;
6421 IOSimpleLockUnlock(sKextAccountsLock
);
6422 if (freeAccount
) IODelete(freeAccount
, OSKextAccount
, 1);
6424 /* Unwire and free the linked executable.
6426 if (linkedExecutable
) {
6428 if (!isInterface()) {
6429 kernel_segment_command_t
*seg
= NULL
;
6430 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6434 kOSKextLogErrorLevel
|
6436 "Failed to free kext %s; couldn't find the kext map.",
6437 getIdentifierCString());
6438 result
= kOSKextReturnInternalError
;
6443 kOSKextLogProgressLevel
|
6445 "Kext %s unwiring and unmapping linked executable.",
6446 getIdentifierCString());
6448 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6450 if (segmentShouldBeWired(seg
)) {
6451 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6452 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6453 if (result
!= KERN_SUCCESS
) {
6455 kOSKextLogErrorLevel
|
6457 "Failed to unwire kext %s.",
6458 getIdentifierCString());
6459 result
= kOSKextReturnInternalError
;
6464 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6468 OSSafeReleaseNULL(linkedExecutable
);
6471 /* An interface kext has a fake kmod_info that was allocated,
6472 * so we have to free it.
6474 if (isInterface()) {
6475 kfree(kmod_info
, sizeof(kmod_info_t
));
6480 flags
.loaded
= false;
6481 flushDependencies();
6483 /* save a copy of the bundle ID for us to check when deciding to
6484 * rebuild the kernel cache file. If a kext was already in the kernel
6485 * cache and unloaded then later loaded we do not need to rebuild the
6486 * kernel cache. 9055303
6488 if (isPrelinked()) {
6489 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6490 IORecursiveLockLock(sKextLock
);
6491 if (sUnloadedPrelinkedKexts
) {
6492 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6494 IORecursiveLockUnlock(sKextLock
);
6499 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6500 "Kext %s unloaded.", getIdentifierCString());
6502 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6503 OSDynamicCast(OSString
, bundleID
));
6506 OSKext::saveLoadedKextPanicList();
6507 OSKext::updateLoadedKextSummaries();
6509 flags
.unloading
= 0;
6513 /*********************************************************************
6514 * Assumes sKextLock is held.
6515 *********************************************************************/
6518 OSKext::queueKextNotification(
6519 const char * notificationName
,
6520 OSString
* kextIdentifier
)
6522 OSReturn result
= kOSReturnError
;
6523 OSDictionary
* loadRequest
= NULL
; // must release
6525 if (!kextIdentifier
) {
6526 result
= kOSKextReturnInvalidArgument
;
6530 /* Create a new request unless one is already sitting
6531 * in sKernelRequests for this bundle identifier
6533 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6534 if (result
!= kOSReturnSuccess
) {
6537 if (!_OSKextSetRequestArgument(loadRequest
,
6538 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6540 result
= kOSKextReturnNoMemory
;
6543 if (!sKernelRequests
->setObject(loadRequest
)) {
6544 result
= kOSKextReturnNoMemory
;
6548 /* We might want to only queue the notification if kextd is active,
6549 * but that wouldn't work for embedded. Note that we don't care if
6550 * the ping immediately succeeds here so don't do anything with the
6551 * result of this call.
6553 OSKext::pingKextd();
6555 result
= kOSReturnSuccess
;
6558 OSSafeReleaseNULL(loadRequest
);
6563 /*********************************************************************
6564 *********************************************************************/
6566 _OSKextConsiderDestroyingLinkContext(
6567 __unused thread_call_param_t p0
,
6568 __unused thread_call_param_t p1
)
6570 /* Take multiple locks in the correct order.
6572 IORecursiveLockLock(sKextLock
);
6573 IORecursiveLockLock(sKextInnerLock
);
6575 /* The first time we destroy the kxldContext is in the first
6576 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6577 * before calling this function. Thereafter any call to this function
6578 * will actually destroy the context.
6580 if (sConsiderUnloadsCalled
&& sKxldContext
) {
6581 kxld_destroy_context(sKxldContext
);
6582 sKxldContext
= NULL
;
6585 /* Free the thread_call that was allocated to execute this function.
6587 if (sDestroyLinkContextThread
) {
6588 if (!thread_call_free(sDestroyLinkContextThread
)) {
6589 OSKextLog(/* kext */ NULL
,
6590 kOSKextLogErrorLevel
|
6591 kOSKextLogGeneralFlag
,
6592 "thread_call_free() failed for kext link context.");
6594 sDestroyLinkContextThread
= 0;
6597 IORecursiveLockUnlock(sKextInnerLock
);
6598 IORecursiveLockUnlock(sKextLock
);
6603 /*********************************************************************
6604 * Destroying the kxldContext requires checking variables under both
6605 * sKextInnerLock and sKextLock, so we do it on a separate thread
6606 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6607 * call relationship.
6609 * This function must be invoked with sKextInnerLock held.
6610 * Do not call any function that takes sKextLock here!
6611 *********************************************************************/
6614 OSKext::considerDestroyingLinkContext(void)
6616 IORecursiveLockLock(sKextInnerLock
);
6618 /* If we have already queued a thread to destroy the link context,
6619 * don't bother resetting; that thread will take care of it.
6621 if (sDestroyLinkContextThread
) {
6625 /* The function to be invoked in the thread will deallocate
6626 * this thread_call, so don't share it around.
6628 sDestroyLinkContextThread
= thread_call_allocate(
6629 &_OSKextConsiderDestroyingLinkContext
, 0);
6630 if (!sDestroyLinkContextThread
) {
6631 OSKextLog(/* kext */ NULL
,
6632 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
| kOSKextLogLinkFlag
,
6633 "Can't create thread to destroy kext link context.");
6637 thread_call_enter(sDestroyLinkContextThread
);
6640 IORecursiveLockUnlock(sKextInnerLock
);
6645 #pragma mark Autounload
6647 /*********************************************************************
6648 * This is a static method because the kext will be deallocated if it
6650 *********************************************************************/
6653 OSKext::autounloadKext(OSKext
* aKext
)
6655 OSReturn result
= kOSKextReturnInUse
;
6657 /* Check for external references to this kext (usu. dependents),
6658 * instances of defined classes (or classes derived from them),
6659 * outstanding requests.
6661 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
6662 !aKext
->flags
.autounloadEnabled
||
6663 aKext
->isKernelComponent()) {
6668 /* Skip a delay-autounload kext, once.
6670 if (aKext
->flags
.delayAutounload
) {
6672 kOSKextLogProgressLevel
|
6673 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6674 "Kext %s has delayed autounload set; skipping and clearing flag.",
6675 aKext
->getIdentifierCString());
6676 aKext
->flags
.delayAutounload
= 0;
6680 if (aKext
->hasOSMetaClassInstances() ||
6681 aKext
->countRequestCallbacks()) {
6685 result
= OSKext::removeKext(aKext
);
6691 /*********************************************************************
6692 *********************************************************************/
6694 _OSKextConsiderUnloads(
6695 __unused thread_call_param_t p0
,
6696 __unused thread_call_param_t p1
)
6698 bool didUnload
= false;
6699 unsigned int count
, i
;
6701 /* Take multiple locks in the correct order
6702 * (note also sKextSummaries lock further down).
6704 IORecursiveLockLock(sKextLock
);
6705 IORecursiveLockLock(sKextInnerLock
);
6707 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6709 /* If the system is powering down, don't try to unload anything.
6715 OSKextLog(/* kext */ NULL
,
6716 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6717 "Checking for unused kexts to autounload.");
6720 * Remove any request callbacks marked as stale,
6721 * and mark as stale any currently in flight.
6723 count
= sRequestCallbackRecords
->getCount();
6727 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
6728 sRequestCallbackRecords
->getObject(i
));
6729 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
6730 callbackRecord
->getObject(kKextRequestStaleKey
));
6732 if (stale
== kOSBooleanTrue
) {
6733 OSKext::invokeRequestCallback(callbackRecord
,
6734 kOSKextReturnTimeout
);
6736 callbackRecord
->setObject(kKextRequestStaleKey
,
6743 * Make multiple passes through the array of loaded kexts until
6744 * we don't unload any. This handles unwinding of dependency
6745 * chains. We have to go *backwards* through the array because
6746 * kexts are removed from it when unloaded, and we cannot make
6747 * a copy or we'll mess up the retain counts we rely on to
6748 * check whether a kext will unload. If only we could have
6749 * nonretaining collections like CF has....
6754 count
= sLoadedKexts
->getCount();
6758 OSKext
* thisKext
= OSDynamicCast(OSKext
,
6759 sLoadedKexts
->getObject(i
));
6760 didUnload
|= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
6763 } while (didUnload
);
6766 sConsiderUnloadsPending
= false;
6767 sConsiderUnloadsExecuted
= true;
6769 (void) OSKext::considerRebuildOfPrelinkedKernel();
6771 IORecursiveLockUnlock(sKextInnerLock
);
6772 IORecursiveLockUnlock(sKextLock
);
6777 /*********************************************************************
6778 * Do not call any function that takes sKextLock here!
6779 *********************************************************************/
6780 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
6784 IORecursiveLockLock(sKextInnerLock
);
6786 if (!sUnloadCallout
) {
6787 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, 0);
6790 /* we only reset delay value for unloading if we already have something
6791 * pending. rescheduleOnlyFlag should not start the count down.
6793 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
6797 thread_call_cancel(sUnloadCallout
);
6798 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
6799 clock_interval_to_deadline(sConsiderUnloadDelay
,
6800 1000 * 1000 * 1000, &when
);
6802 OSKextLog(/* kext */ NULL
,
6803 kOSKextLogProgressLevel
|
6805 "%scheduling %sscan for unused kexts in %lu seconds.",
6806 sConsiderUnloadsPending
? "Res" : "S",
6807 sConsiderUnloadsCalled
? "" : "initial ",
6808 (unsigned long)sConsiderUnloadDelay
);
6810 sConsiderUnloadsPending
= true;
6811 thread_call_enter_delayed(sUnloadCallout
, when
);
6815 /* The kxld context should be reused throughout boot. We mark the end of
6816 * period as the first time considerUnloads() is called, and we destroy
6817 * the first kxld context in that function. Afterwards, it will be
6818 * destroyed in flushNonloadedKexts.
6820 if (!sConsiderUnloadsCalled
) {
6821 sConsiderUnloadsCalled
= true;
6822 OSKext::considerDestroyingLinkContext();
6825 IORecursiveLockUnlock(sKextInnerLock
);
6829 /*********************************************************************
6830 * Do not call any function that takes sKextLock here!
6831 *********************************************************************/
6834 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
);
6835 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
)
6837 IORecursiveLockLock(sKextInnerLock
);
6839 /* If the system is going to sleep, cancel the reaper thread timer,
6840 * and note that we're in a sleep state in case it just fired but hasn't
6841 * taken the lock yet. If we are coming back from sleep, just
6842 * clear the sleep flag; IOService's normal operation will cause
6843 * unloads to be considered soon enough.
6845 if (messageType
== kIOMessageSystemWillSleep
) {
6846 if (sUnloadCallout
) {
6847 thread_call_cancel(sUnloadCallout
);
6849 sSystemSleep
= true;
6850 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
6851 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
6852 sSystemSleep
= false;
6853 clock_get_uptime(&sLastWakeTime
);
6855 IORecursiveLockUnlock(sKextInnerLock
);
6857 return kIOReturnSuccess
;
6864 #pragma mark Prelinked Kernel
6866 /*********************************************************************
6867 * Do not access sConsiderUnloads... variables other than
6868 * sConsiderUnloadsExecuted in this function. They are guarded by a
6870 *********************************************************************/
6873 OSKext::considerRebuildOfPrelinkedKernel(void)
6875 static bool requestedPrelink
= false;
6876 OSReturn checkResult
= kOSReturnError
;
6877 OSDictionary
* prelinkRequest
= NULL
; // must release
6878 OSCollectionIterator
* kextIterator
= NULL
; // must release
6879 const OSSymbol
* thisID
= NULL
; // do not release
6880 bool doRebuild
= false;
6881 AbsoluteTime my_abstime
;
6885 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
6886 if (requestedPrelink
|| !sPrelinkBoot
) {
6890 /* no direct return from this point */
6891 IORecursiveLockLock(sKextLock
);
6893 /* We need to wait for kextd to get up and running with unloads already done
6894 * and any new startup kexts loaded.
6896 if (!sConsiderUnloadsExecuted
||
6897 !sDeferredLoadSucceeded
) {
6901 /* we really only care about boot / system start up related kexts so bail
6902 * if we're here after REBUILD_MAX_TIME.
6904 if (!_OSKextInPrelinkRebuildWindow()) {
6905 OSKextLog(/* kext */ NULL
,
6906 kOSKextLogArchiveFlag
,
6907 "%s prebuild rebuild has expired",
6909 requestedPrelink
= true;
6913 /* we do not want to trigger a rebuild if we get here too close to waking
6914 * up. (see radar 10233768)
6916 IORecursiveLockLock(sKextInnerLock
);
6918 clock_get_uptime(&my_abstime
);
6919 delta_secs
= MINIMUM_WAKEUP_SECONDS
+ 1;
6920 if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) {
6921 SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
);
6922 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
6923 delta_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
6925 IORecursiveLockUnlock(sKextInnerLock
);
6927 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
6928 /* too close to time of last wake from sleep */
6931 requestedPrelink
= true;
6933 /* Now it's time to see if we have a reason to rebuild. We may have done
6934 * some loads and unloads but the kernel cache didn't actually change.
6935 * We will rebuild if any kext is not marked prelinked AND is not in our
6936 * list of prelinked kexts that got unloaded. (see radar 9055303)
6938 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
6939 if (!kextIterator
) {
6943 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
6944 OSKext
* thisKext
; // do not release
6946 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
6947 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
6951 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
6954 /* kext is loaded and was not in current kernel cache so let's rebuild
6957 OSKextLog(/* kext */ NULL
,
6958 kOSKextLogArchiveFlag
,
6959 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
6960 thisKext
->bundleID
->getCStringNoCopy());
6963 sUnloadedPrelinkedKexts
->flushCollection();
6969 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
6971 if (checkResult
!= kOSReturnSuccess
) {
6975 if (!sKernelRequests
->setObject(prelinkRequest
)) {
6979 OSKext::pingKextd();
6982 IORecursiveLockUnlock(sKextLock
);
6983 OSSafeReleaseNULL(prelinkRequest
);
6984 OSSafeReleaseNULL(kextIterator
);
6990 #pragma mark Dependencies
6992 /*********************************************************************
6993 *********************************************************************/
6995 OSKext::resolveDependencies(
6996 OSArray
* loopStack
)
6998 bool result
= false;
6999 OSArray
* localLoopStack
= NULL
; // must release
7000 bool addedToLoopStack
= false;
7001 OSDictionary
* libraries
= NULL
; // do not release
7002 OSCollectionIterator
* libraryIterator
= NULL
; // must release
7003 OSString
* libraryID
= NULL
; // do not release
7004 OSString
* infoString
= NULL
; // do not release
7005 OSString
* readableString
= NULL
; // do not release
7006 OSKext
* libraryKext
= NULL
; // do not release
7007 bool hasRawKernelDependency
= false;
7008 bool hasKernelDependency
= false;
7009 bool hasKPIDependency
= false;
7010 bool hasPrivateKPIDependency
= false;
7013 /* A kernel component will automatically have this flag set,
7014 * and a loaded kext should also have it set (as should all its
7015 * loaded dependencies).
7017 if (flags
.hasAllDependencies
) {
7022 /* Check for loops in the dependency graph.
7025 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
7027 kOSKextLogErrorLevel
|
7028 kOSKextLogDependenciesFlag
,
7029 "Kext %s has a dependency loop; can't resolve dependencies.",
7030 getIdentifierCString());
7035 kOSKextLogStepLevel
|
7036 kOSKextLogDependenciesFlag
,
7037 "Kext %s resolving dependencies.",
7038 getIdentifierCString());
7040 loopStack
= OSArray::withCapacity(6); // any small capacity will do
7043 kOSKextLogErrorLevel
|
7044 kOSKextLogDependenciesFlag
,
7045 "Kext %s can't create bookkeeping stack to resolve dependencies.",
7046 getIdentifierCString());
7049 localLoopStack
= loopStack
;
7051 if (!loopStack
->setObject(this)) {
7053 kOSKextLogErrorLevel
|
7054 kOSKextLogDependenciesFlag
,
7055 "Kext %s - internal error resolving dependencies.",
7056 getIdentifierCString());
7059 addedToLoopStack
= true;
7061 /* Purge any existing kexts in the dependency list and start over.
7063 flushDependencies();
7066 kOSKextLogErrorLevel
|
7067 kOSKextLogDependenciesFlag
,
7068 "Kext %s - internal error resolving dependencies.",
7069 getIdentifierCString());
7072 libraries
= OSDynamicCast(OSDictionary
,
7073 getPropertyForHostArch(kOSBundleLibrariesKey
));
7074 if (libraries
== NULL
|| libraries
->getCount() == 0) {
7076 kOSKextLogErrorLevel
|
7077 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7078 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7079 getIdentifierCString(), kOSBundleLibrariesKey
);
7083 /* Make a new array to hold the dependencies (flush freed the old one).
7085 dependencies
= OSArray::withCapacity(libraries
->getCount());
7086 if (!dependencies
) {
7088 kOSKextLogErrorLevel
|
7089 kOSKextLogDependenciesFlag
,
7090 "Kext %s - can't allocate dependencies array.",
7091 getIdentifierCString());
7095 // xxx - compat: We used to add an implicit dependency on kernel 6.0
7096 // xxx - compat: if none were declared.
7098 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
7099 if (!libraryIterator
) {
7101 kOSKextLogErrorLevel
|
7102 kOSKextLogDependenciesFlag
,
7103 "Kext %s - can't allocate dependencies iterator.",
7104 getIdentifierCString());
7108 while ((libraryID
= OSDynamicCast(OSString
,
7109 libraryIterator
->getNextObject()))) {
7111 const char * library_id
= libraryID
->getCStringNoCopy();
7113 OSString
* libraryVersion
= OSDynamicCast(OSString
,
7114 libraries
->getObject(libraryID
));
7115 if (libraryVersion
== NULL
) {
7117 kOSKextLogErrorLevel
|
7118 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7119 "Kext %s - illegal type in OSBundleLibraries.",
7120 getIdentifierCString());
7124 OSKextVersion libraryVers
=
7125 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
7126 if (libraryVers
== -1) {
7128 kOSKextLogErrorLevel
|
7129 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7130 "Kext %s - invalid library version %s.",
7131 getIdentifierCString(),
7132 libraryVersion
->getCStringNoCopy());
7136 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
7137 if (libraryKext
== NULL
) {
7139 kOSKextLogErrorLevel
|
7140 kOSKextLogDependenciesFlag
,
7141 "Kext %s - library kext %s not found.",
7142 getIdentifierCString(), library_id
);
7146 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
7148 kOSKextLogErrorLevel
|
7149 kOSKextLogDependenciesFlag
,
7150 "Kext %s - library kext %s not compatible "
7151 "with requested version %s.",
7152 getIdentifierCString(), library_id
,
7153 libraryVersion
->getCStringNoCopy());
7157 /* If a nonprelinked library somehow got into the mix for a
7158 * prelinked kext, at any point in the chain, we must fail
7159 * because the prelinked relocs for the library will be all wrong.
7161 if (this->isPrelinked() &&
7162 libraryKext
->declaresExecutable() &&
7163 !libraryKext
->isPrelinked()) {
7166 kOSKextLogErrorLevel
|
7167 kOSKextLogDependenciesFlag
,
7168 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7169 getIdentifierCString(), library_id
,
7170 libraryVersion
->getCStringNoCopy());
7174 if (!libraryKext
->resolveDependencies(loopStack
)) {
7178 /* Add the library directly only if it has an executable to link.
7179 * Otherwise it's just used to collect other dependencies, so put
7180 * *its* dependencies on the list for this kext.
7182 // xxx - We are losing info here; would like to make fake entries or
7183 // xxx - keep these in the dependency graph for loaded kexts.
7184 // xxx - I really want to make kernel components not a special case!
7185 if (libraryKext
->declaresExecutable() ||
7186 libraryKext
->isInterface()) {
7188 if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) {
7189 dependencies
->setObject(libraryKext
);
7192 kOSKextLogDetailLevel
|
7193 kOSKextLogDependenciesFlag
,
7194 "Kext %s added dependency %s.",
7195 getIdentifierCString(),
7196 libraryKext
->getIdentifierCString());
7199 int numLibDependencies
= libraryKext
->getNumDependencies();
7200 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
7203 if (numLibDependencies
) {
7204 // xxx - this msg level should be 1 lower than the per-kext one
7206 kOSKextLogDetailLevel
|
7207 kOSKextLogDependenciesFlag
,
7208 "Kext %s pulling %d dependencies from codeless library %s.",
7209 getIdentifierCString(),
7211 libraryKext
->getIdentifierCString());
7213 for (index
= 0; index
< numLibDependencies
; index
++) {
7214 OSKext
* thisLibDependency
= OSDynamicCast(OSKext
,
7215 libraryDependencies
->getObject(index
));
7216 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) {
7217 dependencies
->setObject(thisLibDependency
);
7219 kOSKextLogDetailLevel
|
7220 kOSKextLogDependenciesFlag
,
7221 "Kext %s added dependency %s from codeless library %s.",
7222 getIdentifierCString(),
7223 thisLibDependency
->getIdentifierCString(),
7224 libraryKext
->getIdentifierCString());
7229 if ((strlen(library_id
) == strlen(KERNEL_LIB
)) &&
7230 0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) {
7232 hasRawKernelDependency
= true;
7233 } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) {
7234 hasKernelDependency
= true;
7235 } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) {
7236 hasKPIDependency
= true;
7237 if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) {
7238 hasPrivateKPIDependency
= true;
7243 if (hasRawKernelDependency
) {
7245 kOSKextLogErrorLevel
|
7246 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7247 "Error - kext %s declares a dependency on %s, which is not permitted.",
7248 getIdentifierCString(), KERNEL_LIB
);
7252 if (hasKernelDependency
) {
7254 kOSKextLogErrorLevel
|
7255 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7256 "Error - kext %s declares %s dependencies. "
7257 "Only %s* dependencies are supported for 64-bit kexts.",
7258 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7261 if (!hasKPIDependency
) {
7263 kOSKextLogWarningLevel
|
7264 kOSKextLogDependenciesFlag
,
7265 "Warning - kext %s declares no %s* dependencies. "
7266 "If it uses any KPIs, the link may fail with undefined symbols.",
7267 getIdentifierCString(), KPI_LIB_PREFIX
);
7269 #else /* __LP64__ */
7270 // xxx - will change to flatly disallow "kernel" dependencies at some point
7271 // xxx - is it invalid to do both "com.apple.kernel" and any
7272 // xxx - "com.apple.kernel.*"?
7274 if (hasKernelDependency
&& hasKPIDependency
) {
7276 kOSKextLogWarningLevel
|
7277 kOSKextLogDependenciesFlag
,
7278 "Warning - kext %s has immediate dependencies on both "
7279 "%s* and %s* components; use only one style.",
7280 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7283 if (!hasKernelDependency
&& !hasKPIDependency
) {
7284 // xxx - do we want to use validation flag for these too?
7286 kOSKextLogWarningLevel
|
7287 kOSKextLogDependenciesFlag
,
7288 "Warning - %s declares no kernel dependencies; using %s.",
7289 getIdentifierCString(), KERNEL6_LIB
);
7290 OSKext
* kernelKext
= OSDynamicCast(OSKext
,
7291 sKextsByID
->getObject(KERNEL6_LIB
));
7293 dependencies
->setObject(kernelKext
);
7296 kOSKextLogErrorLevel
|
7297 kOSKextLogDependenciesFlag
,
7298 "Error - Library %s not found for %s.",
7299 KERNEL6_LIB
, getIdentifierCString());
7303 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7304 * its indirect dependencies to simulate old-style linking. XXX - Should
7305 * check for duplicates.
7307 if (!hasKPIDependency
) {
7310 flags
.hasBleedthrough
= true;
7312 count
= getNumDependencies();
7314 /* We add to the dependencies array in this loop, but do not iterate
7315 * past its original count.
7317 for (i
= 0; i
< count
; i
++) {
7318 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
7319 dependencies
->getObject(i
));
7320 dependencyKext
->addBleedthroughDependencies(dependencies
);
7323 #endif /* __LP64__ */
7325 if (hasPrivateKPIDependency
) {
7326 bool hasApplePrefix
= false;
7327 bool infoCopyrightIsValid
= false;
7328 bool readableCopyrightIsValid
= false;
7330 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
7333 infoString
= OSDynamicCast(OSString
,
7334 getPropertyForHostArch("CFBundleGetInfoString"));
7336 infoCopyrightIsValid
=
7337 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
7340 readableString
= OSDynamicCast(OSString
,
7341 getPropertyForHostArch("NSHumanReadableCopyright"));
7342 if (readableString
) {
7343 readableCopyrightIsValid
=
7344 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
7347 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
7349 kOSKextLogErrorLevel
|
7350 kOSKextLogDependenciesFlag
,
7351 "Error - kext %s declares a dependency on %s. "
7352 "Only Apple kexts may declare a dependency on %s.",
7353 getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
);
7359 flags
.hasAllDependencies
= 1;
7363 if (addedToLoopStack
) {
7364 count
= loopStack
->getCount();
7365 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
7366 loopStack
->removeObject(count
- 1);
7369 kOSKextLogErrorLevel
|
7370 kOSKextLogDependenciesFlag
,
7371 "Kext %s - internal error resolving dependencies.",
7372 getIdentifierCString());
7376 if (result
&& localLoopStack
) {
7378 kOSKextLogStepLevel
|
7379 kOSKextLogDependenciesFlag
,
7380 "Kext %s successfully resolved dependencies.",
7381 getIdentifierCString());
7384 OSSafeReleaseNULL(localLoopStack
);
7385 OSSafeReleaseNULL(libraryIterator
);
7390 /*********************************************************************
7391 *********************************************************************/
7393 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
7395 bool result
= false;
7396 unsigned int dependencyIndex
, dependencyCount
;
7398 dependencyCount
= getNumDependencies();
7400 for (dependencyIndex
= 0;
7401 dependencyIndex
< dependencyCount
;
7402 dependencyIndex
++) {
7404 OSKext
* dependency
= OSDynamicCast(OSKext
,
7405 dependencies
->getObject(dependencyIndex
));
7408 kOSKextLogErrorLevel
|
7409 kOSKextLogDependenciesFlag
,
7410 "Kext %s - internal error propagating compatibility dependencies.",
7411 getIdentifierCString());
7414 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7415 anArray
->setObject(dependency
);
7417 dependency
->addBleedthroughDependencies(anArray
);
7426 /*********************************************************************
7427 *********************************************************************/
7429 OSKext::flushDependencies(bool forceFlag
)
7431 bool result
= false;
7433 /* Only clear the dependencies if the kext isn't loaded;
7434 * we need the info for loaded kexts to track references.
7436 if (!isLoaded() || forceFlag
) {
7438 // xxx - check level
7440 kOSKextLogProgressLevel
|
7441 kOSKextLogDependenciesFlag
,
7442 "Kext %s flushing dependencies.",
7443 getIdentifierCString());
7444 OSSafeReleaseNULL(dependencies
);
7447 if (!isKernelComponent()) {
7448 flags
.hasAllDependencies
= 0;
7456 /*********************************************************************
7457 *********************************************************************/
7459 OSKext::getNumDependencies(void)
7461 if (!dependencies
) {
7464 return dependencies
->getCount();
7467 /*********************************************************************
7468 *********************************************************************/
7470 OSKext::getDependencies(void)
7472 return dependencies
;
7476 #pragma mark OSMetaClass Support
7478 /*********************************************************************
7479 *********************************************************************/
7482 OSMetaClass
* aClass
,
7483 uint32_t numClasses
)
7485 OSReturn result
= kOSMetaClassNoInsKModSet
;
7488 metaClasses
= OSSet::withCapacity(numClasses
);
7494 if (metaClasses
->containsObject(aClass
)) {
7496 kOSKextLogWarningLevel
|
7498 "Notice - kext %s has already registered class %s.",
7499 getIdentifierCString(),
7500 aClass
->getClassName());
7501 result
= kOSReturnSuccess
;
7505 if (!metaClasses
->setObject(aClass
)) {
7509 kOSKextLogDetailLevel
|
7511 "Kext %s registered class %s.",
7512 getIdentifierCString(),
7513 aClass
->getClassName());
7516 if (!flags
.autounloadEnabled
) {
7517 const OSMetaClass
* metaScan
= NULL
; // do not release
7519 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7520 if (metaScan
== OSTypeID(IOService
)) {
7523 kOSKextLogProgressLevel
|
7525 "Kext %s has IOService subclass %s; enabling autounload.",
7526 getIdentifierCString(),
7527 aClass
->getClassName());
7529 flags
.autounloadEnabled
= 1;
7535 notifyAddClassObservers(this, aClass
, flags
);
7537 result
= kOSReturnSuccess
;
7540 if (result
!= kOSReturnSuccess
) {
7542 kOSKextLogErrorLevel
|
7544 "Kext %s failed to register class %s.",
7545 getIdentifierCString(),
7546 aClass
->getClassName());
7552 /*********************************************************************
7553 *********************************************************************/
7555 OSKext::removeClass(
7556 OSMetaClass
* aClass
)
7558 OSReturn result
= kOSMetaClassNoKModSet
;
7564 if (!metaClasses
->containsObject(aClass
)) {
7566 kOSKextLogWarningLevel
|
7568 "Notice - kext %s asked to unregister unknown class %s.",
7569 getIdentifierCString(),
7570 aClass
->getClassName());
7571 result
= kOSReturnSuccess
;
7576 kOSKextLogDetailLevel
|
7578 "Kext %s unregistering class %s.",
7579 getIdentifierCString(),
7580 aClass
->getClassName());
7582 metaClasses
->removeObject(aClass
);
7584 notifyRemoveClassObservers(this, aClass
, flags
);
7586 result
= kOSReturnSuccess
;
7589 if (result
!= kOSReturnSuccess
) {
7591 kOSKextLogErrorLevel
|
7593 "Failed to unregister kext %s class %s.",
7594 getIdentifierCString(),
7595 aClass
->getClassName());
7600 /*********************************************************************
7601 *********************************************************************/
7603 OSKext::getMetaClasses(void)
7608 /*********************************************************************
7609 *********************************************************************/
7611 OSKext::hasOSMetaClassInstances(void)
7613 bool result
= false;
7614 OSCollectionIterator
* classIterator
= NULL
; // must release
7615 OSMetaClass
* checkClass
= NULL
; // do not release
7621 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7622 if (!classIterator
) {
7623 // xxx - log alloc failure?
7626 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7627 if (checkClass
->getInstanceCount()) {
7635 OSSafeReleaseNULL(classIterator
);
7639 /*********************************************************************
7640 *********************************************************************/
7643 OSKext::reportOSMetaClassInstances(
7644 const char * kextIdentifier
,
7645 OSKextLogSpec msgLogSpec
)
7647 OSKext
* theKext
= NULL
; // must release
7649 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
7654 theKext
->reportOSMetaClassInstances(msgLogSpec
);
7656 OSSafeReleaseNULL(theKext
);
7660 /*********************************************************************
7661 *********************************************************************/
7663 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
7665 OSCollectionIterator
* classIterator
= NULL
; // must release
7666 OSMetaClass
* checkClass
= NULL
; // do not release
7672 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7673 if (!classIterator
) {
7676 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7677 if (checkClass
->getInstanceCount()) {
7680 " Kext %s class %s has %d instance%s.",
7681 getIdentifierCString(),
7682 checkClass
->getClassName(),
7683 checkClass
->getInstanceCount(),
7684 checkClass
->getInstanceCount() == 1 ? "" : "s");
7689 OSSafeReleaseNULL(classIterator
);
7694 #pragma mark User-Space Requests
7696 /*********************************************************************
7697 * XXX - this function is a big ugly mess
7698 *********************************************************************/
7701 OSKext::handleRequest(
7702 host_priv_t hostPriv
,
7703 OSKextLogSpec clientLogFilter
,
7704 char * requestBuffer
,
7705 uint32_t requestLength
,
7706 char ** responseOut
,
7707 uint32_t * responseLengthOut
,
7709 uint32_t * logInfoLengthOut
)
7711 OSReturn result
= kOSReturnError
;
7712 kern_return_t kmem_result
= KERN_FAILURE
;
7714 char * response
= NULL
; // returned by reference
7715 uint32_t responseLength
= 0;
7717 OSObject
* parsedXML
= NULL
; // must release
7718 OSDictionary
* requestDict
= NULL
; // do not release
7719 OSString
* errorString
= NULL
; // must release
7721 OSObject
* responseObject
= NULL
; // must release
7723 OSSerialize
* serializer
= NULL
; // must release
7725 OSArray
* logInfoArray
= NULL
; // must release
7727 OSString
* predicate
= NULL
; // do not release
7728 OSString
* kextIdentifier
= NULL
; // do not release
7729 OSArray
* kextIdentifiers
= NULL
; // do not release
7730 OSKext
* theKext
= NULL
; // do not release
7731 OSBoolean
* boolArg
= NULL
; // do not release
7733 IORecursiveLockLock(sKextLock
);
7736 *responseOut
= NULL
;
7737 *responseLengthOut
= 0;
7741 *logInfoLengthOut
= 0;
7744 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
7746 /* XML must be nul-terminated.
7748 if (requestBuffer
[requestLength
- 1] != '\0') {
7749 OSKextLog(/* kext */ NULL
,
7750 kOSKextLogErrorLevel
|
7752 "Invalid request from user space (not nul-terminated).");
7753 result
= kOSKextReturnBadData
;
7756 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
7758 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
7761 const char * errorCString
= "(unknown error)";
7763 if (errorString
&& errorString
->getCStringNoCopy()) {
7764 errorCString
= errorString
->getCStringNoCopy();
7765 } else if (parsedXML
) {
7766 errorCString
= "not a dictionary";
7768 OSKextLog(/* kext */ NULL
,
7769 kOSKextLogErrorLevel
|
7771 "Error unserializing request from user space: %s.",
7773 result
= kOSKextReturnSerialization
;
7777 predicate
= _OSKextGetRequestPredicate(requestDict
);
7779 OSKextLog(/* kext */ NULL
,
7780 kOSKextLogErrorLevel
|
7782 "Recieved kext request from user space with no predicate.");
7783 result
= kOSKextReturnInvalidArgument
;
7787 OSKextLog(/* kext */ NULL
,
7788 kOSKextLogDebugLevel
|
7790 "Received '%s' request from user space.",
7791 predicate
->getCStringNoCopy());
7793 result
= kOSKextReturnNotPrivileged
;
7794 if (hostPriv
== HOST_PRIV_NULL
) {
7795 /* must be root to use these kext requests */
7796 if (predicate
->isEqualTo(kKextRequestPredicateUnload
) ||
7797 predicate
->isEqualTo(kKextRequestPredicateStart
) ||
7798 predicate
->isEqualTo(kKextRequestPredicateStop
) ||
7799 predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
) ||
7800 predicate
->isEqualTo(kKextRequestPredicateSendResource
) ) {
7801 OSKextLog(/* kext */ NULL
,
7802 kOSKextLogErrorLevel
|
7804 "Access Failure - must be root user.");
7809 /* Get common args in anticipation of use.
7811 kextIdentifier
= OSDynamicCast(OSString
, _OSKextGetRequestArgument(
7812 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7813 kextIdentifiers
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument(
7814 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7815 if (kextIdentifier
) {
7816 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
7818 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
7819 requestDict
, kKextRequestArgumentValueKey
));
7821 result
= kOSKextReturnInvalidArgument
;
7823 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
7824 if (!kextIdentifier
) {
7825 OSKextLog(/* kext */ NULL
,
7826 kOSKextLogErrorLevel
|
7828 "Invalid arguments to kext start request.");
7829 } else if (!theKext
) {
7830 OSKextLog(/* kext */ NULL
,
7831 kOSKextLogErrorLevel
|
7833 "Kext %s not found for start request.",
7834 kextIdentifier
->getCStringNoCopy());
7835 result
= kOSKextReturnNotFound
;
7837 result
= theKext
->start();
7840 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
7841 if (!kextIdentifier
) {
7842 OSKextLog(/* kext */ NULL
,
7843 kOSKextLogErrorLevel
|
7845 "Invalid arguments to kext stop request.");
7846 } else if (!theKext
) {
7847 OSKextLog(/* kext */ NULL
,
7848 kOSKextLogErrorLevel
|
7850 "Kext %s not found for stop request.",
7851 kextIdentifier
->getCStringNoCopy());
7852 result
= kOSKextReturnNotFound
;
7854 result
= theKext
->stop();
7857 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
7858 if (!kextIdentifier
) {
7859 OSKextLog(/* kext */ NULL
,
7860 kOSKextLogErrorLevel
|
7862 "Invalid arguments to kext unload request.");
7863 } else if (!theKext
) {
7864 OSKextLog(/* kext */ NULL
,
7865 kOSKextLogErrorLevel
|
7867 "Kext %s not found for unload request.",
7868 kextIdentifier
->getCStringNoCopy());
7869 result
= kOSKextReturnNotFound
;
7871 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
7872 _OSKextGetRequestArgument(requestDict
,
7873 kKextRequestArgumentTerminateIOServicesKey
));
7874 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
7877 } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
7878 result
= OSKext::dispatchResource(requestDict
);
7880 } else if (predicate
->isEqualTo(kKextRequestPredicateGetUUIDByAddress
)) {
7882 OSNumber
*lookupNum
= NULL
;
7883 lookupNum
= OSDynamicCast(OSNumber
,
7884 _OSKextGetRequestArgument(requestDict
,
7885 kKextRequestArgumentLookupAddressKey
));
7887 responseObject
= OSKext::copyKextUUIDForAddress(lookupNum
);
7888 if (responseObject
) {
7889 result
= kOSReturnSuccess
;
7891 OSKextLog(/* kext */ NULL
,
7892 kOSKextLogErrorLevel
|
7894 "Get UUID by Address failed.");
7898 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
) ||
7899 predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
7900 OSBoolean
* delayAutounloadBool
= NULL
;
7901 OSObject
* infoKeysRaw
= NULL
;
7902 OSArray
* infoKeys
= NULL
;
7903 uint32_t infoKeysCount
= 0;
7905 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
7906 _OSKextGetRequestArgument(requestDict
,
7907 kKextRequestArgumentDelayAutounloadKey
));
7909 /* If asked to delay autounload, reset the timer if it's currently set.
7910 * (That is, don't schedule an unload if one isn't already pending.
7912 if (delayAutounloadBool
== kOSBooleanTrue
) {
7913 OSKext::considerUnloads(/* rescheduleOnly? */ true);
7916 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
7917 kKextRequestArgumentInfoKeysKey
);
7918 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
7919 if (infoKeysRaw
&& !infoKeys
) {
7920 OSKextLog(/* kext */ NULL
,
7921 kOSKextLogErrorLevel
|
7923 "Invalid arguments to kext info request.");
7928 infoKeysCount
= infoKeys
->getCount();
7929 for (uint32_t i
= 0; i
< infoKeysCount
; i
++) {
7930 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) {
7931 OSKextLog(/* kext */ NULL
,
7932 kOSKextLogErrorLevel
|
7934 "Invalid arguments to kext info request.");
7940 if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
7941 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
7943 else if (predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
7944 responseObject
= OSKext::copyLoadedKextInfoByUUID(kextIdentifiers
, infoKeys
);
7946 if (!responseObject
) {
7947 result
= kOSKextReturnInternalError
;
7949 OSKextLog(/* kext */ NULL
,
7950 kOSKextLogDebugLevel
|
7952 "Returning loaded kext info.");
7953 result
= kOSReturnSuccess
;
7955 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) {
7957 /* Hand the current sKernelRequests array to the caller
7958 * (who must release it), and make a new one.
7960 responseObject
= sKernelRequests
;
7961 sKernelRequests
= OSArray::withCapacity(0);
7962 sPostedKextLoadIdentifiers
->flushCollection();
7963 OSKextLog(/* kext */ NULL
,
7964 kOSKextLogDebugLevel
|
7966 "Returning kernel requests.");
7967 result
= kOSReturnSuccess
;
7969 } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) {
7971 /* Return the set of all requested bundle identifiers */
7972 responseObject
= sAllKextLoadIdentifiers
;
7973 responseObject
->retain();
7974 OSKextLog(/* kext */ NULL
,
7975 kOSKextLogDebugLevel
|
7977 "Returning load requests.");
7978 result
= kOSReturnSuccess
;
7981 OSKextLog(/* kext */ NULL
,
7982 kOSKextLogDebugLevel
|
7984 "Received '%s' invalid request from user space.",
7985 predicate
->getCStringNoCopy());
7990 * Now we have handle the request, or not. Gather up the response & logging
7991 * info to ship to user space.
7994 /* Note: Nothing in OSKext is supposed to retain requestDict,
7995 * but you never know....
7997 if (requestDict
->getRetainCount() > 1) {
7998 OSKextLog(/* kext */ NULL
,
7999 kOSKextLogWarningLevel
|
8001 "Request from user space still retained by a kext; "
8002 "probable memory leak.");
8005 if (responseOut
&& responseObject
) {
8006 serializer
= OSSerialize::withCapacity(0);
8008 result
= kOSKextReturnNoMemory
;
8012 if (!responseObject
->serialize(serializer
)) {
8013 OSKextLog(/* kext */ NULL
,
8014 kOSKextLogGeneralFlag
| kOSKextLogErrorLevel
,
8015 "Failed to serialize response to request from user space.");
8016 result
= kOSKextReturnSerialization
;
8020 response
= (char *)serializer
->text();
8021 responseLength
= serializer
->getLength();
8024 if (responseOut
&& response
) {
8027 /* This kmem_alloc sets the return value of the function.
8029 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
,
8030 round_page(responseLength
), VM_KERN_MEMORY_OSKEXT
);
8031 if (kmem_result
!= KERN_SUCCESS
) {
8032 OSKextLog(/* kext */ NULL
,
8033 kOSKextLogErrorLevel
|
8035 "Failed to copy response to request from user space.");
8036 result
= kmem_result
;
8039 /* 11981737 - clear uninitialized data in last page */
8040 bzero((void *)(buffer
+ responseLength
),
8041 (round_page(responseLength
) - responseLength
));
8042 memcpy(buffer
, response
, responseLength
);
8043 *responseOut
= buffer
;
8044 *responseLengthOut
= responseLength
;
8050 /* Gather up the collected log messages for user space. Any messages
8051 * messages past this call will not make it up as log messages but
8052 * will be in the system log. Note that we ignore the return of the
8053 * serialize; it has no bearing on the operation at hand even if we
8054 * fail to get the log messages.
8056 logInfoArray
= OSKext::clearUserSpaceLogFilter();
8058 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
8059 (void)OSKext::serializeLogInfo(logInfoArray
,
8060 logInfoOut
, logInfoLengthOut
);
8063 IORecursiveLockUnlock(sKextLock
);
8065 OSSafeReleaseNULL(parsedXML
);
8066 OSSafeReleaseNULL(errorString
);
8067 OSSafeReleaseNULL(responseObject
);
8068 OSSafeReleaseNULL(serializer
);
8069 OSSafeReleaseNULL(logInfoArray
);
8075 // #include <InstrProfiling.h>
8078 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin
,
8079 const char *DataEnd
,
8080 const char *CountersBegin
,
8081 const char *CountersEnd
,
8082 const char *NamesBegin
,
8083 const char *NamesEnd
);
8084 int __llvm_profile_write_buffer_internal(char *Buffer
,
8085 const char *DataBegin
,
8086 const char *DataEnd
,
8087 const char *CountersBegin
,
8088 const char *CountersEnd
,
8089 const char *NamesBegin
,
8090 const char *NamesEnd
);
8095 void OSKextPgoMetadataPut(char *pBuffer
,
8098 uint32_t *num_pairs
,
8102 size_t strlen_key
= strlen(key
);
8103 size_t strlen_value
= strlen(value
);
8104 size_t len
= strlen(key
) + 1 + strlen(value
) + 1;
8105 char *pos
= pBuffer
+ *position
;
8107 if (pBuffer
&& bufferSize
&& *position
<= bufferSize
) {
8108 memcpy(pos
, key
, strlen_key
); pos
+= strlen_key
;
8110 memcpy(pos
, value
, strlen_value
); pos
+= strlen_value
;
8120 void OSKextPgoMetadataPutMax(size_t *position
, const char *key
, size_t value_max
)
8122 *position
+= strlen(key
) + 1 + value_max
+ 1;
8127 void OSKextPgoMetadataPutAll(OSKext
*kext
,
8128 uuid_t instance_uuid
,
8132 uint32_t *num_pairs
)
8134 _static_assert_1_arg(sizeof(clock_sec_t
) % 2 == 0);
8135 //log_10 2^16 ≈ 4.82
8136 const size_t max_secs_string_size
= 5 * sizeof(clock_sec_t
)/2;
8137 const size_t max_timestamp_string_size
= max_secs_string_size
+ 1 + 6;
8140 OSKextPgoMetadataPutMax(position
, "INSTANCE", 36);
8141 OSKextPgoMetadataPutMax(position
, "UUID", 36);
8142 OSKextPgoMetadataPutMax(position
, "TIMESTAMP", max_timestamp_string_size
);
8144 uuid_string_t instance_uuid_string
;
8145 uuid_unparse(instance_uuid
, instance_uuid_string
);
8146 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8147 "INSTANCE", instance_uuid_string
);
8151 uuid_string_t uuid_string
;
8152 uuid_data
= kext
->copyUUID();
8154 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
8155 OSSafeReleaseNULL(uuid_data
);
8156 uuid_unparse(uuid
, uuid_string
);
8157 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8158 "UUID", uuid_string
);
8163 clock_get_calendar_microtime(&secs
, &usecs
);
8164 assert(usecs
< 1000000);
8165 char timestamp
[max_timestamp_string_size
+ 1];
8166 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t
));
8167 snprintf(timestamp
, sizeof(timestamp
), "%lu.%06d", (unsigned long)secs
, (int)usecs
);
8168 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8169 "TIMESTAMP", timestamp
);
8172 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8173 "NAME", kext
->getIdentifierCString());
8175 char versionCString
[kOSKextVersionMaxLength
];
8176 OSKextVersionGetString(kext
->getVersion(), versionCString
, kOSKextVersionMaxLength
);
8177 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8178 "VERSION", versionCString
);
8183 size_t OSKextPgoMetadataSize(OSKext
*kext
)
8185 size_t position
= 0;
8186 uuid_t fakeuuid
= {};
8187 OSKextPgoMetadataPutAll(kext
, fakeuuid
, NULL
, &position
, 0, NULL
);
8192 int OSKextGrabPgoDataLocked(OSKext
*kext
,
8194 uuid_t instance_uuid
,
8197 uint64_t bufferSize
)
8202 kernel_section_t
*sect_prf_data
= NULL
;
8203 kernel_section_t
*sect_prf_name
= NULL
;
8204 kernel_section_t
*sect_prf_cnts
= NULL
;
8206 size_t metadata_size
= 0;
8208 sect_prf_data
= kext
->lookupSection("__DATA", "__llvm_prf_data");
8209 sect_prf_name
= kext
->lookupSection("__DATA", "__llvm_prf_name");
8210 sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8212 if (!sect_prf_data
|| !sect_prf_name
|| !sect_prf_cnts
) {
8217 size
= __llvm_profile_get_size_for_buffer_internal(
8218 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8219 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8220 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8223 metadata_size
= OSKextPgoMetadataSize(kext
);
8224 size
+= metadata_size
;
8225 size
+= sizeof(pgo_metadata_footer
);
8233 if (pBuffer
&& bufferSize
) {
8234 if (bufferSize
< size
) {
8239 err
= __llvm_profile_write_buffer_internal(
8241 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8242 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8243 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8251 char *end_of_buffer
= pBuffer
+ size
;
8252 struct pgo_metadata_footer
*footerp
= (struct pgo_metadata_footer
*) (end_of_buffer
- sizeof(struct pgo_metadata_footer
));
8253 char *metadata_buffer
= end_of_buffer
- (sizeof(struct pgo_metadata_footer
) + metadata_size
);
8255 size_t metadata_position
= 0;
8256 uint32_t num_pairs
= 0;
8257 OSKextPgoMetadataPutAll(kext
, instance_uuid
, metadata_buffer
, &metadata_position
, metadata_size
, &num_pairs
);
8258 while (metadata_position
< metadata_size
) {
8259 metadata_buffer
[metadata_position
++] = 0;
8262 struct pgo_metadata_footer footer
;
8263 footer
.magic
= htonl(0x6d657461);
8264 footer
.number_of_pairs
= htonl( num_pairs
);
8265 footer
.offset_to_pairs
= htonl( sizeof(struct pgo_metadata_footer
) + metadata_size
);
8266 memcpy(footerp
, &footer
, sizeof(footer
));
8277 OSKextGrabPgoData(uuid_t uuid
,
8280 uint64_t bufferSize
,
8281 int wait_for_unload
,
8285 OSKext
*kext
= NULL
;
8288 IORecursiveLockLock(sKextLock
);
8290 kext
= OSKext::lookupKextWithUUID(uuid
);
8296 if (wait_for_unload
) {
8297 OSKextGrabPgoStruct s
;
8299 s
.metadata
= metadata
;
8301 s
.pBuffer
= pBuffer
;
8302 s
.bufferSize
= bufferSize
;
8305 struct list_head
*prev
= &kext
->pendingPgoHead
;
8306 struct list_head
*next
= kext
->pendingPgoHead
.next
;
8308 s
.list_head
.prev
= prev
;
8309 s
.list_head
.next
= next
;
8311 prev
->next
= &s
.list_head
;
8312 next
->prev
= &s
.list_head
;
8317 IORecursiveLockSleep(sKextLock
, &s
, THREAD_ABORTSAFE
);
8319 prev
= s
.list_head
.prev
;
8320 next
= s
.list_head
.next
;
8328 err
= OSKextGrabPgoDataLocked(kext
, metadata
, kext
->instance_uuid
, pSize
, pBuffer
, bufferSize
);
8336 IORecursiveLockUnlock(sKextLock
);
8342 OSKextResetPgoCountersLock()
8344 IORecursiveLockLock(sKextLock
);
8348 OSKextResetPgoCountersUnlock()
8350 IORecursiveLockUnlock(sKextLock
);
8354 extern unsigned int not_in_kdp
;
8357 OSKextResetPgoCounters()
8359 assert(!not_in_kdp
);
8360 uint32_t count
= sLoadedKexts
->getCount();
8361 for (uint32_t i
= 0; i
< count
; i
++) {
8362 OSKext
*kext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8363 kernel_section_t
*sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8364 if (!sect_prf_cnts
) {
8367 memset((void*)sect_prf_cnts
->addr
, 0, sect_prf_cnts
->size
);
8372 OSKext::copyLoadedKextInfoByUUID(
8373 OSArray
* kextIdentifiers
,
8376 OSDictionary
* result
= NULL
;
8377 OSDictionary
* kextInfo
= NULL
; // must release
8379 uint32_t idCount
= 0;
8380 uint32_t idIndex
= 0;
8382 IORecursiveLockLock(sKextLock
);
8385 /* Is the calling process allowed to query kext info? */
8386 if (current_task() != kernel_task
) {
8387 int macCheckResult
= 0;
8388 kauth_cred_t cred
= NULL
;
8390 cred
= kauth_cred_get_with_ref();
8391 macCheckResult
= mac_kext_check_query(cred
);
8392 kauth_cred_unref(&cred
);
8394 if (macCheckResult
!= 0) {
8395 OSKextLog(/* kext */ NULL
,
8396 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8397 "Failed to query kext info (MAC policy error 0x%x).",
8404 /* Empty list of UUIDs is equivalent to no list (get all).
8406 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8407 kextIdentifiers
= NULL
;
8408 } else if (kextIdentifiers
) {
8409 idCount
= kextIdentifiers
->getCount();
8414 if (infoKeys
&& !infoKeys
->getCount()) {
8418 count
= sLoadedKexts
->getCount();
8419 result
= OSDictionary::withCapacity(count
);
8424 for (i
= 0; i
< count
; i
++) {
8425 OSKext
*thisKext
= NULL
; // do not release
8426 Boolean includeThis
= true;
8427 uuid_t thisKextUUID
;
8429 uuid_string_t uuid_key
;
8432 kextInfo
->release();
8436 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8441 uuid_data
= thisKext
->copyUUID();
8446 memcpy(&thisKextUUID
, uuid_data
->getBytesNoCopy(), sizeof(thisKextUUID
));
8447 OSSafeReleaseNULL(uuid_data
);
8449 uuid_unparse(thisKextUUID
, uuid_key
);
8451 /* Skip current kext if we have a list of UUIDs and
8452 * it isn't in the list.
8454 if (kextIdentifiers
) {
8455 includeThis
= false;
8457 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8458 const OSString
* wantedUUID
= OSDynamicCast(OSString
,
8459 kextIdentifiers
->getObject(idIndex
));
8462 uuid_parse(wantedUUID
->getCStringNoCopy(), uuid
);
8464 if (0 == uuid_compare(uuid
, thisKextUUID
)) {
8476 kextInfo
= thisKext
->copyInfo(infoKeys
);
8478 result
->setObject(uuid_key
, kextInfo
);
8483 IORecursiveLockUnlock(sKextLock
);
8485 if (kextInfo
) kextInfo
->release();
8490 /*********************************************************************
8491 *********************************************************************/
8494 OSKext::copyKextUUIDForAddress(OSNumber
*address
)
8496 OSKext
*kext
= NULL
;
8497 OSData
*uuid
= NULL
;
8498 vm_address_t vm_addr
= 0;
8504 /* Is the calling process allowed to query kext info? */
8505 if (current_task() != kernel_task
) {
8506 int macCheckResult
= 0;
8507 kauth_cred_t cred
= NULL
;
8509 cred
= kauth_cred_get_with_ref();
8510 macCheckResult
= mac_kext_check_query(cred
);
8511 kauth_cred_unref(&cred
);
8513 if (macCheckResult
!= 0) {
8514 OSKextLog(/* kext */ NULL
,
8515 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8516 "Failed to query kext UUID (MAC policy error 0x%x).",
8523 vm_addr
= (vm_address_t
)(address
->unsigned64BitValue() + vm_kernel_slide
);
8525 kext
= OSKext::lookupKextWithAddress(vm_addr
);
8527 uuid
= kext
->copyUUID();
8538 /*********************************************************************
8539 *********************************************************************/
8542 OSKext::copyLoadedKextInfo(
8543 OSArray
* kextIdentifiers
,
8546 OSDictionary
* result
= NULL
;
8547 OSDictionary
* kextInfo
= NULL
; // must release
8549 uint32_t idCount
= 0;
8550 uint32_t idIndex
= 0;
8552 IORecursiveLockLock(sKextLock
);
8555 /* Is the calling process allowed to query kext info? */
8556 if (current_task() != kernel_task
) {
8557 int macCheckResult
= 0;
8558 kauth_cred_t cred
= NULL
;
8560 cred
= kauth_cred_get_with_ref();
8561 macCheckResult
= mac_kext_check_query(cred
);
8562 kauth_cred_unref(&cred
);
8564 if (macCheckResult
!= 0) {
8565 OSKextLog(/* kext */ NULL
,
8566 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8567 "Failed to query kext info (MAC policy error 0x%x).",
8574 /* Empty list of bundle ids is equivalent to no list (get all).
8576 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8577 kextIdentifiers
= NULL
;
8578 } else if (kextIdentifiers
) {
8579 idCount
= kextIdentifiers
->getCount();
8584 if (infoKeys
&& !infoKeys
->getCount()) {
8588 count
= sLoadedKexts
->getCount();
8589 result
= OSDictionary::withCapacity(count
);
8595 OSKextLog(/* kext */ NULL
,
8596 kOSKextLogErrorLevel
|
8597 kOSKextLogGeneralFlag
,
8598 "kaslr: vm_kernel_slide 0x%lx \n",
8600 OSKextLog(/* kext */ NULL
,
8601 kOSKextLogErrorLevel
|
8602 kOSKextLogGeneralFlag
,
8603 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
8604 vm_kernel_stext
, vm_kernel_etext
);
8605 OSKextLog(/* kext */ NULL
,
8606 kOSKextLogErrorLevel
|
8607 kOSKextLogGeneralFlag
,
8608 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
8609 vm_kernel_base
, vm_kernel_top
);
8610 OSKextLog(/* kext */ NULL
,
8611 kOSKextLogErrorLevel
|
8612 kOSKextLogGeneralFlag
,
8613 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
8614 vm_kext_base
, vm_kext_top
);
8615 OSKextLog(/* kext */ NULL
,
8616 kOSKextLogErrorLevel
|
8617 kOSKextLogGeneralFlag
,
8618 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
8619 vm_prelink_stext
, vm_prelink_etext
);
8620 OSKextLog(/* kext */ NULL
,
8621 kOSKextLogErrorLevel
|
8622 kOSKextLogGeneralFlag
,
8623 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
8624 vm_prelink_sinfo
, vm_prelink_einfo
);
8625 OSKextLog(/* kext */ NULL
,
8626 kOSKextLogErrorLevel
|
8627 kOSKextLogGeneralFlag
,
8628 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
8629 vm_slinkedit
, vm_elinkedit
);
8632 for (i
= 0; i
< count
; i
++) {
8633 OSKext
* thisKext
= NULL
; // do not release
8634 Boolean includeThis
= true;
8637 kextInfo
->release();
8640 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8645 /* Skip current kext if we have a list of bundle IDs and
8646 * it isn't in the list.
8648 if (kextIdentifiers
) {
8649 const OSString
* thisKextID
= thisKext
->getIdentifier();
8651 includeThis
= false;
8653 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8654 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
8655 kextIdentifiers
->getObject(idIndex
));
8656 if (thisKextID
->isEqualTo(thisRequestID
)) {
8667 kextInfo
= thisKext
->copyInfo(infoKeys
);
8669 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
8674 IORecursiveLockUnlock(sKextLock
);
8676 if (kextInfo
) kextInfo
->release();
8681 /*********************************************************************
8682 * Any info that needs to do allocations must goto finish on alloc
8683 * failure. Info that is just a lookup should just not set the object
8684 * if the info does not exist.
8685 *********************************************************************/
8686 #define _OSKextLoadInfoDictCapacity (12)
8689 OSKext::copyInfo(OSArray
* infoKeys
)
8691 OSDictionary
* result
= NULL
;
8692 bool success
= false;
8693 OSData
* headerData
= NULL
; // must release
8694 OSData
* logData
= NULL
; // must release
8695 OSNumber
* cpuTypeNumber
= NULL
; // must release
8696 OSNumber
* cpuSubtypeNumber
= NULL
; // must release
8697 OSString
* versionString
= NULL
; // do not release
8698 uint32_t executablePathCStringSize
= 0;
8699 char * executablePathCString
= NULL
; // must release
8700 OSString
* executablePathString
= NULL
; // must release
8701 OSData
* uuid
= NULL
; // must release
8702 OSNumber
* scratchNumber
= NULL
; // must release
8703 OSArray
* dependencyLoadTags
= NULL
; // must release
8704 OSCollectionIterator
* metaClassIterator
= NULL
; // must release
8705 OSArray
* metaClassInfo
= NULL
; // must release
8706 OSDictionary
* metaClassDict
= NULL
; // must release
8707 OSMetaClass
* thisMetaClass
= NULL
; // do not release
8708 OSString
* metaClassName
= NULL
; // must release
8709 OSString
* superclassName
= NULL
; // must release
8712 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
8718 /* Empty keys means no keys, but NULL is quicker to check.
8720 if (infoKeys
&& !infoKeys
->getCount()) {
8724 /* Headers, CPU type, and CPU subtype.
8727 _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) ||
8728 _OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
) ||
8729 _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) ||
8730 _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
))
8733 if (linkedExecutable
&& !isInterface()) {
8735 kernel_mach_header_t
*kext_mach_hdr
= (kernel_mach_header_t
*)
8736 linkedExecutable
->getBytesNoCopy();
8739 // do not return macho header info on shipping iOS - 19095897
8740 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) {
8741 kernel_mach_header_t
* temp_kext_mach_hdr
;
8742 struct load_command
* lcp
;
8744 headerData
= OSData::withBytes(kext_mach_hdr
,
8745 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
8750 // unslide any vmaddrs we return to userspace - 10726716
8751 temp_kext_mach_hdr
= (kernel_mach_header_t
*)
8752 headerData
->getBytesNoCopy();
8753 if (temp_kext_mach_hdr
== NULL
) {
8757 lcp
= (struct load_command
*) (temp_kext_mach_hdr
+ 1);
8758 for (i
= 0; i
< temp_kext_mach_hdr
->ncmds
; i
++) {
8759 if (lcp
->cmd
== LC_SEGMENT_KERNEL
) {
8760 kernel_segment_command_t
* segp
;
8761 kernel_section_t
* secp
;
8763 segp
= (kernel_segment_command_t
*) lcp
;
8764 // 10543468 - if we jettisoned __LINKEDIT clear size info
8765 if (flags
.jettisonLinkeditSeg
) {
8766 if (strncmp(segp
->segname
, SEG_LINKEDIT
, sizeof(segp
->segname
)) == 0) {
8773 OSKextLog(/* kext */ NULL
,
8774 kOSKextLogErrorLevel
|
8775 kOSKextLogGeneralFlag
,
8776 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
8777 __FUNCTION__
, segp
->segname
, segp
->vmaddr
,
8778 VM_KERNEL_UNSLIDE(segp
->vmaddr
),
8779 segp
->vmsize
, segp
->nsects
);
8780 if ( (VM_KERNEL_IS_SLID(segp
->vmaddr
) == false) &&
8781 (VM_KERNEL_IS_KEXT(segp
->vmaddr
) == false) &&
8782 (VM_KERNEL_IS_PRELINKTEXT(segp
->vmaddr
) == false) &&
8783 (VM_KERNEL_IS_PRELINKINFO(segp
->vmaddr
) == false) &&
8784 (VM_KERNEL_IS_KEXT_LINKEDIT(segp
->vmaddr
) == false) ) {
8785 OSKextLog(/* kext */ NULL
,
8786 kOSKextLogErrorLevel
|
8787 kOSKextLogGeneralFlag
,
8788 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
8789 __FUNCTION__
, segp
->vmaddr
, vm_kext_base
, vm_kext_top
);
8792 segp
->vmaddr
= VM_KERNEL_UNSLIDE(segp
->vmaddr
);
8794 for (secp
= firstsect(segp
); secp
!= NULL
; secp
= nextsect(segp
, secp
)) {
8795 secp
->addr
= VM_KERNEL_UNSLIDE(secp
->addr
);
8798 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
8800 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
8802 #endif // SECURE_KERNEL
8804 if (_OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
)) {
8805 osLogDataHeaderRef
*header
;
8806 char headerBytes
[offsetof(osLogDataHeaderRef
, sections
) + NUM_OS_LOG_SECTIONS
* sizeof(header
->sections
[0])];
8808 void *os_log_data
= NULL
;
8809 void *cstring_data
= NULL
;
8810 unsigned long os_log_size
= 0;
8811 unsigned long cstring_size
= 0;
8812 uint32_t os_log_offset
= 0;
8813 uint32_t cstring_offset
= 0;
8816 os_log_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__os_log", &os_log_size
);
8817 os_log_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__os_log");
8818 cstring_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__cstring", &cstring_size
);
8819 cstring_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__cstring");
8821 header
= (osLogDataHeaderRef
*) headerBytes
;
8822 header
->version
= OS_LOG_HDR_VERSION
;
8823 header
->sect_count
= NUM_OS_LOG_SECTIONS
;
8824 header
->sections
[OS_LOG_SECT_IDX
].sect_offset
= os_log_offset
;
8825 header
->sections
[OS_LOG_SECT_IDX
].sect_size
= (uint32_t) os_log_size
;
8826 header
->sections
[CSTRING_SECT_IDX
].sect_offset
= cstring_offset
;
8827 header
->sections
[CSTRING_SECT_IDX
].sect_size
= (uint32_t) cstring_size
;
8830 logData
= OSData::withBytes(header
, (u_int
) (sizeof(osLogDataHeaderRef
)));
8834 res
= logData
->appendBytes(&(header
->sections
[0]), (u_int
)(header
->sect_count
* sizeof(header
->sections
[0])));
8839 res
= logData
->appendBytes(os_log_data
, (u_int
)header
->sections
[OS_LOG_SECT_IDX
].sect_size
);
8845 res
= logData
->appendBytes(cstring_data
, (u_int
)header
->sections
[CSTRING_SECT_IDX
].sect_size
);
8850 result
->setObject(kOSBundleLogStringsKey
, logData
);
8853 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) {
8854 cpuTypeNumber
= OSNumber::withNumber(
8855 (uint64_t) kext_mach_hdr
->cputype
,
8856 8 * sizeof(kext_mach_hdr
->cputype
));
8857 if (!cpuTypeNumber
) {
8860 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
8863 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
8864 cpuSubtypeNumber
= OSNumber::withNumber(
8865 (uint64_t) kext_mach_hdr
->cpusubtype
,
8866 8 * sizeof(kext_mach_hdr
->cpusubtype
));
8867 if (!cpuSubtypeNumber
) {
8870 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
8875 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
8877 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
8881 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
8882 versionString
= OSDynamicCast(OSString
,
8883 getPropertyForHostArch(kCFBundleVersionKey
));
8884 if (versionString
) {
8885 result
->setObject(kCFBundleVersionKey
, versionString
);
8889 /* OSBundleCompatibleVersion.
8891 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
8892 versionString
= OSDynamicCast(OSString
,
8893 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
8894 if (versionString
) {
8895 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
8901 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
8903 result
->setObject(kOSBundlePathKey
, path
);
8908 /* OSBundleExecutablePath.
8910 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
8911 if (path
&& executableRelPath
) {
8913 uint32_t pathLength
= path
->getLength(); // gets incremented below
8915 // +1 for slash, +1 for \0
8916 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
8918 executablePathCString
= (char *)kalloc_tag((executablePathCStringSize
) *
8919 sizeof(char), VM_KERN_MEMORY_OSKEXT
); // +1 for \0
8920 if (!executablePathCString
) {
8923 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
8924 executablePathCStringSize
);
8925 executablePathCString
[pathLength
++] = '/';
8926 executablePathCString
[pathLength
++] = '\0';
8927 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
8928 executablePathCStringSize
);
8930 executablePathString
= OSString::withCString(executablePathCString
);
8932 if (!executablePathString
) {
8936 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
8940 /* UUID, if the kext has one.
8942 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
8945 result
->setObject(kOSBundleUUIDKey
, uuid
);
8950 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
8952 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSKernelResourceKey
)) {
8953 result
->setObject(kOSKernelResourceKey
,
8954 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
8957 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
8958 result
->setObject(kOSBundleIsInterfaceKey
,
8959 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
8962 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
8963 result
->setObject(kOSBundlePrelinkedKey
,
8964 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
8967 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
8968 result
->setObject(kOSBundleStartedKey
,
8969 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
8974 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
8975 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
8976 /* numBits */ 8 * sizeof(loadTag
));
8977 if (!scratchNumber
) {
8980 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
8981 OSSafeReleaseNULL(scratchNumber
);
8984 /* LoadAddress, LoadSize.
8987 _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) ||
8988 _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) ||
8989 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
) ||
8990 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
) ||
8991 _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
))
8993 if (isInterface() || linkedExecutable
) {
8994 /* These go to userspace via serialization, so we don't want any doubts
8997 uint64_t loadAddress
= 0;
8998 uint32_t loadSize
= 0;
8999 uint32_t wiredSize
= 0;
9000 uint64_t execLoadAddress
= 0;
9001 uint32_t execLoadSize
= 0;
9003 /* Interfaces always report 0 load address & size.
9004 * Just the way they roll.
9006 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
9007 * xxx - shouldn't have one!
9009 if (linkedExecutable
/* && !isInterface() */) {
9010 kernel_mach_header_t
*mh
= NULL
;
9011 kernel_segment_command_t
*seg
= NULL
;
9013 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
9014 mh
= (kernel_mach_header_t
*)loadAddress
;
9015 loadAddress
= VM_KERNEL_UNSLIDE(loadAddress
);
9016 loadSize
= linkedExecutable
->getLength();
9018 /* Walk through the kext, looking for the first executable
9019 * segment in case we were asked for its size/address.
9021 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
9022 if (seg
->initprot
& VM_PROT_EXECUTE
) {
9023 execLoadAddress
= VM_KERNEL_UNSLIDE(seg
->vmaddr
);
9024 execLoadSize
= seg
->vmsize
;
9029 /* If we have a kmod_info struct, calculated the wired size
9030 * from that. Otherwise it's the full load size.
9033 wiredSize
= loadSize
- kmod_info
->hdr_size
;
9035 wiredSize
= loadSize
;
9039 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
9040 scratchNumber
= OSNumber::withNumber(
9041 (unsigned long long)(loadAddress
),
9042 /* numBits */ 8 * sizeof(loadAddress
));
9043 if (!scratchNumber
) {
9046 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
9047 OSSafeReleaseNULL(scratchNumber
);
9049 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
)) {
9050 scratchNumber
= OSNumber::withNumber(
9051 (unsigned long long)(execLoadAddress
),
9052 /* numBits */ 8 * sizeof(execLoadAddress
));
9053 if (!scratchNumber
) {
9056 result
->setObject(kOSBundleExecLoadAddressKey
, scratchNumber
);
9057 OSSafeReleaseNULL(scratchNumber
);
9059 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
9060 scratchNumber
= OSNumber::withNumber(
9061 (unsigned long long)(loadSize
),
9062 /* numBits */ 8 * sizeof(loadSize
));
9063 if (!scratchNumber
) {
9066 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
9067 OSSafeReleaseNULL(scratchNumber
);
9069 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
)) {
9070 scratchNumber
= OSNumber::withNumber(
9071 (unsigned long long)(execLoadSize
),
9072 /* numBits */ 8 * sizeof(execLoadSize
));
9073 if (!scratchNumber
) {
9076 result
->setObject(kOSBundleExecLoadSizeKey
, scratchNumber
);
9077 OSSafeReleaseNULL(scratchNumber
);
9079 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
9080 scratchNumber
= OSNumber::withNumber(
9081 (unsigned long long)(wiredSize
),
9082 /* numBits */ 8 * sizeof(wiredSize
));
9083 if (!scratchNumber
) {
9086 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
9087 OSSafeReleaseNULL(scratchNumber
);
9092 /* OSBundleDependencies. In descending order for
9093 * easy compatibility with kextstat(8).
9095 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
9096 if ((count
= getNumDependencies())) {
9097 dependencyLoadTags
= OSArray::withCapacity(count
);
9098 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
9102 OSKext
* dependency
= OSDynamicCast(OSKext
,
9103 dependencies
->getObject(i
));
9105 OSSafeReleaseNULL(scratchNumber
);
9110 scratchNumber
= OSNumber::withNumber(
9111 (unsigned long long)dependency
->getLoadTag(),
9112 /* numBits*/ 8 * sizeof(loadTag
));
9113 if (!scratchNumber
) {
9116 dependencyLoadTags
->setObject(scratchNumber
);
9121 OSSafeReleaseNULL(scratchNumber
);
9123 /* OSBundleMetaClasses.
9125 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) {
9126 if (metaClasses
&& metaClasses
->getCount()) {
9127 metaClassIterator
= OSCollectionIterator::withCollection(metaClasses
);
9128 metaClassInfo
= OSArray::withCapacity(metaClasses
->getCount());
9129 if (!metaClassIterator
|| !metaClassInfo
) {
9132 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
9134 while ( (thisMetaClass
= OSDynamicCast(OSMetaClass
,
9135 metaClassIterator
->getNextObject())) ) {
9137 OSSafeReleaseNULL(metaClassDict
);
9138 OSSafeReleaseNULL(scratchNumber
);
9139 OSSafeReleaseNULL(metaClassName
);
9140 OSSafeReleaseNULL(superclassName
);
9142 metaClassDict
= OSDictionary::withCapacity(3);
9143 if (!metaClassDict
) {
9147 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
9148 if (thisMetaClass
->getSuperClass()) {
9149 superclassName
= OSString::withCString(
9150 thisMetaClass
->getSuperClass()->getClassName());
9152 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
9153 8 * sizeof(unsigned int));
9155 /* Bail if any of the essentials is missing. The root class lacks a superclass,
9158 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
9162 metaClassInfo
->setObject(metaClassDict
);
9163 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
9164 if (superclassName
) {
9165 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
9167 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
9172 /* OSBundleRetainCount.
9174 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
9175 OSSafeReleaseNULL(scratchNumber
);
9177 int kextRetainCount
= getRetainCount() - 1;
9181 scratchNumber
= OSNumber::withNumber(
9182 (int)kextRetainCount
,
9183 /* numBits*/ 8 * sizeof(int));
9184 if (scratchNumber
) {
9185 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
9193 OSSafeReleaseNULL(headerData
);
9194 OSSafeReleaseNULL(logData
);
9195 OSSafeReleaseNULL(cpuTypeNumber
);
9196 OSSafeReleaseNULL(cpuSubtypeNumber
);
9197 OSSafeReleaseNULL(executablePathString
);
9198 if (executablePathCString
) kfree(executablePathCString
, executablePathCStringSize
);
9199 OSSafeReleaseNULL(uuid
);
9200 OSSafeReleaseNULL(scratchNumber
);
9201 OSSafeReleaseNULL(dependencyLoadTags
);
9202 OSSafeReleaseNULL(metaClassIterator
);
9203 OSSafeReleaseNULL(metaClassInfo
);
9204 OSSafeReleaseNULL(metaClassDict
);
9205 OSSafeReleaseNULL(metaClassName
);
9206 OSSafeReleaseNULL(superclassName
);
9208 OSSafeReleaseNULL(result
);
9213 /*********************************************************************
9214 *********************************************************************/
9217 OSKext::requestResource(
9218 const char * kextIdentifierCString
,
9219 const char * resourceNameCString
,
9220 OSKextRequestResourceCallback callback
,
9222 OSKextRequestTag
* requestTagOut
)
9224 OSReturn result
= kOSReturnError
;
9225 OSKext
* callbackKext
= NULL
; // must release (looked up)
9227 OSKextRequestTag requestTag
= -1;
9228 OSNumber
* requestTagNum
= NULL
; // must release
9230 OSDictionary
* requestDict
= NULL
; // must release
9231 OSString
* kextIdentifier
= NULL
; // must release
9232 OSString
* resourceName
= NULL
; // must release
9234 OSDictionary
* callbackRecord
= NULL
; // must release
9235 OSData
* callbackWrapper
= NULL
; // must release
9237 OSData
* contextWrapper
= NULL
; // must release
9239 IORecursiveLockLock(sKextLock
);
9241 if (requestTagOut
) {
9242 *requestTagOut
= kOSKextRequestTagInvalid
;
9245 /* If requests to user space are disabled, don't go any further */
9246 if (!sKernelRequestsEnabled
) {
9247 OSKextLog(/* kext */ NULL
,
9248 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9249 "Can't request resource %s for %s - requests to user space are disabled.",
9250 resourceNameCString
,
9251 kextIdentifierCString
);
9252 result
= kOSKextReturnDisabled
;
9256 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
9257 result
= kOSKextReturnInvalidArgument
;
9261 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9262 if (!callbackKext
) {
9263 OSKextLog(/* kext */ NULL
,
9264 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9265 "Resource request has bad callback address.");
9266 result
= kOSKextReturnInvalidArgument
;
9269 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9270 OSKextLog(/* kext */ NULL
,
9271 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9272 "Resource request callback is in a kext that is not started.");
9273 result
= kOSKextReturnInvalidArgument
;
9277 /* Do not allow any new requests to be made on a kext that is unloading.
9279 if (callbackKext
->flags
.stopping
) {
9280 result
= kOSKextReturnStopping
;
9284 /* If we're wrapped the next available request tag around to the negative
9285 * numbers, we can't service any more requests.
9287 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
9288 OSKextLog(/* kext */ NULL
,
9289 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9290 "No more request tags available; restart required.");
9291 result
= kOSKextReturnNoResources
;
9294 requestTag
= sNextRequestTag
++;
9296 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
9298 if (result
!= kOSReturnSuccess
) {
9302 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
9303 resourceName
= OSString::withCString(resourceNameCString
);
9304 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9305 8 * sizeof(requestTag
));
9306 if (!kextIdentifier
||
9309 !_OSKextSetRequestArgument(requestDict
,
9310 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
9311 !_OSKextSetRequestArgument(requestDict
,
9312 kKextRequestArgumentNameKey
, resourceName
) ||
9313 !_OSKextSetRequestArgument(requestDict
,
9314 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
9316 result
= kOSKextReturnNoMemory
;
9320 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
9321 if (!callbackRecord
) {
9322 result
= kOSKextReturnNoMemory
;
9325 // we validate callback address at call time
9326 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
9328 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
9330 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9331 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
9333 result
= kOSKextReturnNoMemory
;
9338 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9339 kKextRequestArgumentContextKey
, contextWrapper
)) {
9341 result
= kOSKextReturnNoMemory
;
9346 /* Only post the requests after all the other potential failure points
9349 if (!sKernelRequests
->setObject(requestDict
) ||
9350 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
9352 result
= kOSKextReturnNoMemory
;
9356 OSKext::pingKextd();
9358 result
= kOSReturnSuccess
;
9359 if (requestTagOut
) {
9360 *requestTagOut
= requestTag
;
9365 /* If we didn't succeed, yank the request & callback
9366 * from their holding arrays.
9368 if (result
!= kOSReturnSuccess
) {
9371 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
9372 if (index
!= (unsigned int)-1) {
9373 sKernelRequests
->removeObject(index
);
9375 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
9376 if (index
!= (unsigned int)-1) {
9377 sRequestCallbackRecords
->removeObject(index
);
9381 OSKext::considerUnloads(/* rescheduleOnly? */ true);
9383 IORecursiveLockUnlock(sKextLock
);
9385 if (callbackKext
) callbackKext
->release();
9386 if (requestTagNum
) requestTagNum
->release();
9388 if (requestDict
) requestDict
->release();
9389 if (kextIdentifier
) kextIdentifier
->release();
9390 if (resourceName
) resourceName
->release();
9392 if (callbackRecord
) callbackRecord
->release();
9393 if (callbackWrapper
) callbackWrapper
->release();
9394 if (contextWrapper
) contextWrapper
->release();
9399 /*********************************************************************
9400 * Assumes sKextLock is held.
9401 *********************************************************************/
9404 OSKext::dequeueCallbackForRequestTag(
9405 OSKextRequestTag requestTag
,
9406 OSDictionary
** callbackRecordOut
)
9408 OSReturn result
= kOSReturnError
;
9409 OSNumber
* requestTagNum
= NULL
; // must release
9411 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9412 8 * sizeof(requestTag
));
9413 if (!requestTagNum
) {
9417 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
9421 OSSafeReleaseNULL(requestTagNum
);
9426 /*********************************************************************
9427 * Assumes sKextLock is held.
9428 *********************************************************************/
9431 OSKext::dequeueCallbackForRequestTag(
9432 OSNumber
* requestTagNum
,
9433 OSDictionary
** callbackRecordOut
)
9435 OSReturn result
= kOSKextReturnInvalidArgument
;
9436 OSDictionary
* callbackRecord
= NULL
; // retain if matched!
9437 OSNumber
* callbackTagNum
= NULL
; // do not release
9438 unsigned int count
, i
;
9440 result
= kOSReturnError
;
9441 count
= sRequestCallbackRecords
->getCount();
9442 for (i
= 0; i
< count
; i
++) {
9443 callbackRecord
= OSDynamicCast(OSDictionary
,
9444 sRequestCallbackRecords
->getObject(i
));
9445 if (!callbackRecord
) {
9449 /* If we don't find a tag, we basically have a leak here. Maybe
9450 * we should just remove it.
9452 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
9453 callbackRecord
, kKextRequestArgumentRequestTagKey
));
9454 if (!callbackTagNum
) {
9458 /* We could be even more paranoid and check that all the incoming
9459 * args match what's in the callback record.
9461 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
9462 if (callbackRecordOut
) {
9463 *callbackRecordOut
= callbackRecord
;
9464 callbackRecord
->retain();
9466 sRequestCallbackRecords
->removeObject(i
);
9467 result
= kOSReturnSuccess
;
9471 result
= kOSKextReturnNotFound
;
9477 /*********************************************************************
9478 * Assumes sKextLock is held.
9479 *********************************************************************/
9482 OSKext::dispatchResource(OSDictionary
* requestDict
)
9484 OSReturn result
= kOSReturnError
;
9485 OSDictionary
* callbackRecord
= NULL
; // must release
9486 OSNumber
* requestTag
= NULL
; // do not release
9487 OSNumber
* requestResult
= NULL
; // do not release
9488 OSData
* dataObj
= NULL
; // do not release
9489 uint32_t dataLength
= 0;
9490 const void * dataPtr
= NULL
; // do not free
9491 OSData
* callbackWrapper
= NULL
; // do not release
9492 OSKextRequestResourceCallback callback
= NULL
;
9493 OSData
* contextWrapper
= NULL
; // do not release
9494 void * context
= NULL
; // do not free
9495 OSKext
* callbackKext
= NULL
; // must release (looked up)
9497 /* Get the args from the request. Right now we need the tag
9498 * to look up the callback record, and the result for invoking the callback.
9500 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9501 kKextRequestArgumentRequestTagKey
));
9502 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9503 kKextRequestArgumentResultKey
));
9504 if (!requestTag
|| !requestResult
) {
9505 result
= kOSKextReturnInvalidArgument
;
9509 /* Look for a callback record matching this request's tag.
9511 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
9512 if (result
!= kOSReturnSuccess
) {
9517 * Get the context pointer of the callback record (if there is one).
9519 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
9520 kKextRequestArgumentContextKey
));
9521 context
= _OSKextExtractPointer(contextWrapper
);
9522 if (contextWrapper
&& !context
) {
9526 callbackWrapper
= OSDynamicCast(OSData
,
9527 _OSKextGetRequestArgument(callbackRecord
,
9528 kKextRequestArgumentCallbackKey
));
9529 callback
= (OSKextRequestResourceCallback
)
9530 _OSKextExtractPointer(callbackWrapper
);
9535 /* Check for a data obj. We might not have one and that's ok, that means
9536 * we didn't find the requested resource, and we still have to tell the
9537 * caller that via the callback.
9539 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
9540 kKextRequestArgumentValueKey
));
9542 dataPtr
= dataObj
->getBytesNoCopy();
9543 dataLength
= dataObj
->getLength();
9546 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9547 if (!callbackKext
) {
9548 OSKextLog(/* kext */ NULL
,
9549 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9550 "Can't invoke callback for resource request; ");
9553 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9554 OSKextLog(/* kext */ NULL
,
9555 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9556 "Can't invoke kext resource callback; ");
9560 (void)callback(requestTag
->unsigned32BitValue(),
9561 (OSReturn
)requestResult
->unsigned32BitValue(),
9562 dataPtr
, dataLength
, context
);
9564 result
= kOSReturnSuccess
;
9567 if (callbackKext
) callbackKext
->release();
9568 if (callbackRecord
) callbackRecord
->release();
9573 /*********************************************************************
9574 *********************************************************************/
9577 OSKext::invokeRequestCallback(
9578 OSDictionary
* callbackRecord
,
9579 OSReturn callbackResult
)
9581 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
9582 OSNumber
* resultNum
= NULL
; // must release
9588 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
9589 8 * sizeof(callbackResult
));
9594 /* Insert the result into the callback record and dispatch it as if it
9595 * were the reply coming down from user space.
9597 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
9600 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
9601 /* This removes the pending callback record.
9603 OSKext::dispatchResource(callbackRecord
);
9607 if (resultNum
) resultNum
->release();
9611 /*********************************************************************
9612 * Assumes sKextLock is held.
9613 *********************************************************************/
9616 OSKext::cancelRequest(
9617 OSKextRequestTag requestTag
,
9620 OSReturn result
= kOSKextReturnNoMemory
;
9621 OSDictionary
* callbackRecord
= NULL
; // must release
9622 OSData
* contextWrapper
= NULL
; // do not release
9624 IORecursiveLockLock(sKextLock
);
9625 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
9627 IORecursiveLockUnlock(sKextLock
);
9629 if (result
== kOSReturnSuccess
&& contextOut
) {
9630 contextWrapper
= OSDynamicCast(OSData
,
9631 _OSKextGetRequestArgument(callbackRecord
,
9632 kKextRequestArgumentContextKey
));
9633 *contextOut
= _OSKextExtractPointer(contextWrapper
);
9636 if (callbackRecord
) callbackRecord
->release();
9641 /*********************************************************************
9642 * Assumes sKextLock is held.
9643 *********************************************************************/
9645 OSKext::invokeOrCancelRequestCallbacks(
9646 OSReturn callbackResult
,
9649 unsigned int count
, i
;
9651 count
= sRequestCallbackRecords
->getCount();
9658 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9659 sRequestCallbackRecords
->getObject(i
));
9664 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9665 _OSKextGetRequestArgument(request
,
9666 kKextRequestArgumentCallbackKey
));
9668 if (!callbackWrapper
) {
9669 sRequestCallbackRecords
->removeObject(i
);
9673 vm_address_t callbackAddress
= (vm_address_t
)
9674 _OSKextExtractPointer(callbackWrapper
);
9676 if ((kmod_info
->address
<= callbackAddress
) &&
9677 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9680 /* This removes the callback record.
9682 invokeRequestCallback(request
, callbackResult
);
9684 sRequestCallbackRecords
->removeObject(i
);
9693 /*********************************************************************
9694 * Assumes sKextLock is held.
9695 *********************************************************************/
9697 OSKext::countRequestCallbacks(void)
9699 uint32_t result
= 0;
9700 unsigned int count
, i
;
9702 count
= sRequestCallbackRecords
->getCount();
9709 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9710 sRequestCallbackRecords
->getObject(i
));
9715 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9716 _OSKextGetRequestArgument(request
,
9717 kKextRequestArgumentCallbackKey
));
9719 if (!callbackWrapper
) {
9723 vm_address_t callbackAddress
= (vm_address_t
)
9724 _OSKextExtractPointer(callbackWrapper
);
9726 if ((kmod_info
->address
<= callbackAddress
) &&
9727 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9737 /*********************************************************************
9738 *********************************************************************/
9739 static OSReturn
_OSKextCreateRequest(
9740 const char * predicate
,
9741 OSDictionary
** requestP
)
9743 OSReturn result
= kOSKextReturnNoMemory
;
9744 OSDictionary
* request
= NULL
; // must release on error
9746 request
= OSDictionary::withCapacity(2);
9750 result
= _OSDictionarySetCStringValue(request
,
9751 kKextRequestPredicateKey
, predicate
);
9752 if (result
!= kOSReturnSuccess
) {
9755 result
= kOSReturnSuccess
;
9758 if (result
!= kOSReturnSuccess
) {
9759 if (request
) request
->release();
9761 *requestP
= request
;
9767 /*********************************************************************
9768 *********************************************************************/
9769 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
9771 return OSDynamicCast(OSString
,
9772 requestDict
->getObject(kKextRequestPredicateKey
));
9775 /*********************************************************************
9776 *********************************************************************/
9777 static OSObject
* _OSKextGetRequestArgument(
9778 OSDictionary
* requestDict
,
9779 const char * argName
)
9781 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9782 requestDict
->getObject(kKextRequestArgumentsKey
));
9784 return args
->getObject(argName
);
9789 /*********************************************************************
9790 *********************************************************************/
9791 static bool _OSKextSetRequestArgument(
9792 OSDictionary
* requestDict
,
9793 const char * argName
,
9796 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9797 requestDict
->getObject(kKextRequestArgumentsKey
));
9799 args
= OSDictionary::withCapacity(2);
9803 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
9807 return args
->setObject(argName
, value
);
9813 /*********************************************************************
9814 *********************************************************************/
9815 static void * _OSKextExtractPointer(OSData
* wrapper
)
9817 void * result
= NULL
;
9818 const void * resultPtr
= NULL
;
9823 resultPtr
= wrapper
->getBytesNoCopy();
9824 result
= *(void **)resultPtr
;
9829 /*********************************************************************
9830 *********************************************************************/
9831 static OSReturn
_OSDictionarySetCStringValue(
9832 OSDictionary
* dict
,
9834 const char * cValue
)
9836 OSReturn result
= kOSKextReturnNoMemory
;
9837 const OSSymbol
* key
= NULL
; // must release
9838 OSString
* value
= NULL
; // must release
9840 key
= OSSymbol::withCString(cKey
);
9841 value
= OSString::withCString(cValue
);
9842 if (!key
|| !value
) {
9845 if (dict
->setObject(key
, value
)) {
9846 result
= kOSReturnSuccess
;
9850 if (key
) key
->release();
9851 if (value
) value
->release();
9856 /*********************************************************************
9857 *********************************************************************/
9858 static bool _OSArrayContainsCString(
9860 const char * cString
)
9862 bool result
= false;
9863 const OSSymbol
* symbol
= NULL
;
9866 if (!array
|| !cString
) {
9870 symbol
= OSSymbol::withCStringNoCopy(cString
);
9875 count
= array
->getCount();
9876 for (i
= 0; i
< count
; i
++) {
9877 OSObject
* thisObject
= array
->getObject(i
);
9878 if (symbol
->isEqualTo(thisObject
)) {
9885 if (symbol
) symbol
->release();
9889 /*********************************************************************
9890 * We really only care about boot / system start up related kexts.
9891 * We return true if we're less than REBUILD_MAX_TIME since start up,
9892 * otherwise return false.
9893 *********************************************************************/
9894 bool _OSKextInPrelinkRebuildWindow(void)
9896 static bool outside_the_window
= false;
9897 AbsoluteTime my_abstime
;
9901 if (outside_the_window
) {
9904 clock_get_uptime(&my_abstime
);
9905 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
9906 my_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
9907 if (my_secs
> REBUILD_MAX_TIME
) {
9908 outside_the_window
= true;
9914 /*********************************************************************
9915 *********************************************************************/
9916 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
9918 int unLoadedCount
, i
;
9919 bool result
= false;
9921 IORecursiveLockLock(sKextLock
);
9923 if (sUnloadedPrelinkedKexts
== NULL
) {
9926 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
9927 if (unLoadedCount
== 0) {
9931 for (i
= 0; i
< unLoadedCount
; i
++) {
9932 const OSSymbol
* myBundleID
; // do not release
9934 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
9935 if (!myBundleID
) continue;
9936 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
9942 IORecursiveLockUnlock(sKextLock
);
9947 #pragma mark Personalities (IOKit Drivers)
9949 /*********************************************************************
9950 *********************************************************************/
9953 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
9955 OSArray
* result
= NULL
; // returned
9956 OSCollectionIterator
* kextIterator
= NULL
; // must release
9957 OSArray
* personalities
= NULL
; // must release
9958 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
9960 OSString
* kextID
= NULL
; // do not release
9961 OSKext
* theKext
= NULL
; // do not release
9963 IORecursiveLockLock(sKextLock
);
9965 /* Let's conservatively guess that any given kext has around 3
9966 * personalities for now.
9968 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
9973 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
9974 if (!kextIterator
) {
9978 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
9979 if (personalitiesIterator
) {
9980 personalitiesIterator
->release();
9981 personalitiesIterator
= NULL
;
9983 if (personalities
) {
9984 personalities
->release();
9985 personalities
= NULL
;
9988 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
9989 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
9990 personalities
= theKext
->copyPersonalitiesArray();
9991 if (!personalities
) {
9994 result
->merge(personalities
);
9996 // xxx - check for better place to put this log msg
9998 kOSKextLogWarningLevel
|
10000 "Kext %s is not loadable during safe boot; "
10001 "omitting its personalities.",
10002 theKext
->getIdentifierCString());
10008 IORecursiveLockUnlock(sKextLock
);
10010 if (kextIterator
) kextIterator
->release();
10011 if (personalitiesIterator
) personalitiesIterator
->release();
10012 if (personalities
) personalities
->release();
10017 /*********************************************************************
10018 *********************************************************************/
10021 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
10023 int numPersonalities
= 0;
10025 OSKextLog(/* kext */ NULL
,
10026 kOSKextLogStepLevel
|
10027 kOSKextLogLoadFlag
,
10028 "Sending all eligible registered kexts' personalities "
10029 "to the IOCatalogue %s.",
10030 startMatching
? "and starting matching" : "but not starting matching");
10032 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
10033 /* filterSafeBootFlag */ true);
10035 if (personalities
) {
10036 gIOCatalogue
->addDrivers(personalities
, startMatching
);
10037 numPersonalities
= personalities
->getCount();
10038 personalities
->release();
10041 OSKextLog(/* kext */ NULL
,
10042 kOSKextLogStepLevel
|
10043 kOSKextLogLoadFlag
,
10044 "%d kext personalit%s sent to the IOCatalogue; %s.",
10045 numPersonalities
, numPersonalities
> 0 ? "ies" : "y",
10046 startMatching
? "matching started" : "matching not started");
10050 /*********************************************************************
10051 * Do not make a deep copy, just convert the IOKitPersonalities dict
10052 * to an array for sending to the IOCatalogue.
10053 *********************************************************************/
10055 OSKext::copyPersonalitiesArray(void)
10057 OSArray
* result
= NULL
;
10058 OSDictionary
* personalities
= NULL
; // do not release
10059 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
10061 OSString
* personalityName
= NULL
; // do not release
10062 OSString
* personalityBundleIdentifier
= NULL
; // do not release
10064 personalities
= OSDynamicCast(OSDictionary
,
10065 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10066 if (!personalities
) {
10070 result
= OSArray::withCapacity(personalities
->getCount());
10075 personalitiesIterator
=
10076 OSCollectionIterator::withCollection(personalities
);
10077 if (!personalitiesIterator
) {
10080 while ((personalityName
= OSDynamicCast(OSString
,
10081 personalitiesIterator
->getNextObject()))) {
10083 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10084 personalities
->getObject(personalityName
));
10087 * If the personality doesn't have a CFBundleIdentifier, or if it
10088 * differs from the kext's, insert the kext's ID so we can find it.
10089 * The publisher ID is used to remove personalities from bundles
10092 personalityBundleIdentifier
= OSDynamicCast(OSString
,
10093 personality
->getObject(kCFBundleIdentifierKey
));
10095 if (!personalityBundleIdentifier
) {
10096 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
10097 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
10098 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
10101 result
->setObject(personality
);
10105 if (personalitiesIterator
) personalitiesIterator
->release();
10110 /*********************************************************************
10111 Might want to change this to a bool return?
10112 *********************************************************************/
10114 OSKext::sendPersonalitiesToCatalog(
10115 bool startMatching
,
10116 OSArray
* personalityNames
)
10118 OSReturn result
= kOSReturnSuccess
;
10119 OSArray
* personalitiesToSend
= NULL
; // must release
10120 OSDictionary
* kextPersonalities
= NULL
; // do not release
10123 if (!sLoadEnabled
) {
10125 kOSKextLogErrorLevel
|
10126 kOSKextLogLoadFlag
,
10127 "Kext loading is disabled (attempt to start matching for kext %s).",
10128 getIdentifierCString());
10129 result
= kOSKextReturnDisabled
;
10133 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
10135 kOSKextLogErrorLevel
|
10136 kOSKextLogLoadFlag
,
10137 "Kext %s is not loadable during safe boot; "
10138 "not sending personalities to the IOCatalogue.",
10139 getIdentifierCString());
10140 result
= kOSKextReturnNotLoadable
;
10144 if (!personalityNames
|| !personalityNames
->getCount()) {
10145 personalitiesToSend
= copyPersonalitiesArray();
10147 kextPersonalities
= OSDynamicCast(OSDictionary
,
10148 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10149 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
10153 personalitiesToSend
= OSArray::withCapacity(0);
10154 if (!personalitiesToSend
) {
10155 result
= kOSKextReturnNoMemory
;
10158 count
= personalityNames
->getCount();
10159 for (i
= 0; i
< count
; i
++) {
10160 OSString
* name
= OSDynamicCast(OSString
,
10161 personalityNames
->getObject(i
));
10165 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10166 kextPersonalities
->getObject(name
));
10168 personalitiesToSend
->setObject(personality
);
10172 if (personalitiesToSend
) {
10173 unsigned numPersonalities
= personalitiesToSend
->getCount();
10175 kOSKextLogStepLevel
|
10176 kOSKextLogLoadFlag
,
10177 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
10178 getIdentifierCString(),
10180 numPersonalities
> 1 ? "ies" : "y",
10181 startMatching
? " and starting matching" : " but not starting matching");
10182 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
10185 if (personalitiesToSend
) {
10186 personalitiesToSend
->release();
10191 /*********************************************************************
10192 * xxx - We should allow removing the kext's declared personalities,
10193 * xxx - even with other bundle identifiers.
10194 *********************************************************************/
10196 OSKext::removePersonalitiesFromCatalog(void)
10198 OSDictionary
* personality
= NULL
; // do not release
10200 personality
= OSDictionary::withCapacity(1);
10201 if (!personality
) {
10204 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
10207 kOSKextLogStepLevel
|
10208 kOSKextLogLoadFlag
,
10209 "Kext %s removing all personalities naming it from the IOCatalogue.",
10210 getIdentifierCString());
10212 /* Have the IOCatalog remove all personalities matching this kext's
10213 * bundle ID and trigger matching anew.
10215 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
10218 if (personality
) personality
->release();
10225 #pragma mark Logging
10227 /*********************************************************************
10228 * Do not call any function that takes sKextLock here!
10229 *********************************************************************/
10232 OSKext::setUserSpaceLogFilter(
10233 OSKextLogSpec newUserLogFilter
,
10236 OSKextLogSpec result
;
10237 bool allocError
= false;
10239 /* Do not call any function that takes sKextLoggingLock during
10240 * this critical block. That means do logging after.
10242 IOLockLock(sKextLoggingLock
);
10244 result
= sUserSpaceKextLogFilter
;
10245 sUserSpaceKextLogFilter
= newUserLogFilter
;
10247 if (newUserLogFilter
&& captureFlag
&&
10248 !sUserSpaceLogSpecArray
&& !sUserSpaceLogMessageArray
) {
10250 // xxx - do some measurements for a good initial capacity?
10251 sUserSpaceLogSpecArray
= OSArray::withCapacity(0);
10252 sUserSpaceLogMessageArray
= OSArray::withCapacity(0);
10254 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
10255 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10256 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10261 IOLockUnlock(sKextLoggingLock
);
10263 /* If the config flag itself is changing, log the state change
10264 * going both ways, before setting up the user-space log arrays,
10265 * so that this is only logged in the kernel.
10267 if (result
!= newUserLogFilter
) {
10268 OSKextLog(/* kext */ NULL
,
10269 kOSKextLogDebugLevel
|
10270 kOSKextLogGeneralFlag
,
10271 "User-space log flags changed from 0x%x to 0x%x.",
10272 result
, newUserLogFilter
);
10275 OSKextLog(/* kext */ NULL
,
10276 kOSKextLogErrorLevel
|
10277 kOSKextLogGeneralFlag
,
10278 "Failed to allocate user-space log message arrays.");
10284 /*********************************************************************
10285 * Do not call any function that takes sKextLock here!
10286 *********************************************************************/
10289 OSKext::clearUserSpaceLogFilter(void)
10291 OSArray
* result
= NULL
;
10292 OSKextLogSpec oldLogFilter
;
10293 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
10295 /* Do not call any function that takes sKextLoggingLock during
10296 * this critical block. That means do logging after.
10298 IOLockLock(sKextLoggingLock
);
10300 result
= OSArray::withCapacity(2);
10302 result
->setObject(sUserSpaceLogSpecArray
);
10303 result
->setObject(sUserSpaceLogMessageArray
);
10305 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10306 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10308 oldLogFilter
= sUserSpaceKextLogFilter
;
10309 sUserSpaceKextLogFilter
= newLogFilter
;
10311 IOLockUnlock(sKextLoggingLock
);
10313 /* If the config flag itself is changing, log the state change
10314 * going both ways, after tearing down the user-space log
10315 * arrays, so this is only logged within the kernel.
10317 if (oldLogFilter
!= newLogFilter
) {
10318 OSKextLog(/* kext */ NULL
,
10319 kOSKextLogDebugLevel
|
10320 kOSKextLogGeneralFlag
,
10321 "User-space log flags changed from 0x%x to 0x%x.",
10322 oldLogFilter
, newLogFilter
);
10329 /*********************************************************************
10330 * Do not call any function that takes sKextLock here!
10331 *********************************************************************/
10334 OSKext::getUserSpaceLogFilter(void)
10336 OSKextLogSpec result
;
10338 IOLockLock(sKextLoggingLock
);
10339 result
= sUserSpaceKextLogFilter
;
10340 IOLockUnlock(sKextLoggingLock
);
10345 /*********************************************************************
10346 * This function is called by OSMetaClass during kernel C++ setup.
10347 * Be careful what you access here; assume only OSKext::initialize()
10350 * Do not call any function that takes sKextLock here!
10351 *********************************************************************/
10352 #define VTRESET "\033[0m"
10354 #define VTBOLD "\033[1m"
10355 #define VTUNDER "\033[4m"
10357 #define VTRED "\033[31m"
10358 #define VTGREEN "\033[32m"
10359 #define VTYELLOW "\033[33m"
10360 #define VTBLUE "\033[34m"
10361 #define VTMAGENTA "\033[35m"
10362 #define VTCYAN "\033[36m"
10364 inline const char * colorForFlags(OSKextLogSpec flags
)
10366 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
10368 switch (logLevel
) {
10369 case kOSKextLogErrorLevel
:
10370 return VTRED VTBOLD
;
10371 case kOSKextLogWarningLevel
:
10373 case kOSKextLogBasicLevel
:
10374 return VTYELLOW VTUNDER
;
10375 case kOSKextLogProgressLevel
:
10377 case kOSKextLogStepLevel
:
10379 case kOSKextLogDetailLevel
:
10381 case kOSKextLogDebugLevel
:
10384 return ""; // white
10388 inline bool logSpecMatch(
10389 OSKextLogSpec msgLogSpec
,
10390 OSKextLogSpec logFilter
)
10392 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
10393 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
10394 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
10396 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
10397 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
10398 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
10400 /* Explicit messages always get logged.
10402 if (msgLevel
== kOSKextLogExplicitLevel
) {
10406 /* Warnings and errors are logged regardless of the flags.
10408 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
10412 /* A verbose message that isn't for a logging-enabled kext and isn't global
10413 * does *not* get logged.
10415 if (!msgKextGlobal
&& !filterKextGlobal
) {
10419 /* Warnings and errors are logged regardless of the flags.
10420 * All other messages must fit the flags and
10421 * have a level at or below the filter.
10424 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
10435 OSKextLogSpec msgLogSpec
,
10436 const char * format
, ...)
10440 va_start(argList
, format
);
10441 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
10448 OSKextLogSpec msgLogSpec
,
10449 const char * format
,
10450 va_list srcArgList
)
10452 extern int disableConsoleOutput
;
10454 bool logForKernel
= false;
10455 bool logForUser
= false;
10457 char stackBuffer
[120];
10458 uint32_t length
= 0;
10459 char * allocBuffer
= NULL
; // must kfree
10460 OSNumber
* logSpecNum
= NULL
; // must release
10461 OSString
* logString
= NULL
; // must release
10462 char * buffer
= stackBuffer
; // do not free
10464 IOLockLock(sKextLoggingLock
);
10466 /* Set the kext/global bit in the message spec if we have no
10467 * kext or if the kext requests logging.
10469 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
10470 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
10473 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
10474 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10475 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
10478 if (! (logForKernel
|| logForUser
) ) {
10482 /* No goto from here until past va_end()!
10484 va_copy(argList
, srcArgList
);
10485 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
10488 if (length
+ 1 >= sizeof(stackBuffer
)) {
10489 allocBuffer
= (char *)kalloc_tag((length
+ 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT
);
10490 if (!allocBuffer
) {
10494 /* No goto from here until past va_end()!
10496 va_copy(argList
, srcArgList
);
10497 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
10500 buffer
= allocBuffer
;
10503 /* If user space wants the log message, queue it up.
10505 if (logForUser
&& sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10506 logSpecNum
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
));
10507 logString
= OSString::withCString(buffer
);
10508 if (logSpecNum
&& logString
) {
10509 sUserSpaceLogSpecArray
->setObject(logSpecNum
);
10510 sUserSpaceLogMessageArray
->setObject(logString
);
10514 /* Always log messages from the kernel according to the kernel's
10517 if (logForKernel
) {
10519 /* If we are in console mode and have a custom log filter,
10520 * colorize the log message.
10522 if (!disableConsoleOutput
&& sBootArgLogFilterFound
) {
10523 const char * color
= ""; // do not free
10524 color
= colorForFlags(msgLogSpec
);
10525 printf("%s%s%s\n", colorForFlags(msgLogSpec
),
10526 buffer
, color
[0] ? VTRESET
: "");
10528 printf("%s\n", buffer
);
10533 IOLockUnlock(sKextLoggingLock
);
10536 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
10538 OSSafeReleaseNULL(logString
);
10539 OSSafeReleaseNULL(logSpecNum
);
10543 #if KASLR_IOREG_DEBUG
10545 #define IOLOG_INDENT( the_indention ) \
10548 for ( i = 0; i < (the_indention); i++ ) { \
10553 extern vm_offset_t vm_kernel_stext
;
10554 extern vm_offset_t vm_kernel_etext
;
10555 extern mach_vm_offset_t kext_alloc_base
;
10556 extern mach_vm_offset_t kext_alloc_max
;
10558 bool ScanForAddrInObject(OSObject
* theObject
,
10561 bool ScanForAddrInObject(OSObject
* theObject
,
10564 const OSMetaClass
* myTypeID
;
10565 OSCollectionIterator
* myIter
;
10567 OSObject
* myValue
;
10568 bool myResult
= false;
10570 if ( theObject
== NULL
) {
10571 IOLog("%s: theObject is NULL \n",
10576 myTypeID
= OSTypeIDInst(theObject
);
10578 if ( myTypeID
== OSTypeID(OSDictionary
) ) {
10579 OSDictionary
* myDictionary
;
10581 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
10582 myIter
= OSCollectionIterator::withCollection( myDictionary
);
10583 if ( myIter
== NULL
)
10587 while ( (myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject())) ) {
10590 myValue
= myDictionary
->getObject(myKey
);
10591 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10592 if (myTempResult
) {
10593 // if we ever get a true result return true
10595 IOLOG_INDENT(indent
);
10596 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
10601 else if ( myTypeID
== OSTypeID(OSArray
) ) {
10604 myArray
= OSDynamicCast(OSArray
, theObject
);
10605 myIter
= OSCollectionIterator::withCollection(myArray
);
10606 if ( myIter
== NULL
)
10610 while ( (myValue
= myIter
->getNextObject()) ) {
10612 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10613 if (myTempResult
) {
10614 // if we ever get a true result return true
10616 IOLOG_INDENT(indent
);
10617 IOLog("OSArray: \n");
10622 else if ( myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
) ) {
10624 // should we look for addresses in strings?
10626 else if ( myTypeID
== OSTypeID(OSData
) ) {
10629 unsigned int myLen
;
10630 OSData
* myDataObj
;
10632 myDataObj
= OSDynamicCast(OSData
, theObject
);
10633 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
10634 myLen
= myDataObj
->getLength();
10636 if (myPtrPtr
&& myLen
&& myLen
> 7) {
10638 int myPtrCount
= (myLen
/ sizeof(void *));
10640 for (i
= 0; i
< myPtrCount
; i
++) {
10641 UInt64 numberValue
= (UInt64
) *(myPtrPtr
);
10643 if ( kext_alloc_max
!= 0 &&
10644 numberValue
>= kext_alloc_base
&&
10645 numberValue
< kext_alloc_max
) {
10647 OSKext
* myKext
= NULL
; // must release (looked up)
10648 // IOLog("found OSData %p in kext map %p to %p \n",
10650 // (void *) kext_alloc_base,
10651 // (void *) kext_alloc_max);
10653 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) *(myPtrPtr
) );
10655 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
10657 myKext
->getIdentifierCString());
10662 if ( vm_kernel_etext
!= 0 &&
10663 numberValue
>= vm_kernel_stext
&&
10664 numberValue
< vm_kernel_etext
) {
10665 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
10667 (void *) vm_kernel_stext
,
10668 (void *) vm_kernel_etext
);
10675 else if ( myTypeID
== OSTypeID(OSBoolean
) ) {
10677 // do nothing here...
10679 else if ( myTypeID
== OSTypeID(OSNumber
) ) {
10681 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
10683 UInt64 numberValue
= number
->unsigned64BitValue();
10685 if ( kext_alloc_max
!= 0 &&
10686 numberValue
>= kext_alloc_base
&&
10687 numberValue
< kext_alloc_max
) {
10689 OSKext
* myKext
= NULL
; // must release (looked up)
10690 IOLog("found OSNumber in kext map %p to %p \n",
10691 (void *) kext_alloc_base
,
10692 (void *) kext_alloc_max
);
10693 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10695 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) numberValue
);
10697 IOLog("found in kext \"%s\" \n",
10698 myKext
->getIdentifierCString());
10704 if ( vm_kernel_etext
!= 0 &&
10705 numberValue
>= vm_kernel_stext
&&
10706 numberValue
< vm_kernel_etext
) {
10707 IOLog("found OSNumber in kernel text segment %p to %p \n",
10708 (void *) vm_kernel_stext
,
10709 (void *) vm_kernel_etext
);
10710 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10716 const OSMetaClass
* myMetaClass
= NULL
;
10718 myMetaClass
= theObject
->getMetaClass();
10719 if ( myMetaClass
) {
10720 IOLog("class %s \n", myMetaClass
->getClassName() );
10723 IOLog("Unknown object \n" );
10730 #endif // KASLR_KEXT_DEBUG
10732 }; /* extern "C" */
10735 #pragma mark Backtrace Dump & kmod_get_info() support
10737 /*********************************************************************
10738 * This function must be safe to call in panic context.
10739 *********************************************************************/
10742 OSKext::printKextsInBacktrace(
10743 vm_offset_t
* addr
,
10745 int (* printf_func
)(const char *fmt
, ...),
10749 addr64_t summary_page
= 0;
10750 addr64_t last_summary_page
= 0;
10751 bool found_kmod
= false;
10755 if (!sKextSummariesLock
) return;
10756 IOLockLock(sKextSummariesLock
);
10759 if (!gLoadedKextSummaries
) {
10760 (*printf_func
)(" can't perform kext scan: no kext summary");
10764 summary_page
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
);
10765 last_summary_page
= round_page(summary_page
+ sLoadedKextSummariesAllocSize
);
10766 for (; summary_page
< last_summary_page
; summary_page
+= PAGE_SIZE
) {
10767 if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) {
10768 (*printf_func
)(" can't perform kext scan: "
10769 "missing kext summary page %p", summary_page
);
10774 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10775 OSKextLoadedKextSummary
* summary
;
10777 summary
= gLoadedKextSummaries
->summaries
+ i
;
10778 if (!summary
->address
) {
10782 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
10787 (*printf_func
)(" Kernel Extensions in backtrace:\n");
10791 printSummary(summary
, printf_func
, doUnslide
);
10796 IOLockUnlock(sKextSummariesLock
);
10802 /*********************************************************************
10803 * This function must be safe to call in panic context.
10804 *********************************************************************/
10807 OSKext::summaryIsInBacktrace(
10808 OSKextLoadedKextSummary
* summary
,
10809 vm_offset_t
* addr
,
10814 for (i
= 0; i
< cnt
; i
++) {
10815 vm_offset_t kscan_addr
= addr
[i
];
10816 if ((kscan_addr
>= summary
->address
) &&
10817 (kscan_addr
< (summary
->address
+ summary
->size
)))
10828 OSKext::kextForAddress(
10831 void *image
= NULL
;
10834 #if !VM_MAPPED_KEXTS
10835 kernel_mach_header_t
*mh
= NULL
;
10836 kernel_segment_command_t
*seg
= NULL
;
10839 if (((vm_offset_t
)(uintptr_t)addr
>= vm_kernel_stext
) &&
10840 ((vm_offset_t
)(uintptr_t)addr
< vm_kernel_etext
)) {
10841 return (void *)&_mh_execute_header
;
10844 if (!sKextSummariesLock
) return image
;
10845 IOLockLock(sKextSummariesLock
);
10847 if (!gLoadedKextSummaries
) {
10851 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10852 OSKextLoadedKextSummary
* summary
;
10854 summary
= gLoadedKextSummaries
->summaries
+ i
;
10855 if (!summary
->address
) {
10859 #if !VM_MAPPED_KEXTS
10860 mh
= (kernel_mach_header_t
*)summary
->address
;
10862 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
10863 if (((uint64_t)addr
>= seg
->vmaddr
) &&
10864 ((uint64_t)addr
< (seg
->vmaddr
+ seg
->vmsize
))) {
10865 image
= (void *)summary
->address
;
10874 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not
10875 * support split kexts, but we also may unmap the kexts, which can
10876 * race with the above codepath (see OSKext::unload). As such,
10877 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
10879 if (((uint64_t)(uintptr_t)addr
>= summary
->address
) &&
10880 ((uint64_t)(uintptr_t)addr
< (summary
->address
+ summary
->size
)))
10882 image
= (void *)(uintptr_t)summary
->address
;
10889 IOLockUnlock(sKextSummariesLock
);
10894 /*********************************************************************
10895 * scan list of loaded kext summaries looking for a load address match and if
10896 * found return the UUID C string. If not found then set empty string.
10897 *********************************************************************/
10898 static void findSummaryUUID(
10900 uuid_string_t uuid
);
10902 static void findSummaryUUID(
10904 uuid_string_t uuid
)
10908 uuid
[0] = 0x00; // default to no UUID
10910 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10911 OSKextLoadedKextSummary
* summary
;
10913 summary
= gLoadedKextSummaries
->summaries
+ i
;
10915 if (summary
->loadTag
== tag_ID
) {
10916 (void) uuid_unparse(summary
->uuid
, uuid
);
10923 /*********************************************************************
10924 * This function must be safe to call in panic context.
10925 *********************************************************************/
10926 void OSKext::printSummary(
10927 OSKextLoadedKextSummary
* summary
,
10928 int (* printf_func
)(const char *fmt
, ...),
10931 kmod_reference_t
* kmod_ref
= NULL
;
10932 uuid_string_t uuid
;
10933 char version
[kOSKextVersionMaxLength
];
10936 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
10937 strlcpy(version
, "unknown version", sizeof(version
));
10939 (void) uuid_unparse(summary
->uuid
, uuid
);
10942 tmpAddr
= VM_KERNEL_UNSLIDE(summary
->address
);
10945 tmpAddr
= summary
->address
;
10947 (*printf_func
)(" %s(%s)[%s]@0x%llx->0x%llx\n",
10948 summary
->name
, version
, uuid
,
10949 tmpAddr
, tmpAddr
+ summary
->size
- 1);
10951 /* print dependency info */
10952 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
10954 kmod_ref
= kmod_ref
->next
) {
10955 kmod_info_t
* rinfo
;
10957 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) {
10958 (*printf_func
)(" kmod dependency scan stopped "
10959 "due to missing dependency page: %p\n",
10960 doUnslide
? (void *)VM_KERNEL_UNSLIDE(kmod_ref
) : kmod_ref
);
10963 rinfo
= kmod_ref
->info
;
10965 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) {
10966 (*printf_func
)(" kmod dependency scan stopped "
10967 "due to missing kmod page: %p\n",
10968 doUnslide
? (void *)VM_KERNEL_UNSLIDE(rinfo
) : rinfo
);
10972 if (!rinfo
->address
) {
10973 continue; // skip fake entries for built-ins
10976 /* locate UUID in gLoadedKextSummaries */
10977 findSummaryUUID(rinfo
->id
, uuid
);
10980 tmpAddr
= VM_KERNEL_UNSLIDE(rinfo
->address
);
10983 tmpAddr
= rinfo
->address
;
10985 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
10986 rinfo
->name
, rinfo
->version
, uuid
, tmpAddr
);
10992 /*******************************************************************************
10993 * substitute() looks at an input string (a pointer within a larger buffer)
10994 * for a match to a substring, and on match it writes the marker & substitution
10995 * character to an output string, updating the scan (from) and
10996 * output (to) indexes as appropriate.
10997 *******************************************************************************/
10998 static int substitute(
10999 const char * scan_string
,
11001 uint32_t * to_index
,
11002 uint32_t * from_index
,
11003 const char * substring
,
11005 char substitution
);
11007 /* string_out must be at least KMOD_MAX_NAME bytes.
11011 const char * scan_string
,
11013 uint32_t * to_index
,
11014 uint32_t * from_index
,
11015 const char * substring
,
11019 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
11021 /* On a substring match, append the marker (if there is one) and then
11022 * the substitution character, updating the output (to) index accordingly.
11023 * Then update the input (from) length by the length of the substring
11024 * that got replaced.
11026 if (!strncmp(scan_string
, substring
, substring_length
)) {
11028 string_out
[(*to_index
)++] = marker
;
11030 string_out
[(*to_index
)++] = substitution
;
11031 (*from_index
) += substring_length
;
11037 /*******************************************************************************
11038 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
11039 * KMOD_MAX_NAME characters and performs various substitutions of common
11040 * prefixes & substrings as defined by tables in kext_panic_report.h.
11041 *******************************************************************************/
11042 static void compactIdentifier(
11043 const char * identifier
,
11044 char * identifier_out
,
11045 char ** identifier_out_end
);
11049 const char * identifier
,
11050 char * identifier_out
,
11051 char ** identifier_out_end
)
11053 uint32_t from_index
, to_index
;
11054 uint32_t scan_from_index
= 0;
11055 uint32_t scan_to_index
= 0;
11056 subs_entry_t
* subs_entry
= NULL
;
11059 from_index
= to_index
= 0;
11060 identifier_out
[0] = '\0';
11062 /* Replace certain identifier prefixes with shorter @+character sequences.
11063 * Check the return value of substitute() so we only replace the prefix.
11065 for (subs_entry
= &kext_identifier_prefix_subs
[0];
11066 subs_entry
->substring
&& !did_sub
;
11069 did_sub
= substitute(identifier
, identifier_out
,
11070 &scan_to_index
, &scan_from_index
,
11071 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
11075 /* Now scan through the identifier looking for the common substrings
11076 * and replacing them with shorter !+character sequences via substitute().
11078 for (/* see above */;
11079 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
11082 const char * scan_string
= &identifier
[scan_from_index
];
11086 if (scan_from_index
) {
11087 for (subs_entry
= &kext_identifier_substring_subs
[0];
11088 subs_entry
->substring
&& !did_sub
;
11091 did_sub
= substitute(scan_string
, identifier_out
,
11092 &scan_to_index
, &scan_from_index
,
11093 subs_entry
->substring
, '!', subs_entry
->substitute
);
11097 /* If we didn't substitute, copy the input character to the output.
11100 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
11104 identifier_out
[scan_to_index
] = '\0';
11105 if (identifier_out_end
) {
11106 *identifier_out_end
= &identifier_out
[scan_to_index
];
11112 /*******************************************************************************
11113 * assemble_identifier_and_version() adds to a string buffer a compacted
11114 * bundle identifier followed by a version string.
11115 *******************************************************************************/
11117 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
11119 static int assemble_identifier_and_version(
11120 kmod_info_t
* kmod_info
,
11121 char * identPlusVers
,
11125 assemble_identifier_and_version(
11126 kmod_info_t
* kmod_info
,
11127 char * identPlusVers
,
11132 compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
);
11133 result
= strnlen(identPlusVers
, KMOD_MAX_NAME
- 1);
11134 identPlusVers
[result
++] = '\t'; // increment for real char
11135 identPlusVers
[result
] = '\0'; // don't increment for nul char
11136 result
= strlcat(identPlusVers
, kmod_info
->version
, bufSize
);
11137 if (result
>= bufSize
) {
11138 identPlusVers
[bufSize
- 1] = '\0';
11139 result
= bufSize
- 1;
11145 /*******************************************************************************
11146 * Assumes sKextLock is held.
11147 *******************************************************************************/
11150 OSKext::saveLoadedKextPanicListTyped(
11151 const char * prefix
,
11155 uint32_t list_size
)
11158 unsigned int count
, i
;
11160 count
= sLoadedKexts
->getCount();
11167 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
11168 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
11170 uint32_t identPlusVersLength
;
11172 char identPlusVers
[2*KMOD_MAX_NAME
];
11175 printf("OSKext::saveLoadedKextPanicListTyped - "
11176 "NULL kext in loaded kext list; continuing\n");
11181 printf("OSKext::saveLoadedKextPanicListTyped - "
11182 "Kext type cast failed in loaded kext list; continuing\n");
11186 /* Skip all built-in kexts.
11188 if (theKext
->isKernelComponent()) {
11192 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
11194 /* Filter for kmod name (bundle identifier).
11196 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
11197 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
11201 /* Filter for libraries (kexts that have a compatible version).
11203 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
11204 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
11210 !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) {
11212 printf("kext scan stopped due to missing kmod_info page: %p\n",
11217 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
11219 sizeof(identPlusVers
));
11220 if (!identPlusVersLength
) {
11221 printf("error saving loaded kext info\n");
11225 /* make sure everything fits and we null terminate.
11227 tempLen
= strlcat(paniclist
, identPlusVers
, list_size
);
11228 if (tempLen
>= list_size
) {
11229 // panic list is full, keep it and null terminate
11230 paniclist
[list_size
- 1] = 0x00;
11234 tempLen
= strlcat(paniclist
, "\n", list_size
);
11235 if (tempLen
>= list_size
) {
11236 // panic list is full, keep it and null terminate
11237 paniclist
[list_size
- 1] = 0x00;
11249 /*********************************************************************
11250 *********************************************************************/
11253 OSKext::saveLoadedKextPanicList(void)
11255 char * newlist
= NULL
;
11256 uint32_t newlist_size
= 0;
11258 newlist_size
= KEXT_PANICLIST_SIZE
;
11259 newlist
= (char *)kalloc_tag(newlist_size
, VM_KERN_MEMORY_OSKEXT
);
11262 OSKextLog(/* kext */ NULL
,
11263 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
11264 "Couldn't allocate kext panic log buffer.");
11270 // non-"com.apple." kexts
11271 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
11272 /* libs? */ -1, newlist
, newlist_size
) != 0) {
11276 // "com.apple." nonlibrary kexts
11277 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11278 /* libs? */ 0, newlist
, newlist_size
) != 0) {
11282 // "com.apple." library kexts
11283 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11284 /* libs? */ 1, newlist
, newlist_size
) != 0) {
11289 if (loaded_kext_paniclist
) {
11290 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
11292 loaded_kext_paniclist
= newlist
;
11294 loaded_kext_paniclist_size
= newlist_size
;
11298 kfree(newlist
, newlist_size
);
11303 /*********************************************************************
11304 * Assumes sKextLock is held.
11305 *********************************************************************/
11307 OSKext::savePanicString(bool isLoading
)
11312 return; // do not goto finish here b/c of lock
11315 len
= assemble_identifier_and_version( kmod_info
,
11316 (isLoading
) ? last_loaded_str_buf
: last_unloaded_str_buf
,
11317 (isLoading
) ? sizeof(last_loaded_str_buf
) : sizeof(last_unloaded_str_buf
) );
11319 printf("error saving unloaded kext info\n");
11324 last_loaded_strlen
= len
;
11325 last_loaded_address
= (void *)kmod_info
->address
;
11326 last_loaded_size
= kmod_info
->size
;
11327 clock_get_uptime(&last_loaded_timestamp
);
11329 last_unloaded_strlen
= len
;
11330 last_unloaded_address
= (void *)kmod_info
->address
;
11331 last_unloaded_size
= kmod_info
->size
;
11332 clock_get_uptime(&last_unloaded_timestamp
);
11339 /*********************************************************************
11340 *********************************************************************/
11343 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
11345 if (last_loaded_strlen
) {
11346 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
11347 AbsoluteTime_to_scalar(&last_loaded_timestamp
),
11348 last_loaded_strlen
, last_loaded_str_buf
,
11349 last_loaded_address
, last_loaded_size
);
11352 if (last_unloaded_strlen
) {
11353 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
11354 AbsoluteTime_to_scalar(&last_unloaded_timestamp
),
11355 last_unloaded_strlen
, last_unloaded_str_buf
,
11356 last_unloaded_address
, last_unloaded_size
);
11359 printf_func("loaded kexts:\n");
11360 if (loaded_kext_paniclist
&&
11361 pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) &&
11362 loaded_kext_paniclist
[0]) {
11364 printf_func("%.*s",
11365 strnlen(loaded_kext_paniclist
, loaded_kext_paniclist_size
),
11366 loaded_kext_paniclist
);
11368 printf_func("(none)\n");
11373 /*********************************************************************
11374 * Assumes sKextLock is held.
11375 *********************************************************************/
11378 OSKext::updateLoadedKextSummaries(void)
11380 kern_return_t result
= KERN_FAILURE
;
11381 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
11382 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
11384 vm_map_offset_t start
, end
;
11385 size_t summarySize
= 0;
11390 OSKextActiveAccount
* accountingList
;
11391 OSKextActiveAccount
* prevAccountingList
;
11392 uint32_t idx
, accountingListAlloc
, accountingListCount
, prevAccountingListCount
;
11394 prevAccountingList
= NULL
;
11395 prevAccountingListCount
= 0;
11397 #if DEVELOPMENT || DEBUG
11398 if (IORecursiveLockHaveLock(sKextLock
) == false) {
11399 panic("sKextLock must be held");
11403 IOLockLock(sKextSummariesLock
);
11405 count
= sLoadedKexts
->getCount();
11406 for (i
= 0, maxKexts
= 0; i
< count
; ++i
) {
11407 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11408 maxKexts
+= (aKext
&& aKext
->isExecutable());
11411 if (!maxKexts
) goto finish
;
11412 if (maxKexts
< kOSKextTypicalLoadCount
) maxKexts
= kOSKextTypicalLoadCount
;
11414 /* Calculate the size needed for the new summary headers.
11417 size
= sizeof(*gLoadedKextSummaries
);
11418 size
+= maxKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
11419 size
= round_page(size
);
11421 if (gLoadedKextSummaries
== NULL
|| sLoadedKextSummariesAllocSize
< size
) {
11422 if (gLoadedKextSummaries
) {
11423 kmem_free(kernel_map
, (vm_offset_t
)gLoadedKextSummaries
, sLoadedKextSummariesAllocSize
);
11424 gLoadedKextSummaries
= NULL
;
11425 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11426 sLoadedKextSummariesAllocSize
= 0;
11428 result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&summaryHeaderAlloc
, size
, VM_KERN_MEMORY_OSKEXT
);
11429 if (result
!= KERN_SUCCESS
) goto finish
;
11430 summaryHeader
= summaryHeaderAlloc
;
11431 summarySize
= size
;
11434 summaryHeader
= gLoadedKextSummaries
;
11435 summarySize
= sLoadedKextSummariesAllocSize
;
11437 start
= (vm_map_offset_t
) summaryHeader
;
11438 end
= start
+ summarySize
;
11439 result
= vm_map_protect(kernel_map
,
11444 if (result
!= KERN_SUCCESS
) goto finish
;
11447 /* Populate the summary header.
11450 bzero(summaryHeader
, summarySize
);
11451 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
11452 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
11454 /* Populate each kext summary.
11457 count
= sLoadedKexts
->getCount();
11458 accountingListAlloc
= 0;
11459 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11460 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11461 if (!aKext
|| !aKext
->isExecutable()) {
11465 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
11466 summaryHeader
->numSummaries
++;
11467 accountingListAlloc
++;
11470 accountingList
= IONew(typeof(accountingList
[0]), accountingListAlloc
);
11471 accountingListCount
= 0;
11472 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11473 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11474 if (!aKext
|| !aKext
->isExecutable()) {
11478 OSKextActiveAccount activeAccount
;
11479 aKext
->updateActiveAccount(&activeAccount
);
11480 // order by address
11481 for (idx
= 0; idx
< accountingListCount
; idx
++)
11483 if (activeAccount
.address
< accountingList
[idx
].address
) break;
11485 bcopy(&accountingList
[idx
], &accountingList
[idx
+ 1], (accountingListCount
- idx
) * sizeof(accountingList
[0]));
11486 accountingList
[idx
] = activeAccount
;
11487 accountingListCount
++;
11489 assert(accountingListCount
== accountingListAlloc
);
11490 /* Write protect the buffer and move it into place.
11493 start
= (vm_map_offset_t
) summaryHeader
;
11494 end
= start
+ summarySize
;
11496 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_READ
, FALSE
);
11497 if (result
!= KERN_SUCCESS
)
11500 gLoadedKextSummaries
= summaryHeader
;
11501 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11502 sLoadedKextSummariesAllocSize
= summarySize
;
11503 summaryHeaderAlloc
= NULL
;
11505 /* Call the magic breakpoint function through a static function pointer so
11506 * the compiler can't optimize the function away.
11508 if (sLoadedKextSummariesUpdated
) (*sLoadedKextSummariesUpdated
)();
11510 IOSimpleLockLock(sKextAccountsLock
);
11511 prevAccountingList
= sKextAccounts
;
11512 prevAccountingListCount
= sKextAccountsCount
;
11513 sKextAccounts
= accountingList
;
11514 sKextAccountsCount
= accountingListCount
;
11515 IOSimpleLockUnlock(sKextAccountsLock
);
11518 IOLockUnlock(sKextSummariesLock
);
11520 /* If we had to allocate a new buffer but failed to generate the summaries,
11523 if (summaryHeaderAlloc
) {
11524 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
11526 if (prevAccountingList
) {
11527 IODelete(prevAccountingList
, typeof(accountingList
[0]), prevAccountingListCount
);
11533 /*********************************************************************
11534 *********************************************************************/
11536 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
11540 strlcpy(summary
->name
, getIdentifierCString(),
11541 sizeof(summary
->name
));
11545 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
11546 OSSafeReleaseNULL(uuid
);
11549 summary
->address
= kmod_info
->address
;
11550 summary
->size
= kmod_info
->size
;
11551 summary
->version
= getVersion();
11552 summary
->loadTag
= kmod_info
->id
;
11553 summary
->flags
= 0;
11554 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
11559 /*********************************************************************
11560 *********************************************************************/
11563 OSKext::updateActiveAccount(OSKextActiveAccount
*accountp
)
11565 kernel_mach_header_t
*hdr
= NULL
;
11566 kernel_segment_command_t
*seg
= NULL
;
11568 hdr
= (kernel_mach_header_t
*)kmod_info
->address
;
11570 if (getcommandfromheader(hdr
, LC_SEGMENT_SPLIT_INFO
)) {
11571 /* If this kext supports split segments, use the first
11572 * executable segment as the range for instructions
11573 * (and thus for backtracing.
11575 for (seg
= firstsegfromheader(hdr
); seg
!= NULL
; seg
= nextsegfromheader(hdr
, seg
)) {
11576 if (seg
->initprot
& VM_PROT_EXECUTE
) {
11582 bzero(accountp
, sizeof(*accountp
));
11584 accountp
->address
= seg
->vmaddr
;
11585 if (accountp
->address
) {
11586 accountp
->address_end
= seg
->vmaddr
+ seg
->vmsize
;
11589 /* For non-split kexts and for kexts without executable
11590 * segments, just use the kmod_info range (as the kext
11591 * is either all in one range or should not show up in
11592 * instruction backtraces).
11594 accountp
->address
= kmod_info
->address
;
11595 if (accountp
->address
) {
11596 accountp
->address_end
= kmod_info
->address
+ kmod_info
->size
;
11599 accountp
->account
= this->account
;
11602 extern "C" const vm_allocation_site_t
*
11603 OSKextGetAllocationSiteForCaller(uintptr_t address
)
11605 OSKextActiveAccount
* active
;
11606 vm_allocation_site_t
* site
;
11610 IOSimpleLockLock(sKextAccountsLock
);
11612 // bsearch sKextAccounts list
11613 for (baseIdx
= 0, lim
= sKextAccountsCount
; lim
; lim
>>= 1)
11615 active
= &sKextAccounts
[baseIdx
+ (lim
>> 1)];
11616 if ((address
>= active
->address
) && (address
< active
->address_end
))
11618 site
= &active
->account
->site
;
11619 if (!site
->tag
) vm_tag_alloc_locked(site
);
11622 else if (address
> active
->address
)
11625 baseIdx
+= (lim
>> 1) + 1;
11630 IOSimpleLockUnlock(sKextAccountsLock
);
11635 extern "C" uint32_t
11636 OSKextGetKmodIDForSite(vm_allocation_site_t
* site
, char * name
, vm_size_t namelen
)
11638 OSKextAccount
* account
= (typeof(account
)) site
;
11639 const char * kname
;
11643 if (account
->kext
) kname
= account
->kext
->getIdentifierCString();
11645 strlcpy(name
, kname
, namelen
);
11648 return (account
->loadTag
);
11652 OSKextFreeSite(vm_allocation_site_t
* site
)
11654 OSKextAccount
* freeAccount
= (typeof(freeAccount
)) site
;
11655 IODelete(freeAccount
, OSKextAccount
, 1);
11658 /*********************************************************************
11659 *********************************************************************/
11661 #if CONFIG_KEC_FIPS
11664 #pragma mark Kernel External Components for FIPS compliance
11667 /*********************************************************************
11668 * Kernel External Components for FIPS compliance (KEC_FIPS)
11669 *********************************************************************/
11671 GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
)
11673 AppleTEXTHash_t my_ath
= {2, 0, NULL
};
11674 AppleTEXTHash_t
* my_athp
= NULL
; // do not release
11675 OSData
* segmentHash
= NULL
; // do not release
11677 if (theKext
== NULL
|| theInfoDict
== NULL
) {
11681 // Get the part of the plist associate with kAppleTextHashesKey and let
11682 // the crypto library do further parsing (slice/architecture)
11683 segmentHash
= OSDynamicCast(OSData
, theInfoDict
->getObject(kAppleTextHashesKey
));
11684 // Support for ATH v1 while rolling out ATH v2 without revision locking submissions
11685 // Remove this when v2 PLIST are supported
11686 if (segmentHash
== NULL
) {
11687 // If this fails, we may be dealing with a v1 PLIST
11688 OSDictionary
* textHashDict
= NULL
; // do not release
11689 textHashDict
= OSDynamicCast(OSDictionary
, theInfoDict
->getObject(kAppleTextHashesKey
));
11690 if (textHashDict
== NULL
) {
11693 my_ath
.ath_version
=1;
11694 segmentHash
= OSDynamicCast(OSData
,textHashDict
->getObject(ARCHNAME
));
11695 } // end of v2 rollout
11697 if (segmentHash
== NULL
) {
11701 // KEC_FIPS type kexts never unload so we don't have to clean up our
11703 if (kmem_alloc(kernel_map
, (vm_offset_t
*) &my_athp
,
11704 sizeof(AppleTEXTHash_t
), VM_KERN_MEMORY_OSKEXT
) != KERN_SUCCESS
) {
11708 memcpy(my_athp
, &my_ath
, sizeof(my_ath
));
11709 my_athp
->ath_length
= segmentHash
->getLength();
11710 if (my_athp
->ath_length
> 0) {
11711 my_athp
->ath_hash
= (void *)segmentHash
->getBytesNoCopy();
11716 kOSKextLogErrorLevel
|
11717 kOSKextLogGeneralFlag
,
11718 "Kext %s ath_version %d ath_length %d ath_hash %p",
11719 theKext
->getIdentifierCString(),
11720 my_athp
->ath_version
,
11721 my_athp
->ath_length
,
11722 my_athp
->ath_hash
);
11725 return( (void *) my_athp
);
11728 #endif // CONFIG_KEC_FIPS