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 IORecursiveLockLock(sKextLock
);
4425 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4426 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4429 // xxx - need to find a way to associate this whole func w/the kext
4430 OSKextLog(/* kext */ NULL
,
4431 // xxx - check level
4432 kOSKextLogStepLevel
|
4433 kOSKextLogArchiveFlag
,
4434 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4435 kextIdentifier
->getCStringNoCopy());
4438 IORecursiveLockUnlock(sKextLock
);
4443 OSKextLog(/* kext */ NULL
,
4444 kOSKextLogErrorLevel
|
4445 kOSKextLogArchiveFlag
,
4446 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4447 kextIdentifier
->getCStringNoCopy());
4449 OSSafeReleaseNULL(kextIdentifierSymbol
);
4453 /*********************************************************************
4454 *********************************************************************/
4457 OSKextExcludeLevel startOpt
,
4458 OSKextExcludeLevel startMatchingOpt
,
4459 OSArray
* personalityNames
)
4461 OSReturn result
= kOSReturnError
;
4462 kern_return_t kxldResult
;
4463 OSKextExcludeLevel dependenciesStartOpt
= startOpt
;
4464 OSKextExcludeLevel dependenciesStartMatchingOpt
= startMatchingOpt
;
4465 unsigned int i
, count
;
4466 Boolean alreadyLoaded
= false;
4467 OSKext
* lastLoadedKext
= NULL
;
4469 if (isInExcludeList()) {
4471 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
|
4473 "Kext %s is in exclude list, not loadable",
4474 getIdentifierCString());
4476 result
= kOSKextReturnNotLoadable
;
4481 alreadyLoaded
= true;
4482 result
= kOSReturnSuccess
;
4485 kOSKextLogDebugLevel
|
4486 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4487 "Kext %s is already loaded.",
4488 getIdentifierCString());
4493 if (current_task() != kernel_task
) {
4494 int macCheckResult
= 0;
4495 kauth_cred_t cred
= NULL
;
4497 cred
= kauth_cred_get_with_ref();
4498 macCheckResult
= mac_kext_check_load(cred
, getIdentifierCString());
4499 kauth_cred_unref(&cred
);
4501 if (macCheckResult
!= 0) {
4502 result
= kOSReturnError
;
4504 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4505 "Failed to load kext %s (MAC policy error 0x%x).",
4506 getIdentifierCString(), macCheckResult
);
4512 if (!sLoadEnabled
) {
4514 kOSKextLogErrorLevel
|
4516 "Kext loading is disabled (attempt to load kext %s).",
4517 getIdentifierCString());
4518 result
= kOSKextReturnDisabled
;
4522 /* If we've pushed the next available load tag to the invalid value,
4523 * we can't load any more kexts.
4525 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4527 kOSKextLogErrorLevel
|
4529 "Can't load kext %s - no more load tags to assign.",
4530 getIdentifierCString());
4531 result
= kOSKextReturnNoResources
;
4535 /* This is a bit of a hack, because we shouldn't be handling
4536 * personalities within the load function.
4538 if (!declaresExecutable()) {
4539 result
= kOSReturnSuccess
;
4543 /* Are we in safe boot?
4545 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4547 kOSKextLogErrorLevel
|
4549 "Can't load kext %s - not loadable during safe boot.",
4550 getIdentifierCString());
4551 result
= kOSKextReturnBootLevel
;
4556 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4558 getIdentifierCString());
4560 if (!sKxldContext
) {
4561 kxldResult
= kxld_create_context(&sKxldContext
, &kern_allocate
,
4562 &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,
4563 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
4566 kOSKextLogErrorLevel
|
4567 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4568 "Can't load kext %s - failed to create link context.",
4569 getIdentifierCString());
4570 result
= kOSKextReturnNoMemory
;
4575 /* We only need to resolve dependencies once for the whole graph, but
4576 * resolveDependencies will just return if there's no work to do, so it's
4577 * safe to call it more than once.
4579 if (!resolveDependencies()) {
4580 // xxx - check resolveDependencies() for log msg
4582 kOSKextLogErrorLevel
|
4583 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4584 "Can't load kext %s - failed to resolve library dependencies.",
4585 getIdentifierCString());
4586 result
= kOSKextReturnDependencies
;
4590 /* If we are excluding just the kext being loaded now (and not its
4591 * dependencies), drop the exclusion level to none so dependencies
4592 * start and/or add their personalities.
4594 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4595 dependenciesStartOpt
= kOSKextExcludeNone
;
4598 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4599 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4602 /* Load the dependencies, recursively.
4604 count
= getNumDependencies();
4605 for (i
= 0; i
< count
; i
++) {
4606 OSKext
* dependency
= OSDynamicCast(OSKext
,
4607 dependencies
->getObject(i
));
4608 if (dependency
== NULL
) {
4610 kOSKextLogErrorLevel
|
4611 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4612 "Internal error loading kext %s; dependency disappeared.",
4613 getIdentifierCString());
4614 result
= kOSKextReturnInternalError
;
4618 /* Dependencies must be started accorting to the opt,
4619 * but not given the personality names of the main kext.
4621 result
= dependency
->load(dependenciesStartOpt
,
4622 dependenciesStartMatchingOpt
,
4623 /* personalityNames */ NULL
);
4624 if (result
!= KERN_SUCCESS
) {
4626 kOSKextLogErrorLevel
|
4627 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4628 "Dependency %s of kext %s failed to load.",
4629 dependency
->getIdentifierCString(),
4630 getIdentifierCString());
4632 OSKext::removeKext(dependency
,
4633 /* terminateService/removePersonalities */ true);
4634 result
= kOSKextReturnDependencyLoadError
;
4640 result
= loadExecutable();
4641 if (result
!= KERN_SUCCESS
) {
4645 pendingPgoHead
.next
= &pendingPgoHead
;
4646 pendingPgoHead
.prev
= &pendingPgoHead
;
4648 uuid_generate(instance_uuid
);
4649 account
= IONew(OSKextAccount
, 1);
4651 result
= KERN_MEMORY_ERROR
;
4654 bzero(account
, sizeof(*account
));
4655 account
->loadTag
= kmod_info
->id
;
4656 account
->site
.flags
= VM_TAG_KMOD
;
4657 account
->kext
= this;
4659 flags
.loaded
= true;
4661 /* Add the kext to the list of loaded kexts and update the kmod_info
4662 * struct to point to that of the last loaded kext (which is the way
4663 * it's always been done, though I'd rather do them in order now).
4665 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
4666 sLoadedKexts
->setObject(this);
4668 /* Keep the kernel itself out of the kmod list.
4670 if (lastLoadedKext
->isKernel()) {
4671 lastLoadedKext
= NULL
;
4674 if (lastLoadedKext
) {
4675 kmod_info
->next
= lastLoadedKext
->kmod_info
;
4678 notifyKextLoadObservers(this, kmod_info
);
4680 /* Make the global kmod list point at the just-loaded kext. Note that the
4681 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4682 * although we do report it in kextstat these days by using the newer
4683 * OSArray of loaded kexts, which does contain it.
4685 * (The OSKext object representing the kernel doesn't even have a kmod_info
4686 * struct, though I suppose we could stick a pointer to it from the
4687 * static struct in OSRuntime.cpp.)
4691 /* Save the list of loaded kexts in case we panic.
4693 OSKext::saveLoadedKextPanicList();
4695 if (isExecutable()) {
4696 OSKext::updateLoadedKextSummaries();
4697 savePanicString(/* isLoading */ true);
4700 registerWithDTrace();
4702 jettisonLinkeditSegment();
4703 #endif /* CONFIG_DTRACE */
4705 #if !VM_MAPPED_KEXTS
4706 /* If there is a page (or more) worth of padding after the end
4707 * of the last data section but before the end of the data segment
4708 * then free it in the same manner the LinkeditSegment is freed
4710 jettisonDATASegmentPadding();
4715 if (isExecutable() && !flags
.started
) {
4716 if (startOpt
== kOSKextExcludeNone
) {
4718 if (result
!= kOSReturnSuccess
) {
4720 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4721 "Kext %s start failed (result 0x%x).",
4722 getIdentifierCString(), result
);
4723 result
= kOSKextReturnStartStopError
;
4728 /* If not excluding matching, send the personalities to the kernel.
4729 * This never affects the result of the load operation.
4730 * This is a bit of a hack, because we shouldn't be handling
4731 * personalities within the load function.
4733 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
4734 result
= sendPersonalitiesToCatalog(true, personalityNames
);
4739 /* More hack! If the kext doesn't declare an executable, even if we
4740 * "loaded" it, we have to remove any personalities naming it, or we'll
4741 * never see the registry go quiet. Errors here do not count for the
4742 * load operation itself.
4744 * Note that in every other regard it's perfectly ok for a kext to
4745 * not declare an executable and serve only as a package for personalities
4746 * naming another kext, so we do have to allow such kexts to be "loaded"
4747 * so that those other personalities get added & matched.
4749 if (!declaresExecutable()) {
4751 kOSKextLogStepLevel
| kOSKextLogLoadFlag
,
4752 "Kext %s has no executable; removing any personalities naming it.",
4753 getIdentifierCString());
4754 removePersonalitiesFromCatalog();
4757 if (result
!= kOSReturnSuccess
) {
4759 kOSKextLogErrorLevel
|
4761 "Kext %s failed to load (0x%x).",
4762 getIdentifierCString(), (int)result
);
4763 } else if (!alreadyLoaded
) {
4765 kOSKextLogProgressLevel
|
4768 getIdentifierCString());
4770 queueKextNotification(kKextRequestPredicateLoadNotification
,
4771 OSDynamicCast(OSString
, bundleID
));
4776 /*********************************************************************
4778 *********************************************************************/
4779 static char * strdup(const char * string
)
4781 char * result
= NULL
;
4788 size
= 1 + strlen(string
);
4789 result
= (char *)kalloc_tag(size
, VM_KERN_MEMORY_OSKEXT
);
4794 memcpy(result
, string
, size
);
4800 /*********************************************************************
4802 *********************************************************************/
4805 OSKext::lookupSection(const char *segname
, const char *secname
)
4807 kernel_section_t
* found_section
= NULL
;
4808 kernel_mach_header_t
* mh
= NULL
;
4809 kernel_segment_command_t
* seg
= NULL
;
4810 kernel_section_t
* sec
= NULL
;
4812 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4814 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4816 if (0 != strcmp(seg
->segname
, segname
)) {
4820 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4822 if (0 == strcmp(sec
->sectname
, secname
)) {
4823 found_section
= sec
;
4830 return found_section
;
4833 /*********************************************************************
4835 *********************************************************************/
4838 OSKext::slidePrelinkedExecutable(bool doCoalesedSlides
)
4840 OSReturn result
= kOSKextReturnBadData
;
4841 kernel_mach_header_t
* mh
= NULL
;
4842 kernel_segment_command_t
* seg
= NULL
;
4843 kernel_segment_command_t
* linkeditSeg
= NULL
;
4844 kernel_section_t
* sec
= NULL
;
4845 char * linkeditBase
= NULL
;
4846 bool haveLinkeditBase
= false;
4847 char * relocBase
= NULL
;
4848 bool haveRelocBase
= false;
4849 struct dysymtab_command
* dysymtab
= NULL
;
4850 struct linkedit_data_command
* segmentSplitInfo
= NULL
;
4851 struct symtab_command
* symtab
= NULL
;
4852 kernel_nlist_t
* sym
= NULL
;
4853 struct relocation_info
* reloc
= NULL
;
4856 vm_offset_t new_kextsize
;
4858 if (linkedExecutable
== NULL
|| vm_kernel_slide
== 0) {
4859 result
= kOSReturnSuccess
;
4863 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4864 segmentSplitInfo
= (struct linkedit_data_command
*) getcommandfromheader(mh
, LC_SEGMENT_SPLIT_INFO
);
4866 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4870 seg
->vmaddr
+= vm_kernel_slide
;
4872 #if KASLR_KEXT_DEBUG
4873 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
4875 (unsigned long)VM_KERNEL_UNSLIDE(seg
->vmaddr
),
4876 (unsigned long)seg
->vmaddr
);
4879 if (!haveRelocBase
) {
4880 relocBase
= (char *) seg
->vmaddr
;
4881 haveRelocBase
= true;
4883 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
4884 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
4885 haveLinkeditBase
= true;
4888 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4889 sec
->addr
+= vm_kernel_slide
;
4891 #if KASLR_KEXT_DEBUG
4892 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
4894 (unsigned long)VM_KERNEL_UNSLIDE(sec
->addr
),
4895 (unsigned long)sec
->addr
);
4900 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
4902 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
4904 if (symtab
!= NULL
&& doCoalesedSlides
== false) {
4905 /* Some pseudo-kexts have symbol tables without segments.
4907 if (symtab
->nsyms
> 0 && haveLinkeditBase
) {
4908 sym
= (kernel_nlist_t
*) (linkeditBase
+ symtab
->symoff
);
4909 for (i
= 0; i
< symtab
->nsyms
; i
++) {
4910 if (sym
[i
].n_type
& N_STAB
) {
4913 sym
[i
].n_value
+= vm_kernel_slide
;
4915 #if KASLR_KEXT_DEBUG
4916 #define MAX_SYMS_TO_LOG 5
4917 if ( i
< MAX_SYMS_TO_LOG
) {
4918 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
4919 (unsigned long)VM_KERNEL_UNSLIDE(sym
[i
].n_value
),
4920 (unsigned long)sym
[i
].n_value
);
4927 if (dysymtab
!= NULL
&& doCoalesedSlides
== false) {
4928 if (dysymtab
->nextrel
> 0) {
4930 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4932 "Sliding kext %s: External relocations found.",
4933 getIdentifierCString());
4937 if (dysymtab
->nlocrel
> 0) {
4938 if (!haveLinkeditBase
) {
4940 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4942 "Sliding kext %s: No linkedit segment.",
4943 getIdentifierCString());
4947 if (!haveRelocBase
) {
4949 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4952 "Sliding kext %s: No writable segments.",
4954 "Sliding kext %s: No segments.",
4956 getIdentifierCString());
4960 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
4961 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
4963 for (i
= 0; i
< dysymtab
->nlocrel
; i
++) {
4964 if ( reloc
[i
].r_extern
!= 0
4965 || reloc
[i
].r_type
!= 0
4966 || reloc
[i
].r_length
!= (sizeof(void *) == 8 ? 3 : 2)
4969 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4971 "Sliding kext %s: Unexpected relocation found.",
4972 getIdentifierCString());
4975 if (reloc
[i
].r_pcrel
!= 0) {
4978 *((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)) += vm_kernel_slide
;
4980 #if KASLR_KEXT_DEBUG
4981 #define MAX_DYSYMS_TO_LOG 5
4982 if ( i
< MAX_DYSYMS_TO_LOG
) {
4983 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
4984 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
))),
4985 (unsigned long)*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)));
4990 /* We should free these relocations, not just delete the reference to them.
4991 * <rdar://problem/10535549> Free relocations from PIE kexts.
4993 * For now, we do not free LINKEDIT for kexts with split segments.
4995 new_kextsize
= round_page(kmod_info
->size
- reloc_size
);
4996 if (((kmod_info
->size
- new_kextsize
) > PAGE_SIZE
) && (!segmentSplitInfo
)) {
4997 vm_offset_t endofkext
= kmod_info
->address
+ kmod_info
->size
;
4998 vm_offset_t new_endofkext
= kmod_info
->address
+ new_kextsize
;
4999 vm_offset_t endofrelocInfo
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
);
5000 int bytes_remaining
= endofkext
- endofrelocInfo
;
5001 OSData
* new_osdata
= NULL
;
5003 /* fix up symbol offsets if they are after the dsymtab local relocs */
5005 if (dysymtab
->locreloff
< symtab
->symoff
){
5006 symtab
->symoff
-= reloc_size
;
5008 if (dysymtab
->locreloff
< symtab
->stroff
) {
5009 symtab
->stroff
-= reloc_size
;
5012 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
5013 dysymtab
->extreloff
-= reloc_size
;
5016 /* move data behind reloc info down to new offset */
5017 if (endofrelocInfo
< endofkext
) {
5018 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
5021 /* Create a new OSData for the smaller kext object and reflect
5022 * new linkedit segment size.
5024 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
5025 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
5027 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
5029 /* Fix up kmod info and linkedExecutable.
5031 kmod_info
->size
= new_kextsize
;
5033 new_osdata
->setDeallocFunction(osdata_kext_free
);
5035 new_osdata
->setDeallocFunction(osdata_phys_free
);
5037 linkedExecutable
->setDeallocFunction(NULL
);
5038 linkedExecutable
->release();
5039 linkedExecutable
= new_osdata
;
5042 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
5044 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
5048 dysymtab
->nlocrel
= 0;
5049 dysymtab
->locreloff
= 0;
5053 result
= kOSReturnSuccess
;
5058 /*********************************************************************
5059 * called only by load()
5060 *********************************************************************/
5062 OSKext::loadExecutable()
5064 OSReturn result
= kOSReturnError
;
5065 kern_return_t kxldResult
;
5066 KXLDDependency
* kxlddeps
= NULL
; // must kfree
5067 uint32_t num_kxlddeps
= 0;
5068 OSArray
* linkDependencies
= NULL
; // must release
5069 uint32_t numDirectDependencies
= 0;
5070 uint32_t num_kmod_refs
= 0;
5071 struct mach_header
** kxldHeaderPtr
= NULL
; // do not free
5072 struct mach_header
* kxld_header
= NULL
; // xxx - need to free here?
5073 OSData
* theExecutable
= NULL
; // do not release
5074 OSString
* versString
= NULL
; // do not release
5075 const char * versCString
= NULL
; // do not free
5076 const char * string
= NULL
; // do not free
5079 /* We need the version string for a variety of bits below.
5081 versString
= OSDynamicCast(OSString
,
5082 getPropertyForHostArch(kCFBundleVersionKey
));
5086 versCString
= versString
->getCStringNoCopy();
5088 if (isKernelComponent()) {
5089 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
5091 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
5093 kOSKextLogErrorLevel
|
5095 "Kernel component %s has incorrect version %s; "
5097 getIdentifierCString(),
5098 versCString
, KERNEL6_VERSION
);
5099 result
= kOSKextReturnInternalError
;
5101 } else if (strcmp(versCString
, osrelease
)) {
5103 kOSKextLogErrorLevel
|
5105 "Kernel component %s has incorrect version %s; "
5107 getIdentifierCString(),
5108 versCString
, osrelease
);
5109 result
= kOSKextReturnInternalError
;
5115 if (isPrelinked()) {
5119 /* <rdar://problem/21444003> all callers must be entitled */
5120 if (FALSE
== IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management")) {
5122 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5123 "Not entitled to link kext '%s'",
5124 getIdentifierCString());
5125 result
= kOSKextReturnNotPrivileged
;
5129 theExecutable
= getExecutable();
5130 if (!theExecutable
) {
5131 if (declaresExecutable()) {
5133 kOSKextLogErrorLevel
|
5135 "Can't load kext %s - executable is missing.",
5136 getIdentifierCString());
5137 result
= kOSKextReturnValidation
;
5143 if (isInterface()) {
5144 OSData
*executableCopy
= OSData::withData(theExecutable
);
5145 setLinkedExecutable(executableCopy
);
5146 executableCopy
->release();
5150 numDirectDependencies
= getNumDependencies();
5152 if (flags
.hasBleedthrough
) {
5153 linkDependencies
= dependencies
;
5154 linkDependencies
->retain();
5156 linkDependencies
= OSArray::withArray(dependencies
);
5157 if (!linkDependencies
) {
5159 kOSKextLogErrorLevel
|
5160 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5161 "Can't allocate link dependencies to load kext %s.",
5162 getIdentifierCString());
5166 for (i
= 0; i
< numDirectDependencies
; ++i
) {
5167 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
5168 dependencies
->getObject(i
));
5169 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
5173 num_kxlddeps
= linkDependencies
->getCount();
5174 if (!num_kxlddeps
) {
5176 kOSKextLogErrorLevel
|
5177 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
5178 "Can't load kext %s - it has no library dependencies.",
5179 getIdentifierCString());
5183 kxlddeps
= (KXLDDependency
*)kalloc_tag(num_kxlddeps
* sizeof(*kxlddeps
), VM_KERN_MEMORY_OSKEXT
);
5186 kOSKextLogErrorLevel
|
5187 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5188 "Can't allocate link context to load kext %s.",
5189 getIdentifierCString());
5192 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
5194 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5195 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
5197 if (dependency
->isInterface()) {
5198 OSKext
*interfaceTargetKext
= NULL
;
5199 OSData
* interfaceTarget
= NULL
;
5201 if (dependency
->isKernelComponent()) {
5202 interfaceTargetKext
= sKernelKext
;
5203 interfaceTarget
= sKernelKext
->linkedExecutable
;
5205 interfaceTargetKext
= OSDynamicCast(OSKext
,
5206 dependency
->dependencies
->getObject(0));
5208 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
5211 if (!interfaceTarget
) {
5216 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5217 * it will be useful to have them in the debugger.
5218 * strdup() failing isn't critical right here so we don't check that.
5220 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
5221 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
5222 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
5224 kxlddeps
[i
].interface
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5225 kxlddeps
[i
].interface_size
= dependency
->linkedExecutable
->getLength();
5226 kxlddeps
[i
].interface_name
= strdup(dependency
->getIdentifierCString());
5228 kxlddeps
[i
].kext
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5229 kxlddeps
[i
].kext_size
= dependency
->linkedExecutable
->getLength();
5230 kxlddeps
[i
].kext_name
= strdup(dependency
->getIdentifierCString());
5233 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
5236 kxldHeaderPtr
= &kxld_header
;
5240 kOSKextLogExplicitLevel
|
5241 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5242 "Kext %s - calling kxld_link_file:\n"
5243 " kxld_context: %p\n"
5244 " executable: %p executable_length: %d\n"
5246 " kxld_dependencies: %p num_dependencies: %d\n"
5247 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5248 getIdentifierCString(), sKxldContext
,
5249 theExecutable
->getBytesNoCopy(), theExecutable
->getLength(),
5250 this, kxlddeps
, num_kxlddeps
,
5251 kxldHeaderPtr
, &kmod_info
);
5254 /* After this call, the linkedExecutable instance variable
5257 kxldResult
= kxld_link_file(sKxldContext
,
5258 (u_char
*)theExecutable
->getBytesNoCopy(),
5259 theExecutable
->getLength(),
5260 getIdentifierCString(), this, kxlddeps
, num_kxlddeps
,
5261 (u_char
**)kxldHeaderPtr
, (kxld_addr_t
*)&kmod_info
);
5263 if (kxldResult
!= KERN_SUCCESS
) {
5264 // xxx - add kxldResult here?
5266 kOSKextLogErrorLevel
|
5268 "Can't load kext %s - link failed.",
5269 getIdentifierCString());
5270 result
= kOSKextReturnLinkError
;
5274 /* We've written data & instructions into kernel memory, so flush the data
5275 * cache and invalidate the instruction cache.
5276 * I/D caches are coherent on x86
5278 #if !defined(__i386__) && !defined(__x86_64__)
5279 flush_dcache(kmod_info
->address
, kmod_info
->size
, false);
5280 invalidate_icache(kmod_info
->address
, kmod_info
->size
, false);
5284 if (isInterface()) {
5286 /* Whip up a fake kmod_info entry for the interface kext.
5288 kmod_info
= (kmod_info_t
*)kalloc_tag(sizeof(kmod_info_t
), VM_KERN_MEMORY_OSKEXT
);
5290 result
= KERN_MEMORY_ERROR
;
5294 /* A pseudokext has almost nothing in its kmod_info struct.
5296 bzero(kmod_info
, sizeof(kmod_info_t
));
5298 kmod_info
->info_version
= KMOD_INFO_VERSION
;
5300 /* An interface kext doesn't have a linkedExecutable, so save a
5301 * copy of the UUID out of the original executable via copyUUID()
5302 * while we still have the original executable.
5304 interfaceUUID
= copyUUID();
5307 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5308 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5310 /* Stamp the bundle ID and version from the OSKext over anything
5311 * resident inside the kmod_info.
5313 string
= getIdentifierCString();
5314 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5316 string
= versCString
;
5317 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5319 /* Add the dependencies' kmod_info structs as kmod_references.
5321 num_kmod_refs
= getNumDependencies();
5322 if (num_kmod_refs
) {
5323 kmod_info
->reference_list
= (kmod_reference_t
*)kalloc_tag(
5324 num_kmod_refs
* sizeof(kmod_reference_t
), VM_KERN_MEMORY_OSKEXT
);
5325 if (!kmod_info
->reference_list
) {
5326 result
= KERN_MEMORY_ERROR
;
5329 bzero(kmod_info
->reference_list
,
5330 num_kmod_refs
* sizeof(kmod_reference_t
));
5331 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5332 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5333 OSKext
* refKext
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
));
5334 ref
->info
= refKext
->kmod_info
;
5335 ref
->info
->reference_count
++;
5337 if (refIndex
+ 1 < num_kmod_refs
) {
5338 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5343 if (!isInterface() && linkedExecutable
) {
5345 kOSKextLogProgressLevel
|
5347 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5349 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5350 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5351 (unsigned)kmod_info
->id
);
5354 /* if prelinked, VM protections are already set */
5355 result
= setVMAttributes(!isPrelinked(), true);
5356 if (result
!= KERN_SUCCESS
) {
5360 result
= kOSReturnSuccess
;
5363 OSSafeReleaseNULL(linkDependencies
);
5365 /* Clear up locally allocated dependency info.
5367 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5370 if (kxlddeps
[i
].kext_name
) {
5371 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5372 kfree(kxlddeps
[i
].kext_name
, size
);
5374 if (kxlddeps
[i
].interface_name
) {
5375 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5376 kfree(kxlddeps
[i
].interface_name
, size
);
5379 if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5381 /* We no longer need the unrelocated executable (which the linker
5382 * has altered anyhow).
5384 setExecutable(NULL
);
5386 if (result
!= kOSReturnSuccess
) {
5388 kOSKextLogErrorLevel
|
5390 "Failed to load executable for kext %s.",
5391 getIdentifierCString());
5393 if (kmod_info
&& kmod_info
->reference_list
) {
5394 kfree(kmod_info
->reference_list
,
5395 num_kmod_refs
* sizeof(kmod_reference_t
));
5397 if (isInterface()) {
5398 kfree(kmod_info
, sizeof(kmod_info_t
));
5401 if (linkedExecutable
) {
5402 linkedExecutable
->release();
5403 linkedExecutable
= NULL
;
5410 /*********************************************************************
5411 * The linkedit segment is used by the kext linker for dependency
5412 * resolution, and by dtrace for probe initialization. We can free it
5413 * for non-library kexts, since no kexts depend on non-library kexts
5414 * by definition, once dtrace has been initialized.
5415 *********************************************************************/
5417 OSKext::jettisonLinkeditSegment(void)
5419 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5420 kernel_segment_command_t
* linkedit
= NULL
;
5422 vm_size_t linkeditsize
, kextsize
;
5423 OSData
* data
= NULL
;
5426 /* We can free symbol tables for all embedded kexts because we don't
5427 * support runtime kext linking.
5429 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5431 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5436 /* Find the linkedit segment. If it's not the last segment, then freeing
5437 * it will fragment the kext into multiple VM regions, which OSKext is not
5438 * designed to handle, so we'll have to skip it.
5440 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5445 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5446 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
))
5451 /* Create a new OSData for the smaller kext object.
5453 linkeditsize
= round_page(linkedit
->vmsize
);
5454 kextsize
= kmod_info
->size
- linkeditsize
;
5455 start
= linkedit
->vmaddr
;
5457 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5462 /* Fix the kmod info and linkedExecutable.
5464 kmod_info
->size
= kextsize
;
5467 data
->setDeallocFunction(osdata_kext_free
);
5469 data
->setDeallocFunction(osdata_phys_free
);
5471 linkedExecutable
->setDeallocFunction(NULL
);
5472 linkedExecutable
->release();
5473 linkedExecutable
= data
;
5474 flags
.jettisonLinkeditSeg
= 1;
5476 /* Free the linkedit segment.
5479 kext_free(start
, linkeditsize
);
5481 ml_static_mfree(start
, linkeditsize
);
5488 /*********************************************************************
5489 * If there are whole pages that are unused betweem the last section
5490 * of the DATA segment and the end of the DATA segment then we can free
5492 *********************************************************************/
5494 OSKext::jettisonDATASegmentPadding(void)
5496 kernel_mach_header_t
* mh
;
5497 kernel_segment_command_t
* dataSeg
;
5498 kernel_section_t
* sec
, * lastSec
;
5499 vm_offset_t dataSegEnd
, lastSecEnd
;
5502 mh
= (kernel_mach_header_t
*)kmod_info
->address
;
5504 dataSeg
= getsegbynamefromheader(mh
, SEG_DATA
);
5505 if (dataSeg
== NULL
) {
5510 sec
= firstsect(dataSeg
);
5511 while (sec
!= NULL
) {
5513 sec
= nextsect(dataSeg
, sec
);
5516 if (lastSec
== NULL
) {
5520 if ((dataSeg
->vmaddr
!= round_page(dataSeg
->vmaddr
)) ||
5521 (dataSeg
->vmsize
!= round_page(dataSeg
->vmsize
))) {
5525 dataSegEnd
= dataSeg
->vmaddr
+ dataSeg
->vmsize
;
5526 lastSecEnd
= round_page(lastSec
->addr
+ lastSec
->size
);
5528 if (dataSegEnd
<= lastSecEnd
) {
5532 padSize
= dataSegEnd
- lastSecEnd
;
5534 if (padSize
>= PAGE_SIZE
) {
5536 kext_free(lastSecEnd
, padSize
);
5538 ml_static_mfree(lastSecEnd
, padSize
);
5543 /*********************************************************************
5544 *********************************************************************/
5546 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5548 if (linkedExecutable
) {
5549 panic("Attempt to set linked executable on kext "
5550 "that already has one (%s).\n",
5551 getIdentifierCString());
5553 linkedExecutable
= anExecutable
;
5554 linkedExecutable
->retain();
5559 /*********************************************************************
5560 * Go through all loaded kexts and tell them to register with dtrace.
5561 * The instance method only registers if necessary.
5562 *********************************************************************/
5565 OSKext::registerKextsWithDTrace(void)
5567 uint32_t count
= sLoadedKexts
->getCount();
5570 IORecursiveLockLock(sKextLock
);
5572 for (i
= 0; i
< count
; i
++) {
5573 OSKext
* thisKext
= NULL
; // do not release
5575 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5576 if (!thisKext
|| !thisKext
->isExecutable()) {
5580 thisKext
->registerWithDTrace();
5583 IORecursiveLockUnlock(sKextLock
);
5589 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5590 extern int (*dtrace_modunload
)(struct kmod_info
*);
5593 /*********************************************************************
5594 *********************************************************************/
5596 OSKext::registerWithDTrace(void)
5598 /* Register kext with dtrace. A dtrace_modload failure should not
5599 * prevent a kext from loading, so we ignore the return code.
5601 if (!flags
.dtraceInitialized
&& (dtrace_modload
!= NULL
)) {
5602 uint32_t modflag
= 0;
5603 OSObject
* forceInit
= getPropertyForHostArch("OSBundleForceDTraceInit");
5604 if (forceInit
== kOSBooleanTrue
) {
5605 modflag
|= KMOD_DTRACE_FORCE_INIT
;
5608 (void)(*dtrace_modload
)(kmod_info
, modflag
);
5609 flags
.dtraceInitialized
= true;
5610 jettisonLinkeditSegment();
5614 /*********************************************************************
5615 *********************************************************************/
5617 OSKext::unregisterWithDTrace(void)
5619 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5620 * prevent a kext from loading, so we ignore the return code.
5622 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
5623 (void)(*dtrace_modunload
)(kmod_info
);
5624 flags
.dtraceInitialized
= false;
5628 #endif /* CONFIG_DTRACE */
5631 /*********************************************************************
5632 * called only by loadExecutable()
5633 *********************************************************************/
5634 #if !VM_MAPPED_KEXTS
5635 #error Unrecognized architecture
5637 static inline kern_return_t
5640 vm_map_offset_t start
,
5641 vm_map_offset_t end
,
5645 if (start
== end
) { // 10538581
5646 return(KERN_SUCCESS
);
5648 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
5651 static inline kern_return_t
5654 vm_map_offset_t start
,
5655 vm_map_offset_t end
,
5656 vm_prot_t access_type
,
5657 boolean_t user_wire
)
5659 return vm_map_wire(map
, start
, end
, access_type
| VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_KEXT
), user_wire
);
5664 OSKext::setVMAttributes(bool protect
, bool wire
)
5666 vm_map_t kext_map
= NULL
;
5667 kernel_segment_command_t
* seg
= NULL
;
5668 vm_map_offset_t start
= 0;
5669 vm_map_offset_t end
= 0;
5670 OSReturn result
= kOSReturnError
;
5672 if (isInterface() || !declaresExecutable()) {
5673 result
= kOSReturnSuccess
;
5677 /* Get the kext's vm map */
5678 kext_map
= kext_get_vm_map(kmod_info
);
5680 result
= KERN_MEMORY_ERROR
;
5684 #if !VM_MAPPED_KEXTS
5685 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
5686 /* This is a split kext in a prelinked kernelcache; we'll let the
5687 * platform code take care of protecting it. It is already wired.
5689 /* TODO: Should this still allow protections for the first segment
5690 * to go through, in the event that we have a mix of split and
5693 result
= KERN_SUCCESS
;
5698 /* Protect the headers as read-only; they do not need to be wired */
5699 result
= (protect
) ? OSKext_protect(kext_map
, kmod_info
->address
,
5700 kmod_info
->address
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
)
5702 if (result
!= KERN_SUCCESS
) {
5706 /* Set the VM protections and wire down each of the segments */
5707 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5711 start
= round_page(seg
->vmaddr
);
5712 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
5715 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
5716 if (result
!= KERN_SUCCESS
) {
5718 kOSKextLogErrorLevel
|
5720 "Kext %s failed to set maximum VM protections "
5721 "for segment %s - 0x%x.",
5722 getIdentifierCString(), seg
->segname
, (int)result
);
5726 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5727 if (result
!= KERN_SUCCESS
) {
5729 kOSKextLogErrorLevel
|
5731 "Kext %s failed to set initial VM protections "
5732 "for segment %s - 0x%x.",
5733 getIdentifierCString(), seg
->segname
, (int)result
);
5738 if (segmentShouldBeWired(seg
) && wire
) {
5739 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5740 if (result
!= KERN_SUCCESS
) {
5745 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5752 /*********************************************************************
5753 *********************************************************************/
5755 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
5757 return (sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
)));
5760 /*********************************************************************
5761 *********************************************************************/
5763 OSKext::validateKextMapping(bool startFlag
)
5765 OSReturn result
= kOSReturnError
;
5766 const char * whichOp
= startFlag
? "start" : "stop";
5767 kern_return_t kern_result
= 0;
5768 vm_map_t kext_map
= NULL
;
5769 kernel_segment_command_t
* seg
= NULL
;
5770 mach_vm_address_t address
= 0;
5771 mach_vm_size_t size
= 0;
5773 mach_msg_type_number_t count
;
5774 vm_region_submap_short_info_data_64_t info
;
5776 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
5777 bzero(&info
, sizeof(info
));
5779 // xxx - do we need a distinct OSReturn value for these or is "bad data"
5780 // xxx - sufficient?
5782 /* Verify that the kmod_info and start/stop pointers are non-NULL.
5786 kOSKextLogErrorLevel
|
5788 "Kext %s - NULL kmod_info pointer.",
5789 getIdentifierCString());
5790 result
= kOSKextReturnBadData
;
5795 address
= (mach_vm_address_t
)kmod_info
->start
;
5797 address
= (mach_vm_address_t
)kmod_info
->stop
;
5802 kOSKextLogErrorLevel
|
5804 "Kext %s - NULL module %s pointer.",
5805 getIdentifierCString(), whichOp
);
5806 result
= kOSKextReturnBadData
;
5810 kext_map
= kext_get_vm_map(kmod_info
);
5811 depth
= (kernel_map
== kext_map
) ? 1 : 2;
5813 /* Verify that the start/stop function lies within the kext's address range.
5815 if (getcommandfromheader((kernel_mach_header_t
*)kmod_info
->address
, LC_SEGMENT_SPLIT_INFO
)) {
5816 /* This will likely be how we deal with split kexts; walk the segments to
5817 * check that the function lies inside one of the segments of this kext.
5819 for (seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5821 seg
= nextsegfromheader((kernel_mach_header_t
*)kmod_info
->address
, seg
)) {
5822 if ((address
>= seg
->vmaddr
) && address
< (seg
->vmaddr
+ seg
->vmsize
)) {
5829 kOSKextLogErrorLevel
|
5831 "Kext %s module %s pointer is outside of kext range "
5832 "(%s %p - kext starts at %p).",
5833 getIdentifierCString(),
5836 (void *)VM_KERNEL_UNSLIDE(address
),
5837 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
));
5838 result
= kOSKextReturnBadData
;
5844 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
5845 kmod_info
->address
+ kmod_info
->size
<= address
)
5848 kOSKextLogErrorLevel
|
5850 "Kext %s module %s pointer is outside of kext range "
5851 "(%s %p - kext at %p-%p).",
5852 getIdentifierCString(),
5855 (void *)VM_KERNEL_UNSLIDE(address
),
5856 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5857 (void *)(VM_KERNEL_UNSLIDE(kmod_info
->address
) + kmod_info
->size
));
5858 result
= kOSKextReturnBadData
;
5863 /* Only do these checks before calling the start function;
5864 * If anything goes wrong with the mapping while the kext is running,
5865 * we'll likely have panicked well before any attempt to stop the kext.
5869 /* Verify that the start/stop function is executable.
5871 kern_result
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
,
5872 (vm_region_recurse_info_t
)&info
, &count
);
5873 if (kern_result
!= KERN_SUCCESS
) {
5875 kOSKextLogErrorLevel
|
5877 "Kext %s - bad %s pointer %p.",
5878 getIdentifierCString(),
5879 whichOp
, (void *)VM_KERNEL_UNSLIDE(address
));
5880 result
= kOSKextReturnBadData
;
5885 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
5887 kOSKextLogErrorLevel
|
5889 "Kext %s - memory region containing module %s function "
5890 "is not executable.",
5891 getIdentifierCString(), whichOp
);
5892 result
= kOSKextReturnBadData
;
5897 /* Verify that the kext's segments are backed by physical memory.
5899 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5901 if (!verifySegmentMapping(seg
)) {
5902 result
= kOSKextReturnBadData
;
5906 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5911 result
= kOSReturnSuccess
;
5916 /*********************************************************************
5917 *********************************************************************/
5919 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
5921 mach_vm_address_t address
= 0;
5923 if (!segmentShouldBeWired(seg
)) return true;
5925 for (address
= seg
->vmaddr
;
5926 address
< round_page(seg
->vmaddr
+ seg
->vmsize
);
5927 address
+= PAGE_SIZE
)
5929 if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) {
5931 kOSKextLogErrorLevel
|
5933 "Kext %s - page %p is not backed by physical memory.",
5934 getIdentifierCString(),
5943 /*********************************************************************
5944 *********************************************************************/
5946 OSKextLogKextInfo(OSKext
*aKext
, uint64_t address
, uint64_t size
, firehose_tracepoint_code_t code
)
5950 firehose_tracepoint_id_u trace_id
;
5951 struct firehose_trace_uuid_info_s uuid_info_s
;
5952 firehose_trace_uuid_info_t uuid_info
= &uuid_info_s
;
5953 size_t uuid_info_len
= sizeof(struct firehose_trace_uuid_info_s
);
5956 stamp
= firehose_tracepoint_time(firehose_activity_flags_default
);
5957 trace_id
.ftid_value
= FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata
, _firehose_tracepoint_type_metadata_kext
, (firehose_tracepoint_flags_t
)0, code
);
5959 uuid_data
= aKext
->copyUUID();
5961 memcpy(uuid_info
->ftui_uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid_info
->ftui_uuid
));
5962 OSSafeReleaseNULL(uuid_data
);
5965 uuid_info
->ftui_size
= size
;
5966 uuid_info
->ftui_address
= VM_KERNEL_UNSLIDE(address
);
5968 firehose_trace_metadata(firehose_stream_metadata
, trace_id
, stamp
, uuid_info
, uuid_info_len
);
5972 /*********************************************************************
5973 *********************************************************************/
5975 OSKext::start(bool startDependenciesFlag
)
5977 OSReturn result
= kOSReturnError
;
5978 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
5979 unsigned int i
, count
;
5980 void * kmodStartData
= NULL
;
5982 if (isStarted() || isInterface() || isKernelComponent()) {
5983 result
= kOSReturnSuccess
;
5989 kOSKextLogErrorLevel
|
5991 "Attempt to start nonloaded kext %s.",
5992 getIdentifierCString());
5993 result
= kOSKextReturnInvalidArgument
;
5997 if (!sLoadEnabled
) {
5999 kOSKextLogErrorLevel
|
6001 "Kext loading is disabled (attempt to start kext %s).",
6002 getIdentifierCString());
6003 result
= kOSKextReturnDisabled
;
6007 result
= validateKextMapping(/* start? */ true);
6008 if (result
!= kOSReturnSuccess
) {
6012 startfunc
= kmod_info
->start
;
6014 count
= getNumDependencies();
6015 for (i
= 0; i
< count
; i
++) {
6016 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
6017 if (dependency
== NULL
) {
6019 kOSKextLogErrorLevel
|
6021 "Kext %s start - internal error, dependency disappeared.",
6022 getIdentifierCString());
6025 if (!dependency
->isStarted()) {
6026 if (startDependenciesFlag
) {
6027 OSReturn dependencyResult
=
6028 dependency
->start(startDependenciesFlag
);
6029 if (dependencyResult
!= KERN_SUCCESS
) {
6031 kOSKextLogErrorLevel
|
6033 "Kext %s start - dependency %s failed to start (error 0x%x).",
6034 getIdentifierCString(),
6035 dependency
->getIdentifierCString(),
6041 kOSKextLogErrorLevel
|
6043 "Not starting %s - dependency %s not started yet.",
6044 getIdentifierCString(),
6045 dependency
->getIdentifierCString());
6046 result
= kOSKextReturnStartStopError
; // xxx - make new return?
6053 kOSKextLogDetailLevel
|
6055 "Kext %s calling module start function.",
6056 getIdentifierCString());
6060 // Drop a log message so logd can grab the needed information to decode this kext
6061 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_load
);
6063 #if !CONFIG_STATIC_CPPINIT
6064 result
= OSRuntimeInitializeCPP(kmod_info
, NULL
);
6065 if (result
== KERN_SUCCESS
) {
6069 kmodStartData
= GetAppleTEXTHashForKext(this, this->infoDict
);
6072 if (kmodStartData
) {
6074 kOSKextLogErrorLevel
|
6075 kOSKextLogGeneralFlag
,
6076 "Kext %s calling module start function. kmodStartData %p. arch %s",
6077 getIdentifierCString(), kmodStartData
, ARCHNAME
);
6080 #endif // CONFIG_KEC_FIPS
6081 result
= startfunc(kmod_info
, kmodStartData
);
6083 #if !CONFIG_STATIC_CPPINIT
6084 if (result
!= KERN_SUCCESS
) {
6085 (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6092 /* On success overlap the setting of started/starting. On failure just
6095 if (result
== KERN_SUCCESS
) {
6098 // xxx - log start error from kernel?
6100 kOSKextLogProgressLevel
|
6102 "Kext %s is now started.",
6103 getIdentifierCString());
6105 invokeOrCancelRequestCallbacks(
6106 /* result not actually used */ kOSKextReturnStartStopError
,
6107 /* invokeFlag */ false);
6109 kOSKextLogProgressLevel
|
6111 "Kext %s did not start (return code 0x%x).",
6112 getIdentifierCString(), result
);
6119 /*********************************************************************
6120 *********************************************************************/
6122 bool OSKext::canUnloadKextWithIdentifier(
6123 OSString
* kextIdentifier
,
6124 bool checkClassesFlag
)
6126 bool result
= false;
6127 OSKext
* aKext
= NULL
; // do not release
6129 IORecursiveLockLock(sKextLock
);
6131 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
6134 goto finish
; // can't unload what's not loaded
6137 if (aKext
->isLoaded()) {
6138 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
6141 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
6149 IORecursiveLockUnlock(sKextLock
);
6153 /*********************************************************************
6154 *********************************************************************/
6158 OSReturn result
= kOSReturnError
;
6159 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
6161 if (!isStarted() || isInterface()) {
6162 result
= kOSReturnSuccess
;
6168 kOSKextLogErrorLevel
|
6170 "Attempt to stop nonloaded kext %s.",
6171 getIdentifierCString());
6172 result
= kOSKextReturnInvalidArgument
;
6176 /* Refuse to stop if we have clients or instances. It is up to
6177 * the caller to make sure those aren't true.
6179 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6181 kOSKextLogErrorLevel
|
6183 "Kext %s - C++ instances; can't stop.",
6184 getIdentifierCString());
6185 result
= kOSKextReturnInUse
;
6189 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6192 kOSKextLogErrorLevel
|
6194 "Kext %s - has references (linkage or tracking object); "
6196 getIdentifierCString());
6197 result
= kOSKextReturnInUse
;
6201 /* Note: If validateKextMapping fails on the stop & unload path,
6202 * we are in serious trouble and a kernel panic is likely whether
6203 * we stop & unload the kext or not.
6205 result
= validateKextMapping(/* start? */ false);
6206 if (result
!= kOSReturnSuccess
) {
6210 stopfunc
= kmod_info
->stop
;
6213 kOSKextLogDetailLevel
|
6215 "Kext %s calling module stop function.",
6216 getIdentifierCString());
6220 result
= stopfunc(kmod_info
, /* userData */ NULL
);
6221 #if !CONFIG_STATIC_CPPINIT
6222 if (result
== KERN_SUCCESS
) {
6223 result
= OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6229 if (result
== KERN_SUCCESS
) {
6233 kOSKextLogDetailLevel
|
6235 "Kext %s is now stopped and ready to unload.",
6236 getIdentifierCString());
6239 kOSKextLogErrorLevel
|
6241 "Kext %s did not stop (return code 0x%x).",
6242 getIdentifierCString(), result
);
6243 result
= kOSKextReturnStartStopError
;
6248 // Drop a log message so logd can update this kext's metadata
6249 OSKextLogKextInfo(this, kmod_info
->address
, kmod_info
->size
, firehose_tracepoint_code_unload
);
6253 /*********************************************************************
6254 *********************************************************************/
6256 OSKext::unload(void)
6258 OSReturn result
= kOSReturnError
;
6260 uint32_t num_kmod_refs
= 0;
6261 OSKextAccount
* freeAccount
;
6263 if (!sUnloadEnabled
) {
6265 kOSKextLogErrorLevel
|
6267 "Kext unloading is disabled (%s).",
6268 this->getIdentifierCString());
6270 result
= kOSKextReturnDisabled
;
6274 /* Refuse to unload if we have clients or instances. It is up to
6275 * the caller to make sure those aren't true.
6277 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6278 // xxx - Don't log under errors? this is more of an info thing
6280 kOSKextLogErrorLevel
|
6281 kOSKextLogKextBookkeepingFlag
,
6282 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6283 getIdentifierCString());
6284 result
= kOSKextReturnInUse
;
6288 if (hasOSMetaClassInstances()) {
6290 kOSKextLogErrorLevel
|
6291 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6292 "Can't unload kext %s; classes have instances:",
6293 getIdentifierCString());
6294 reportOSMetaClassInstances(kOSKextLogErrorLevel
|
6295 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
);
6296 result
= kOSKextReturnInUse
;
6301 result
= kOSReturnSuccess
;
6305 if (isKernelComponent()) {
6306 result
= kOSKextReturnInvalidArgument
;
6310 /* Note that the kext is unloading before running any code that
6311 * might be in the kext (request callbacks, module stop function).
6312 * We will deny certain requests made against a kext in the process
6315 flags
.unloading
= 1;
6317 /* Update the string describing the last kext to unload in case we panic.
6319 savePanicString(/* isLoading */ false);
6323 if (result
!= KERN_SUCCESS
) {
6325 kOSKextLogErrorLevel
|
6327 "Kext %s can't unload - module stop returned 0x%x.",
6328 getIdentifierCString(), (unsigned)result
);
6329 result
= kOSKextReturnStartStopError
;
6335 kOSKextLogProgressLevel
|
6337 "Kext %s unloading.",
6338 getIdentifierCString());
6341 struct list_head
*p
;
6342 struct list_head
*prev
;
6343 struct list_head
*next
;
6344 for (p
= pendingPgoHead
.next
; p
!= &pendingPgoHead
; p
= next
) {
6345 OSKextGrabPgoStruct
*s
= container_of(p
, OSKextGrabPgoStruct
, list_head
);
6346 s
->err
= OSKextGrabPgoDataLocked(this, s
->metadata
, instance_uuid
, s
->pSize
, s
->pBuffer
, s
->bufferSize
);
6353 IORecursiveLockWakeup(sKextLock
, s
, false);
6358 /* Even if we don't call the stop function, we want to be sure we
6359 * have no OSMetaClass references before unloading the kext executable
6360 * from memory. OSMetaClasses may have pointers into the kext executable
6361 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6364 metaClasses
->flushCollection();
6367 /* Remove the kext from the list of loaded kexts, patch the gap
6368 * in the kmod_info_t linked list, and reset "kmod" to point to the
6369 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6371 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
6372 if (index
!= (unsigned int)-1) {
6374 sLoadedKexts
->removeObject(index
);
6376 OSKext
* nextKext
= OSDynamicCast(OSKext
,
6377 sLoadedKexts
->getObject(index
));
6381 OSKext
* gapKext
= OSDynamicCast(OSKext
,
6382 sLoadedKexts
->getObject(index
- 1));
6384 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
6386 } else /* index == 0 */ {
6387 nextKext
->kmod_info
->next
= NULL
;
6391 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
6392 if (lastKext
&& !lastKext
->isKernel()) {
6393 kmod
= lastKext
->kmod_info
;
6395 kmod
= NULL
; // clear the global kmod variable
6399 /* Clear out the kmod references that we're keeping for compatibility
6400 * with current panic backtrace code & kgmacros.
6401 * xxx - will want to update those bits sometime and remove this.
6403 num_kmod_refs
= getNumDependencies();
6404 if (num_kmod_refs
&& kmod_info
&& kmod_info
->reference_list
) {
6405 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
6406 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
6407 ref
->info
->reference_count
--;
6409 kfree(kmod_info
->reference_list
,
6410 num_kmod_refs
* sizeof(kmod_reference_t
));
6414 unregisterWithDTrace();
6415 #endif /* CONFIG_DTRACE */
6417 notifyKextUnloadObservers(this);
6420 IOSimpleLockLock(sKextAccountsLock
);
6421 account
->kext
= NULL
;
6422 if (account
->site
.tag
) account
->site
.flags
|= VM_TAG_UNLOAD
;
6423 else freeAccount
= account
;
6424 IOSimpleLockUnlock(sKextAccountsLock
);
6425 if (freeAccount
) IODelete(freeAccount
, OSKextAccount
, 1);
6427 /* Unwire and free the linked executable.
6429 if (linkedExecutable
) {
6431 if (!isInterface()) {
6432 kernel_segment_command_t
*seg
= NULL
;
6433 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6437 kOSKextLogErrorLevel
|
6439 "Failed to free kext %s; couldn't find the kext map.",
6440 getIdentifierCString());
6441 result
= kOSKextReturnInternalError
;
6446 kOSKextLogProgressLevel
|
6448 "Kext %s unwiring and unmapping linked executable.",
6449 getIdentifierCString());
6451 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6453 if (segmentShouldBeWired(seg
)) {
6454 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6455 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6456 if (result
!= KERN_SUCCESS
) {
6458 kOSKextLogErrorLevel
|
6460 "Failed to unwire kext %s.",
6461 getIdentifierCString());
6462 result
= kOSKextReturnInternalError
;
6467 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6471 OSSafeReleaseNULL(linkedExecutable
);
6474 /* An interface kext has a fake kmod_info that was allocated,
6475 * so we have to free it.
6477 if (isInterface()) {
6478 kfree(kmod_info
, sizeof(kmod_info_t
));
6483 flags
.loaded
= false;
6484 flushDependencies();
6486 /* save a copy of the bundle ID for us to check when deciding to
6487 * rebuild the kernel cache file. If a kext was already in the kernel
6488 * cache and unloaded then later loaded we do not need to rebuild the
6489 * kernel cache. 9055303
6491 if (isPrelinked()) {
6492 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6493 IORecursiveLockLock(sKextLock
);
6494 if (sUnloadedPrelinkedKexts
) {
6495 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6497 IORecursiveLockUnlock(sKextLock
);
6502 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6503 "Kext %s unloaded.", getIdentifierCString());
6505 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6506 OSDynamicCast(OSString
, bundleID
));
6509 OSKext::saveLoadedKextPanicList();
6510 OSKext::updateLoadedKextSummaries();
6512 flags
.unloading
= 0;
6516 /*********************************************************************
6517 * Assumes sKextLock is held.
6518 *********************************************************************/
6521 OSKext::queueKextNotification(
6522 const char * notificationName
,
6523 OSString
* kextIdentifier
)
6525 OSReturn result
= kOSReturnError
;
6526 OSDictionary
* loadRequest
= NULL
; // must release
6528 if (!kextIdentifier
) {
6529 result
= kOSKextReturnInvalidArgument
;
6533 /* Create a new request unless one is already sitting
6534 * in sKernelRequests for this bundle identifier
6536 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6537 if (result
!= kOSReturnSuccess
) {
6540 if (!_OSKextSetRequestArgument(loadRequest
,
6541 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6543 result
= kOSKextReturnNoMemory
;
6546 if (!sKernelRequests
->setObject(loadRequest
)) {
6547 result
= kOSKextReturnNoMemory
;
6551 /* We might want to only queue the notification if kextd is active,
6552 * but that wouldn't work for embedded. Note that we don't care if
6553 * the ping immediately succeeds here so don't do anything with the
6554 * result of this call.
6556 OSKext::pingKextd();
6558 result
= kOSReturnSuccess
;
6561 OSSafeReleaseNULL(loadRequest
);
6566 /*********************************************************************
6567 *********************************************************************/
6569 _OSKextConsiderDestroyingLinkContext(
6570 __unused thread_call_param_t p0
,
6571 __unused thread_call_param_t p1
)
6573 /* Take multiple locks in the correct order.
6575 IORecursiveLockLock(sKextLock
);
6576 IORecursiveLockLock(sKextInnerLock
);
6578 /* The first time we destroy the kxldContext is in the first
6579 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6580 * before calling this function. Thereafter any call to this function
6581 * will actually destroy the context.
6583 if (sConsiderUnloadsCalled
&& sKxldContext
) {
6584 kxld_destroy_context(sKxldContext
);
6585 sKxldContext
= NULL
;
6588 /* Free the thread_call that was allocated to execute this function.
6590 if (sDestroyLinkContextThread
) {
6591 if (!thread_call_free(sDestroyLinkContextThread
)) {
6592 OSKextLog(/* kext */ NULL
,
6593 kOSKextLogErrorLevel
|
6594 kOSKextLogGeneralFlag
,
6595 "thread_call_free() failed for kext link context.");
6597 sDestroyLinkContextThread
= 0;
6600 IORecursiveLockUnlock(sKextInnerLock
);
6601 IORecursiveLockUnlock(sKextLock
);
6606 /*********************************************************************
6607 * Destroying the kxldContext requires checking variables under both
6608 * sKextInnerLock and sKextLock, so we do it on a separate thread
6609 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6610 * call relationship.
6612 * This function must be invoked with sKextInnerLock held.
6613 * Do not call any function that takes sKextLock here!
6614 *********************************************************************/
6617 OSKext::considerDestroyingLinkContext(void)
6619 IORecursiveLockLock(sKextInnerLock
);
6621 /* If we have already queued a thread to destroy the link context,
6622 * don't bother resetting; that thread will take care of it.
6624 if (sDestroyLinkContextThread
) {
6628 /* The function to be invoked in the thread will deallocate
6629 * this thread_call, so don't share it around.
6631 sDestroyLinkContextThread
= thread_call_allocate(
6632 &_OSKextConsiderDestroyingLinkContext
, 0);
6633 if (!sDestroyLinkContextThread
) {
6634 OSKextLog(/* kext */ NULL
,
6635 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
| kOSKextLogLinkFlag
,
6636 "Can't create thread to destroy kext link context.");
6640 thread_call_enter(sDestroyLinkContextThread
);
6643 IORecursiveLockUnlock(sKextInnerLock
);
6648 #pragma mark Autounload
6650 /*********************************************************************
6651 * This is a static method because the kext will be deallocated if it
6653 *********************************************************************/
6656 OSKext::autounloadKext(OSKext
* aKext
)
6658 OSReturn result
= kOSKextReturnInUse
;
6660 /* Check for external references to this kext (usu. dependents),
6661 * instances of defined classes (or classes derived from them),
6662 * outstanding requests.
6664 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
6665 !aKext
->flags
.autounloadEnabled
||
6666 aKext
->isKernelComponent()) {
6671 /* Skip a delay-autounload kext, once.
6673 if (aKext
->flags
.delayAutounload
) {
6675 kOSKextLogProgressLevel
|
6676 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6677 "Kext %s has delayed autounload set; skipping and clearing flag.",
6678 aKext
->getIdentifierCString());
6679 aKext
->flags
.delayAutounload
= 0;
6683 if (aKext
->hasOSMetaClassInstances() ||
6684 aKext
->countRequestCallbacks()) {
6688 result
= OSKext::removeKext(aKext
);
6694 /*********************************************************************
6695 *********************************************************************/
6697 _OSKextConsiderUnloads(
6698 __unused thread_call_param_t p0
,
6699 __unused thread_call_param_t p1
)
6701 bool didUnload
= false;
6702 unsigned int count
, i
;
6704 /* Take multiple locks in the correct order
6705 * (note also sKextSummaries lock further down).
6707 IORecursiveLockLock(sKextLock
);
6708 IORecursiveLockLock(sKextInnerLock
);
6710 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6712 /* If the system is powering down, don't try to unload anything.
6718 OSKextLog(/* kext */ NULL
,
6719 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6720 "Checking for unused kexts to autounload.");
6723 * Remove any request callbacks marked as stale,
6724 * and mark as stale any currently in flight.
6726 count
= sRequestCallbackRecords
->getCount();
6730 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
6731 sRequestCallbackRecords
->getObject(i
));
6732 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
6733 callbackRecord
->getObject(kKextRequestStaleKey
));
6735 if (stale
== kOSBooleanTrue
) {
6736 OSKext::invokeRequestCallback(callbackRecord
,
6737 kOSKextReturnTimeout
);
6739 callbackRecord
->setObject(kKextRequestStaleKey
,
6746 * Make multiple passes through the array of loaded kexts until
6747 * we don't unload any. This handles unwinding of dependency
6748 * chains. We have to go *backwards* through the array because
6749 * kexts are removed from it when unloaded, and we cannot make
6750 * a copy or we'll mess up the retain counts we rely on to
6751 * check whether a kext will unload. If only we could have
6752 * nonretaining collections like CF has....
6757 count
= sLoadedKexts
->getCount();
6761 OSKext
* thisKext
= OSDynamicCast(OSKext
,
6762 sLoadedKexts
->getObject(i
));
6763 didUnload
|= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
6766 } while (didUnload
);
6769 sConsiderUnloadsPending
= false;
6770 sConsiderUnloadsExecuted
= true;
6772 (void) OSKext::considerRebuildOfPrelinkedKernel();
6774 IORecursiveLockUnlock(sKextInnerLock
);
6775 IORecursiveLockUnlock(sKextLock
);
6780 /*********************************************************************
6781 * Do not call any function that takes sKextLock here!
6782 *********************************************************************/
6783 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
6787 IORecursiveLockLock(sKextInnerLock
);
6789 if (!sUnloadCallout
) {
6790 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, 0);
6793 /* we only reset delay value for unloading if we already have something
6794 * pending. rescheduleOnlyFlag should not start the count down.
6796 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
6800 thread_call_cancel(sUnloadCallout
);
6801 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
6802 clock_interval_to_deadline(sConsiderUnloadDelay
,
6803 1000 * 1000 * 1000, &when
);
6805 OSKextLog(/* kext */ NULL
,
6806 kOSKextLogProgressLevel
|
6808 "%scheduling %sscan for unused kexts in %lu seconds.",
6809 sConsiderUnloadsPending
? "Res" : "S",
6810 sConsiderUnloadsCalled
? "" : "initial ",
6811 (unsigned long)sConsiderUnloadDelay
);
6813 sConsiderUnloadsPending
= true;
6814 thread_call_enter_delayed(sUnloadCallout
, when
);
6818 /* The kxld context should be reused throughout boot. We mark the end of
6819 * period as the first time considerUnloads() is called, and we destroy
6820 * the first kxld context in that function. Afterwards, it will be
6821 * destroyed in flushNonloadedKexts.
6823 if (!sConsiderUnloadsCalled
) {
6824 sConsiderUnloadsCalled
= true;
6825 OSKext::considerDestroyingLinkContext();
6828 IORecursiveLockUnlock(sKextInnerLock
);
6832 /*********************************************************************
6833 * Do not call any function that takes sKextLock here!
6834 *********************************************************************/
6837 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
);
6838 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
)
6840 IORecursiveLockLock(sKextInnerLock
);
6842 /* If the system is going to sleep, cancel the reaper thread timer,
6843 * and note that we're in a sleep state in case it just fired but hasn't
6844 * taken the lock yet. If we are coming back from sleep, just
6845 * clear the sleep flag; IOService's normal operation will cause
6846 * unloads to be considered soon enough.
6848 if (messageType
== kIOMessageSystemWillSleep
) {
6849 if (sUnloadCallout
) {
6850 thread_call_cancel(sUnloadCallout
);
6852 sSystemSleep
= true;
6853 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
6854 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
6855 sSystemSleep
= false;
6856 clock_get_uptime(&sLastWakeTime
);
6858 IORecursiveLockUnlock(sKextInnerLock
);
6860 return kIOReturnSuccess
;
6867 #pragma mark Prelinked Kernel
6869 /*********************************************************************
6870 * Do not access sConsiderUnloads... variables other than
6871 * sConsiderUnloadsExecuted in this function. They are guarded by a
6873 *********************************************************************/
6876 OSKext::considerRebuildOfPrelinkedKernel(void)
6878 static bool requestedPrelink
= false;
6879 OSReturn checkResult
= kOSReturnError
;
6880 OSDictionary
* prelinkRequest
= NULL
; // must release
6881 OSCollectionIterator
* kextIterator
= NULL
; // must release
6882 const OSSymbol
* thisID
= NULL
; // do not release
6883 bool doRebuild
= false;
6884 AbsoluteTime my_abstime
;
6888 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
6889 if (requestedPrelink
|| !sPrelinkBoot
) {
6893 /* no direct return from this point */
6894 IORecursiveLockLock(sKextLock
);
6896 /* We need to wait for kextd to get up and running with unloads already done
6897 * and any new startup kexts loaded.
6899 if (!sConsiderUnloadsExecuted
||
6900 !sDeferredLoadSucceeded
) {
6904 /* we really only care about boot / system start up related kexts so bail
6905 * if we're here after REBUILD_MAX_TIME.
6907 if (!_OSKextInPrelinkRebuildWindow()) {
6908 OSKextLog(/* kext */ NULL
,
6909 kOSKextLogArchiveFlag
,
6910 "%s prebuild rebuild has expired",
6912 requestedPrelink
= true;
6916 /* we do not want to trigger a rebuild if we get here too close to waking
6917 * up. (see radar 10233768)
6919 IORecursiveLockLock(sKextInnerLock
);
6921 clock_get_uptime(&my_abstime
);
6922 delta_secs
= MINIMUM_WAKEUP_SECONDS
+ 1;
6923 if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) {
6924 SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
);
6925 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
6926 delta_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
6928 IORecursiveLockUnlock(sKextInnerLock
);
6930 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
6931 /* too close to time of last wake from sleep */
6934 requestedPrelink
= true;
6936 /* Now it's time to see if we have a reason to rebuild. We may have done
6937 * some loads and unloads but the kernel cache didn't actually change.
6938 * We will rebuild if any kext is not marked prelinked AND is not in our
6939 * list of prelinked kexts that got unloaded. (see radar 9055303)
6941 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
6942 if (!kextIterator
) {
6946 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
6947 OSKext
* thisKext
; // do not release
6949 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
6950 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
6954 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
6957 /* kext is loaded and was not in current kernel cache so let's rebuild
6960 OSKextLog(/* kext */ NULL
,
6961 kOSKextLogArchiveFlag
,
6962 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
6963 thisKext
->bundleID
->getCStringNoCopy());
6966 sUnloadedPrelinkedKexts
->flushCollection();
6972 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
6974 if (checkResult
!= kOSReturnSuccess
) {
6978 if (!sKernelRequests
->setObject(prelinkRequest
)) {
6982 OSKext::pingKextd();
6985 IORecursiveLockUnlock(sKextLock
);
6986 OSSafeReleaseNULL(prelinkRequest
);
6987 OSSafeReleaseNULL(kextIterator
);
6993 #pragma mark Dependencies
6995 /*********************************************************************
6996 *********************************************************************/
6998 OSKext::resolveDependencies(
6999 OSArray
* loopStack
)
7001 bool result
= false;
7002 OSArray
* localLoopStack
= NULL
; // must release
7003 bool addedToLoopStack
= false;
7004 OSDictionary
* libraries
= NULL
; // do not release
7005 OSCollectionIterator
* libraryIterator
= NULL
; // must release
7006 OSString
* libraryID
= NULL
; // do not release
7007 OSString
* infoString
= NULL
; // do not release
7008 OSString
* readableString
= NULL
; // do not release
7009 OSKext
* libraryKext
= NULL
; // do not release
7010 bool hasRawKernelDependency
= false;
7011 bool hasKernelDependency
= false;
7012 bool hasKPIDependency
= false;
7013 bool hasPrivateKPIDependency
= false;
7016 /* A kernel component will automatically have this flag set,
7017 * and a loaded kext should also have it set (as should all its
7018 * loaded dependencies).
7020 if (flags
.hasAllDependencies
) {
7025 /* Check for loops in the dependency graph.
7028 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
7030 kOSKextLogErrorLevel
|
7031 kOSKextLogDependenciesFlag
,
7032 "Kext %s has a dependency loop; can't resolve dependencies.",
7033 getIdentifierCString());
7038 kOSKextLogStepLevel
|
7039 kOSKextLogDependenciesFlag
,
7040 "Kext %s resolving dependencies.",
7041 getIdentifierCString());
7043 loopStack
= OSArray::withCapacity(6); // any small capacity will do
7046 kOSKextLogErrorLevel
|
7047 kOSKextLogDependenciesFlag
,
7048 "Kext %s can't create bookkeeping stack to resolve dependencies.",
7049 getIdentifierCString());
7052 localLoopStack
= loopStack
;
7054 if (!loopStack
->setObject(this)) {
7056 kOSKextLogErrorLevel
|
7057 kOSKextLogDependenciesFlag
,
7058 "Kext %s - internal error resolving dependencies.",
7059 getIdentifierCString());
7062 addedToLoopStack
= true;
7064 /* Purge any existing kexts in the dependency list and start over.
7066 flushDependencies();
7069 kOSKextLogErrorLevel
|
7070 kOSKextLogDependenciesFlag
,
7071 "Kext %s - internal error resolving dependencies.",
7072 getIdentifierCString());
7075 libraries
= OSDynamicCast(OSDictionary
,
7076 getPropertyForHostArch(kOSBundleLibrariesKey
));
7077 if (libraries
== NULL
|| libraries
->getCount() == 0) {
7079 kOSKextLogErrorLevel
|
7080 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7081 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7082 getIdentifierCString(), kOSBundleLibrariesKey
);
7086 /* Make a new array to hold the dependencies (flush freed the old one).
7088 dependencies
= OSArray::withCapacity(libraries
->getCount());
7089 if (!dependencies
) {
7091 kOSKextLogErrorLevel
|
7092 kOSKextLogDependenciesFlag
,
7093 "Kext %s - can't allocate dependencies array.",
7094 getIdentifierCString());
7098 // xxx - compat: We used to add an implicit dependency on kernel 6.0
7099 // xxx - compat: if none were declared.
7101 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
7102 if (!libraryIterator
) {
7104 kOSKextLogErrorLevel
|
7105 kOSKextLogDependenciesFlag
,
7106 "Kext %s - can't allocate dependencies iterator.",
7107 getIdentifierCString());
7111 while ((libraryID
= OSDynamicCast(OSString
,
7112 libraryIterator
->getNextObject()))) {
7114 const char * library_id
= libraryID
->getCStringNoCopy();
7116 OSString
* libraryVersion
= OSDynamicCast(OSString
,
7117 libraries
->getObject(libraryID
));
7118 if (libraryVersion
== NULL
) {
7120 kOSKextLogErrorLevel
|
7121 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7122 "Kext %s - illegal type in OSBundleLibraries.",
7123 getIdentifierCString());
7127 OSKextVersion libraryVers
=
7128 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
7129 if (libraryVers
== -1) {
7131 kOSKextLogErrorLevel
|
7132 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7133 "Kext %s - invalid library version %s.",
7134 getIdentifierCString(),
7135 libraryVersion
->getCStringNoCopy());
7139 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
7140 if (libraryKext
== NULL
) {
7142 kOSKextLogErrorLevel
|
7143 kOSKextLogDependenciesFlag
,
7144 "Kext %s - library kext %s not found.",
7145 getIdentifierCString(), library_id
);
7149 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
7151 kOSKextLogErrorLevel
|
7152 kOSKextLogDependenciesFlag
,
7153 "Kext %s - library kext %s not compatible "
7154 "with requested version %s.",
7155 getIdentifierCString(), library_id
,
7156 libraryVersion
->getCStringNoCopy());
7160 /* If a nonprelinked library somehow got into the mix for a
7161 * prelinked kext, at any point in the chain, we must fail
7162 * because the prelinked relocs for the library will be all wrong.
7164 if (this->isPrelinked() &&
7165 libraryKext
->declaresExecutable() &&
7166 !libraryKext
->isPrelinked()) {
7169 kOSKextLogErrorLevel
|
7170 kOSKextLogDependenciesFlag
,
7171 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7172 getIdentifierCString(), library_id
,
7173 libraryVersion
->getCStringNoCopy());
7177 if (!libraryKext
->resolveDependencies(loopStack
)) {
7181 /* Add the library directly only if it has an executable to link.
7182 * Otherwise it's just used to collect other dependencies, so put
7183 * *its* dependencies on the list for this kext.
7185 // xxx - We are losing info here; would like to make fake entries or
7186 // xxx - keep these in the dependency graph for loaded kexts.
7187 // xxx - I really want to make kernel components not a special case!
7188 if (libraryKext
->declaresExecutable() ||
7189 libraryKext
->isInterface()) {
7191 if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) {
7192 dependencies
->setObject(libraryKext
);
7195 kOSKextLogDetailLevel
|
7196 kOSKextLogDependenciesFlag
,
7197 "Kext %s added dependency %s.",
7198 getIdentifierCString(),
7199 libraryKext
->getIdentifierCString());
7202 int numLibDependencies
= libraryKext
->getNumDependencies();
7203 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
7206 if (numLibDependencies
) {
7207 // xxx - this msg level should be 1 lower than the per-kext one
7209 kOSKextLogDetailLevel
|
7210 kOSKextLogDependenciesFlag
,
7211 "Kext %s pulling %d dependencies from codeless library %s.",
7212 getIdentifierCString(),
7214 libraryKext
->getIdentifierCString());
7216 for (index
= 0; index
< numLibDependencies
; index
++) {
7217 OSKext
* thisLibDependency
= OSDynamicCast(OSKext
,
7218 libraryDependencies
->getObject(index
));
7219 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) {
7220 dependencies
->setObject(thisLibDependency
);
7222 kOSKextLogDetailLevel
|
7223 kOSKextLogDependenciesFlag
,
7224 "Kext %s added dependency %s from codeless library %s.",
7225 getIdentifierCString(),
7226 thisLibDependency
->getIdentifierCString(),
7227 libraryKext
->getIdentifierCString());
7232 if ((strlen(library_id
) == strlen(KERNEL_LIB
)) &&
7233 0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) {
7235 hasRawKernelDependency
= true;
7236 } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) {
7237 hasKernelDependency
= true;
7238 } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) {
7239 hasKPIDependency
= true;
7240 if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) {
7241 hasPrivateKPIDependency
= true;
7246 if (hasRawKernelDependency
) {
7248 kOSKextLogErrorLevel
|
7249 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7250 "Error - kext %s declares a dependency on %s, which is not permitted.",
7251 getIdentifierCString(), KERNEL_LIB
);
7255 if (hasKernelDependency
) {
7257 kOSKextLogErrorLevel
|
7258 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7259 "Error - kext %s declares %s dependencies. "
7260 "Only %s* dependencies are supported for 64-bit kexts.",
7261 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7264 if (!hasKPIDependency
) {
7266 kOSKextLogWarningLevel
|
7267 kOSKextLogDependenciesFlag
,
7268 "Warning - kext %s declares no %s* dependencies. "
7269 "If it uses any KPIs, the link may fail with undefined symbols.",
7270 getIdentifierCString(), KPI_LIB_PREFIX
);
7272 #else /* __LP64__ */
7273 // xxx - will change to flatly disallow "kernel" dependencies at some point
7274 // xxx - is it invalid to do both "com.apple.kernel" and any
7275 // xxx - "com.apple.kernel.*"?
7277 if (hasKernelDependency
&& hasKPIDependency
) {
7279 kOSKextLogWarningLevel
|
7280 kOSKextLogDependenciesFlag
,
7281 "Warning - kext %s has immediate dependencies on both "
7282 "%s* and %s* components; use only one style.",
7283 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7286 if (!hasKernelDependency
&& !hasKPIDependency
) {
7287 // xxx - do we want to use validation flag for these too?
7289 kOSKextLogWarningLevel
|
7290 kOSKextLogDependenciesFlag
,
7291 "Warning - %s declares no kernel dependencies; using %s.",
7292 getIdentifierCString(), KERNEL6_LIB
);
7293 OSKext
* kernelKext
= OSDynamicCast(OSKext
,
7294 sKextsByID
->getObject(KERNEL6_LIB
));
7296 dependencies
->setObject(kernelKext
);
7299 kOSKextLogErrorLevel
|
7300 kOSKextLogDependenciesFlag
,
7301 "Error - Library %s not found for %s.",
7302 KERNEL6_LIB
, getIdentifierCString());
7306 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7307 * its indirect dependencies to simulate old-style linking. XXX - Should
7308 * check for duplicates.
7310 if (!hasKPIDependency
) {
7313 flags
.hasBleedthrough
= true;
7315 count
= getNumDependencies();
7317 /* We add to the dependencies array in this loop, but do not iterate
7318 * past its original count.
7320 for (i
= 0; i
< count
; i
++) {
7321 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
7322 dependencies
->getObject(i
));
7323 dependencyKext
->addBleedthroughDependencies(dependencies
);
7326 #endif /* __LP64__ */
7328 if (hasPrivateKPIDependency
) {
7329 bool hasApplePrefix
= false;
7330 bool infoCopyrightIsValid
= false;
7331 bool readableCopyrightIsValid
= false;
7333 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
7336 infoString
= OSDynamicCast(OSString
,
7337 getPropertyForHostArch("CFBundleGetInfoString"));
7339 infoCopyrightIsValid
=
7340 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
7343 readableString
= OSDynamicCast(OSString
,
7344 getPropertyForHostArch("NSHumanReadableCopyright"));
7345 if (readableString
) {
7346 readableCopyrightIsValid
=
7347 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
7350 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
7352 kOSKextLogErrorLevel
|
7353 kOSKextLogDependenciesFlag
,
7354 "Error - kext %s declares a dependency on %s. "
7355 "Only Apple kexts may declare a dependency on %s.",
7356 getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
);
7362 flags
.hasAllDependencies
= 1;
7366 if (addedToLoopStack
) {
7367 count
= loopStack
->getCount();
7368 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
7369 loopStack
->removeObject(count
- 1);
7372 kOSKextLogErrorLevel
|
7373 kOSKextLogDependenciesFlag
,
7374 "Kext %s - internal error resolving dependencies.",
7375 getIdentifierCString());
7379 if (result
&& localLoopStack
) {
7381 kOSKextLogStepLevel
|
7382 kOSKextLogDependenciesFlag
,
7383 "Kext %s successfully resolved dependencies.",
7384 getIdentifierCString());
7387 OSSafeReleaseNULL(localLoopStack
);
7388 OSSafeReleaseNULL(libraryIterator
);
7393 /*********************************************************************
7394 *********************************************************************/
7396 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
7398 bool result
= false;
7399 unsigned int dependencyIndex
, dependencyCount
;
7401 dependencyCount
= getNumDependencies();
7403 for (dependencyIndex
= 0;
7404 dependencyIndex
< dependencyCount
;
7405 dependencyIndex
++) {
7407 OSKext
* dependency
= OSDynamicCast(OSKext
,
7408 dependencies
->getObject(dependencyIndex
));
7411 kOSKextLogErrorLevel
|
7412 kOSKextLogDependenciesFlag
,
7413 "Kext %s - internal error propagating compatibility dependencies.",
7414 getIdentifierCString());
7417 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7418 anArray
->setObject(dependency
);
7420 dependency
->addBleedthroughDependencies(anArray
);
7429 /*********************************************************************
7430 *********************************************************************/
7432 OSKext::flushDependencies(bool forceFlag
)
7434 bool result
= false;
7436 /* Only clear the dependencies if the kext isn't loaded;
7437 * we need the info for loaded kexts to track references.
7439 if (!isLoaded() || forceFlag
) {
7441 // xxx - check level
7443 kOSKextLogProgressLevel
|
7444 kOSKextLogDependenciesFlag
,
7445 "Kext %s flushing dependencies.",
7446 getIdentifierCString());
7447 OSSafeReleaseNULL(dependencies
);
7450 if (!isKernelComponent()) {
7451 flags
.hasAllDependencies
= 0;
7459 /*********************************************************************
7460 *********************************************************************/
7462 OSKext::getNumDependencies(void)
7464 if (!dependencies
) {
7467 return dependencies
->getCount();
7470 /*********************************************************************
7471 *********************************************************************/
7473 OSKext::getDependencies(void)
7475 return dependencies
;
7479 #pragma mark OSMetaClass Support
7481 /*********************************************************************
7482 *********************************************************************/
7485 OSMetaClass
* aClass
,
7486 uint32_t numClasses
)
7488 OSReturn result
= kOSMetaClassNoInsKModSet
;
7491 metaClasses
= OSSet::withCapacity(numClasses
);
7497 if (metaClasses
->containsObject(aClass
)) {
7499 kOSKextLogWarningLevel
|
7501 "Notice - kext %s has already registered class %s.",
7502 getIdentifierCString(),
7503 aClass
->getClassName());
7504 result
= kOSReturnSuccess
;
7508 if (!metaClasses
->setObject(aClass
)) {
7512 kOSKextLogDetailLevel
|
7514 "Kext %s registered class %s.",
7515 getIdentifierCString(),
7516 aClass
->getClassName());
7519 if (!flags
.autounloadEnabled
) {
7520 const OSMetaClass
* metaScan
= NULL
; // do not release
7522 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7523 if (metaScan
== OSTypeID(IOService
)) {
7526 kOSKextLogProgressLevel
|
7528 "Kext %s has IOService subclass %s; enabling autounload.",
7529 getIdentifierCString(),
7530 aClass
->getClassName());
7532 flags
.autounloadEnabled
= 1;
7538 notifyAddClassObservers(this, aClass
, flags
);
7540 result
= kOSReturnSuccess
;
7543 if (result
!= kOSReturnSuccess
) {
7545 kOSKextLogErrorLevel
|
7547 "Kext %s failed to register class %s.",
7548 getIdentifierCString(),
7549 aClass
->getClassName());
7555 /*********************************************************************
7556 *********************************************************************/
7558 OSKext::removeClass(
7559 OSMetaClass
* aClass
)
7561 OSReturn result
= kOSMetaClassNoKModSet
;
7567 if (!metaClasses
->containsObject(aClass
)) {
7569 kOSKextLogWarningLevel
|
7571 "Notice - kext %s asked to unregister unknown class %s.",
7572 getIdentifierCString(),
7573 aClass
->getClassName());
7574 result
= kOSReturnSuccess
;
7579 kOSKextLogDetailLevel
|
7581 "Kext %s unregistering class %s.",
7582 getIdentifierCString(),
7583 aClass
->getClassName());
7585 metaClasses
->removeObject(aClass
);
7587 notifyRemoveClassObservers(this, aClass
, flags
);
7589 result
= kOSReturnSuccess
;
7592 if (result
!= kOSReturnSuccess
) {
7594 kOSKextLogErrorLevel
|
7596 "Failed to unregister kext %s class %s.",
7597 getIdentifierCString(),
7598 aClass
->getClassName());
7603 /*********************************************************************
7604 *********************************************************************/
7606 OSKext::getMetaClasses(void)
7611 /*********************************************************************
7612 *********************************************************************/
7614 OSKext::hasOSMetaClassInstances(void)
7616 bool result
= false;
7617 OSCollectionIterator
* classIterator
= NULL
; // must release
7618 OSMetaClass
* checkClass
= NULL
; // do not release
7624 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7625 if (!classIterator
) {
7626 // xxx - log alloc failure?
7629 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7630 if (checkClass
->getInstanceCount()) {
7638 OSSafeReleaseNULL(classIterator
);
7642 /*********************************************************************
7643 *********************************************************************/
7646 OSKext::reportOSMetaClassInstances(
7647 const char * kextIdentifier
,
7648 OSKextLogSpec msgLogSpec
)
7650 OSKext
* theKext
= NULL
; // must release
7652 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
7657 theKext
->reportOSMetaClassInstances(msgLogSpec
);
7659 OSSafeReleaseNULL(theKext
);
7663 /*********************************************************************
7664 *********************************************************************/
7666 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
7668 OSCollectionIterator
* classIterator
= NULL
; // must release
7669 OSMetaClass
* checkClass
= NULL
; // do not release
7675 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7676 if (!classIterator
) {
7679 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7680 if (checkClass
->getInstanceCount()) {
7683 " Kext %s class %s has %d instance%s.",
7684 getIdentifierCString(),
7685 checkClass
->getClassName(),
7686 checkClass
->getInstanceCount(),
7687 checkClass
->getInstanceCount() == 1 ? "" : "s");
7692 OSSafeReleaseNULL(classIterator
);
7697 #pragma mark User-Space Requests
7699 /*********************************************************************
7700 * XXX - this function is a big ugly mess
7701 *********************************************************************/
7704 OSKext::handleRequest(
7705 host_priv_t hostPriv
,
7706 OSKextLogSpec clientLogFilter
,
7707 char * requestBuffer
,
7708 uint32_t requestLength
,
7709 char ** responseOut
,
7710 uint32_t * responseLengthOut
,
7712 uint32_t * logInfoLengthOut
)
7714 OSReturn result
= kOSReturnError
;
7715 kern_return_t kmem_result
= KERN_FAILURE
;
7717 char * response
= NULL
; // returned by reference
7718 uint32_t responseLength
= 0;
7720 OSObject
* parsedXML
= NULL
; // must release
7721 OSDictionary
* requestDict
= NULL
; // do not release
7722 OSString
* errorString
= NULL
; // must release
7724 OSObject
* responseObject
= NULL
; // must release
7726 OSSerialize
* serializer
= NULL
; // must release
7728 OSArray
* logInfoArray
= NULL
; // must release
7730 OSString
* predicate
= NULL
; // do not release
7731 OSString
* kextIdentifier
= NULL
; // do not release
7732 OSArray
* kextIdentifiers
= NULL
; // do not release
7733 OSKext
* theKext
= NULL
; // do not release
7734 OSBoolean
* boolArg
= NULL
; // do not release
7736 IORecursiveLockLock(sKextLock
);
7739 *responseOut
= NULL
;
7740 *responseLengthOut
= 0;
7744 *logInfoLengthOut
= 0;
7747 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
7749 /* XML must be nul-terminated.
7751 if (requestBuffer
[requestLength
- 1] != '\0') {
7752 OSKextLog(/* kext */ NULL
,
7753 kOSKextLogErrorLevel
|
7755 "Invalid request from user space (not nul-terminated).");
7756 result
= kOSKextReturnBadData
;
7759 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
7761 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
7764 const char * errorCString
= "(unknown error)";
7766 if (errorString
&& errorString
->getCStringNoCopy()) {
7767 errorCString
= errorString
->getCStringNoCopy();
7768 } else if (parsedXML
) {
7769 errorCString
= "not a dictionary";
7771 OSKextLog(/* kext */ NULL
,
7772 kOSKextLogErrorLevel
|
7774 "Error unserializing request from user space: %s.",
7776 result
= kOSKextReturnSerialization
;
7780 predicate
= _OSKextGetRequestPredicate(requestDict
);
7782 OSKextLog(/* kext */ NULL
,
7783 kOSKextLogErrorLevel
|
7785 "Recieved kext request from user space with no predicate.");
7786 result
= kOSKextReturnInvalidArgument
;
7790 OSKextLog(/* kext */ NULL
,
7791 kOSKextLogDebugLevel
|
7793 "Received '%s' request from user space.",
7794 predicate
->getCStringNoCopy());
7796 result
= kOSKextReturnNotPrivileged
;
7797 if (hostPriv
== HOST_PRIV_NULL
) {
7798 /* must be root to use these kext requests */
7799 if (predicate
->isEqualTo(kKextRequestPredicateUnload
) ||
7800 predicate
->isEqualTo(kKextRequestPredicateStart
) ||
7801 predicate
->isEqualTo(kKextRequestPredicateStop
) ||
7802 predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
) ||
7803 predicate
->isEqualTo(kKextRequestPredicateSendResource
) ) {
7804 OSKextLog(/* kext */ NULL
,
7805 kOSKextLogErrorLevel
|
7807 "Access Failure - must be root user.");
7812 /* Get common args in anticipation of use.
7814 kextIdentifier
= OSDynamicCast(OSString
, _OSKextGetRequestArgument(
7815 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7816 kextIdentifiers
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument(
7817 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7818 if (kextIdentifier
) {
7819 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
7821 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
7822 requestDict
, kKextRequestArgumentValueKey
));
7824 result
= kOSKextReturnInvalidArgument
;
7826 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
7827 if (!kextIdentifier
) {
7828 OSKextLog(/* kext */ NULL
,
7829 kOSKextLogErrorLevel
|
7831 "Invalid arguments to kext start request.");
7832 } else if (!theKext
) {
7833 OSKextLog(/* kext */ NULL
,
7834 kOSKextLogErrorLevel
|
7836 "Kext %s not found for start request.",
7837 kextIdentifier
->getCStringNoCopy());
7838 result
= kOSKextReturnNotFound
;
7840 result
= theKext
->start();
7843 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
7844 if (!kextIdentifier
) {
7845 OSKextLog(/* kext */ NULL
,
7846 kOSKextLogErrorLevel
|
7848 "Invalid arguments to kext stop request.");
7849 } else if (!theKext
) {
7850 OSKextLog(/* kext */ NULL
,
7851 kOSKextLogErrorLevel
|
7853 "Kext %s not found for stop request.",
7854 kextIdentifier
->getCStringNoCopy());
7855 result
= kOSKextReturnNotFound
;
7857 result
= theKext
->stop();
7860 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
7861 if (!kextIdentifier
) {
7862 OSKextLog(/* kext */ NULL
,
7863 kOSKextLogErrorLevel
|
7865 "Invalid arguments to kext unload request.");
7866 } else if (!theKext
) {
7867 OSKextLog(/* kext */ NULL
,
7868 kOSKextLogErrorLevel
|
7870 "Kext %s not found for unload request.",
7871 kextIdentifier
->getCStringNoCopy());
7872 result
= kOSKextReturnNotFound
;
7874 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
7875 _OSKextGetRequestArgument(requestDict
,
7876 kKextRequestArgumentTerminateIOServicesKey
));
7877 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
7880 } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
7881 result
= OSKext::dispatchResource(requestDict
);
7883 } else if (predicate
->isEqualTo(kKextRequestPredicateGetUUIDByAddress
)) {
7885 OSNumber
*lookupNum
= NULL
;
7886 lookupNum
= OSDynamicCast(OSNumber
,
7887 _OSKextGetRequestArgument(requestDict
,
7888 kKextRequestArgumentLookupAddressKey
));
7890 responseObject
= OSKext::copyKextUUIDForAddress(lookupNum
);
7891 if (responseObject
) {
7892 result
= kOSReturnSuccess
;
7894 OSKextLog(/* kext */ NULL
,
7895 kOSKextLogErrorLevel
|
7897 "Get UUID by Address failed.");
7901 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
) ||
7902 predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
7903 OSBoolean
* delayAutounloadBool
= NULL
;
7904 OSObject
* infoKeysRaw
= NULL
;
7905 OSArray
* infoKeys
= NULL
;
7906 uint32_t infoKeysCount
= 0;
7908 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
7909 _OSKextGetRequestArgument(requestDict
,
7910 kKextRequestArgumentDelayAutounloadKey
));
7912 /* If asked to delay autounload, reset the timer if it's currently set.
7913 * (That is, don't schedule an unload if one isn't already pending.
7915 if (delayAutounloadBool
== kOSBooleanTrue
) {
7916 OSKext::considerUnloads(/* rescheduleOnly? */ true);
7919 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
7920 kKextRequestArgumentInfoKeysKey
);
7921 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
7922 if (infoKeysRaw
&& !infoKeys
) {
7923 OSKextLog(/* kext */ NULL
,
7924 kOSKextLogErrorLevel
|
7926 "Invalid arguments to kext info request.");
7931 infoKeysCount
= infoKeys
->getCount();
7932 for (uint32_t i
= 0; i
< infoKeysCount
; i
++) {
7933 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) {
7934 OSKextLog(/* kext */ NULL
,
7935 kOSKextLogErrorLevel
|
7937 "Invalid arguments to kext info request.");
7943 if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
7944 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
7946 else if (predicate
->isEqualTo(kKextRequestPredicateGetLoadedByUUID
)) {
7947 responseObject
= OSKext::copyLoadedKextInfoByUUID(kextIdentifiers
, infoKeys
);
7949 if (!responseObject
) {
7950 result
= kOSKextReturnInternalError
;
7952 OSKextLog(/* kext */ NULL
,
7953 kOSKextLogDebugLevel
|
7955 "Returning loaded kext info.");
7956 result
= kOSReturnSuccess
;
7958 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) {
7960 /* Hand the current sKernelRequests array to the caller
7961 * (who must release it), and make a new one.
7963 responseObject
= sKernelRequests
;
7964 sKernelRequests
= OSArray::withCapacity(0);
7965 sPostedKextLoadIdentifiers
->flushCollection();
7966 OSKextLog(/* kext */ NULL
,
7967 kOSKextLogDebugLevel
|
7969 "Returning kernel requests.");
7970 result
= kOSReturnSuccess
;
7972 } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) {
7974 /* Return the set of all requested bundle identifiers */
7975 responseObject
= sAllKextLoadIdentifiers
;
7976 responseObject
->retain();
7977 OSKextLog(/* kext */ NULL
,
7978 kOSKextLogDebugLevel
|
7980 "Returning load requests.");
7981 result
= kOSReturnSuccess
;
7984 OSKextLog(/* kext */ NULL
,
7985 kOSKextLogDebugLevel
|
7987 "Received '%s' invalid request from user space.",
7988 predicate
->getCStringNoCopy());
7993 * Now we have handle the request, or not. Gather up the response & logging
7994 * info to ship to user space.
7997 /* Note: Nothing in OSKext is supposed to retain requestDict,
7998 * but you never know....
8000 if (requestDict
->getRetainCount() > 1) {
8001 OSKextLog(/* kext */ NULL
,
8002 kOSKextLogWarningLevel
|
8004 "Request from user space still retained by a kext; "
8005 "probable memory leak.");
8008 if (responseOut
&& responseObject
) {
8009 serializer
= OSSerialize::withCapacity(0);
8011 result
= kOSKextReturnNoMemory
;
8015 if (!responseObject
->serialize(serializer
)) {
8016 OSKextLog(/* kext */ NULL
,
8017 kOSKextLogGeneralFlag
| kOSKextLogErrorLevel
,
8018 "Failed to serialize response to request from user space.");
8019 result
= kOSKextReturnSerialization
;
8023 response
= (char *)serializer
->text();
8024 responseLength
= serializer
->getLength();
8027 if (responseOut
&& response
) {
8030 /* This kmem_alloc sets the return value of the function.
8032 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
,
8033 round_page(responseLength
), VM_KERN_MEMORY_OSKEXT
);
8034 if (kmem_result
!= KERN_SUCCESS
) {
8035 OSKextLog(/* kext */ NULL
,
8036 kOSKextLogErrorLevel
|
8038 "Failed to copy response to request from user space.");
8039 result
= kmem_result
;
8042 /* 11981737 - clear uninitialized data in last page */
8043 bzero((void *)(buffer
+ responseLength
),
8044 (round_page(responseLength
) - responseLength
));
8045 memcpy(buffer
, response
, responseLength
);
8046 *responseOut
= buffer
;
8047 *responseLengthOut
= responseLength
;
8053 /* Gather up the collected log messages for user space. Any messages
8054 * messages past this call will not make it up as log messages but
8055 * will be in the system log. Note that we ignore the return of the
8056 * serialize; it has no bearing on the operation at hand even if we
8057 * fail to get the log messages.
8059 logInfoArray
= OSKext::clearUserSpaceLogFilter();
8061 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
8062 (void)OSKext::serializeLogInfo(logInfoArray
,
8063 logInfoOut
, logInfoLengthOut
);
8066 IORecursiveLockUnlock(sKextLock
);
8068 OSSafeReleaseNULL(parsedXML
);
8069 OSSafeReleaseNULL(errorString
);
8070 OSSafeReleaseNULL(responseObject
);
8071 OSSafeReleaseNULL(serializer
);
8072 OSSafeReleaseNULL(logInfoArray
);
8078 // #include <InstrProfiling.h>
8081 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin
,
8082 const char *DataEnd
,
8083 const char *CountersBegin
,
8084 const char *CountersEnd
,
8085 const char *NamesBegin
,
8086 const char *NamesEnd
);
8087 int __llvm_profile_write_buffer_internal(char *Buffer
,
8088 const char *DataBegin
,
8089 const char *DataEnd
,
8090 const char *CountersBegin
,
8091 const char *CountersEnd
,
8092 const char *NamesBegin
,
8093 const char *NamesEnd
);
8098 void OSKextPgoMetadataPut(char *pBuffer
,
8101 uint32_t *num_pairs
,
8105 size_t strlen_key
= strlen(key
);
8106 size_t strlen_value
= strlen(value
);
8107 size_t len
= strlen(key
) + 1 + strlen(value
) + 1;
8108 char *pos
= pBuffer
+ *position
;
8110 if (pBuffer
&& bufferSize
&& *position
<= bufferSize
) {
8111 memcpy(pos
, key
, strlen_key
); pos
+= strlen_key
;
8113 memcpy(pos
, value
, strlen_value
); pos
+= strlen_value
;
8123 void OSKextPgoMetadataPutMax(size_t *position
, const char *key
, size_t value_max
)
8125 *position
+= strlen(key
) + 1 + value_max
+ 1;
8130 void OSKextPgoMetadataPutAll(OSKext
*kext
,
8131 uuid_t instance_uuid
,
8135 uint32_t *num_pairs
)
8137 _static_assert_1_arg(sizeof(clock_sec_t
) % 2 == 0);
8138 //log_10 2^16 ≈ 4.82
8139 const size_t max_secs_string_size
= 5 * sizeof(clock_sec_t
)/2;
8140 const size_t max_timestamp_string_size
= max_secs_string_size
+ 1 + 6;
8143 OSKextPgoMetadataPutMax(position
, "INSTANCE", 36);
8144 OSKextPgoMetadataPutMax(position
, "UUID", 36);
8145 OSKextPgoMetadataPutMax(position
, "TIMESTAMP", max_timestamp_string_size
);
8147 uuid_string_t instance_uuid_string
;
8148 uuid_unparse(instance_uuid
, instance_uuid_string
);
8149 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8150 "INSTANCE", instance_uuid_string
);
8154 uuid_string_t uuid_string
;
8155 uuid_data
= kext
->copyUUID();
8157 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
8158 OSSafeReleaseNULL(uuid_data
);
8159 uuid_unparse(uuid
, uuid_string
);
8160 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8161 "UUID", uuid_string
);
8166 clock_get_calendar_microtime(&secs
, &usecs
);
8167 assert(usecs
< 1000000);
8168 char timestamp
[max_timestamp_string_size
+ 1];
8169 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t
));
8170 snprintf(timestamp
, sizeof(timestamp
), "%lu.%06d", (unsigned long)secs
, (int)usecs
);
8171 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8172 "TIMESTAMP", timestamp
);
8175 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8176 "NAME", kext
->getIdentifierCString());
8178 char versionCString
[kOSKextVersionMaxLength
];
8179 OSKextVersionGetString(kext
->getVersion(), versionCString
, kOSKextVersionMaxLength
);
8180 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8181 "VERSION", versionCString
);
8186 size_t OSKextPgoMetadataSize(OSKext
*kext
)
8188 size_t position
= 0;
8189 uuid_t fakeuuid
= {};
8190 OSKextPgoMetadataPutAll(kext
, fakeuuid
, NULL
, &position
, 0, NULL
);
8195 int OSKextGrabPgoDataLocked(OSKext
*kext
,
8197 uuid_t instance_uuid
,
8200 uint64_t bufferSize
)
8205 kernel_section_t
*sect_prf_data
= NULL
;
8206 kernel_section_t
*sect_prf_name
= NULL
;
8207 kernel_section_t
*sect_prf_cnts
= NULL
;
8209 size_t metadata_size
= 0;
8211 sect_prf_data
= kext
->lookupSection("__DATA", "__llvm_prf_data");
8212 sect_prf_name
= kext
->lookupSection("__DATA", "__llvm_prf_name");
8213 sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8215 if (!sect_prf_data
|| !sect_prf_name
|| !sect_prf_cnts
) {
8220 size
= __llvm_profile_get_size_for_buffer_internal(
8221 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8222 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8223 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8226 metadata_size
= OSKextPgoMetadataSize(kext
);
8227 size
+= metadata_size
;
8228 size
+= sizeof(pgo_metadata_footer
);
8236 if (pBuffer
&& bufferSize
) {
8237 if (bufferSize
< size
) {
8242 err
= __llvm_profile_write_buffer_internal(
8244 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8245 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8246 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8254 char *end_of_buffer
= pBuffer
+ size
;
8255 struct pgo_metadata_footer
*footerp
= (struct pgo_metadata_footer
*) (end_of_buffer
- sizeof(struct pgo_metadata_footer
));
8256 char *metadata_buffer
= end_of_buffer
- (sizeof(struct pgo_metadata_footer
) + metadata_size
);
8258 size_t metadata_position
= 0;
8259 uint32_t num_pairs
= 0;
8260 OSKextPgoMetadataPutAll(kext
, instance_uuid
, metadata_buffer
, &metadata_position
, metadata_size
, &num_pairs
);
8261 while (metadata_position
< metadata_size
) {
8262 metadata_buffer
[metadata_position
++] = 0;
8265 struct pgo_metadata_footer footer
;
8266 footer
.magic
= htonl(0x6d657461);
8267 footer
.number_of_pairs
= htonl( num_pairs
);
8268 footer
.offset_to_pairs
= htonl( sizeof(struct pgo_metadata_footer
) + metadata_size
);
8269 memcpy(footerp
, &footer
, sizeof(footer
));
8280 OSKextGrabPgoData(uuid_t uuid
,
8283 uint64_t bufferSize
,
8284 int wait_for_unload
,
8288 OSKext
*kext
= NULL
;
8291 IORecursiveLockLock(sKextLock
);
8293 kext
= OSKext::lookupKextWithUUID(uuid
);
8299 if (wait_for_unload
) {
8300 OSKextGrabPgoStruct s
;
8302 s
.metadata
= metadata
;
8304 s
.pBuffer
= pBuffer
;
8305 s
.bufferSize
= bufferSize
;
8308 struct list_head
*prev
= &kext
->pendingPgoHead
;
8309 struct list_head
*next
= kext
->pendingPgoHead
.next
;
8311 s
.list_head
.prev
= prev
;
8312 s
.list_head
.next
= next
;
8314 prev
->next
= &s
.list_head
;
8315 next
->prev
= &s
.list_head
;
8320 IORecursiveLockSleep(sKextLock
, &s
, THREAD_ABORTSAFE
);
8322 prev
= s
.list_head
.prev
;
8323 next
= s
.list_head
.next
;
8331 err
= OSKextGrabPgoDataLocked(kext
, metadata
, kext
->instance_uuid
, pSize
, pBuffer
, bufferSize
);
8339 IORecursiveLockUnlock(sKextLock
);
8345 OSKextResetPgoCountersLock()
8347 IORecursiveLockLock(sKextLock
);
8351 OSKextResetPgoCountersUnlock()
8353 IORecursiveLockUnlock(sKextLock
);
8357 extern unsigned int not_in_kdp
;
8360 OSKextResetPgoCounters()
8362 assert(!not_in_kdp
);
8363 uint32_t count
= sLoadedKexts
->getCount();
8364 for (uint32_t i
= 0; i
< count
; i
++) {
8365 OSKext
*kext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8366 kernel_section_t
*sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8367 if (!sect_prf_cnts
) {
8370 memset((void*)sect_prf_cnts
->addr
, 0, sect_prf_cnts
->size
);
8375 OSKext::copyLoadedKextInfoByUUID(
8376 OSArray
* kextIdentifiers
,
8379 OSDictionary
* result
= NULL
;
8380 OSDictionary
* kextInfo
= NULL
; // must release
8382 uint32_t idCount
= 0;
8383 uint32_t idIndex
= 0;
8385 IORecursiveLockLock(sKextLock
);
8388 /* Is the calling process allowed to query kext info? */
8389 if (current_task() != kernel_task
) {
8390 int macCheckResult
= 0;
8391 kauth_cred_t cred
= NULL
;
8393 cred
= kauth_cred_get_with_ref();
8394 macCheckResult
= mac_kext_check_query(cred
);
8395 kauth_cred_unref(&cred
);
8397 if (macCheckResult
!= 0) {
8398 OSKextLog(/* kext */ NULL
,
8399 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8400 "Failed to query kext info (MAC policy error 0x%x).",
8407 /* Empty list of UUIDs is equivalent to no list (get all).
8409 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8410 kextIdentifiers
= NULL
;
8411 } else if (kextIdentifiers
) {
8412 idCount
= kextIdentifiers
->getCount();
8417 if (infoKeys
&& !infoKeys
->getCount()) {
8421 count
= sLoadedKexts
->getCount();
8422 result
= OSDictionary::withCapacity(count
);
8427 for (i
= 0; i
< count
; i
++) {
8428 OSKext
*thisKext
= NULL
; // do not release
8429 Boolean includeThis
= true;
8430 uuid_t thisKextUUID
;
8432 uuid_string_t uuid_key
;
8435 kextInfo
->release();
8439 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8444 uuid_data
= thisKext
->copyUUID();
8449 memcpy(&thisKextUUID
, uuid_data
->getBytesNoCopy(), sizeof(thisKextUUID
));
8450 OSSafeReleaseNULL(uuid_data
);
8452 uuid_unparse(thisKextUUID
, uuid_key
);
8454 /* Skip current kext if we have a list of UUIDs and
8455 * it isn't in the list.
8457 if (kextIdentifiers
) {
8458 includeThis
= false;
8460 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8461 const OSString
* wantedUUID
= OSDynamicCast(OSString
,
8462 kextIdentifiers
->getObject(idIndex
));
8465 uuid_parse(wantedUUID
->getCStringNoCopy(), uuid
);
8467 if (0 == uuid_compare(uuid
, thisKextUUID
)) {
8479 kextInfo
= thisKext
->copyInfo(infoKeys
);
8481 result
->setObject(uuid_key
, kextInfo
);
8486 IORecursiveLockUnlock(sKextLock
);
8488 if (kextInfo
) kextInfo
->release();
8493 /*********************************************************************
8494 *********************************************************************/
8497 OSKext::copyKextUUIDForAddress(OSNumber
*address
)
8499 OSKext
*kext
= NULL
;
8500 OSData
*uuid
= NULL
;
8501 vm_address_t vm_addr
= 0;
8507 /* Is the calling process allowed to query kext info? */
8508 if (current_task() != kernel_task
) {
8509 int macCheckResult
= 0;
8510 kauth_cred_t cred
= NULL
;
8512 cred
= kauth_cred_get_with_ref();
8513 macCheckResult
= mac_kext_check_query(cred
);
8514 kauth_cred_unref(&cred
);
8516 if (macCheckResult
!= 0) {
8517 OSKextLog(/* kext */ NULL
,
8518 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8519 "Failed to query kext UUID (MAC policy error 0x%x).",
8526 vm_addr
= (vm_address_t
)(address
->unsigned64BitValue() + vm_kernel_slide
);
8528 kext
= OSKext::lookupKextWithAddress(vm_addr
);
8530 uuid
= kext
->copyUUID();
8541 /*********************************************************************
8542 *********************************************************************/
8545 OSKext::copyLoadedKextInfo(
8546 OSArray
* kextIdentifiers
,
8549 OSDictionary
* result
= NULL
;
8550 OSDictionary
* kextInfo
= NULL
; // must release
8552 uint32_t idCount
= 0;
8553 uint32_t idIndex
= 0;
8555 IORecursiveLockLock(sKextLock
);
8558 /* Is the calling process allowed to query kext info? */
8559 if (current_task() != kernel_task
) {
8560 int macCheckResult
= 0;
8561 kauth_cred_t cred
= NULL
;
8563 cred
= kauth_cred_get_with_ref();
8564 macCheckResult
= mac_kext_check_query(cred
);
8565 kauth_cred_unref(&cred
);
8567 if (macCheckResult
!= 0) {
8568 OSKextLog(/* kext */ NULL
,
8569 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8570 "Failed to query kext info (MAC policy error 0x%x).",
8577 /* Empty list of bundle ids is equivalent to no list (get all).
8579 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8580 kextIdentifiers
= NULL
;
8581 } else if (kextIdentifiers
) {
8582 idCount
= kextIdentifiers
->getCount();
8587 if (infoKeys
&& !infoKeys
->getCount()) {
8591 count
= sLoadedKexts
->getCount();
8592 result
= OSDictionary::withCapacity(count
);
8598 OSKextLog(/* kext */ NULL
,
8599 kOSKextLogErrorLevel
|
8600 kOSKextLogGeneralFlag
,
8601 "kaslr: vm_kernel_slide 0x%lx \n",
8603 OSKextLog(/* kext */ NULL
,
8604 kOSKextLogErrorLevel
|
8605 kOSKextLogGeneralFlag
,
8606 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
8607 vm_kernel_stext
, vm_kernel_etext
);
8608 OSKextLog(/* kext */ NULL
,
8609 kOSKextLogErrorLevel
|
8610 kOSKextLogGeneralFlag
,
8611 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
8612 vm_kernel_base
, vm_kernel_top
);
8613 OSKextLog(/* kext */ NULL
,
8614 kOSKextLogErrorLevel
|
8615 kOSKextLogGeneralFlag
,
8616 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
8617 vm_kext_base
, vm_kext_top
);
8618 OSKextLog(/* kext */ NULL
,
8619 kOSKextLogErrorLevel
|
8620 kOSKextLogGeneralFlag
,
8621 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
8622 vm_prelink_stext
, vm_prelink_etext
);
8623 OSKextLog(/* kext */ NULL
,
8624 kOSKextLogErrorLevel
|
8625 kOSKextLogGeneralFlag
,
8626 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
8627 vm_prelink_sinfo
, vm_prelink_einfo
);
8628 OSKextLog(/* kext */ NULL
,
8629 kOSKextLogErrorLevel
|
8630 kOSKextLogGeneralFlag
,
8631 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
8632 vm_slinkedit
, vm_elinkedit
);
8635 for (i
= 0; i
< count
; i
++) {
8636 OSKext
* thisKext
= NULL
; // do not release
8637 Boolean includeThis
= true;
8640 kextInfo
->release();
8643 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8648 /* Skip current kext if we have a list of bundle IDs and
8649 * it isn't in the list.
8651 if (kextIdentifiers
) {
8652 const OSString
* thisKextID
= thisKext
->getIdentifier();
8654 includeThis
= false;
8656 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8657 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
8658 kextIdentifiers
->getObject(idIndex
));
8659 if (thisKextID
->isEqualTo(thisRequestID
)) {
8670 kextInfo
= thisKext
->copyInfo(infoKeys
);
8672 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
8677 IORecursiveLockUnlock(sKextLock
);
8679 if (kextInfo
) kextInfo
->release();
8684 /*********************************************************************
8685 * Any info that needs to do allocations must goto finish on alloc
8686 * failure. Info that is just a lookup should just not set the object
8687 * if the info does not exist.
8688 *********************************************************************/
8689 #define _OSKextLoadInfoDictCapacity (12)
8692 OSKext::copyInfo(OSArray
* infoKeys
)
8694 OSDictionary
* result
= NULL
;
8695 bool success
= false;
8696 OSData
* headerData
= NULL
; // must release
8697 OSData
* logData
= NULL
; // must release
8698 OSNumber
* cpuTypeNumber
= NULL
; // must release
8699 OSNumber
* cpuSubtypeNumber
= NULL
; // must release
8700 OSString
* versionString
= NULL
; // do not release
8701 uint32_t executablePathCStringSize
= 0;
8702 char * executablePathCString
= NULL
; // must release
8703 OSString
* executablePathString
= NULL
; // must release
8704 OSData
* uuid
= NULL
; // must release
8705 OSNumber
* scratchNumber
= NULL
; // must release
8706 OSArray
* dependencyLoadTags
= NULL
; // must release
8707 OSCollectionIterator
* metaClassIterator
= NULL
; // must release
8708 OSArray
* metaClassInfo
= NULL
; // must release
8709 OSDictionary
* metaClassDict
= NULL
; // must release
8710 OSMetaClass
* thisMetaClass
= NULL
; // do not release
8711 OSString
* metaClassName
= NULL
; // must release
8712 OSString
* superclassName
= NULL
; // must release
8715 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
8721 /* Empty keys means no keys, but NULL is quicker to check.
8723 if (infoKeys
&& !infoKeys
->getCount()) {
8727 /* Headers, CPU type, and CPU subtype.
8730 _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) ||
8731 _OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
) ||
8732 _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) ||
8733 _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
))
8736 if (linkedExecutable
&& !isInterface()) {
8738 kernel_mach_header_t
*kext_mach_hdr
= (kernel_mach_header_t
*)
8739 linkedExecutable
->getBytesNoCopy();
8742 // do not return macho header info on shipping iOS - 19095897
8743 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) {
8744 kernel_mach_header_t
* temp_kext_mach_hdr
;
8745 struct load_command
* lcp
;
8747 headerData
= OSData::withBytes(kext_mach_hdr
,
8748 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
8753 // unslide any vmaddrs we return to userspace - 10726716
8754 temp_kext_mach_hdr
= (kernel_mach_header_t
*)
8755 headerData
->getBytesNoCopy();
8756 if (temp_kext_mach_hdr
== NULL
) {
8760 lcp
= (struct load_command
*) (temp_kext_mach_hdr
+ 1);
8761 for (i
= 0; i
< temp_kext_mach_hdr
->ncmds
; i
++) {
8762 if (lcp
->cmd
== LC_SEGMENT_KERNEL
) {
8763 kernel_segment_command_t
* segp
;
8764 kernel_section_t
* secp
;
8766 segp
= (kernel_segment_command_t
*) lcp
;
8767 // 10543468 - if we jettisoned __LINKEDIT clear size info
8768 if (flags
.jettisonLinkeditSeg
) {
8769 if (strncmp(segp
->segname
, SEG_LINKEDIT
, sizeof(segp
->segname
)) == 0) {
8776 OSKextLog(/* kext */ NULL
,
8777 kOSKextLogErrorLevel
|
8778 kOSKextLogGeneralFlag
,
8779 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
8780 __FUNCTION__
, segp
->segname
, segp
->vmaddr
,
8781 VM_KERNEL_UNSLIDE(segp
->vmaddr
),
8782 segp
->vmsize
, segp
->nsects
);
8783 if ( (VM_KERNEL_IS_SLID(segp
->vmaddr
) == false) &&
8784 (VM_KERNEL_IS_KEXT(segp
->vmaddr
) == false) &&
8785 (VM_KERNEL_IS_PRELINKTEXT(segp
->vmaddr
) == false) &&
8786 (VM_KERNEL_IS_PRELINKINFO(segp
->vmaddr
) == false) &&
8787 (VM_KERNEL_IS_KEXT_LINKEDIT(segp
->vmaddr
) == false) ) {
8788 OSKextLog(/* kext */ NULL
,
8789 kOSKextLogErrorLevel
|
8790 kOSKextLogGeneralFlag
,
8791 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
8792 __FUNCTION__
, segp
->vmaddr
, vm_kext_base
, vm_kext_top
);
8795 segp
->vmaddr
= VM_KERNEL_UNSLIDE(segp
->vmaddr
);
8797 for (secp
= firstsect(segp
); secp
!= NULL
; secp
= nextsect(segp
, secp
)) {
8798 secp
->addr
= VM_KERNEL_UNSLIDE(secp
->addr
);
8801 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
8803 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
8805 #endif // SECURE_KERNEL
8807 if (_OSArrayContainsCString(infoKeys
, kOSBundleLogStringsKey
)) {
8808 osLogDataHeaderRef
*header
;
8809 char headerBytes
[offsetof(osLogDataHeaderRef
, sections
) + NUM_OS_LOG_SECTIONS
* sizeof(header
->sections
[0])];
8811 void *os_log_data
= NULL
;
8812 void *cstring_data
= NULL
;
8813 unsigned long os_log_size
= 0;
8814 unsigned long cstring_size
= 0;
8815 uint32_t os_log_offset
= 0;
8816 uint32_t cstring_offset
= 0;
8819 os_log_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__os_log", &os_log_size
);
8820 os_log_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__os_log");
8821 cstring_data
= getsectdatafromheader(kext_mach_hdr
, "__TEXT", "__cstring", &cstring_size
);
8822 cstring_offset
= getsectoffsetfromheader(kext_mach_hdr
, "__TEXT", "__cstring");
8824 header
= (osLogDataHeaderRef
*) headerBytes
;
8825 header
->version
= OS_LOG_HDR_VERSION
;
8826 header
->sect_count
= NUM_OS_LOG_SECTIONS
;
8827 header
->sections
[OS_LOG_SECT_IDX
].sect_offset
= os_log_offset
;
8828 header
->sections
[OS_LOG_SECT_IDX
].sect_size
= (uint32_t) os_log_size
;
8829 header
->sections
[CSTRING_SECT_IDX
].sect_offset
= cstring_offset
;
8830 header
->sections
[CSTRING_SECT_IDX
].sect_size
= (uint32_t) cstring_size
;
8833 logData
= OSData::withBytes(header
, (u_int
) (sizeof(osLogDataHeaderRef
)));
8837 res
= logData
->appendBytes(&(header
->sections
[0]), (u_int
)(header
->sect_count
* sizeof(header
->sections
[0])));
8842 res
= logData
->appendBytes(os_log_data
, (u_int
)header
->sections
[OS_LOG_SECT_IDX
].sect_size
);
8848 res
= logData
->appendBytes(cstring_data
, (u_int
)header
->sections
[CSTRING_SECT_IDX
].sect_size
);
8853 result
->setObject(kOSBundleLogStringsKey
, logData
);
8856 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) {
8857 cpuTypeNumber
= OSNumber::withNumber(
8858 (uint64_t) kext_mach_hdr
->cputype
,
8859 8 * sizeof(kext_mach_hdr
->cputype
));
8860 if (!cpuTypeNumber
) {
8863 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
8866 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
8867 cpuSubtypeNumber
= OSNumber::withNumber(
8868 (uint64_t) kext_mach_hdr
->cpusubtype
,
8869 8 * sizeof(kext_mach_hdr
->cpusubtype
));
8870 if (!cpuSubtypeNumber
) {
8873 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
8878 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
8880 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
8884 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
8885 versionString
= OSDynamicCast(OSString
,
8886 getPropertyForHostArch(kCFBundleVersionKey
));
8887 if (versionString
) {
8888 result
->setObject(kCFBundleVersionKey
, versionString
);
8892 /* OSBundleCompatibleVersion.
8894 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
8895 versionString
= OSDynamicCast(OSString
,
8896 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
8897 if (versionString
) {
8898 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
8904 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
8906 result
->setObject(kOSBundlePathKey
, path
);
8911 /* OSBundleExecutablePath.
8913 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
8914 if (path
&& executableRelPath
) {
8916 uint32_t pathLength
= path
->getLength(); // gets incremented below
8918 // +1 for slash, +1 for \0
8919 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
8921 executablePathCString
= (char *)kalloc_tag((executablePathCStringSize
) *
8922 sizeof(char), VM_KERN_MEMORY_OSKEXT
); // +1 for \0
8923 if (!executablePathCString
) {
8926 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
8927 executablePathCStringSize
);
8928 executablePathCString
[pathLength
++] = '/';
8929 executablePathCString
[pathLength
++] = '\0';
8930 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
8931 executablePathCStringSize
);
8933 executablePathString
= OSString::withCString(executablePathCString
);
8935 if (!executablePathString
) {
8939 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
8943 /* UUID, if the kext has one.
8945 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
8948 result
->setObject(kOSBundleUUIDKey
, uuid
);
8953 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
8955 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSKernelResourceKey
)) {
8956 result
->setObject(kOSKernelResourceKey
,
8957 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
8960 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
8961 result
->setObject(kOSBundleIsInterfaceKey
,
8962 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
8965 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
8966 result
->setObject(kOSBundlePrelinkedKey
,
8967 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
8970 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
8971 result
->setObject(kOSBundleStartedKey
,
8972 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
8977 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
8978 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
8979 /* numBits */ 8 * sizeof(loadTag
));
8980 if (!scratchNumber
) {
8983 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
8984 OSSafeReleaseNULL(scratchNumber
);
8987 /* LoadAddress, LoadSize.
8990 _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) ||
8991 _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) ||
8992 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
) ||
8993 _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
) ||
8994 _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
))
8996 if (isInterface() || linkedExecutable
) {
8997 /* These go to userspace via serialization, so we don't want any doubts
9000 uint64_t loadAddress
= 0;
9001 uint32_t loadSize
= 0;
9002 uint32_t wiredSize
= 0;
9003 uint64_t execLoadAddress
= 0;
9004 uint32_t execLoadSize
= 0;
9006 /* Interfaces always report 0 load address & size.
9007 * Just the way they roll.
9009 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
9010 * xxx - shouldn't have one!
9012 if (linkedExecutable
/* && !isInterface() */) {
9013 kernel_mach_header_t
*mh
= NULL
;
9014 kernel_segment_command_t
*seg
= NULL
;
9016 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
9017 mh
= (kernel_mach_header_t
*)loadAddress
;
9018 loadAddress
= VM_KERNEL_UNSLIDE(loadAddress
);
9019 loadSize
= linkedExecutable
->getLength();
9021 /* Walk through the kext, looking for the first executable
9022 * segment in case we were asked for its size/address.
9024 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
9025 if (seg
->initprot
& VM_PROT_EXECUTE
) {
9026 execLoadAddress
= VM_KERNEL_UNSLIDE(seg
->vmaddr
);
9027 execLoadSize
= seg
->vmsize
;
9032 /* If we have a kmod_info struct, calculated the wired size
9033 * from that. Otherwise it's the full load size.
9036 wiredSize
= loadSize
- kmod_info
->hdr_size
;
9038 wiredSize
= loadSize
;
9042 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
9043 scratchNumber
= OSNumber::withNumber(
9044 (unsigned long long)(loadAddress
),
9045 /* numBits */ 8 * sizeof(loadAddress
));
9046 if (!scratchNumber
) {
9049 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
9050 OSSafeReleaseNULL(scratchNumber
);
9052 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadAddressKey
)) {
9053 scratchNumber
= OSNumber::withNumber(
9054 (unsigned long long)(execLoadAddress
),
9055 /* numBits */ 8 * sizeof(execLoadAddress
));
9056 if (!scratchNumber
) {
9059 result
->setObject(kOSBundleExecLoadAddressKey
, scratchNumber
);
9060 OSSafeReleaseNULL(scratchNumber
);
9062 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
9063 scratchNumber
= OSNumber::withNumber(
9064 (unsigned long long)(loadSize
),
9065 /* numBits */ 8 * sizeof(loadSize
));
9066 if (!scratchNumber
) {
9069 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
9070 OSSafeReleaseNULL(scratchNumber
);
9072 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecLoadSizeKey
)) {
9073 scratchNumber
= OSNumber::withNumber(
9074 (unsigned long long)(execLoadSize
),
9075 /* numBits */ 8 * sizeof(execLoadSize
));
9076 if (!scratchNumber
) {
9079 result
->setObject(kOSBundleExecLoadSizeKey
, scratchNumber
);
9080 OSSafeReleaseNULL(scratchNumber
);
9082 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
9083 scratchNumber
= OSNumber::withNumber(
9084 (unsigned long long)(wiredSize
),
9085 /* numBits */ 8 * sizeof(wiredSize
));
9086 if (!scratchNumber
) {
9089 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
9090 OSSafeReleaseNULL(scratchNumber
);
9095 /* OSBundleDependencies. In descending order for
9096 * easy compatibility with kextstat(8).
9098 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
9099 if ((count
= getNumDependencies())) {
9100 dependencyLoadTags
= OSArray::withCapacity(count
);
9101 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
9105 OSKext
* dependency
= OSDynamicCast(OSKext
,
9106 dependencies
->getObject(i
));
9108 OSSafeReleaseNULL(scratchNumber
);
9113 scratchNumber
= OSNumber::withNumber(
9114 (unsigned long long)dependency
->getLoadTag(),
9115 /* numBits*/ 8 * sizeof(loadTag
));
9116 if (!scratchNumber
) {
9119 dependencyLoadTags
->setObject(scratchNumber
);
9124 OSSafeReleaseNULL(scratchNumber
);
9126 /* OSBundleMetaClasses.
9128 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) {
9129 if (metaClasses
&& metaClasses
->getCount()) {
9130 metaClassIterator
= OSCollectionIterator::withCollection(metaClasses
);
9131 metaClassInfo
= OSArray::withCapacity(metaClasses
->getCount());
9132 if (!metaClassIterator
|| !metaClassInfo
) {
9135 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
9137 while ( (thisMetaClass
= OSDynamicCast(OSMetaClass
,
9138 metaClassIterator
->getNextObject())) ) {
9140 OSSafeReleaseNULL(metaClassDict
);
9141 OSSafeReleaseNULL(scratchNumber
);
9142 OSSafeReleaseNULL(metaClassName
);
9143 OSSafeReleaseNULL(superclassName
);
9145 metaClassDict
= OSDictionary::withCapacity(3);
9146 if (!metaClassDict
) {
9150 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
9151 if (thisMetaClass
->getSuperClass()) {
9152 superclassName
= OSString::withCString(
9153 thisMetaClass
->getSuperClass()->getClassName());
9155 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
9156 8 * sizeof(unsigned int));
9158 /* Bail if any of the essentials is missing. The root class lacks a superclass,
9161 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
9165 metaClassInfo
->setObject(metaClassDict
);
9166 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
9167 if (superclassName
) {
9168 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
9170 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
9175 /* OSBundleRetainCount.
9177 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
9178 OSSafeReleaseNULL(scratchNumber
);
9180 int kextRetainCount
= getRetainCount() - 1;
9184 scratchNumber
= OSNumber::withNumber(
9185 (int)kextRetainCount
,
9186 /* numBits*/ 8 * sizeof(int));
9187 if (scratchNumber
) {
9188 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
9196 OSSafeReleaseNULL(headerData
);
9197 OSSafeReleaseNULL(logData
);
9198 OSSafeReleaseNULL(cpuTypeNumber
);
9199 OSSafeReleaseNULL(cpuSubtypeNumber
);
9200 OSSafeReleaseNULL(executablePathString
);
9201 if (executablePathCString
) kfree(executablePathCString
, executablePathCStringSize
);
9202 OSSafeReleaseNULL(uuid
);
9203 OSSafeReleaseNULL(scratchNumber
);
9204 OSSafeReleaseNULL(dependencyLoadTags
);
9205 OSSafeReleaseNULL(metaClassIterator
);
9206 OSSafeReleaseNULL(metaClassInfo
);
9207 OSSafeReleaseNULL(metaClassDict
);
9208 OSSafeReleaseNULL(metaClassName
);
9209 OSSafeReleaseNULL(superclassName
);
9211 OSSafeReleaseNULL(result
);
9216 /*********************************************************************
9217 *********************************************************************/
9220 OSKext::requestResource(
9221 const char * kextIdentifierCString
,
9222 const char * resourceNameCString
,
9223 OSKextRequestResourceCallback callback
,
9225 OSKextRequestTag
* requestTagOut
)
9227 OSReturn result
= kOSReturnError
;
9228 OSKext
* callbackKext
= NULL
; // must release (looked up)
9230 OSKextRequestTag requestTag
= -1;
9231 OSNumber
* requestTagNum
= NULL
; // must release
9233 OSDictionary
* requestDict
= NULL
; // must release
9234 OSString
* kextIdentifier
= NULL
; // must release
9235 OSString
* resourceName
= NULL
; // must release
9237 OSDictionary
* callbackRecord
= NULL
; // must release
9238 OSData
* callbackWrapper
= NULL
; // must release
9240 OSData
* contextWrapper
= NULL
; // must release
9242 IORecursiveLockLock(sKextLock
);
9244 if (requestTagOut
) {
9245 *requestTagOut
= kOSKextRequestTagInvalid
;
9248 /* If requests to user space are disabled, don't go any further */
9249 if (!sKernelRequestsEnabled
) {
9250 OSKextLog(/* kext */ NULL
,
9251 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9252 "Can't request resource %s for %s - requests to user space are disabled.",
9253 resourceNameCString
,
9254 kextIdentifierCString
);
9255 result
= kOSKextReturnDisabled
;
9259 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
9260 result
= kOSKextReturnInvalidArgument
;
9264 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9265 if (!callbackKext
) {
9266 OSKextLog(/* kext */ NULL
,
9267 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9268 "Resource request has bad callback address.");
9269 result
= kOSKextReturnInvalidArgument
;
9272 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9273 OSKextLog(/* kext */ NULL
,
9274 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9275 "Resource request callback is in a kext that is not started.");
9276 result
= kOSKextReturnInvalidArgument
;
9280 /* Do not allow any new requests to be made on a kext that is unloading.
9282 if (callbackKext
->flags
.stopping
) {
9283 result
= kOSKextReturnStopping
;
9287 /* If we're wrapped the next available request tag around to the negative
9288 * numbers, we can't service any more requests.
9290 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
9291 OSKextLog(/* kext */ NULL
,
9292 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9293 "No more request tags available; restart required.");
9294 result
= kOSKextReturnNoResources
;
9297 requestTag
= sNextRequestTag
++;
9299 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
9301 if (result
!= kOSReturnSuccess
) {
9305 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
9306 resourceName
= OSString::withCString(resourceNameCString
);
9307 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9308 8 * sizeof(requestTag
));
9309 if (!kextIdentifier
||
9312 !_OSKextSetRequestArgument(requestDict
,
9313 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
9314 !_OSKextSetRequestArgument(requestDict
,
9315 kKextRequestArgumentNameKey
, resourceName
) ||
9316 !_OSKextSetRequestArgument(requestDict
,
9317 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
9319 result
= kOSKextReturnNoMemory
;
9323 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
9324 if (!callbackRecord
) {
9325 result
= kOSKextReturnNoMemory
;
9328 // we validate callback address at call time
9329 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
9331 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
9333 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9334 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
9336 result
= kOSKextReturnNoMemory
;
9341 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
9342 kKextRequestArgumentContextKey
, contextWrapper
)) {
9344 result
= kOSKextReturnNoMemory
;
9349 /* Only post the requests after all the other potential failure points
9352 if (!sKernelRequests
->setObject(requestDict
) ||
9353 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
9355 result
= kOSKextReturnNoMemory
;
9359 OSKext::pingKextd();
9361 result
= kOSReturnSuccess
;
9362 if (requestTagOut
) {
9363 *requestTagOut
= requestTag
;
9368 /* If we didn't succeed, yank the request & callback
9369 * from their holding arrays.
9371 if (result
!= kOSReturnSuccess
) {
9374 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
9375 if (index
!= (unsigned int)-1) {
9376 sKernelRequests
->removeObject(index
);
9378 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
9379 if (index
!= (unsigned int)-1) {
9380 sRequestCallbackRecords
->removeObject(index
);
9384 OSKext::considerUnloads(/* rescheduleOnly? */ true);
9386 IORecursiveLockUnlock(sKextLock
);
9388 if (callbackKext
) callbackKext
->release();
9389 if (requestTagNum
) requestTagNum
->release();
9391 if (requestDict
) requestDict
->release();
9392 if (kextIdentifier
) kextIdentifier
->release();
9393 if (resourceName
) resourceName
->release();
9395 if (callbackRecord
) callbackRecord
->release();
9396 if (callbackWrapper
) callbackWrapper
->release();
9397 if (contextWrapper
) contextWrapper
->release();
9402 /*********************************************************************
9403 * Assumes sKextLock is held.
9404 *********************************************************************/
9407 OSKext::dequeueCallbackForRequestTag(
9408 OSKextRequestTag requestTag
,
9409 OSDictionary
** callbackRecordOut
)
9411 OSReturn result
= kOSReturnError
;
9412 OSNumber
* requestTagNum
= NULL
; // must release
9414 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
9415 8 * sizeof(requestTag
));
9416 if (!requestTagNum
) {
9420 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
9424 OSSafeReleaseNULL(requestTagNum
);
9429 /*********************************************************************
9430 * Assumes sKextLock is held.
9431 *********************************************************************/
9434 OSKext::dequeueCallbackForRequestTag(
9435 OSNumber
* requestTagNum
,
9436 OSDictionary
** callbackRecordOut
)
9438 OSReturn result
= kOSKextReturnInvalidArgument
;
9439 OSDictionary
* callbackRecord
= NULL
; // retain if matched!
9440 OSNumber
* callbackTagNum
= NULL
; // do not release
9441 unsigned int count
, i
;
9443 result
= kOSReturnError
;
9444 count
= sRequestCallbackRecords
->getCount();
9445 for (i
= 0; i
< count
; i
++) {
9446 callbackRecord
= OSDynamicCast(OSDictionary
,
9447 sRequestCallbackRecords
->getObject(i
));
9448 if (!callbackRecord
) {
9452 /* If we don't find a tag, we basically have a leak here. Maybe
9453 * we should just remove it.
9455 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
9456 callbackRecord
, kKextRequestArgumentRequestTagKey
));
9457 if (!callbackTagNum
) {
9461 /* We could be even more paranoid and check that all the incoming
9462 * args match what's in the callback record.
9464 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
9465 if (callbackRecordOut
) {
9466 *callbackRecordOut
= callbackRecord
;
9467 callbackRecord
->retain();
9469 sRequestCallbackRecords
->removeObject(i
);
9470 result
= kOSReturnSuccess
;
9474 result
= kOSKextReturnNotFound
;
9480 /*********************************************************************
9481 * Assumes sKextLock is held.
9482 *********************************************************************/
9485 OSKext::dispatchResource(OSDictionary
* requestDict
)
9487 OSReturn result
= kOSReturnError
;
9488 OSDictionary
* callbackRecord
= NULL
; // must release
9489 OSNumber
* requestTag
= NULL
; // do not release
9490 OSNumber
* requestResult
= NULL
; // do not release
9491 OSData
* dataObj
= NULL
; // do not release
9492 uint32_t dataLength
= 0;
9493 const void * dataPtr
= NULL
; // do not free
9494 OSData
* callbackWrapper
= NULL
; // do not release
9495 OSKextRequestResourceCallback callback
= NULL
;
9496 OSData
* contextWrapper
= NULL
; // do not release
9497 void * context
= NULL
; // do not free
9498 OSKext
* callbackKext
= NULL
; // must release (looked up)
9500 /* Get the args from the request. Right now we need the tag
9501 * to look up the callback record, and the result for invoking the callback.
9503 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9504 kKextRequestArgumentRequestTagKey
));
9505 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9506 kKextRequestArgumentResultKey
));
9507 if (!requestTag
|| !requestResult
) {
9508 result
= kOSKextReturnInvalidArgument
;
9512 /* Look for a callback record matching this request's tag.
9514 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
9515 if (result
!= kOSReturnSuccess
) {
9520 * Get the context pointer of the callback record (if there is one).
9522 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
9523 kKextRequestArgumentContextKey
));
9524 context
= _OSKextExtractPointer(contextWrapper
);
9525 if (contextWrapper
&& !context
) {
9529 callbackWrapper
= OSDynamicCast(OSData
,
9530 _OSKextGetRequestArgument(callbackRecord
,
9531 kKextRequestArgumentCallbackKey
));
9532 callback
= (OSKextRequestResourceCallback
)
9533 _OSKextExtractPointer(callbackWrapper
);
9538 /* Check for a data obj. We might not have one and that's ok, that means
9539 * we didn't find the requested resource, and we still have to tell the
9540 * caller that via the callback.
9542 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
9543 kKextRequestArgumentValueKey
));
9545 dataPtr
= dataObj
->getBytesNoCopy();
9546 dataLength
= dataObj
->getLength();
9549 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9550 if (!callbackKext
) {
9551 OSKextLog(/* kext */ NULL
,
9552 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9553 "Can't invoke callback for resource request; ");
9556 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9557 OSKextLog(/* kext */ NULL
,
9558 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9559 "Can't invoke kext resource callback; ");
9563 (void)callback(requestTag
->unsigned32BitValue(),
9564 (OSReturn
)requestResult
->unsigned32BitValue(),
9565 dataPtr
, dataLength
, context
);
9567 result
= kOSReturnSuccess
;
9570 if (callbackKext
) callbackKext
->release();
9571 if (callbackRecord
) callbackRecord
->release();
9576 /*********************************************************************
9577 *********************************************************************/
9580 OSKext::invokeRequestCallback(
9581 OSDictionary
* callbackRecord
,
9582 OSReturn callbackResult
)
9584 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
9585 OSNumber
* resultNum
= NULL
; // must release
9591 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
9592 8 * sizeof(callbackResult
));
9597 /* Insert the result into the callback record and dispatch it as if it
9598 * were the reply coming down from user space.
9600 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
9603 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
9604 /* This removes the pending callback record.
9606 OSKext::dispatchResource(callbackRecord
);
9610 if (resultNum
) resultNum
->release();
9614 /*********************************************************************
9615 * Assumes sKextLock is held.
9616 *********************************************************************/
9619 OSKext::cancelRequest(
9620 OSKextRequestTag requestTag
,
9623 OSReturn result
= kOSKextReturnNoMemory
;
9624 OSDictionary
* callbackRecord
= NULL
; // must release
9625 OSData
* contextWrapper
= NULL
; // do not release
9627 IORecursiveLockLock(sKextLock
);
9628 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
9630 IORecursiveLockUnlock(sKextLock
);
9632 if (result
== kOSReturnSuccess
&& contextOut
) {
9633 contextWrapper
= OSDynamicCast(OSData
,
9634 _OSKextGetRequestArgument(callbackRecord
,
9635 kKextRequestArgumentContextKey
));
9636 *contextOut
= _OSKextExtractPointer(contextWrapper
);
9639 if (callbackRecord
) callbackRecord
->release();
9644 /*********************************************************************
9645 * Assumes sKextLock is held.
9646 *********************************************************************/
9648 OSKext::invokeOrCancelRequestCallbacks(
9649 OSReturn callbackResult
,
9652 unsigned int count
, i
;
9654 count
= sRequestCallbackRecords
->getCount();
9661 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9662 sRequestCallbackRecords
->getObject(i
));
9667 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9668 _OSKextGetRequestArgument(request
,
9669 kKextRequestArgumentCallbackKey
));
9671 if (!callbackWrapper
) {
9672 sRequestCallbackRecords
->removeObject(i
);
9676 vm_address_t callbackAddress
= (vm_address_t
)
9677 _OSKextExtractPointer(callbackWrapper
);
9679 if ((kmod_info
->address
<= callbackAddress
) &&
9680 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9683 /* This removes the callback record.
9685 invokeRequestCallback(request
, callbackResult
);
9687 sRequestCallbackRecords
->removeObject(i
);
9696 /*********************************************************************
9697 * Assumes sKextLock is held.
9698 *********************************************************************/
9700 OSKext::countRequestCallbacks(void)
9702 uint32_t result
= 0;
9703 unsigned int count
, i
;
9705 count
= sRequestCallbackRecords
->getCount();
9712 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9713 sRequestCallbackRecords
->getObject(i
));
9718 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9719 _OSKextGetRequestArgument(request
,
9720 kKextRequestArgumentCallbackKey
));
9722 if (!callbackWrapper
) {
9726 vm_address_t callbackAddress
= (vm_address_t
)
9727 _OSKextExtractPointer(callbackWrapper
);
9729 if ((kmod_info
->address
<= callbackAddress
) &&
9730 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9740 /*********************************************************************
9741 *********************************************************************/
9742 static OSReturn
_OSKextCreateRequest(
9743 const char * predicate
,
9744 OSDictionary
** requestP
)
9746 OSReturn result
= kOSKextReturnNoMemory
;
9747 OSDictionary
* request
= NULL
; // must release on error
9749 request
= OSDictionary::withCapacity(2);
9753 result
= _OSDictionarySetCStringValue(request
,
9754 kKextRequestPredicateKey
, predicate
);
9755 if (result
!= kOSReturnSuccess
) {
9758 result
= kOSReturnSuccess
;
9761 if (result
!= kOSReturnSuccess
) {
9762 if (request
) request
->release();
9764 *requestP
= request
;
9770 /*********************************************************************
9771 *********************************************************************/
9772 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
9774 return OSDynamicCast(OSString
,
9775 requestDict
->getObject(kKextRequestPredicateKey
));
9778 /*********************************************************************
9779 *********************************************************************/
9780 static OSObject
* _OSKextGetRequestArgument(
9781 OSDictionary
* requestDict
,
9782 const char * argName
)
9784 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9785 requestDict
->getObject(kKextRequestArgumentsKey
));
9787 return args
->getObject(argName
);
9792 /*********************************************************************
9793 *********************************************************************/
9794 static bool _OSKextSetRequestArgument(
9795 OSDictionary
* requestDict
,
9796 const char * argName
,
9799 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9800 requestDict
->getObject(kKextRequestArgumentsKey
));
9802 args
= OSDictionary::withCapacity(2);
9806 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
9810 return args
->setObject(argName
, value
);
9816 /*********************************************************************
9817 *********************************************************************/
9818 static void * _OSKextExtractPointer(OSData
* wrapper
)
9820 void * result
= NULL
;
9821 const void * resultPtr
= NULL
;
9826 resultPtr
= wrapper
->getBytesNoCopy();
9827 result
= *(void **)resultPtr
;
9832 /*********************************************************************
9833 *********************************************************************/
9834 static OSReturn
_OSDictionarySetCStringValue(
9835 OSDictionary
* dict
,
9837 const char * cValue
)
9839 OSReturn result
= kOSKextReturnNoMemory
;
9840 const OSSymbol
* key
= NULL
; // must release
9841 OSString
* value
= NULL
; // must release
9843 key
= OSSymbol::withCString(cKey
);
9844 value
= OSString::withCString(cValue
);
9845 if (!key
|| !value
) {
9848 if (dict
->setObject(key
, value
)) {
9849 result
= kOSReturnSuccess
;
9853 if (key
) key
->release();
9854 if (value
) value
->release();
9859 /*********************************************************************
9860 *********************************************************************/
9861 static bool _OSArrayContainsCString(
9863 const char * cString
)
9865 bool result
= false;
9866 const OSSymbol
* symbol
= NULL
;
9869 if (!array
|| !cString
) {
9873 symbol
= OSSymbol::withCStringNoCopy(cString
);
9878 count
= array
->getCount();
9879 for (i
= 0; i
< count
; i
++) {
9880 OSObject
* thisObject
= array
->getObject(i
);
9881 if (symbol
->isEqualTo(thisObject
)) {
9888 if (symbol
) symbol
->release();
9892 /*********************************************************************
9893 * We really only care about boot / system start up related kexts.
9894 * We return true if we're less than REBUILD_MAX_TIME since start up,
9895 * otherwise return false.
9896 *********************************************************************/
9897 bool _OSKextInPrelinkRebuildWindow(void)
9899 static bool outside_the_window
= false;
9900 AbsoluteTime my_abstime
;
9904 if (outside_the_window
) {
9907 clock_get_uptime(&my_abstime
);
9908 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
9909 my_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
9910 if (my_secs
> REBUILD_MAX_TIME
) {
9911 outside_the_window
= true;
9917 /*********************************************************************
9918 *********************************************************************/
9919 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
9921 int unLoadedCount
, i
;
9922 bool result
= false;
9924 IORecursiveLockLock(sKextLock
);
9926 if (sUnloadedPrelinkedKexts
== NULL
) {
9929 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
9930 if (unLoadedCount
== 0) {
9934 for (i
= 0; i
< unLoadedCount
; i
++) {
9935 const OSSymbol
* myBundleID
; // do not release
9937 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
9938 if (!myBundleID
) continue;
9939 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
9945 IORecursiveLockUnlock(sKextLock
);
9950 #pragma mark Personalities (IOKit Drivers)
9952 /*********************************************************************
9953 *********************************************************************/
9956 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
9958 OSArray
* result
= NULL
; // returned
9959 OSCollectionIterator
* kextIterator
= NULL
; // must release
9960 OSArray
* personalities
= NULL
; // must release
9961 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
9963 OSString
* kextID
= NULL
; // do not release
9964 OSKext
* theKext
= NULL
; // do not release
9966 IORecursiveLockLock(sKextLock
);
9968 /* Let's conservatively guess that any given kext has around 3
9969 * personalities for now.
9971 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
9976 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
9977 if (!kextIterator
) {
9981 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
9982 if (personalitiesIterator
) {
9983 personalitiesIterator
->release();
9984 personalitiesIterator
= NULL
;
9986 if (personalities
) {
9987 personalities
->release();
9988 personalities
= NULL
;
9991 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
9992 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
9993 personalities
= theKext
->copyPersonalitiesArray();
9994 if (!personalities
) {
9997 result
->merge(personalities
);
9999 // xxx - check for better place to put this log msg
10001 kOSKextLogWarningLevel
|
10002 kOSKextLogLoadFlag
,
10003 "Kext %s is not loadable during safe boot; "
10004 "omitting its personalities.",
10005 theKext
->getIdentifierCString());
10011 IORecursiveLockUnlock(sKextLock
);
10013 if (kextIterator
) kextIterator
->release();
10014 if (personalitiesIterator
) personalitiesIterator
->release();
10015 if (personalities
) personalities
->release();
10020 /*********************************************************************
10021 *********************************************************************/
10024 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
10026 int numPersonalities
= 0;
10028 OSKextLog(/* kext */ NULL
,
10029 kOSKextLogStepLevel
|
10030 kOSKextLogLoadFlag
,
10031 "Sending all eligible registered kexts' personalities "
10032 "to the IOCatalogue %s.",
10033 startMatching
? "and starting matching" : "but not starting matching");
10035 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
10036 /* filterSafeBootFlag */ true);
10038 if (personalities
) {
10039 gIOCatalogue
->addDrivers(personalities
, startMatching
);
10040 numPersonalities
= personalities
->getCount();
10041 personalities
->release();
10044 OSKextLog(/* kext */ NULL
,
10045 kOSKextLogStepLevel
|
10046 kOSKextLogLoadFlag
,
10047 "%d kext personalit%s sent to the IOCatalogue; %s.",
10048 numPersonalities
, numPersonalities
> 0 ? "ies" : "y",
10049 startMatching
? "matching started" : "matching not started");
10053 /*********************************************************************
10054 * Do not make a deep copy, just convert the IOKitPersonalities dict
10055 * to an array for sending to the IOCatalogue.
10056 *********************************************************************/
10058 OSKext::copyPersonalitiesArray(void)
10060 OSArray
* result
= NULL
;
10061 OSDictionary
* personalities
= NULL
; // do not release
10062 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
10064 OSString
* personalityName
= NULL
; // do not release
10065 OSString
* personalityBundleIdentifier
= NULL
; // do not release
10067 personalities
= OSDynamicCast(OSDictionary
,
10068 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10069 if (!personalities
) {
10073 result
= OSArray::withCapacity(personalities
->getCount());
10078 personalitiesIterator
=
10079 OSCollectionIterator::withCollection(personalities
);
10080 if (!personalitiesIterator
) {
10083 while ((personalityName
= OSDynamicCast(OSString
,
10084 personalitiesIterator
->getNextObject()))) {
10086 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10087 personalities
->getObject(personalityName
));
10090 * If the personality doesn't have a CFBundleIdentifier, or if it
10091 * differs from the kext's, insert the kext's ID so we can find it.
10092 * The publisher ID is used to remove personalities from bundles
10095 personalityBundleIdentifier
= OSDynamicCast(OSString
,
10096 personality
->getObject(kCFBundleIdentifierKey
));
10098 if (!personalityBundleIdentifier
) {
10099 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
10100 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
10101 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
10104 result
->setObject(personality
);
10108 if (personalitiesIterator
) personalitiesIterator
->release();
10113 /*********************************************************************
10114 Might want to change this to a bool return?
10115 *********************************************************************/
10117 OSKext::sendPersonalitiesToCatalog(
10118 bool startMatching
,
10119 OSArray
* personalityNames
)
10121 OSReturn result
= kOSReturnSuccess
;
10122 OSArray
* personalitiesToSend
= NULL
; // must release
10123 OSDictionary
* kextPersonalities
= NULL
; // do not release
10126 if (!sLoadEnabled
) {
10128 kOSKextLogErrorLevel
|
10129 kOSKextLogLoadFlag
,
10130 "Kext loading is disabled (attempt to start matching for kext %s).",
10131 getIdentifierCString());
10132 result
= kOSKextReturnDisabled
;
10136 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
10138 kOSKextLogErrorLevel
|
10139 kOSKextLogLoadFlag
,
10140 "Kext %s is not loadable during safe boot; "
10141 "not sending personalities to the IOCatalogue.",
10142 getIdentifierCString());
10143 result
= kOSKextReturnNotLoadable
;
10147 if (!personalityNames
|| !personalityNames
->getCount()) {
10148 personalitiesToSend
= copyPersonalitiesArray();
10150 kextPersonalities
= OSDynamicCast(OSDictionary
,
10151 getPropertyForHostArch(kIOKitPersonalitiesKey
));
10152 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
10156 personalitiesToSend
= OSArray::withCapacity(0);
10157 if (!personalitiesToSend
) {
10158 result
= kOSKextReturnNoMemory
;
10161 count
= personalityNames
->getCount();
10162 for (i
= 0; i
< count
; i
++) {
10163 OSString
* name
= OSDynamicCast(OSString
,
10164 personalityNames
->getObject(i
));
10168 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
10169 kextPersonalities
->getObject(name
));
10171 personalitiesToSend
->setObject(personality
);
10175 if (personalitiesToSend
) {
10176 unsigned numPersonalities
= personalitiesToSend
->getCount();
10178 kOSKextLogStepLevel
|
10179 kOSKextLogLoadFlag
,
10180 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
10181 getIdentifierCString(),
10183 numPersonalities
> 1 ? "ies" : "y",
10184 startMatching
? " and starting matching" : " but not starting matching");
10185 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
10188 if (personalitiesToSend
) {
10189 personalitiesToSend
->release();
10194 /*********************************************************************
10195 * xxx - We should allow removing the kext's declared personalities,
10196 * xxx - even with other bundle identifiers.
10197 *********************************************************************/
10199 OSKext::removePersonalitiesFromCatalog(void)
10201 OSDictionary
* personality
= NULL
; // do not release
10203 personality
= OSDictionary::withCapacity(1);
10204 if (!personality
) {
10207 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
10210 kOSKextLogStepLevel
|
10211 kOSKextLogLoadFlag
,
10212 "Kext %s removing all personalities naming it from the IOCatalogue.",
10213 getIdentifierCString());
10215 /* Have the IOCatalog remove all personalities matching this kext's
10216 * bundle ID and trigger matching anew.
10218 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
10221 if (personality
) personality
->release();
10228 #pragma mark Logging
10230 /*********************************************************************
10231 * Do not call any function that takes sKextLock here!
10232 *********************************************************************/
10235 OSKext::setUserSpaceLogFilter(
10236 OSKextLogSpec newUserLogFilter
,
10239 OSKextLogSpec result
;
10240 bool allocError
= false;
10242 /* Do not call any function that takes sKextLoggingLock during
10243 * this critical block. That means do logging after.
10245 IOLockLock(sKextLoggingLock
);
10247 result
= sUserSpaceKextLogFilter
;
10248 sUserSpaceKextLogFilter
= newUserLogFilter
;
10250 if (newUserLogFilter
&& captureFlag
&&
10251 !sUserSpaceLogSpecArray
&& !sUserSpaceLogMessageArray
) {
10253 // xxx - do some measurements for a good initial capacity?
10254 sUserSpaceLogSpecArray
= OSArray::withCapacity(0);
10255 sUserSpaceLogMessageArray
= OSArray::withCapacity(0);
10257 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
10258 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10259 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10264 IOLockUnlock(sKextLoggingLock
);
10266 /* If the config flag itself is changing, log the state change
10267 * going both ways, before setting up the user-space log arrays,
10268 * so that this is only logged in the kernel.
10270 if (result
!= newUserLogFilter
) {
10271 OSKextLog(/* kext */ NULL
,
10272 kOSKextLogDebugLevel
|
10273 kOSKextLogGeneralFlag
,
10274 "User-space log flags changed from 0x%x to 0x%x.",
10275 result
, newUserLogFilter
);
10278 OSKextLog(/* kext */ NULL
,
10279 kOSKextLogErrorLevel
|
10280 kOSKextLogGeneralFlag
,
10281 "Failed to allocate user-space log message arrays.");
10287 /*********************************************************************
10288 * Do not call any function that takes sKextLock here!
10289 *********************************************************************/
10292 OSKext::clearUserSpaceLogFilter(void)
10294 OSArray
* result
= NULL
;
10295 OSKextLogSpec oldLogFilter
;
10296 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
10298 /* Do not call any function that takes sKextLoggingLock during
10299 * this critical block. That means do logging after.
10301 IOLockLock(sKextLoggingLock
);
10303 result
= OSArray::withCapacity(2);
10305 result
->setObject(sUserSpaceLogSpecArray
);
10306 result
->setObject(sUserSpaceLogMessageArray
);
10308 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
10309 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
10311 oldLogFilter
= sUserSpaceKextLogFilter
;
10312 sUserSpaceKextLogFilter
= newLogFilter
;
10314 IOLockUnlock(sKextLoggingLock
);
10316 /* If the config flag itself is changing, log the state change
10317 * going both ways, after tearing down the user-space log
10318 * arrays, so this is only logged within the kernel.
10320 if (oldLogFilter
!= newLogFilter
) {
10321 OSKextLog(/* kext */ NULL
,
10322 kOSKextLogDebugLevel
|
10323 kOSKextLogGeneralFlag
,
10324 "User-space log flags changed from 0x%x to 0x%x.",
10325 oldLogFilter
, newLogFilter
);
10332 /*********************************************************************
10333 * Do not call any function that takes sKextLock here!
10334 *********************************************************************/
10337 OSKext::getUserSpaceLogFilter(void)
10339 OSKextLogSpec result
;
10341 IOLockLock(sKextLoggingLock
);
10342 result
= sUserSpaceKextLogFilter
;
10343 IOLockUnlock(sKextLoggingLock
);
10348 /*********************************************************************
10349 * This function is called by OSMetaClass during kernel C++ setup.
10350 * Be careful what you access here; assume only OSKext::initialize()
10353 * Do not call any function that takes sKextLock here!
10354 *********************************************************************/
10355 #define VTRESET "\033[0m"
10357 #define VTBOLD "\033[1m"
10358 #define VTUNDER "\033[4m"
10360 #define VTRED "\033[31m"
10361 #define VTGREEN "\033[32m"
10362 #define VTYELLOW "\033[33m"
10363 #define VTBLUE "\033[34m"
10364 #define VTMAGENTA "\033[35m"
10365 #define VTCYAN "\033[36m"
10367 inline const char * colorForFlags(OSKextLogSpec flags
)
10369 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
10371 switch (logLevel
) {
10372 case kOSKextLogErrorLevel
:
10373 return VTRED VTBOLD
;
10374 case kOSKextLogWarningLevel
:
10376 case kOSKextLogBasicLevel
:
10377 return VTYELLOW VTUNDER
;
10378 case kOSKextLogProgressLevel
:
10380 case kOSKextLogStepLevel
:
10382 case kOSKextLogDetailLevel
:
10384 case kOSKextLogDebugLevel
:
10387 return ""; // white
10391 inline bool logSpecMatch(
10392 OSKextLogSpec msgLogSpec
,
10393 OSKextLogSpec logFilter
)
10395 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
10396 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
10397 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
10399 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
10400 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
10401 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
10403 /* Explicit messages always get logged.
10405 if (msgLevel
== kOSKextLogExplicitLevel
) {
10409 /* Warnings and errors are logged regardless of the flags.
10411 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
10415 /* A verbose message that isn't for a logging-enabled kext and isn't global
10416 * does *not* get logged.
10418 if (!msgKextGlobal
&& !filterKextGlobal
) {
10422 /* Warnings and errors are logged regardless of the flags.
10423 * All other messages must fit the flags and
10424 * have a level at or below the filter.
10427 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
10438 OSKextLogSpec msgLogSpec
,
10439 const char * format
, ...)
10443 va_start(argList
, format
);
10444 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
10451 OSKextLogSpec msgLogSpec
,
10452 const char * format
,
10453 va_list srcArgList
)
10455 extern int disableConsoleOutput
;
10457 bool logForKernel
= false;
10458 bool logForUser
= false;
10460 char stackBuffer
[120];
10461 uint32_t length
= 0;
10462 char * allocBuffer
= NULL
; // must kfree
10463 OSNumber
* logSpecNum
= NULL
; // must release
10464 OSString
* logString
= NULL
; // must release
10465 char * buffer
= stackBuffer
; // do not free
10467 IOLockLock(sKextLoggingLock
);
10469 /* Set the kext/global bit in the message spec if we have no
10470 * kext or if the kext requests logging.
10472 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
10473 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
10476 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
10477 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10478 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
10481 if (! (logForKernel
|| logForUser
) ) {
10485 /* No goto from here until past va_end()!
10487 va_copy(argList
, srcArgList
);
10488 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
10491 if (length
+ 1 >= sizeof(stackBuffer
)) {
10492 allocBuffer
= (char *)kalloc_tag((length
+ 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT
);
10493 if (!allocBuffer
) {
10497 /* No goto from here until past va_end()!
10499 va_copy(argList
, srcArgList
);
10500 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
10503 buffer
= allocBuffer
;
10506 /* If user space wants the log message, queue it up.
10508 if (logForUser
&& sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10509 logSpecNum
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
));
10510 logString
= OSString::withCString(buffer
);
10511 if (logSpecNum
&& logString
) {
10512 sUserSpaceLogSpecArray
->setObject(logSpecNum
);
10513 sUserSpaceLogMessageArray
->setObject(logString
);
10517 /* Always log messages from the kernel according to the kernel's
10520 if (logForKernel
) {
10522 /* If we are in console mode and have a custom log filter,
10523 * colorize the log message.
10525 if (!disableConsoleOutput
&& sBootArgLogFilterFound
) {
10526 const char * color
= ""; // do not free
10527 color
= colorForFlags(msgLogSpec
);
10528 printf("%s%s%s\n", colorForFlags(msgLogSpec
),
10529 buffer
, color
[0] ? VTRESET
: "");
10531 printf("%s\n", buffer
);
10536 IOLockUnlock(sKextLoggingLock
);
10539 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
10541 OSSafeReleaseNULL(logString
);
10542 OSSafeReleaseNULL(logSpecNum
);
10546 #if KASLR_IOREG_DEBUG
10548 #define IOLOG_INDENT( the_indention ) \
10551 for ( i = 0; i < (the_indention); i++ ) { \
10556 extern vm_offset_t vm_kernel_stext
;
10557 extern vm_offset_t vm_kernel_etext
;
10558 extern mach_vm_offset_t kext_alloc_base
;
10559 extern mach_vm_offset_t kext_alloc_max
;
10561 bool ScanForAddrInObject(OSObject
* theObject
,
10564 bool ScanForAddrInObject(OSObject
* theObject
,
10567 const OSMetaClass
* myTypeID
;
10568 OSCollectionIterator
* myIter
;
10570 OSObject
* myValue
;
10571 bool myResult
= false;
10573 if ( theObject
== NULL
) {
10574 IOLog("%s: theObject is NULL \n",
10579 myTypeID
= OSTypeIDInst(theObject
);
10581 if ( myTypeID
== OSTypeID(OSDictionary
) ) {
10582 OSDictionary
* myDictionary
;
10584 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
10585 myIter
= OSCollectionIterator::withCollection( myDictionary
);
10586 if ( myIter
== NULL
)
10590 while ( (myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject())) ) {
10593 myValue
= myDictionary
->getObject(myKey
);
10594 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10595 if (myTempResult
) {
10596 // if we ever get a true result return true
10598 IOLOG_INDENT(indent
);
10599 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
10604 else if ( myTypeID
== OSTypeID(OSArray
) ) {
10607 myArray
= OSDynamicCast(OSArray
, theObject
);
10608 myIter
= OSCollectionIterator::withCollection(myArray
);
10609 if ( myIter
== NULL
)
10613 while ( (myValue
= myIter
->getNextObject()) ) {
10615 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10616 if (myTempResult
) {
10617 // if we ever get a true result return true
10619 IOLOG_INDENT(indent
);
10620 IOLog("OSArray: \n");
10625 else if ( myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
) ) {
10627 // should we look for addresses in strings?
10629 else if ( myTypeID
== OSTypeID(OSData
) ) {
10632 unsigned int myLen
;
10633 OSData
* myDataObj
;
10635 myDataObj
= OSDynamicCast(OSData
, theObject
);
10636 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
10637 myLen
= myDataObj
->getLength();
10639 if (myPtrPtr
&& myLen
&& myLen
> 7) {
10641 int myPtrCount
= (myLen
/ sizeof(void *));
10643 for (i
= 0; i
< myPtrCount
; i
++) {
10644 UInt64 numberValue
= (UInt64
) *(myPtrPtr
);
10646 if ( kext_alloc_max
!= 0 &&
10647 numberValue
>= kext_alloc_base
&&
10648 numberValue
< kext_alloc_max
) {
10650 OSKext
* myKext
= NULL
; // must release (looked up)
10651 // IOLog("found OSData %p in kext map %p to %p \n",
10653 // (void *) kext_alloc_base,
10654 // (void *) kext_alloc_max);
10656 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) *(myPtrPtr
) );
10658 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
10660 myKext
->getIdentifierCString());
10665 if ( vm_kernel_etext
!= 0 &&
10666 numberValue
>= vm_kernel_stext
&&
10667 numberValue
< vm_kernel_etext
) {
10668 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
10670 (void *) vm_kernel_stext
,
10671 (void *) vm_kernel_etext
);
10678 else if ( myTypeID
== OSTypeID(OSBoolean
) ) {
10680 // do nothing here...
10682 else if ( myTypeID
== OSTypeID(OSNumber
) ) {
10684 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
10686 UInt64 numberValue
= number
->unsigned64BitValue();
10688 if ( kext_alloc_max
!= 0 &&
10689 numberValue
>= kext_alloc_base
&&
10690 numberValue
< kext_alloc_max
) {
10692 OSKext
* myKext
= NULL
; // must release (looked up)
10693 IOLog("found OSNumber in kext map %p to %p \n",
10694 (void *) kext_alloc_base
,
10695 (void *) kext_alloc_max
);
10696 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10698 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) numberValue
);
10700 IOLog("found in kext \"%s\" \n",
10701 myKext
->getIdentifierCString());
10707 if ( vm_kernel_etext
!= 0 &&
10708 numberValue
>= vm_kernel_stext
&&
10709 numberValue
< vm_kernel_etext
) {
10710 IOLog("found OSNumber in kernel text segment %p to %p \n",
10711 (void *) vm_kernel_stext
,
10712 (void *) vm_kernel_etext
);
10713 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10719 const OSMetaClass
* myMetaClass
= NULL
;
10721 myMetaClass
= theObject
->getMetaClass();
10722 if ( myMetaClass
) {
10723 IOLog("class %s \n", myMetaClass
->getClassName() );
10726 IOLog("Unknown object \n" );
10733 #endif // KASLR_KEXT_DEBUG
10735 }; /* extern "C" */
10738 #pragma mark Backtrace Dump & kmod_get_info() support
10740 /*********************************************************************
10741 * This function must be safe to call in panic context.
10742 *********************************************************************/
10745 OSKext::printKextsInBacktrace(
10746 vm_offset_t
* addr
,
10748 int (* printf_func
)(const char *fmt
, ...),
10752 addr64_t summary_page
= 0;
10753 addr64_t last_summary_page
= 0;
10754 bool found_kmod
= false;
10758 if (!sKextSummariesLock
) return;
10759 IOLockLock(sKextSummariesLock
);
10762 if (!gLoadedKextSummaries
) {
10763 (*printf_func
)(" can't perform kext scan: no kext summary");
10767 summary_page
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
);
10768 last_summary_page
= round_page(summary_page
+ sLoadedKextSummariesAllocSize
);
10769 for (; summary_page
< last_summary_page
; summary_page
+= PAGE_SIZE
) {
10770 if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) {
10771 (*printf_func
)(" can't perform kext scan: "
10772 "missing kext summary page %p", summary_page
);
10777 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10778 OSKextLoadedKextSummary
* summary
;
10780 summary
= gLoadedKextSummaries
->summaries
+ i
;
10781 if (!summary
->address
) {
10785 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
10790 (*printf_func
)(" Kernel Extensions in backtrace:\n");
10794 printSummary(summary
, printf_func
, doUnslide
);
10799 IOLockUnlock(sKextSummariesLock
);
10805 /*********************************************************************
10806 * This function must be safe to call in panic context.
10807 *********************************************************************/
10810 OSKext::summaryIsInBacktrace(
10811 OSKextLoadedKextSummary
* summary
,
10812 vm_offset_t
* addr
,
10817 for (i
= 0; i
< cnt
; i
++) {
10818 vm_offset_t kscan_addr
= addr
[i
];
10819 if ((kscan_addr
>= summary
->address
) &&
10820 (kscan_addr
< (summary
->address
+ summary
->size
)))
10831 OSKext::kextForAddress(
10834 void *image
= NULL
;
10837 #if !VM_MAPPED_KEXTS
10838 kernel_mach_header_t
*mh
= NULL
;
10839 kernel_segment_command_t
*seg
= NULL
;
10842 if (((vm_offset_t
)(uintptr_t)addr
>= vm_kernel_stext
) &&
10843 ((vm_offset_t
)(uintptr_t)addr
< vm_kernel_etext
)) {
10844 return (void *)&_mh_execute_header
;
10847 if (!sKextSummariesLock
) return image
;
10848 IOLockLock(sKextSummariesLock
);
10850 if (!gLoadedKextSummaries
) {
10854 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10855 OSKextLoadedKextSummary
* summary
;
10857 summary
= gLoadedKextSummaries
->summaries
+ i
;
10858 if (!summary
->address
) {
10862 #if !VM_MAPPED_KEXTS
10863 mh
= (kernel_mach_header_t
*)summary
->address
;
10865 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
10866 if (((uint64_t)addr
>= seg
->vmaddr
) &&
10867 ((uint64_t)addr
< (seg
->vmaddr
+ seg
->vmsize
))) {
10868 image
= (void *)summary
->address
;
10877 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not
10878 * support split kexts, but we also may unmap the kexts, which can
10879 * race with the above codepath (see OSKext::unload). As such,
10880 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
10882 if (((uint64_t)(uintptr_t)addr
>= summary
->address
) &&
10883 ((uint64_t)(uintptr_t)addr
< (summary
->address
+ summary
->size
)))
10885 image
= (void *)(uintptr_t)summary
->address
;
10892 IOLockUnlock(sKextSummariesLock
);
10897 /*********************************************************************
10898 * scan list of loaded kext summaries looking for a load address match and if
10899 * found return the UUID C string. If not found then set empty string.
10900 *********************************************************************/
10901 static void findSummaryUUID(
10903 uuid_string_t uuid
);
10905 static void findSummaryUUID(
10907 uuid_string_t uuid
)
10911 uuid
[0] = 0x00; // default to no UUID
10913 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10914 OSKextLoadedKextSummary
* summary
;
10916 summary
= gLoadedKextSummaries
->summaries
+ i
;
10918 if (summary
->loadTag
== tag_ID
) {
10919 (void) uuid_unparse(summary
->uuid
, uuid
);
10926 /*********************************************************************
10927 * This function must be safe to call in panic context.
10928 *********************************************************************/
10929 void OSKext::printSummary(
10930 OSKextLoadedKextSummary
* summary
,
10931 int (* printf_func
)(const char *fmt
, ...),
10934 kmod_reference_t
* kmod_ref
= NULL
;
10935 uuid_string_t uuid
;
10936 char version
[kOSKextVersionMaxLength
];
10939 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
10940 strlcpy(version
, "unknown version", sizeof(version
));
10942 (void) uuid_unparse(summary
->uuid
, uuid
);
10945 tmpAddr
= VM_KERNEL_UNSLIDE(summary
->address
);
10948 tmpAddr
= summary
->address
;
10950 (*printf_func
)(" %s(%s)[%s]@0x%llx->0x%llx\n",
10951 summary
->name
, version
, uuid
,
10952 tmpAddr
, tmpAddr
+ summary
->size
- 1);
10954 /* print dependency info */
10955 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
10957 kmod_ref
= kmod_ref
->next
) {
10958 kmod_info_t
* rinfo
;
10960 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) {
10961 (*printf_func
)(" kmod dependency scan stopped "
10962 "due to missing dependency page: %p\n",
10963 doUnslide
? (void *)VM_KERNEL_UNSLIDE(kmod_ref
) : kmod_ref
);
10966 rinfo
= kmod_ref
->info
;
10968 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) {
10969 (*printf_func
)(" kmod dependency scan stopped "
10970 "due to missing kmod page: %p\n",
10971 doUnslide
? (void *)VM_KERNEL_UNSLIDE(rinfo
) : rinfo
);
10975 if (!rinfo
->address
) {
10976 continue; // skip fake entries for built-ins
10979 /* locate UUID in gLoadedKextSummaries */
10980 findSummaryUUID(rinfo
->id
, uuid
);
10983 tmpAddr
= VM_KERNEL_UNSLIDE(rinfo
->address
);
10986 tmpAddr
= rinfo
->address
;
10988 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
10989 rinfo
->name
, rinfo
->version
, uuid
, tmpAddr
);
10995 /*******************************************************************************
10996 * substitute() looks at an input string (a pointer within a larger buffer)
10997 * for a match to a substring, and on match it writes the marker & substitution
10998 * character to an output string, updating the scan (from) and
10999 * output (to) indexes as appropriate.
11000 *******************************************************************************/
11001 static int substitute(
11002 const char * scan_string
,
11004 uint32_t * to_index
,
11005 uint32_t * from_index
,
11006 const char * substring
,
11008 char substitution
);
11010 /* string_out must be at least KMOD_MAX_NAME bytes.
11014 const char * scan_string
,
11016 uint32_t * to_index
,
11017 uint32_t * from_index
,
11018 const char * substring
,
11022 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
11024 /* On a substring match, append the marker (if there is one) and then
11025 * the substitution character, updating the output (to) index accordingly.
11026 * Then update the input (from) length by the length of the substring
11027 * that got replaced.
11029 if (!strncmp(scan_string
, substring
, substring_length
)) {
11031 string_out
[(*to_index
)++] = marker
;
11033 string_out
[(*to_index
)++] = substitution
;
11034 (*from_index
) += substring_length
;
11040 /*******************************************************************************
11041 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
11042 * KMOD_MAX_NAME characters and performs various substitutions of common
11043 * prefixes & substrings as defined by tables in kext_panic_report.h.
11044 *******************************************************************************/
11045 static void compactIdentifier(
11046 const char * identifier
,
11047 char * identifier_out
,
11048 char ** identifier_out_end
);
11052 const char * identifier
,
11053 char * identifier_out
,
11054 char ** identifier_out_end
)
11056 uint32_t from_index
, to_index
;
11057 uint32_t scan_from_index
= 0;
11058 uint32_t scan_to_index
= 0;
11059 subs_entry_t
* subs_entry
= NULL
;
11062 from_index
= to_index
= 0;
11063 identifier_out
[0] = '\0';
11065 /* Replace certain identifier prefixes with shorter @+character sequences.
11066 * Check the return value of substitute() so we only replace the prefix.
11068 for (subs_entry
= &kext_identifier_prefix_subs
[0];
11069 subs_entry
->substring
&& !did_sub
;
11072 did_sub
= substitute(identifier
, identifier_out
,
11073 &scan_to_index
, &scan_from_index
,
11074 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
11078 /* Now scan through the identifier looking for the common substrings
11079 * and replacing them with shorter !+character sequences via substitute().
11081 for (/* see above */;
11082 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
11085 const char * scan_string
= &identifier
[scan_from_index
];
11089 if (scan_from_index
) {
11090 for (subs_entry
= &kext_identifier_substring_subs
[0];
11091 subs_entry
->substring
&& !did_sub
;
11094 did_sub
= substitute(scan_string
, identifier_out
,
11095 &scan_to_index
, &scan_from_index
,
11096 subs_entry
->substring
, '!', subs_entry
->substitute
);
11100 /* If we didn't substitute, copy the input character to the output.
11103 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
11107 identifier_out
[scan_to_index
] = '\0';
11108 if (identifier_out_end
) {
11109 *identifier_out_end
= &identifier_out
[scan_to_index
];
11115 /*******************************************************************************
11116 * assemble_identifier_and_version() adds to a string buffer a compacted
11117 * bundle identifier followed by a version string.
11118 *******************************************************************************/
11120 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
11122 static int assemble_identifier_and_version(
11123 kmod_info_t
* kmod_info
,
11124 char * identPlusVers
,
11128 assemble_identifier_and_version(
11129 kmod_info_t
* kmod_info
,
11130 char * identPlusVers
,
11135 compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
);
11136 result
= strnlen(identPlusVers
, KMOD_MAX_NAME
- 1);
11137 identPlusVers
[result
++] = '\t'; // increment for real char
11138 identPlusVers
[result
] = '\0'; // don't increment for nul char
11139 result
= strlcat(identPlusVers
, kmod_info
->version
, bufSize
);
11140 if (result
>= bufSize
) {
11141 identPlusVers
[bufSize
- 1] = '\0';
11142 result
= bufSize
- 1;
11148 /*******************************************************************************
11149 * Assumes sKextLock is held.
11150 *******************************************************************************/
11153 OSKext::saveLoadedKextPanicListTyped(
11154 const char * prefix
,
11158 uint32_t list_size
)
11161 unsigned int count
, i
;
11163 count
= sLoadedKexts
->getCount();
11170 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
11171 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
11173 uint32_t identPlusVersLength
;
11175 char identPlusVers
[2*KMOD_MAX_NAME
];
11178 printf("OSKext::saveLoadedKextPanicListTyped - "
11179 "NULL kext in loaded kext list; continuing\n");
11184 printf("OSKext::saveLoadedKextPanicListTyped - "
11185 "Kext type cast failed in loaded kext list; continuing\n");
11189 /* Skip all built-in kexts.
11191 if (theKext
->isKernelComponent()) {
11195 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
11197 /* Filter for kmod name (bundle identifier).
11199 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
11200 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
11204 /* Filter for libraries (kexts that have a compatible version).
11206 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
11207 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
11213 !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) {
11215 printf("kext scan stopped due to missing kmod_info page: %p\n",
11220 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
11222 sizeof(identPlusVers
));
11223 if (!identPlusVersLength
) {
11224 printf("error saving loaded kext info\n");
11228 /* make sure everything fits and we null terminate.
11230 tempLen
= strlcat(paniclist
, identPlusVers
, list_size
);
11231 if (tempLen
>= list_size
) {
11232 // panic list is full, keep it and null terminate
11233 paniclist
[list_size
- 1] = 0x00;
11237 tempLen
= strlcat(paniclist
, "\n", list_size
);
11238 if (tempLen
>= list_size
) {
11239 // panic list is full, keep it and null terminate
11240 paniclist
[list_size
- 1] = 0x00;
11252 /*********************************************************************
11253 *********************************************************************/
11256 OSKext::saveLoadedKextPanicList(void)
11258 char * newlist
= NULL
;
11259 uint32_t newlist_size
= 0;
11261 newlist_size
= KEXT_PANICLIST_SIZE
;
11262 newlist
= (char *)kalloc_tag(newlist_size
, VM_KERN_MEMORY_OSKEXT
);
11265 OSKextLog(/* kext */ NULL
,
11266 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
11267 "Couldn't allocate kext panic log buffer.");
11273 // non-"com.apple." kexts
11274 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
11275 /* libs? */ -1, newlist
, newlist_size
) != 0) {
11279 // "com.apple." nonlibrary kexts
11280 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11281 /* libs? */ 0, newlist
, newlist_size
) != 0) {
11285 // "com.apple." library kexts
11286 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11287 /* libs? */ 1, newlist
, newlist_size
) != 0) {
11292 if (loaded_kext_paniclist
) {
11293 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
11295 loaded_kext_paniclist
= newlist
;
11297 loaded_kext_paniclist_size
= newlist_size
;
11301 kfree(newlist
, newlist_size
);
11306 /*********************************************************************
11307 * Assumes sKextLock is held.
11308 *********************************************************************/
11310 OSKext::savePanicString(bool isLoading
)
11315 return; // do not goto finish here b/c of lock
11318 len
= assemble_identifier_and_version( kmod_info
,
11319 (isLoading
) ? last_loaded_str_buf
: last_unloaded_str_buf
,
11320 (isLoading
) ? sizeof(last_loaded_str_buf
) : sizeof(last_unloaded_str_buf
) );
11322 printf("error saving unloaded kext info\n");
11327 last_loaded_strlen
= len
;
11328 last_loaded_address
= (void *)kmod_info
->address
;
11329 last_loaded_size
= kmod_info
->size
;
11330 clock_get_uptime(&last_loaded_timestamp
);
11332 last_unloaded_strlen
= len
;
11333 last_unloaded_address
= (void *)kmod_info
->address
;
11334 last_unloaded_size
= kmod_info
->size
;
11335 clock_get_uptime(&last_unloaded_timestamp
);
11342 /*********************************************************************
11343 *********************************************************************/
11346 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
11348 if (last_loaded_strlen
) {
11349 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
11350 AbsoluteTime_to_scalar(&last_loaded_timestamp
),
11351 last_loaded_strlen
, last_loaded_str_buf
,
11352 last_loaded_address
, last_loaded_size
);
11355 if (last_unloaded_strlen
) {
11356 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
11357 AbsoluteTime_to_scalar(&last_unloaded_timestamp
),
11358 last_unloaded_strlen
, last_unloaded_str_buf
,
11359 last_unloaded_address
, last_unloaded_size
);
11362 printf_func("loaded kexts:\n");
11363 if (loaded_kext_paniclist
&&
11364 pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) &&
11365 loaded_kext_paniclist
[0]) {
11367 printf_func("%.*s",
11368 strnlen(loaded_kext_paniclist
, loaded_kext_paniclist_size
),
11369 loaded_kext_paniclist
);
11371 printf_func("(none)\n");
11376 /*********************************************************************
11377 * Assumes sKextLock is held.
11378 *********************************************************************/
11381 OSKext::updateLoadedKextSummaries(void)
11383 kern_return_t result
= KERN_FAILURE
;
11384 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
11385 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
11387 vm_map_offset_t start
, end
;
11388 size_t summarySize
= 0;
11393 OSKextActiveAccount
* accountingList
;
11394 OSKextActiveAccount
* prevAccountingList
;
11395 uint32_t idx
, accountingListAlloc
, accountingListCount
, prevAccountingListCount
;
11397 prevAccountingList
= NULL
;
11398 prevAccountingListCount
= 0;
11400 #if DEVELOPMENT || DEBUG
11401 if (IORecursiveLockHaveLock(sKextLock
) == false) {
11402 panic("sKextLock must be held");
11406 IOLockLock(sKextSummariesLock
);
11408 count
= sLoadedKexts
->getCount();
11409 for (i
= 0, maxKexts
= 0; i
< count
; ++i
) {
11410 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11411 maxKexts
+= (aKext
&& aKext
->isExecutable());
11414 if (!maxKexts
) goto finish
;
11415 if (maxKexts
< kOSKextTypicalLoadCount
) maxKexts
= kOSKextTypicalLoadCount
;
11417 /* Calculate the size needed for the new summary headers.
11420 size
= sizeof(*gLoadedKextSummaries
);
11421 size
+= maxKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
11422 size
= round_page(size
);
11424 if (gLoadedKextSummaries
== NULL
|| sLoadedKextSummariesAllocSize
< size
) {
11425 if (gLoadedKextSummaries
) {
11426 kmem_free(kernel_map
, (vm_offset_t
)gLoadedKextSummaries
, sLoadedKextSummariesAllocSize
);
11427 gLoadedKextSummaries
= NULL
;
11428 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11429 sLoadedKextSummariesAllocSize
= 0;
11431 result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&summaryHeaderAlloc
, size
, VM_KERN_MEMORY_OSKEXT
);
11432 if (result
!= KERN_SUCCESS
) goto finish
;
11433 summaryHeader
= summaryHeaderAlloc
;
11434 summarySize
= size
;
11437 summaryHeader
= gLoadedKextSummaries
;
11438 summarySize
= sLoadedKextSummariesAllocSize
;
11440 start
= (vm_map_offset_t
) summaryHeader
;
11441 end
= start
+ summarySize
;
11442 result
= vm_map_protect(kernel_map
,
11447 if (result
!= KERN_SUCCESS
) goto finish
;
11450 /* Populate the summary header.
11453 bzero(summaryHeader
, summarySize
);
11454 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
11455 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
11457 /* Populate each kext summary.
11460 count
= sLoadedKexts
->getCount();
11461 accountingListAlloc
= 0;
11462 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11463 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11464 if (!aKext
|| !aKext
->isExecutable()) {
11468 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
11469 summaryHeader
->numSummaries
++;
11470 accountingListAlloc
++;
11473 accountingList
= IONew(typeof(accountingList
[0]), accountingListAlloc
);
11474 accountingListCount
= 0;
11475 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
11476 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
11477 if (!aKext
|| !aKext
->isExecutable()) {
11481 OSKextActiveAccount activeAccount
;
11482 aKext
->updateActiveAccount(&activeAccount
);
11483 // order by address
11484 for (idx
= 0; idx
< accountingListCount
; idx
++)
11486 if (activeAccount
.address
< accountingList
[idx
].address
) break;
11488 bcopy(&accountingList
[idx
], &accountingList
[idx
+ 1], (accountingListCount
- idx
) * sizeof(accountingList
[0]));
11489 accountingList
[idx
] = activeAccount
;
11490 accountingListCount
++;
11492 assert(accountingListCount
== accountingListAlloc
);
11493 /* Write protect the buffer and move it into place.
11496 start
= (vm_map_offset_t
) summaryHeader
;
11497 end
= start
+ summarySize
;
11499 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_READ
, FALSE
);
11500 if (result
!= KERN_SUCCESS
)
11503 gLoadedKextSummaries
= summaryHeader
;
11504 gLoadedKextSummariesTimestamp
= mach_absolute_time();
11505 sLoadedKextSummariesAllocSize
= summarySize
;
11506 summaryHeaderAlloc
= NULL
;
11508 /* Call the magic breakpoint function through a static function pointer so
11509 * the compiler can't optimize the function away.
11511 if (sLoadedKextSummariesUpdated
) (*sLoadedKextSummariesUpdated
)();
11513 IOSimpleLockLock(sKextAccountsLock
);
11514 prevAccountingList
= sKextAccounts
;
11515 prevAccountingListCount
= sKextAccountsCount
;
11516 sKextAccounts
= accountingList
;
11517 sKextAccountsCount
= accountingListCount
;
11518 IOSimpleLockUnlock(sKextAccountsLock
);
11521 IOLockUnlock(sKextSummariesLock
);
11523 /* If we had to allocate a new buffer but failed to generate the summaries,
11526 if (summaryHeaderAlloc
) {
11527 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
11529 if (prevAccountingList
) {
11530 IODelete(prevAccountingList
, typeof(accountingList
[0]), prevAccountingListCount
);
11536 /*********************************************************************
11537 *********************************************************************/
11539 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
11543 strlcpy(summary
->name
, getIdentifierCString(),
11544 sizeof(summary
->name
));
11548 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
11549 OSSafeReleaseNULL(uuid
);
11552 summary
->address
= kmod_info
->address
;
11553 summary
->size
= kmod_info
->size
;
11554 summary
->version
= getVersion();
11555 summary
->loadTag
= kmod_info
->id
;
11556 summary
->flags
= 0;
11557 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
11562 /*********************************************************************
11563 *********************************************************************/
11566 OSKext::updateActiveAccount(OSKextActiveAccount
*accountp
)
11568 kernel_mach_header_t
*hdr
= NULL
;
11569 kernel_segment_command_t
*seg
= NULL
;
11571 hdr
= (kernel_mach_header_t
*)kmod_info
->address
;
11573 if (getcommandfromheader(hdr
, LC_SEGMENT_SPLIT_INFO
)) {
11574 /* If this kext supports split segments, use the first
11575 * executable segment as the range for instructions
11576 * (and thus for backtracing.
11578 for (seg
= firstsegfromheader(hdr
); seg
!= NULL
; seg
= nextsegfromheader(hdr
, seg
)) {
11579 if (seg
->initprot
& VM_PROT_EXECUTE
) {
11585 bzero(accountp
, sizeof(*accountp
));
11587 accountp
->address
= seg
->vmaddr
;
11588 if (accountp
->address
) {
11589 accountp
->address_end
= seg
->vmaddr
+ seg
->vmsize
;
11592 /* For non-split kexts and for kexts without executable
11593 * segments, just use the kmod_info range (as the kext
11594 * is either all in one range or should not show up in
11595 * instruction backtraces).
11597 accountp
->address
= kmod_info
->address
;
11598 if (accountp
->address
) {
11599 accountp
->address_end
= kmod_info
->address
+ kmod_info
->size
;
11602 accountp
->account
= this->account
;
11605 extern "C" const vm_allocation_site_t
*
11606 OSKextGetAllocationSiteForCaller(uintptr_t address
)
11608 OSKextActiveAccount
* active
;
11609 vm_allocation_site_t
* site
;
11613 IOSimpleLockLock(sKextAccountsLock
);
11615 // bsearch sKextAccounts list
11616 for (baseIdx
= 0, lim
= sKextAccountsCount
; lim
; lim
>>= 1)
11618 active
= &sKextAccounts
[baseIdx
+ (lim
>> 1)];
11619 if ((address
>= active
->address
) && (address
< active
->address_end
))
11621 site
= &active
->account
->site
;
11622 if (!site
->tag
) vm_tag_alloc_locked(site
);
11625 else if (address
> active
->address
)
11628 baseIdx
+= (lim
>> 1) + 1;
11633 IOSimpleLockUnlock(sKextAccountsLock
);
11638 extern "C" uint32_t
11639 OSKextGetKmodIDForSite(vm_allocation_site_t
* site
, char * name
, vm_size_t namelen
)
11641 OSKextAccount
* account
= (typeof(account
)) site
;
11642 const char * kname
;
11646 if (account
->kext
) kname
= account
->kext
->getIdentifierCString();
11648 strlcpy(name
, kname
, namelen
);
11651 return (account
->loadTag
);
11655 OSKextFreeSite(vm_allocation_site_t
* site
)
11657 OSKextAccount
* freeAccount
= (typeof(freeAccount
)) site
;
11658 IODelete(freeAccount
, OSKextAccount
, 1);
11661 /*********************************************************************
11662 *********************************************************************/
11664 #if CONFIG_KEC_FIPS
11667 #pragma mark Kernel External Components for FIPS compliance
11670 /*********************************************************************
11671 * Kernel External Components for FIPS compliance (KEC_FIPS)
11672 *********************************************************************/
11674 GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
)
11676 AppleTEXTHash_t my_ath
= {2, 0, NULL
};
11677 AppleTEXTHash_t
* my_athp
= NULL
; // do not release
11678 OSData
* segmentHash
= NULL
; // do not release
11680 if (theKext
== NULL
|| theInfoDict
== NULL
) {
11684 // Get the part of the plist associate with kAppleTextHashesKey and let
11685 // the crypto library do further parsing (slice/architecture)
11686 segmentHash
= OSDynamicCast(OSData
, theInfoDict
->getObject(kAppleTextHashesKey
));
11687 // Support for ATH v1 while rolling out ATH v2 without revision locking submissions
11688 // Remove this when v2 PLIST are supported
11689 if (segmentHash
== NULL
) {
11690 // If this fails, we may be dealing with a v1 PLIST
11691 OSDictionary
* textHashDict
= NULL
; // do not release
11692 textHashDict
= OSDynamicCast(OSDictionary
, theInfoDict
->getObject(kAppleTextHashesKey
));
11693 if (textHashDict
== NULL
) {
11696 my_ath
.ath_version
=1;
11697 segmentHash
= OSDynamicCast(OSData
,textHashDict
->getObject(ARCHNAME
));
11698 } // end of v2 rollout
11700 if (segmentHash
== NULL
) {
11704 // KEC_FIPS type kexts never unload so we don't have to clean up our
11706 if (kmem_alloc(kernel_map
, (vm_offset_t
*) &my_athp
,
11707 sizeof(AppleTEXTHash_t
), VM_KERN_MEMORY_OSKEXT
) != KERN_SUCCESS
) {
11711 memcpy(my_athp
, &my_ath
, sizeof(my_ath
));
11712 my_athp
->ath_length
= segmentHash
->getLength();
11713 if (my_athp
->ath_length
> 0) {
11714 my_athp
->ath_hash
= (void *)segmentHash
->getBytesNoCopy();
11719 kOSKextLogErrorLevel
|
11720 kOSKextLogGeneralFlag
,
11721 "Kext %s ath_version %d ath_length %d ath_hash %p",
11722 theKext
->getIdentifierCString(),
11723 my_athp
->ath_version
,
11724 my_athp
->ath_length
,
11725 my_athp
->ath_hash
);
11728 return( (void *) my_athp
);
11731 #endif // CONFIG_KEC_FIPS