2 * Copyright (c) 2008-2012 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@
30 #include <kern/clock.h>
31 #include <kern/host.h>
32 #include <kern/kext_alloc.h>
33 #include <kextd/kextd_mach.h>
34 #include <libkern/kernel_mach_header.h>
35 #include <libkern/kext_panic_report.h>
36 #include <libkern/kext_request_keys.h>
37 #include <libkern/mkext.h>
38 #include <libkern/prelink.h>
39 #include <libkern/version.h>
40 #include <libkern/zlib.h>
41 #include <mach/host_special_ports.h>
42 #include <mach/mach_vm.h>
43 #include <mach/mach_time.h>
44 #include <sys/sysctl.h>
45 #include <uuid/uuid.h>
46 // 04/18/11 - gab: <rdar://problem/9236163>
47 #include <sys/random.h>
50 #include <sys/kauth.h>
51 #include <security/mac_framework.h>
55 #include <libkern/OSKextLibPrivate.h>
56 #include <libkern/c++/OSKext.h>
57 #include <libkern/c++/OSLib.h>
59 #include <IOKit/IOLib.h>
60 #include <IOKit/IOCatalogue.h>
61 #include <IOKit/IORegistryEntry.h>
62 #include <IOKit/IOService.h>
64 #include <IOKit/IOStatisticsPrivate.h>
67 #pragma mark External & Internal Function Protos
69 /*********************************************************************
70 *********************************************************************/
72 extern int IODTGetLoaderInfo(const char * key
, void ** infoAddr
, int * infoSize
);
73 extern void IODTFreeLoaderInfo(const char * key
, void * infoAddr
, int infoSize
);
74 extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t
* segment
);
75 extern void OSRuntimeUnloadCPP(kmod_info_t
* ki
, void * data
);
77 extern ppnum_t
pmap_find_phys(pmap_t pmap
, addr64_t va
); /* osfmk/machine/pmap.h */
80 static OSReturn
_OSKextCreateRequest(
81 const char * predicate
,
82 OSDictionary
** requestP
);
83 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
);
84 static OSObject
* _OSKextGetRequestArgument(
85 OSDictionary
* requestDict
,
86 const char * argName
);
87 static bool _OSKextSetRequestArgument(
88 OSDictionary
* requestDict
,
91 static void * _OSKextExtractPointer(OSData
* wrapper
);
92 static OSReturn
_OSDictionarySetCStringValue(
96 static bool _OSKextInPrelinkRebuildWindow(void);
97 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol
* theBundleID
);
99 // We really should add containsObject() & containsCString to OSCollection & subclasses.
100 // So few pad slots, though....
101 static bool _OSArrayContainsCString(OSArray
* array
, const char * cString
);
104 static void * GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
);
105 #endif // CONFIG_KEC_FIPS
107 /* Prelinked arm kexts do not have VM entries because the method we use to
108 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
109 * not work on ARM. To get around that, we must free prelinked kext
110 * executables with ml_static_mfree() instead of kext_free().
112 #if __i386__ || __x86_64__
113 #define VM_MAPPED_KEXTS 1
114 #define KASLR_KEXT_DEBUG 0
115 #define KASLR_IOREG_DEBUG 0
117 #error Unsupported architecture
121 #pragma mark Constants & Macros
123 /*********************************************************************
125 *********************************************************************/
127 /* Use this number to create containers.
129 #define kOSKextTypicalLoadCount (150)
131 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
132 * A loaded kext will no dependents or external retains will have 2 retains.
134 #define kOSKextMinRetainCount (1)
135 #define kOSKextMinLoadedRetainCount (2)
138 * Strings and substrings used in dependency resolution.
140 #define APPLE_KEXT_PREFIX "com.apple."
141 #define KERNEL_LIB "com.apple.kernel"
143 #define PRIVATE_KPI "com.apple.kpi.private"
145 /* Version for compatbility pseudokexts (com.apple.kernel.*),
146 * compatible back to v6.0.
148 #define KERNEL6_LIB "com.apple.kernel.6.0"
149 #define KERNEL6_VERSION "7.9.9"
151 #define KERNEL_LIB_PREFIX "com.apple.kernel."
152 #define KPI_LIB_PREFIX "com.apple.kpi."
154 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0)
156 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
157 #define MINIMUM_WAKEUP_SECONDS (30)
159 /*********************************************************************
160 * infoDict keys for internally-stored data. Saves on ivar slots for
161 * objects we don't keep around past boot time or during active load.
162 *********************************************************************/
164 /* A usable, uncompressed file is stored under this key.
166 #define _kOSKextExecutableKey "_OSKextExecutable"
168 /* An indirect reference to the executable file from an mkext
169 * is stored under this key.
171 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference"
173 /* If the file is contained in a larger buffer laid down by the booter or
174 * sent from user space, the OSKext stores that OSData under this key so that
175 * references are properly tracked. This is always an mkext, right now.
177 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
180 #pragma mark Typedefs
182 /*********************************************************************
184 *********************************************************************/
186 /*********************************************************************
187 * MkextEntryRef describes the contents of an OSData object
188 * referencing a file entry from an mkext so that we can uncompress
189 * (if necessary) and extract it on demand.
191 * It contains the mkextVersion in case we ever wind up supporting
192 * multiple mkext formats. Mkext format 1 is officially retired as of
194 *********************************************************************/
195 typedef struct MkextEntryRef
{
196 mkext_basic_header
* mkext
; // beginning of whole mkext file
197 void * fileinfo
; // mkext2_file_entry or equiv; see mkext.h
201 #pragma mark Global and static Module Variables
203 /*********************************************************************
204 * Global & static variables, used to keep track of kexts.
205 *********************************************************************/
207 static bool sPrelinkBoot
= false;
208 static bool sSafeBoot
= false;
209 static bool sKeepSymbols
= false;
211 /*********************************************************************
212 * sKextLock is the principal lock for OSKext, and guards all static
213 * and global variables not owned by other locks (declared further
214 * below). It must be taken by any entry-point method or function,
215 * including internal functions called on scheduled threads.
217 * sKextLock and sKextInnerLock are recursive due to multiple functions
218 * that are called both externally and internally. The other locks are
221 * Which locks are taken depends on what they protect, but if more than
222 * one must be taken, they must always be locked in this order
223 * (and unlocked in reverse order) to prevent deadlocks:
227 * 3. sKextSummariesLock
228 * 4. sKextLoggingLock
230 static IORecursiveLock
* sKextLock
= NULL
;
232 static OSDictionary
* sKextsByID
= NULL
;
233 static OSDictionary
* sExcludeListByID
= NULL
;
234 static OSArray
* sLoadedKexts
= NULL
;
235 static OSArray
* sUnloadedPrelinkedKexts
= NULL
;
237 // Requests to kextd waiting to be picked up.
238 static OSArray
* sKernelRequests
= NULL
;
239 // Identifier of kext load requests in sKernelRequests
240 static OSSet
* sPostedKextLoadIdentifiers
= NULL
;
241 static OSArray
* sRequestCallbackRecords
= NULL
;
243 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
244 static OSSet
* sAllKextLoadIdentifiers
= NULL
;
245 static KXLDContext
* sKxldContext
= NULL
;
246 static uint32_t sNextLoadTag
= 0;
247 static uint32_t sNextRequestTag
= 0;
249 static bool sUserLoadsActive
= false;
250 static bool sKextdActive
= false;
251 static bool sDeferredLoadSucceeded
= false;
252 static bool sConsiderUnloadsExecuted
= false;
255 static bool sKernelRequestsEnabled
= false;
257 static bool sKernelRequestsEnabled
= true;
259 static bool sLoadEnabled
= true;
260 static bool sUnloadEnabled
= true;
262 /*********************************************************************
263 * Stuff for the OSKext representing the kernel itself.
265 static OSKext
* sKernelKext
= NULL
;
267 /* Set up a fake kmod_info struct for the kernel.
268 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
269 * before OSKext is initialized; that call only needs the name
270 * and address to be set correctly.
272 * We don't do much else with the kerne's kmod_info; we never
273 * put it into the kmod list, never adjust the reference count,
274 * and never have kernel components reference it.
275 * For that matter, we don't do much with kmod_info structs
276 * at all anymore! We just keep them filled in for gdb and
277 * binary compability.
279 kmod_info_t g_kernel_kmod_info
= {
281 /* info_version */ KMOD_INFO_VERSION
,
282 /* id */ 0, // loadTag: kernel is always 0
283 /* name */ kOSKextKernelIdentifier
, // bundle identifier
284 /* version */ "0", // filled in in OSKext::initialize()
285 /* reference_count */ -1, // never adjusted; kernel never unloads
286 /* reference_list */ NULL
,
288 /* size */ 0, // filled in in OSKext::initialize()
295 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
296 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
297 // misc_protos.h, db_low_trace.c, kgmacros
298 // 'kmod' is a holdover from the old kmod system, we can't rename it.
299 kmod_info_t
* kmod
= NULL
;
301 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
304 static char * loaded_kext_paniclist
= NULL
;
305 static uint32_t loaded_kext_paniclist_size
= 0;
307 AbsoluteTime last_loaded_timestamp
;
308 static char last_loaded_str_buf
[2*KMOD_MAX_NAME
];
309 static u_long last_loaded_strlen
= 0;
310 static void * last_loaded_address
= NULL
;
311 static u_long last_loaded_size
= 0;
313 AbsoluteTime last_unloaded_timestamp
;
314 static char last_unloaded_str_buf
[2*KMOD_MAX_NAME
];
315 static u_long last_unloaded_strlen
= 0;
316 static void * last_unloaded_address
= NULL
;
317 static u_long last_unloaded_size
= 0;
319 /*********************************************************************
320 * sKextInnerLock protects against cross-calls with IOService and
321 * IOCatalogue, and owns the variables declared immediately below.
323 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
325 * When both sKextLock and sKextInnerLock need to be taken,
326 * always lock sKextLock first and unlock it second. Never take both
327 * locks in an entry point to OSKext; if you need to do so, you must
328 * spawn an independent thread to avoid potential deadlocks for threads
329 * calling into OSKext.
331 static IORecursiveLock
* sKextInnerLock
= NULL
;
333 static bool sAutounloadEnabled
= true;
334 static bool sConsiderUnloadsCalled
= false;
335 static bool sConsiderUnloadsPending
= false;
337 static unsigned int sConsiderUnloadDelay
= 60; // seconds
338 static thread_call_t sUnloadCallout
= 0;
339 static thread_call_t sDestroyLinkContextThread
= 0; // one-shot, one-at-a-time thread
340 static bool sSystemSleep
= false; // true when system going to sleep
341 static AbsoluteTime sLastWakeTime
; // last time we woke up
343 /*********************************************************************
344 * Backtraces can be printed at various times so we need a tight lock
345 * on data used for that. sKextSummariesLock protects the variables
346 * declared immediately below.
348 * gLoadedKextSummaries is accessed by other modules, but only during
349 * a panic so the lock isn't needed then.
351 * gLoadedKextSummaries has the "used" attribute in order to ensure
352 * that it remains visible even when we are performing extremely
353 * aggressive optimizations, as it is needed to allow the debugger
354 * to automatically parse the list of loaded kexts.
356 static IOLock
* sKextSummariesLock
= NULL
;
358 void (*sLoadedKextSummariesUpdated
)(void) = OSKextLoadedKextSummariesUpdated
;
359 OSKextLoadedKextSummaryHeader
* gLoadedKextSummaries
__attribute__((used
)) = NULL
;
360 static size_t sLoadedKextSummariesAllocSize
= 0;
363 /*********************************************************************
364 * sKextLoggingLock protects the logging variables declared immediately below.
366 static IOLock
* sKextLoggingLock
= NULL
;
368 static const OSKextLogSpec kDefaultKernelLogFilter
= kOSKextLogBasicLevel
|
369 kOSKextLogVerboseFlagsMask
;
370 static OSKextLogSpec sKernelLogFilter
= kDefaultKernelLogFilter
;
371 static bool sBootArgLogFilterFound
= false;
372 SYSCTL_UINT(_debug
, OID_AUTO
, kextlog
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &sKernelLogFilter
,
373 sKernelLogFilter
, "kernel kext logging");
375 static OSKextLogSpec sUserSpaceKextLogFilter
= kOSKextLogSilentFilter
;
376 static OSArray
* sUserSpaceLogSpecArray
= NULL
;
377 static OSArray
* sUserSpaceLogMessageArray
= NULL
;
380 * End scope for sKextInnerLock-protected variables.
381 *********************************************************************/
384 #pragma mark OSData callbacks (need to move to OSData)
386 /*********************************************************************
387 * C functions used for callbacks.
388 *********************************************************************/
390 void osdata_kmem_free(void * ptr
, unsigned int length
) {
391 kmem_free(kernel_map
, (vm_address_t
)ptr
, length
);
395 void osdata_phys_free(void * ptr
, unsigned int length
) {
396 ml_static_mfree((vm_offset_t
)ptr
, length
);
400 void osdata_vm_deallocate(void * ptr
, unsigned int length
)
402 (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
);
406 void osdata_kext_free(void * ptr
, unsigned int length
)
408 (void)kext_free((vm_offset_t
)ptr
, length
);
414 #pragma mark KXLD Allocation Callback
416 /*********************************************************************
417 * KXLD Allocation Callback
418 *********************************************************************/
422 KXLDAllocateFlags
* flags
,
425 vm_address_t result
= 0; // returned
426 kern_return_t mach_result
= KERN_FAILURE
;
427 bool success
= false;
428 OSKext
* theKext
= (OSKext
*)user_data
;
429 u_long roundSize
= round_page(size
);
430 OSData
* linkBuffer
= NULL
; // must release
432 mach_result
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
);
433 if (mach_result
!= KERN_SUCCESS
) {
435 kOSKextLogErrorLevel
|
436 kOSKextLogGeneralFlag
,
437 "Can't allocate kernel memory to link %s.",
438 theKext
->getIdentifierCString());
442 /* Create an OSData wrapper for the allocated buffer.
444 linkBuffer
= OSData::withBytesNoCopy((void *)result
, roundSize
);
447 kOSKextLogErrorLevel
|
448 kOSKextLogGeneralFlag
,
449 "Can't allocate linked executable wrapper for %s.",
450 theKext
->getIdentifierCString());
453 linkBuffer
->setDeallocFunction(osdata_kext_free
);
455 kOSKextLogProgressLevel
|
456 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
457 "Allocated link buffer for kext %s at %p (%lu bytes).",
458 theKext
->getIdentifierCString(),
459 (void *)result
, (unsigned long)roundSize
);
461 theKext
->setLinkedExecutable(linkBuffer
);
463 *flags
= kKxldAllocateWritable
;
467 if (!success
&& result
) {
468 kext_free(result
, roundSize
);
472 OSSafeRelease(linkBuffer
);
474 return (kxld_addr_t
)result
;
477 /*********************************************************************
478 *********************************************************************/
481 KXLDLogSubsystem subsystem
,
487 OSKext
*theKext
= (OSKext
*) user_data
;
488 OSKextLogSpec logSpec
= 0;
491 case kKxldLogLinking
:
492 logSpec
|= kOSKextLogLinkFlag
;
494 case kKxldLogPatching
:
495 logSpec
|= kOSKextLogPatchFlag
;
500 case kKxldLogExplicit
:
501 logSpec
|= kOSKextLogExplicitLevel
;
504 logSpec
|= kOSKextLogErrorLevel
;
507 logSpec
|= kOSKextLogWarningLevel
;
510 logSpec
|= kOSKextLogProgressLevel
;
513 logSpec
|= kOSKextLogDetailLevel
;
516 logSpec
|= kOSKextLogDebugLevel
;
520 OSKextVLog(theKext
, logSpec
, format
, argList
);
524 #pragma mark IOStatistics defines
529 #define notifyKextLoadObservers(kext, kmod_info) \
531 IOStatistics::onKextLoad(kext, kmod_info); \
534 #define notifyKextUnloadObservers(kext) \
536 IOStatistics::onKextUnload(kext); \
539 #define notifyAddClassObservers(kext, addedClass, flags) \
541 IOStatistics::onClassAdded(kext, addedClass); \
544 #define notifyRemoveClassObservers(kext, removedClass, flags) \
546 IOStatistics::onClassRemoved(kext, removedClass); \
551 #define notifyKextLoadObservers(kext, kmod_info)
552 #define notifyKextUnloadObservers(kext)
553 #define notifyAddClassObservers(kext, addedClass, flags)
554 #define notifyRemoveClassObservers(kext, removedClass, flags)
556 #endif /* IOKITSTATS */
559 #pragma mark Module Config (Startup & Shutdown)
561 /*********************************************************************
562 * Module Config (Class Definition & Class Methods)
563 *********************************************************************/
564 #define super OSObject
565 OSDefineMetaClassAndStructors(OSKext
, OSObject
)
567 /*********************************************************************
568 *********************************************************************/
571 OSKext::initialize(void)
573 OSData
* kernelExecutable
= NULL
; // do not release
574 u_char
* kernelStart
= NULL
; // do not free
575 size_t kernelLength
= 0;
576 OSString
* scratchString
= NULL
; // must release
577 IORegistryEntry
* registryRoot
= NULL
; // do not release
578 OSNumber
* kernelCPUType
= NULL
; // must release
579 OSNumber
* kernelCPUSubtype
= NULL
; // must release
580 OSKextLogSpec bootLogFilter
= kOSKextLogSilentFilter
;
581 bool setResult
= false;
582 uint64_t * timestamp
= 0;
583 char bootArgBuffer
[16]; // for PE_parse_boot_argn w/strings
585 /* This must be the first thing allocated. Everything else grabs this lock.
587 sKextLock
= IORecursiveLockAlloc();
588 sKextInnerLock
= IORecursiveLockAlloc();
589 sKextSummariesLock
= IOLockAlloc();
590 sKextLoggingLock
= IOLockAlloc();
592 assert(sKextInnerLock
);
593 assert(sKextSummariesLock
);
594 assert(sKextLoggingLock
);
596 sKextsByID
= OSDictionary::withCapacity(kOSKextTypicalLoadCount
);
597 sLoadedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
);
598 sUnloadedPrelinkedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
/ 10);
599 sKernelRequests
= OSArray::withCapacity(0);
600 sPostedKextLoadIdentifiers
= OSSet::withCapacity(0);
601 sAllKextLoadIdentifiers
= OSSet::withCapacity(kOSKextTypicalLoadCount
);
602 sRequestCallbackRecords
= OSArray::withCapacity(0);
603 assert(sKextsByID
&& sLoadedKexts
&& sKernelRequests
&&
604 sPostedKextLoadIdentifiers
&& sAllKextLoadIdentifiers
&&
605 sRequestCallbackRecords
&& sUnloadedPrelinkedKexts
);
607 /* Read the log flag boot-args and set the log flags.
609 if (PE_parse_boot_argn("kextlog", &bootLogFilter
, sizeof(bootLogFilter
))) {
610 sBootArgLogFilterFound
= true;
611 sKernelLogFilter
= bootLogFilter
;
612 // log this if any flags are set
613 OSKextLog(/* kext */ NULL
,
614 kOSKextLogBasicLevel
|
616 "Kernel kext log filter 0x%x per kextlog boot arg.",
617 (unsigned)sKernelLogFilter
);
620 sSafeBoot
= PE_parse_boot_argn("-x", bootArgBuffer
,
621 sizeof(bootArgBuffer
)) ? true : false;
624 OSKextLog(/* kext */ NULL
,
625 kOSKextLogWarningLevel
|
626 kOSKextLogGeneralFlag
,
627 "SAFE BOOT DETECTED - "
628 "only valid OSBundleRequired kexts will be loaded.");
631 PE_parse_boot_argn("keepsyms", &sKeepSymbols
, sizeof(sKeepSymbols
));
633 /* Set up an OSKext instance to represent the kernel itself.
635 sKernelKext
= new OSKext
;
638 kernelStart
= (u_char
*)&_mh_execute_header
;
639 kernelLength
= getlastaddr() - (vm_offset_t
)kernelStart
;
640 kernelExecutable
= OSData::withBytesNoCopy(
641 kernelStart
, kernelLength
);
642 assert(kernelExecutable
);
645 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu \n",
646 (unsigned long)kernelStart
,
647 (unsigned long)getlastaddr(),
651 sKernelKext
->loadTag
= sNextLoadTag
++; // the kernel is load tag 0
652 sKernelKext
->bundleID
= OSSymbol::withCString(kOSKextKernelIdentifier
);
654 sKernelKext
->version
= OSKextParseVersionString(osrelease
);
655 sKernelKext
->compatibleVersion
= sKernelKext
->version
;
656 sKernelKext
->linkedExecutable
= kernelExecutable
;
658 sKernelKext
->flags
.hasAllDependencies
= 1;
659 sKernelKext
->flags
.kernelComponent
= 1;
660 sKernelKext
->flags
.prelinked
= 0;
661 sKernelKext
->flags
.loaded
= 1;
662 sKernelKext
->flags
.started
= 1;
663 sKernelKext
->flags
.CPPInitialized
= 0;
664 sKernelKext
->flags
.jettisonLinkeditSeg
= 0;
666 sKernelKext
->kmod_info
= &g_kernel_kmod_info
;
667 strlcpy(g_kernel_kmod_info
.version
, osrelease
,
668 sizeof(g_kernel_kmod_info
.version
));
669 g_kernel_kmod_info
.size
= kernelLength
;
670 g_kernel_kmod_info
.id
= sKernelKext
->loadTag
;
672 /* Cons up an info dict, so we don't have to have special-case
675 sKernelKext
->infoDict
= OSDictionary::withCapacity(5);
676 assert(sKernelKext
->infoDict
);
677 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
,
678 sKernelKext
->bundleID
);
680 setResult
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
,
684 scratchString
= OSString::withCStringNoCopy(osrelease
);
685 assert(scratchString
);
686 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
,
689 OSSafeReleaseNULL(scratchString
);
691 scratchString
= OSString::withCStringNoCopy("mach_kernel");
692 assert(scratchString
);
693 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
,
696 OSSafeReleaseNULL(scratchString
);
698 /* Add the kernel kext to the bookkeeping dictionaries. Note that
699 * the kernel kext doesn't have a kmod_info struct. copyInfo()
700 * gathers info from other places anyhow.
702 setResult
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
);
704 setResult
= sLoadedKexts
->setObject(sKernelKext
);
706 sKernelKext
->release();
708 registryRoot
= IORegistryEntry::getRegistryRoot();
709 kernelCPUType
= OSNumber::withNumber(
710 (long long unsigned int)_mh_execute_header
.cputype
,
711 8 * sizeof(_mh_execute_header
.cputype
));
712 kernelCPUSubtype
= OSNumber::withNumber(
713 (long long unsigned int)_mh_execute_header
.cpusubtype
,
714 8 * sizeof(_mh_execute_header
.cpusubtype
));
715 assert(registryRoot
&& kernelCPUSubtype
&& kernelCPUType
);
717 registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
);
718 registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
);
720 OSSafeRelease(kernelCPUType
);
721 OSSafeRelease(kernelCPUSubtype
);
723 timestamp
= __OSAbsoluteTimePtr(&last_loaded_timestamp
);
725 timestamp
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
);
727 timestamp
= __OSAbsoluteTimePtr(&sLastWakeTime
);
730 OSKextLog(/* kext */ NULL
,
731 kOSKextLogProgressLevel
|
732 kOSKextLogGeneralFlag
,
733 "Kext system initialized.");
735 notifyKextLoadObservers(sKernelKext
, sKernelKext
->kmod_info
);
740 /*********************************************************************
741 * This could be in OSKextLib.cpp but we need to hold a lock
742 * while removing all the segments and sKextLock will do.
743 *********************************************************************/
746 OSKext::removeKextBootstrap(void)
748 OSReturn result
= kOSReturnError
;
750 static bool alreadyDone
= false;
752 const char * dt_kernel_header_name
= "Kernel-__HEADER";
753 const char * dt_kernel_symtab_name
= "Kernel-__SYMTAB";
754 kernel_mach_header_t
* dt_mach_header
= NULL
;
755 int dt_mach_header_size
= 0;
756 struct symtab_command
* dt_symtab
= NULL
;
757 int dt_symtab_size
= 0;
760 kernel_segment_command_t
* seg_to_remove
= NULL
;
763 /* This must be the very first thing done by this function.
765 IORecursiveLockLock(sKextLock
);
767 /* If we already did this, it's a success.
770 result
= kOSReturnSuccess
;
774 OSKextLog(/* kext */ NULL
,
775 kOSKextLogProgressLevel
|
776 kOSKextLogGeneralFlag
,
777 "Jettisoning kext bootstrap segments.");
780 * Dispose of unnecessary stuff that the booter didn't need to load.
782 dt_result
= IODTGetLoaderInfo(dt_kernel_header_name
,
783 (void **)&dt_mach_header
, &dt_mach_header_size
);
784 if (dt_result
== 0 && dt_mach_header
) {
785 IODTFreeLoaderInfo(dt_kernel_header_name
, (void *)dt_mach_header
,
786 round_page_32(dt_mach_header_size
));
788 dt_result
= IODTGetLoaderInfo(dt_kernel_symtab_name
,
789 (void **)&dt_symtab
, &dt_symtab_size
);
790 if (dt_result
== 0 && dt_symtab
) {
791 IODTFreeLoaderInfo(dt_kernel_symtab_name
, (void *)dt_symtab
,
792 round_page_32(dt_symtab_size
));
796 * KLD bootstrap segment.
798 // xxx - should rename KLD segment
799 seg_to_remove
= getsegbyname("__KLD");
801 OSRuntimeUnloadCPPForSegment(seg_to_remove
);
804 #if __i386__ || __x86_64__
805 /* On x86, use the mapping data from the segment load command to
806 * unload KLD directly.
807 * This may invalidate any assumptions about "avail_start"
808 * defining the lower bound for valid physical addresses.
810 if (seg_to_remove
&& seg_to_remove
->vmaddr
&& seg_to_remove
->vmsize
) {
811 // 04/18/11 - gab: <rdar://problem/9236163>
812 // overwrite memory occupied by KLD segment with random data before
814 read_frandom((void *) seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
815 ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
821 seg_to_remove
= NULL
;
824 * Prelinked kernel's symtab (if there is one).
826 kernel_section_t
* sect
;
827 sect
= getsectbyname("__PRELINK", "__symtab");
828 if (sect
&& sect
->addr
&& sect
->size
) {
829 ml_static_mfree(sect
->addr
, sect
->size
);
832 seg_to_remove
= (kernel_segment_command_t
*)getsegbyname("__LINKEDIT");
834 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
835 * pageable, unless keepsyms is set. To do that, we have to copy it from
836 * its booter-allocated memory, free the booter memory, reallocate proper
837 * managed memory, then copy the segment back in.
841 kern_return_t mem_result
;
842 void *seg_copy
= NULL
;
843 void *seg_data
= NULL
;
844 vm_map_offset_t seg_offset
= 0;
845 vm_map_offset_t seg_copy_offset
= 0;
846 vm_map_size_t seg_length
= 0;
848 seg_data
= (void *) seg_to_remove
->vmaddr
;
849 seg_offset
= (vm_map_offset_t
) seg_to_remove
->vmaddr
;
850 seg_length
= (vm_map_size_t
) seg_to_remove
->vmsize
;
852 /* Allocate space for the LINKEDIT copy.
854 mem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*) &seg_copy
,
856 if (mem_result
!= KERN_SUCCESS
) {
857 OSKextLog(/* kext */ NULL
,
858 kOSKextLogErrorLevel
|
859 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
860 "Can't copy __LINKEDIT segment for VM reassign.");
863 seg_copy_offset
= (vm_map_offset_t
) seg_copy
;
867 memcpy(seg_copy
, seg_data
, seg_length
);
869 /* Dump the booter memory.
871 ml_static_mfree(seg_offset
, seg_length
);
873 /* Set up the VM region.
875 mem_result
= vm_map_enter_mem_object(
878 seg_length
, /* mask */ 0,
879 VM_FLAGS_FIXED
| VM_FLAGS_OVERWRITE
,
881 (vm_object_offset_t
) 0,
883 /* cur_protection */ VM_PROT_READ
| VM_PROT_WRITE
,
884 /* max_protection */ VM_PROT_ALL
,
885 /* inheritance */ VM_INHERIT_DEFAULT
);
886 if ((mem_result
!= KERN_SUCCESS
) ||
887 (seg_offset
!= (vm_map_offset_t
) seg_data
))
889 OSKextLog(/* kext */ NULL
,
890 kOSKextLogErrorLevel
|
891 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
892 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
893 seg_data
, seg_length
, mem_result
);
899 memcpy(seg_data
, seg_copy
, seg_length
);
903 kmem_free(kernel_map
, seg_copy_offset
, seg_length
);
905 #else /* we are not CONFIG_KXLD */
906 #error CONFIG_KXLD is expected for this arch
909 * Dump the LINKEDIT segment, unless keepsyms is set.
912 const char *dt_segment_name
= "Kernel-__LINKEDIT";
913 if (0 == IODTGetLoaderInfo(dt_segment_name
,
914 &segment_paddress
, &segment_size
)) {
916 vm_offset_t vmaddr
= ml_static_ptovirt((vm_offset_t
)segment_paddress
);
917 bzero((void*)vmaddr
, segment_size
);
919 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
923 OSKextLog(/* kext */ NULL
,
924 kOSKextLogBasicLevel
|
925 kOSKextLogGeneralFlag
,
926 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
928 #endif /* CONFIG_KXLD */
930 seg_to_remove
= NULL
;
933 result
= kOSReturnSuccess
;
937 /* This must be the very last thing done before returning.
939 IORecursiveLockUnlock(sKextLock
);
944 /*********************************************************************
945 *********************************************************************/
947 OSKext::flushNonloadedKexts(
948 Boolean flushPrelinkedKexts
)
950 OSSet
* prelinkedKexts
= NULL
; // must release
951 OSCollectionIterator
* kextIterator
= NULL
; // must release
952 OSCollectionIterator
* prelinkIterator
= NULL
; // must release
953 const OSSymbol
* thisID
= NULL
; // do not release
954 OSKext
* thisKext
= NULL
; // do not release
957 IORecursiveLockLock(sKextLock
);
959 OSKextLog(/* kext */ NULL
,
960 kOSKextLogProgressLevel
|
961 kOSKextLogKextBookkeepingFlag
,
962 "Flushing nonloaded kexts and other unused data.");
964 OSKext::considerDestroyingLinkContext();
966 /* If we aren't flushing unused prelinked kexts, we have to put them
967 * aside while we flush everything else so make a container for them.
969 if (!flushPrelinkedKexts
) {
970 prelinkedKexts
= OSSet::withCapacity(0);
971 if (!prelinkedKexts
) {
976 /* Set aside prelinked kexts (in-use or not) and break
977 * any lingering inter-kext references for nonloaded kexts
978 * so they have min. retain counts.
980 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
985 while ((thisID
= OSDynamicCast(OSSymbol
,
986 kextIterator
->getNextObject()))) {
988 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
991 if (prelinkedKexts
&& thisKext
->isPrelinked()) {
992 prelinkedKexts
->setObject(thisKext
);
994 thisKext
->flushDependencies(/* forceIfLoaded */ false);
998 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1000 sKextsByID
->flushCollection();
1002 /* Now put the loaded kexts back into the ID dictionary.
1004 count
= sLoadedKexts
->getCount();
1005 for (i
= 0; i
< count
; i
++) {
1006 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
1007 sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
);
1010 /* Finally, put back the prelinked kexts if we saved any.
1012 if (prelinkedKexts
) {
1013 prelinkIterator
= OSCollectionIterator::withCollection(prelinkedKexts
);
1014 if (!prelinkIterator
) {
1018 while ((thisKext
= OSDynamicCast(OSKext
,
1019 prelinkIterator
->getNextObject()))) {
1021 sKextsByID
->setObject(thisKext
->getIdentifierCString(),
1027 IORecursiveLockUnlock(sKextLock
);
1029 OSSafeRelease(prelinkedKexts
);
1030 OSSafeRelease(kextIterator
);
1031 OSSafeRelease(prelinkIterator
);
1036 /*********************************************************************
1037 *********************************************************************/
1040 OSKext::setKextdActive(Boolean active
)
1042 IORecursiveLockLock(sKextLock
);
1043 sKextdActive
= active
;
1044 if (sKernelRequests
->getCount()) {
1045 OSKext::pingKextd();
1047 IORecursiveLockUnlock(sKextLock
);
1052 /*********************************************************************
1053 * OSKextLib.cpp might need access to this someday but for now it's
1055 *********************************************************************/
1057 extern void ipc_port_release_send(ipc_port_t
);
1062 OSKext::pingKextd(void)
1064 OSReturn result
= kOSReturnError
;
1066 mach_port_t kextd_port
= IPC_PORT_NULL
;
1068 if (!sKextdActive
) {
1069 result
= kOSKextReturnDisabled
; // basically unavailable
1073 result
= host_get_kextd_port(host_priv_self(), &kextd_port
);
1074 if (result
!= KERN_SUCCESS
|| !IPC_PORT_VALID(kextd_port
)) {
1075 OSKextLog(/* kext */ NULL
,
1076 kOSKextLogErrorLevel
|
1078 "Can't get kextd port.");
1082 result
= kextd_ping(kextd_port
);
1083 if (result
!= KERN_SUCCESS
) {
1084 OSKextLog(/* kext */ NULL
,
1085 kOSKextLogErrorLevel
|
1087 "kextd ping failed (0x%x).", (int)result
);
1092 if (IPC_PORT_VALID(kextd_port
)) {
1093 ipc_port_release_send(kextd_port
);
1100 /*********************************************************************
1101 *********************************************************************/
1104 OSKext::setDeferredLoadSucceeded(Boolean succeeded
)
1106 IORecursiveLockLock(sKextLock
);
1107 sDeferredLoadSucceeded
= succeeded
;
1108 IORecursiveLockUnlock(sKextLock
);
1113 /*********************************************************************
1114 * Called from IOSystemShutdownNotification.
1115 *********************************************************************/
1118 OSKext::willShutdown(void)
1121 OSReturn checkResult
= kOSReturnError
;
1123 OSDictionary
* exitRequest
= NULL
; // must release
1125 IORecursiveLockLock(sKextLock
);
1127 OSKext::setLoadEnabled(false);
1128 OSKext::setUnloadEnabled(false);
1129 OSKext::setAutounloadsEnabled(false);
1130 OSKext::setKernelRequestsEnabled(false);
1133 OSKextLog(/* kext */ NULL
,
1134 kOSKextLogProgressLevel
|
1135 kOSKextLogGeneralFlag
,
1136 "System shutdown; requesting immediate kextd exit.");
1138 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
,
1140 if (checkResult
!= kOSReturnSuccess
) {
1143 if (!sKernelRequests
->setObject(exitRequest
)) {
1147 OSKext::pingKextd();
1152 IORecursiveLockUnlock(sKextLock
);
1154 OSSafeRelease(exitRequest
);
1158 /*********************************************************************
1159 *********************************************************************/
1162 OSKext::getLoadEnabled(void)
1166 IORecursiveLockLock(sKextLock
);
1167 result
= sLoadEnabled
;
1168 IORecursiveLockUnlock(sKextLock
);
1172 /*********************************************************************
1173 *********************************************************************/
1176 OSKext::setLoadEnabled(bool flag
)
1180 IORecursiveLockLock(sKextLock
);
1181 result
= sLoadEnabled
;
1182 sLoadEnabled
= (flag
? true : false);
1184 if (sLoadEnabled
!= result
) {
1185 OSKextLog(/* kext */ NULL
,
1186 kOSKextLogBasicLevel
|
1188 "Kext loading now %sabled.", sLoadEnabled
? "en" : "dis");
1191 IORecursiveLockUnlock(sKextLock
);
1196 /*********************************************************************
1197 *********************************************************************/
1200 OSKext::getUnloadEnabled(void)
1204 IORecursiveLockLock(sKextLock
);
1205 result
= sUnloadEnabled
;
1206 IORecursiveLockUnlock(sKextLock
);
1210 /*********************************************************************
1211 *********************************************************************/
1214 OSKext::setUnloadEnabled(bool flag
)
1218 IORecursiveLockLock(sKextLock
);
1219 result
= sUnloadEnabled
;
1220 sUnloadEnabled
= (flag
? true : false);
1221 IORecursiveLockUnlock(sKextLock
);
1223 if (sUnloadEnabled
!= result
) {
1224 OSKextLog(/* kext */ NULL
,
1225 kOSKextLogBasicLevel
|
1226 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1227 "Kext unloading now %sabled.", sUnloadEnabled
? "en" : "dis");
1233 /*********************************************************************
1234 * Do not call any function that takes sKextLock here!
1235 *********************************************************************/
1238 OSKext::getAutounloadEnabled(void)
1242 IORecursiveLockLock(sKextInnerLock
);
1243 result
= sAutounloadEnabled
? true : false;
1244 IORecursiveLockUnlock(sKextInnerLock
);
1248 /*********************************************************************
1249 * Do not call any function that takes sKextLock here!
1250 *********************************************************************/
1253 OSKext::setAutounloadsEnabled(bool flag
)
1257 IORecursiveLockLock(sKextInnerLock
);
1259 result
= sAutounloadEnabled
;
1260 sAutounloadEnabled
= (flag
? true : false);
1261 if (!sAutounloadEnabled
&& sUnloadCallout
) {
1262 thread_call_cancel(sUnloadCallout
);
1265 if (sAutounloadEnabled
!= result
) {
1266 OSKextLog(/* kext */ NULL
,
1267 kOSKextLogBasicLevel
|
1268 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1269 "Kext autounloading now %sabled.",
1270 sAutounloadEnabled
? "en" : "dis");
1273 IORecursiveLockUnlock(sKextInnerLock
);
1278 /*********************************************************************
1279 *********************************************************************/
1280 /* instance method operating on OSKext field */
1282 OSKext::setAutounloadEnabled(bool flag
)
1284 bool result
= flags
.autounloadEnabled
? true : false;
1285 flags
.autounloadEnabled
= flag
? 1 : 0;
1287 if (result
!= (flag
? true : false)) {
1289 kOSKextLogProgressLevel
|
1290 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
1291 "Autounloading for kext %s now %sabled.",
1292 getIdentifierCString(),
1293 flags
.autounloadEnabled
? "en" : "dis");
1298 /*********************************************************************
1299 *********************************************************************/
1302 OSKext::setKernelRequestsEnabled(bool flag
)
1306 IORecursiveLockLock(sKextLock
);
1307 result
= sKernelRequestsEnabled
;
1308 sKernelRequestsEnabled
= flag
? true : false;
1310 if (sKernelRequestsEnabled
!= result
) {
1311 OSKextLog(/* kext */ NULL
,
1312 kOSKextLogBasicLevel
|
1313 kOSKextLogGeneralFlag
,
1314 "Kernel requests now %sabled.",
1315 sKernelRequestsEnabled
? "en" : "dis");
1317 IORecursiveLockUnlock(sKextLock
);
1321 /*********************************************************************
1322 *********************************************************************/
1325 OSKext::getKernelRequestsEnabled(void)
1329 IORecursiveLockLock(sKextLock
);
1330 result
= sKernelRequestsEnabled
;
1331 IORecursiveLockUnlock(sKextLock
);
1336 #pragma mark Kext Life Cycle
1338 /*********************************************************************
1339 *********************************************************************/
1341 OSKext::withPrelinkedInfoDict(
1342 OSDictionary
* anInfoDict
)
1344 OSKext
* newKext
= new OSKext
;
1346 if (newKext
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
)) {
1354 /*********************************************************************
1355 *********************************************************************/
1357 OSKext::initWithPrelinkedInfoDict(
1358 OSDictionary
* anInfoDict
)
1360 bool result
= false;
1361 OSString
* kextPath
= NULL
; // do not release
1362 OSNumber
* addressNum
= NULL
; // reused; do not release
1363 OSNumber
* lengthNum
= NULL
; // reused; do not release
1364 void * data
= NULL
; // do not free
1365 void * srcData
= NULL
; // do not free
1366 OSData
* prelinkedExecutable
= NULL
; // must release
1367 uint32_t length
= 0; // reused
1369 if (!super::init()) {
1373 /* Get the path. Don't look for an arch-specific path property.
1375 kextPath
= OSDynamicCast(OSString
,
1376 anInfoDict
->getObject(kPrelinkBundlePathKey
));
1378 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
1381 #if KASLR_KEXT_DEBUG
1382 IOLog("kaslr: kext %s \n", getIdentifierCString());
1385 /* Also get the executable's bundle-relative path if present.
1386 * Don't look for an arch-specific path property.
1388 executableRelPath
= OSDynamicCast(OSString
,
1389 anInfoDict
->getObject(kPrelinkExecutableRelativePathKey
));
1390 if (executableRelPath
) {
1391 executableRelPath
->retain();
1394 /* Don't need the paths to be in the info dictionary any more.
1396 anInfoDict
->removeObject(kPrelinkBundlePathKey
);
1397 anInfoDict
->removeObject(kPrelinkExecutableRelativePathKey
);
1399 /* Create an OSData wrapper around the linked executable.
1401 addressNum
= OSDynamicCast(OSNumber
,
1402 anInfoDict
->getObject(kPrelinkExecutableLoadKey
));
1404 lengthNum
= OSDynamicCast(OSNumber
,
1405 anInfoDict
->getObject(kPrelinkExecutableSizeKey
));
1408 kOSKextLogErrorLevel
|
1409 kOSKextLogArchiveFlag
,
1410 "Kext %s can't find prelinked kext executable size.",
1411 getIdentifierCString());
1415 data
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1416 length
= (uint32_t) (lengthNum
->unsigned32BitValue());
1418 #if KASLR_KEXT_DEBUG
1419 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1420 (unsigned long)VM_KERNEL_UNSLIDE(data
),
1421 (unsigned long)data
,
1425 anInfoDict
->removeObject(kPrelinkExecutableLoadKey
);
1426 anInfoDict
->removeObject(kPrelinkExecutableSizeKey
);
1428 /* If the kext's load address differs from its source address, allocate
1429 * space in the kext map at the load address and copy the kext over.
1431 addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
));
1433 srcData
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1435 #if KASLR_KEXT_DEBUG
1436 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1437 (unsigned long)VM_KERNEL_UNSLIDE(srcData
),
1438 (unsigned long)srcData
);
1441 if (data
!= srcData
) {
1443 kern_return_t alloc_result
;
1445 alloc_result
= kext_alloc((vm_offset_t
*)&data
, length
, /* fixed */ TRUE
);
1446 if (alloc_result
!= KERN_SUCCESS
) {
1448 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1449 "Failed to allocate space for prelinked kext %s.",
1450 getIdentifierCString());
1453 memcpy(data
, srcData
, length
);
1456 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1457 "Error: prelinked kext %s - source and load addresses "
1458 "differ on ILP32 architecture.",
1459 getIdentifierCString());
1461 #endif /* __LP64__ */
1464 anInfoDict
->removeObject(kPrelinkExecutableSourceKey
);
1467 prelinkedExecutable
= OSData::withBytesNoCopy(data
, length
);
1468 if (!prelinkedExecutable
) {
1470 kOSKextLogErrorLevel
|
1471 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
1472 "Kext %s failed to create executable wrapper.",
1473 getIdentifierCString());
1478 prelinkedExecutable
->setDeallocFunction(osdata_kext_free
);
1480 prelinkedExecutable
->setDeallocFunction(osdata_phys_free
);
1482 setLinkedExecutable(prelinkedExecutable
);
1483 addressNum
= OSDynamicCast(OSNumber
,
1484 anInfoDict
->getObject(kPrelinkKmodInfoKey
));
1487 kOSKextLogErrorLevel
|
1488 kOSKextLogArchiveFlag
,
1489 "Kext %s can't find prelinked kext kmod_info address.",
1490 getIdentifierCString());
1494 if (addressNum
->unsigned64BitValue() != 0) {
1495 kmod_info
= (kmod_info_t
*) (intptr_t) (addressNum
->unsigned64BitValue() + vm_kernel_slide
);
1496 kmod_info
->address
+= vm_kernel_slide
;
1497 #if KASLR_KEXT_DEBUG
1498 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1499 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
),
1500 (unsigned long)kmod_info
);
1501 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1502 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
1503 (unsigned long)kmod_info
->address
);
1507 anInfoDict
->removeObject(kPrelinkKmodInfoKey
);
1510 /* If the plist has a UUID for an interface, save that off.
1512 if (isInterface()) {
1513 interfaceUUID
= OSDynamicCast(OSData
,
1514 anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
));
1515 if (interfaceUUID
) {
1516 interfaceUUID
->retain();
1517 anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
);
1521 flags
.prelinked
= true;
1523 /* If we created a kext from prelink info,
1524 * we must be booting from a prelinked kernel.
1526 sPrelinkBoot
= true;
1528 result
= registerIdentifier();
1531 OSSafeRelease(prelinkedExecutable
);
1536 /*********************************************************************
1537 *********************************************************************/
1539 OSKext::withBooterData(
1540 OSString
* deviceTreeName
,
1541 OSData
* booterData
)
1543 OSKext
* newKext
= new OSKext
;
1545 if (newKext
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) {
1553 /*********************************************************************
1554 *********************************************************************/
1555 typedef struct _BooterKextFileInfo
{
1556 uint32_t infoDictPhysAddr
;
1557 uint32_t infoDictLength
;
1558 uint32_t executablePhysAddr
;
1559 uint32_t executableLength
;
1560 uint32_t bundlePathPhysAddr
;
1561 uint32_t bundlePathLength
;
1562 } _BooterKextFileInfo
;
1565 OSKext::initWithBooterData(
1566 OSString
* deviceTreeName
,
1567 OSData
* booterData
)
1569 bool result
= false;
1570 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not free
1571 char * infoDictAddr
= NULL
; // do not free
1572 void * executableAddr
= NULL
; // do not free
1573 char * bundlePathAddr
= NULL
; // do not free
1575 OSObject
* parsedXML
= NULL
; // must release
1576 OSDictionary
* theInfoDict
= NULL
; // do not release
1577 OSString
* kextPath
= NULL
; // must release
1578 OSString
* errorString
= NULL
; // must release
1579 OSData
* executable
= NULL
; // must release
1581 if (!super::init()) {
1585 kextFileInfo
= (_BooterKextFileInfo
*)booterData
->getBytesNoCopy();
1586 if (!kextFileInfo
) {
1588 kOSKextLogErrorLevel
|
1589 kOSKextLogGeneralFlag
,
1590 "No booter-provided data for kext device tree entry %s.",
1591 deviceTreeName
->getCStringNoCopy());
1595 /* The info plist must exist or we can't read the kext.
1597 if (!kextFileInfo
->infoDictPhysAddr
|| !kextFileInfo
->infoDictLength
) {
1599 kOSKextLogErrorLevel
|
1600 kOSKextLogGeneralFlag
,
1601 "No kext info dictionary for booter device tree entry %s.",
1602 deviceTreeName
->getCStringNoCopy());
1606 infoDictAddr
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
1607 if (!infoDictAddr
) {
1609 kOSKextLogErrorLevel
|
1610 kOSKextLogGeneralFlag
,
1611 "Can't translate physical address 0x%x of kext info dictionary "
1612 "for device tree entry %s.",
1613 (int)kextFileInfo
->infoDictPhysAddr
,
1614 deviceTreeName
->getCStringNoCopy());
1618 parsedXML
= OSUnserializeXML(infoDictAddr
, &errorString
);
1620 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
1623 const char * errorCString
= "(unknown error)";
1625 if (errorString
&& errorString
->getCStringNoCopy()) {
1626 errorCString
= errorString
->getCStringNoCopy();
1627 } else if (parsedXML
) {
1628 errorCString
= "not a dictionary";
1631 kOSKextLogErrorLevel
|
1632 kOSKextLogGeneralFlag
,
1633 "Error unserializing info dictionary for device tree entry %s: %s.",
1634 deviceTreeName
->getCStringNoCopy(), errorCString
);
1638 /* A bundle path is not mandatory.
1640 if (kextFileInfo
->bundlePathPhysAddr
&& kextFileInfo
->bundlePathLength
) {
1641 bundlePathAddr
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
);
1642 if (!bundlePathAddr
) {
1644 kOSKextLogErrorLevel
|
1645 kOSKextLogGeneralFlag
,
1646 "Can't translate physical address 0x%x of kext bundle path "
1647 "for device tree entry %s.",
1648 (int)kextFileInfo
->bundlePathPhysAddr
,
1649 deviceTreeName
->getCStringNoCopy());
1652 bundlePathAddr
[kextFileInfo
->bundlePathLength
-1] = '\0'; // just in case!
1654 kextPath
= OSString::withCString(bundlePathAddr
);
1657 kOSKextLogErrorLevel
|
1658 kOSKextLogGeneralFlag
,
1659 "Failed to create wrapper for device tree entry %s kext path %s.",
1660 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
);
1665 if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) {
1669 /* An executable is not mandatory.
1671 if (kextFileInfo
->executablePhysAddr
&& kextFileInfo
->executableLength
) {
1672 executableAddr
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
);
1673 if (!executableAddr
) {
1675 kOSKextLogErrorLevel
|
1676 kOSKextLogGeneralFlag
,
1677 "Can't translate physical address 0x%x of kext executable "
1678 "for device tree entry %s.",
1679 (int)kextFileInfo
->executablePhysAddr
,
1680 deviceTreeName
->getCStringNoCopy());
1684 executable
= OSData::withBytesNoCopy(executableAddr
,
1685 kextFileInfo
->executableLength
);
1688 kOSKextLogErrorLevel
|
1689 kOSKextLogGeneralFlag
,
1690 "Failed to create executable wrapper for device tree entry %s.",
1691 deviceTreeName
->getCStringNoCopy());
1695 /* A kext with an executable needs to retain the whole booterData
1696 * object to keep the executable in memory.
1698 if (!setExecutable(executable
, booterData
)) {
1700 kOSKextLogErrorLevel
|
1701 kOSKextLogGeneralFlag
,
1702 "Failed to set kext executable for device tree entry %s.",
1703 deviceTreeName
->getCStringNoCopy());
1708 result
= registerIdentifier();
1711 OSSafeRelease(parsedXML
);
1712 OSSafeRelease(kextPath
);
1713 OSSafeRelease(errorString
);
1714 OSSafeRelease(executable
);
1719 /*********************************************************************
1720 *********************************************************************/
1722 OSKext::registerIdentifier(void)
1724 bool result
= false;
1725 OSKext
* existingKext
= NULL
; // do not release
1726 bool existingIsLoaded
= false;
1727 bool existingIsPrelinked
= false;
1728 OSKextVersion newVersion
= -1;
1729 OSKextVersion existingVersion
= -1;
1730 char newVersionCString
[kOSKextVersionMaxLength
];
1731 char existingVersionCString
[kOSKextVersionMaxLength
];
1732 OSData
* newUUID
= NULL
; // must release
1733 OSData
* existingUUID
= NULL
; // must release
1735 IORecursiveLockLock(sKextLock
);
1737 /* Get the new kext's version for checks & log messages.
1739 newVersion
= getVersion();
1740 OSKextVersionGetString(newVersion
, newVersionCString
,
1741 kOSKextVersionMaxLength
);
1743 /* If we don't have an existing kext with this identifier,
1744 * just record the new kext and we're done!
1746 existingKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
));
1747 if (!existingKext
) {
1748 sKextsByID
->setObject(bundleID
, this);
1753 /* Get the existing kext's version for checks & log messages.
1755 existingVersion
= existingKext
->getVersion();
1756 OSKextVersionGetString(existingVersion
,
1757 existingVersionCString
, kOSKextVersionMaxLength
);
1759 existingIsLoaded
= existingKext
->isLoaded();
1760 existingIsPrelinked
= existingKext
->isPrelinked();
1762 /* If we have a kext with this identifier that's already loaded/prelinked,
1763 * we can't use the new one, but let's be really thorough and check how
1764 * the two are related for a precise diagnostic log message.
1766 * Note that user space can't find out about nonloaded prelinked kexts,
1767 * so in this case we log a message when new & existing are equivalent
1768 * at the step rather than warning level, because we are always going
1769 * be getting a copy of the kext in the user load request mkext.
1771 if (existingIsLoaded
|| existingIsPrelinked
) {
1772 bool sameVersion
= (newVersion
== existingVersion
);
1773 bool sameExecutable
= true; // assume true unless we have UUIDs
1775 /* Only get the UUID if the existing kext is loaded. Doing so
1776 * might have to uncompress an mkext executable and we shouldn't
1777 * take that hit when neither kext is loaded.
1779 newUUID
= copyUUID();
1780 existingUUID
= existingKext
->copyUUID();
1782 /* I'm entirely too paranoid about checking equivalence of executables,
1783 * but I remember nasty problems with it in the past.
1785 * - If we have UUIDs for both kexts, compare them.
1786 * - If only one kext has a UUID, they're definitely different.
1788 if (newUUID
&& existingUUID
) {
1789 sameExecutable
= newUUID
->isEqualTo(existingUUID
);
1790 } else if (newUUID
|| existingUUID
) {
1791 sameExecutable
= false;
1794 if (!newUUID
&& !existingUUID
) {
1796 /* If there are no UUIDs, we can't really tell that the executables
1797 * are *different* without a lot of work; the loaded kext's
1798 * unrelocated executable is no longer around (and we never had it
1799 * in-kernel for a prelinked kext). We certainly don't want to do
1800 * a whole fake link for the new kext just to compare, either.
1803 OSKextVersionGetString(version
, newVersionCString
,
1804 sizeof(newVersionCString
));
1806 kOSKextLogWarningLevel
|
1807 kOSKextLogKextBookkeepingFlag
,
1808 "Notice - new kext %s, v%s matches %s kext "
1809 "but can't determine if executables are the same (no UUIDs).",
1810 getIdentifierCString(),
1812 (existingIsLoaded
? "loaded" : "prelinked"));
1815 if (sameVersion
&& sameExecutable
) {
1817 (existingIsLoaded
? kOSKextLogWarningLevel
: kOSKextLogStepLevel
) |
1818 kOSKextLogKextBookkeepingFlag
,
1819 "Refusing new kext %s, v%s: a %s copy is already present "
1820 "(same version and executable).",
1821 getIdentifierCString(), newVersionCString
,
1822 (existingIsLoaded
? "loaded" : "prelinked"));
1825 /* This condition is significant so log it under warnings.
1828 kOSKextLogWarningLevel
|
1829 kOSKextLogKextBookkeepingFlag
,
1830 "Refusing new kext %s, v%s: already have %s v%s.",
1831 getIdentifierCString(),
1833 (existingIsLoaded
? "loaded" : "prelinked"),
1834 existingVersionCString
);
1836 /* This condition is significant so log it under warnings.
1839 kOSKextLogWarningLevel
| kOSKextLogKextBookkeepingFlag
,
1840 "Refusing new kext %s, v%s: a %s copy with a different "
1841 "executable UUID is already present.",
1842 getIdentifierCString(), newVersionCString
,
1843 (existingIsLoaded
? "loaded" : "prelinked"));
1847 } /* if (existingIsLoaded || existingIsPrelinked) */
1849 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
1850 * user loads are happening or if we're still in early boot. User agents are
1851 * supposed to resolve dependencies topside and include only the exact
1852 * kexts needed; so we always accept the new kext (in fact we should never
1853 * see an older unloaded copy hanging around).
1855 if (sUserLoadsActive
) {
1856 sKextsByID
->setObject(bundleID
, this);
1860 kOSKextLogStepLevel
|
1861 kOSKextLogKextBookkeepingFlag
,
1862 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
1863 getIdentifierCString(),
1864 existingVersionCString
,
1870 /* During early boot, the kext with the highest version always wins out.
1871 * Prelinked kernels will never hit this, but mkexts and booter-read
1872 * kexts might have duplicates.
1874 if (newVersion
> existingVersion
) {
1875 sKextsByID
->setObject(bundleID
, this);
1879 kOSKextLogStepLevel
|
1880 kOSKextLogKextBookkeepingFlag
,
1881 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
1882 existingVersionCString
,
1883 getIdentifierCString(),
1888 kOSKextLogStepLevel
|
1889 kOSKextLogKextBookkeepingFlag
,
1890 "Kext %s is already registered with a higher/same version (v%s); "
1891 "dropping newly-added (v%s).",
1892 getIdentifierCString(),
1893 existingVersionCString
,
1897 /* result has been set appropriately by now. */
1901 IORecursiveLockUnlock(sKextLock
);
1905 kOSKextLogStepLevel
|
1906 kOSKextLogKextBookkeepingFlag
,
1907 "Kext %s, v%s registered and available for loading.",
1908 getIdentifierCString(), newVersionCString
);
1911 OSSafeRelease(newUUID
);
1912 OSSafeRelease(existingUUID
);
1917 /*********************************************************************
1918 * Does the bare minimum validation to look up a kext.
1919 * All other validation is done on the spot as needed.
1920 **********************************************************************/
1922 OSKext::setInfoDictionaryAndPath(
1923 OSDictionary
* aDictionary
,
1926 bool result
= false;
1927 OSString
* bundleIDString
= NULL
; // do not release
1928 OSString
* versionString
= NULL
; // do not release
1929 OSString
* compatibleVersionString
= NULL
; // do not release
1930 const char * versionCString
= NULL
; // do not free
1931 const char * compatibleVersionCString
= NULL
; // do not free
1932 OSBoolean
* scratchBool
= NULL
; // do not release
1933 OSDictionary
* scratchDict
= NULL
; // do not release
1936 panic("Attempt to set info dictionary on a kext "
1937 "that already has one (%s).",
1938 getIdentifierCString());
1941 if (!aDictionary
|| !OSDynamicCast(OSDictionary
, aDictionary
)) {
1945 infoDict
= aDictionary
;
1948 /* Check right away if the info dictionary has any log flags.
1950 scratchBool
= OSDynamicCast(OSBoolean
,
1951 getPropertyForHostArch(kOSBundleEnableKextLoggingKey
));
1952 if (scratchBool
== kOSBooleanTrue
) {
1953 flags
.loggingEnabled
= 1;
1956 /* The very next thing to get is the bundle identifier. Unlike
1957 * in user space, a kext with no bundle identifier gets axed
1960 bundleIDString
= OSDynamicCast(OSString
,
1961 getPropertyForHostArch(kCFBundleIdentifierKey
));
1962 if (!bundleIDString
) {
1964 kOSKextLogErrorLevel
|
1965 kOSKextLogValidationFlag
,
1966 "CFBundleIdentifier missing/invalid type in kext %s.",
1967 aPath
? aPath
->getCStringNoCopy() : "(unknown)");
1970 bundleID
= OSSymbol::withString(bundleIDString
);
1973 kOSKextLogErrorLevel
|
1974 kOSKextLogValidationFlag
,
1975 "Can't copy bundle identifier as symbol for kext %s.",
1976 bundleIDString
->getCStringNoCopy());
1980 /* Save the path if we got one (it should always be available but it's
1981 * just something nice to have for bookkeeping).
1989 * Minimal validation to initialize. We'll do other validation on the spot.
1991 if (bundleID
->getLength() >= KMOD_MAX_NAME
) {
1993 kOSKextLogErrorLevel
|
1994 kOSKextLogValidationFlag
,
1995 "Kext %s error - CFBundleIdentifier over max length %d.",
1996 getIdentifierCString(), KMOD_MAX_NAME
- 1);
2000 version
= compatibleVersion
= -1;
2002 versionString
= OSDynamicCast(OSString
,
2003 getPropertyForHostArch(kCFBundleVersionKey
));
2004 if (!versionString
) {
2006 kOSKextLogErrorLevel
|
2007 kOSKextLogValidationFlag
,
2008 "Kext %s error - CFBundleVersion missing/invalid type.",
2009 getIdentifierCString());
2012 versionCString
= versionString
->getCStringNoCopy();
2013 version
= OSKextParseVersionString(versionCString
);
2016 kOSKextLogErrorLevel
|
2017 kOSKextLogValidationFlag
,
2018 "Kext %s error - CFBundleVersion bad value '%s'.",
2019 getIdentifierCString(), versionCString
);
2023 compatibleVersion
= -1; // set to illegal value for kexts that don't have
2025 compatibleVersionString
= OSDynamicCast(OSString
,
2026 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
2027 if (compatibleVersionString
) {
2028 compatibleVersionCString
= compatibleVersionString
->getCStringNoCopy();
2029 compatibleVersion
= OSKextParseVersionString(compatibleVersionCString
);
2030 if (compatibleVersion
< 0) {
2032 kOSKextLogErrorLevel
|
2033 kOSKextLogValidationFlag
,
2034 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2035 getIdentifierCString(), compatibleVersionCString
);
2039 if (compatibleVersion
> version
) {
2041 kOSKextLogErrorLevel
|
2042 kOSKextLogValidationFlag
,
2043 "Kext %s error - %s %s > %s %s (must be <=).",
2044 getIdentifierCString(),
2045 kOSBundleCompatibleVersionKey
, compatibleVersionCString
,
2046 kCFBundleVersionKey
, versionCString
);
2051 /* Check to see if this kext is in exclude list */
2052 if ( isInExcludeList() ) {
2054 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
2055 "Kext %s is in exclude list, not loadable",
2056 getIdentifierCString());
2060 /* Set flags for later use if the infoDict gets flushed. We only
2061 * check for true values, not false ones(!)
2063 scratchBool
= OSDynamicCast(OSBoolean
,
2064 getPropertyForHostArch(kOSBundleIsInterfaceKey
));
2065 if (scratchBool
== kOSBooleanTrue
) {
2066 flags
.interface
= 1;
2069 scratchBool
= OSDynamicCast(OSBoolean
,
2070 getPropertyForHostArch(kOSKernelResourceKey
));
2071 if (scratchBool
== kOSBooleanTrue
) {
2072 flags
.kernelComponent
= 1;
2073 flags
.interface
= 1; // xxx - hm. the kernel itself isn't an interface...
2076 /* A kernel component has one implicit dependency on the kernel.
2078 flags
.hasAllDependencies
= 1;
2081 /* Make sure common string values in personalities are uniqued to OSSymbols.
2083 scratchDict
= OSDynamicCast(OSDictionary
,
2084 getPropertyForHostArch(kIOKitPersonalitiesKey
));
2086 uniquePersonalityProperties(scratchDict
);
2096 /*********************************************************************
2097 * Not used for prelinked kernel boot as there is no unrelocated
2099 *********************************************************************/
2101 OSKext::setExecutable(
2102 OSData
* anExecutable
,
2103 OSData
* externalData
,
2104 bool externalDataIsMkext
)
2106 bool result
= false;
2107 const char * executableKey
= NULL
; // do not free
2109 if (!anExecutable
) {
2110 infoDict
->removeObject(_kOSKextExecutableKey
);
2111 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
2112 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
2117 if (infoDict
->getObject(_kOSKextExecutableKey
) ||
2118 infoDict
->getObject(_kOSKextMkextExecutableReferenceKey
)) {
2120 panic("Attempt to set an executable on a kext "
2121 "that already has one (%s).",
2122 getIdentifierCString());
2126 if (externalDataIsMkext
) {
2127 executableKey
= _kOSKextMkextExecutableReferenceKey
;
2129 executableKey
= _kOSKextExecutableKey
;
2133 infoDict
->setObject(executableKey
, anExecutable
);
2135 infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
);
2145 /*********************************************************************
2146 *********************************************************************/
2148 uniqueStringPlistProperty(OSDictionary
* dict
, const char * key
)
2150 OSString
* stringValue
= NULL
; // do not release
2151 const OSSymbol
* symbolValue
= NULL
; // must release
2153 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2158 symbolValue
= OSSymbol::withString(stringValue
);
2163 dict
->setObject(key
, symbolValue
);
2166 if (symbolValue
) symbolValue
->release();
2171 /*********************************************************************
2172 *********************************************************************/
2174 uniqueStringPlistProperty(OSDictionary
* dict
, const OSString
* key
)
2176 OSString
* stringValue
= NULL
; // do not release
2177 const OSSymbol
* symbolValue
= NULL
; // must release
2179 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2184 symbolValue
= OSSymbol::withString(stringValue
);
2189 dict
->setObject(key
, symbolValue
);
2192 if (symbolValue
) symbolValue
->release();
2197 /*********************************************************************
2198 * Replace common personality property values with uniqued instances
2199 * to save on wired memory.
2200 *********************************************************************/
2203 OSKext::uniquePersonalityProperties(OSDictionary
* personalityDict
)
2205 /* Properties every personality has.
2207 uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKey
);
2208 uniqueStringPlistProperty(personalityDict
, kIOProviderClassKey
);
2209 uniqueStringPlistProperty(personalityDict
, gIOClassKey
);
2211 /* Other commonly used properties.
2213 uniqueStringPlistProperty(personalityDict
, gIOMatchCategoryKey
);
2214 uniqueStringPlistProperty(personalityDict
, gIOResourceMatchKey
);
2215 uniqueStringPlistProperty(personalityDict
, gIOUserClientClassKey
);
2217 uniqueStringPlistProperty(personalityDict
, "HIDDefaultBehavior");
2218 uniqueStringPlistProperty(personalityDict
, "HIDPointerAccelerationType");
2219 uniqueStringPlistProperty(personalityDict
, "HIDRemoteControlType");
2220 uniqueStringPlistProperty(personalityDict
, "HIDScrollAccelerationType");
2221 uniqueStringPlistProperty(personalityDict
, "IOPersonalityPublisher");
2222 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect");
2223 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect Location");
2224 uniqueStringPlistProperty(personalityDict
, "Vendor");
2225 uniqueStringPlistProperty(personalityDict
, "Vendor Identification");
2226 uniqueStringPlistProperty(personalityDict
, "Vendor Name");
2227 uniqueStringPlistProperty(personalityDict
, "bConfigurationValue");
2228 uniqueStringPlistProperty(personalityDict
, "bInterfaceNumber");
2229 uniqueStringPlistProperty(personalityDict
, "idProduct");
2234 /*********************************************************************
2235 *********************************************************************/
2240 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2243 OSSafeRelease(infoDict
);
2244 OSSafeRelease(bundleID
);
2245 OSSafeRelease(path
);
2246 OSSafeRelease(executableRelPath
);
2247 OSSafeRelease(dependencies
);
2248 OSSafeRelease(linkedExecutable
);
2249 OSSafeRelease(metaClasses
);
2250 OSSafeRelease(interfaceUUID
);
2252 if (isInterface() && kmod_info
) {
2253 kfree(kmod_info
, sizeof(kmod_info_t
));
2261 #pragma mark Mkext files
2263 /*********************************************************************
2264 *********************************************************************/
2266 OSKext::readMkextArchive(OSData
* mkextData
,
2267 uint32_t * checksumPtr
)
2269 OSReturn result
= kOSKextReturnBadData
;
2270 uint32_t mkextLength
= 0;
2271 mkext_header
* mkextHeader
= 0; // do not free
2272 uint32_t mkextVersion
= 0;
2274 /* Note default return of kOSKextReturnBadData above.
2276 mkextLength
= mkextData
->getLength();
2277 if (mkextLength
< sizeof(mkext_basic_header
)) {
2278 OSKextLog(/* kext */ NULL
,
2279 kOSKextLogErrorLevel
|
2280 kOSKextLogArchiveFlag
,
2281 "Mkext archive too small to be valid.");
2285 mkextHeader
= (mkext_header
*)mkextData
->getBytesNoCopy();
2287 if (MKEXT_GET_MAGIC(mkextHeader
) != MKEXT_MAGIC
||
2288 MKEXT_GET_SIGNATURE(mkextHeader
) != MKEXT_SIGN
) {
2289 OSKextLog(/* kext */ NULL
,
2290 kOSKextLogErrorLevel
|
2291 kOSKextLogArchiveFlag
,
2292 "Mkext archive has invalid magic or signature.");
2296 if (MKEXT_GET_LENGTH(mkextHeader
) != mkextLength
) {
2297 OSKextLog(/* kext */ NULL
,
2298 kOSKextLogErrorLevel
|
2299 kOSKextLogArchiveFlag
,
2300 "Mkext archive recorded length doesn't match actual file length.");
2304 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2306 if (mkextVersion
== MKEXT_VERS_2
) {
2307 result
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
);
2309 OSKextLog(/* kext */ NULL
,
2310 kOSKextLogErrorLevel
|
2311 kOSKextLogArchiveFlag
,
2312 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
);
2313 result
= kOSKextReturnUnsupported
;
2320 /*********************************************************************
2321 * Assumes magic, signature, version, length have been checked.
2322 * xxx - need to add further bounds checking for each file entry
2324 * Should keep track of all kexts created so far, and if we hit a
2325 * fatal error halfway through, remove those kexts. If we've dropped
2326 * an older version that had already been read, whoops! Might want to
2327 * add a level of buffering?
2328 *********************************************************************/
2331 OSKext::readMkext2Archive(
2333 OSDictionary
** mkextPlistOut
,
2334 uint32_t * checksumPtr
)
2336 OSReturn result
= kOSReturnError
;
2337 uint32_t mkextLength
;
2338 mkext2_header
* mkextHeader
= NULL
; // do not free
2339 void * mkextEnd
= NULL
; // do not free
2340 uint32_t mkextVersion
;
2341 uint8_t * crc_address
= NULL
;
2343 uint32_t mkextPlistOffset
;
2344 uint32_t mkextPlistCompressedSize
;
2345 char * mkextPlistEnd
= NULL
; // do not free
2346 uint32_t mkextPlistFullSize
;
2347 OSString
* errorString
= NULL
; // must release
2348 OSData
* mkextPlistUncompressedData
= NULL
; // must release
2349 const char * mkextPlistDataBuffer
= NULL
; // do not free
2350 OSObject
* parsedXML
= NULL
; // must release
2351 OSDictionary
* mkextPlist
= NULL
; // do not release
2352 OSArray
* mkextInfoDictArray
= NULL
; // do not release
2355 mkextLength
= mkextData
->getLength();
2356 mkextHeader
= (mkext2_header
*)mkextData
->getBytesNoCopy();
2357 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2358 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2360 crc_address
= (u_int8_t
*)&mkextHeader
->version
;
2361 checksum
= mkext_adler32(crc_address
,
2362 (uintptr_t)mkextHeader
+
2363 MKEXT_GET_LENGTH(mkextHeader
) - (uintptr_t)crc_address
);
2365 if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) {
2366 OSKextLog(/* kext */ NULL
,
2367 kOSKextLogErrorLevel
|
2368 kOSKextLogArchiveFlag
,
2369 "Mkext archive has bad checksum.");
2370 result
= kOSKextReturnBadData
;
2375 *checksumPtr
= checksum
;
2378 /* Check that the CPU type & subtype match that of the running kernel. */
2379 if (MKEXT_GET_CPUTYPE(mkextHeader
) == (UInt32
)CPU_TYPE_ANY
) {
2380 OSKextLog(/* kext */ NULL
,
2381 kOSKextLogErrorLevel
|
2382 kOSKextLogArchiveFlag
,
2383 "Mkext archive must have a specific CPU type.");
2384 result
= kOSKextReturnBadData
;
2387 if ((UInt32
)_mh_execute_header
.cputype
!=
2388 MKEXT_GET_CPUTYPE(mkextHeader
)) {
2390 OSKextLog(/* kext */ NULL
,
2391 kOSKextLogErrorLevel
|
2392 kOSKextLogArchiveFlag
,
2393 "Mkext archive does not match the running kernel's CPU type.");
2394 result
= kOSKextReturnArchNotFound
;
2399 mkextPlistOffset
= MKEXT2_GET_PLIST(mkextHeader
);
2400 mkextPlistCompressedSize
= MKEXT2_GET_PLIST_COMPSIZE(mkextHeader
);
2401 mkextPlistEnd
= (char *)mkextHeader
+ mkextPlistOffset
+
2402 mkextPlistCompressedSize
;
2403 if (mkextPlistEnd
> mkextEnd
) {
2404 OSKextLog(/* kext */ NULL
,
2405 kOSKextLogErrorLevel
|
2406 kOSKextLogArchiveFlag
,
2407 "Mkext archive file overrun.");
2408 result
= kOSKextReturnBadData
;
2411 mkextPlistFullSize
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
);
2412 if (mkextPlistCompressedSize
) {
2413 mkextPlistUncompressedData
= sKernelKext
->extractMkext2FileData(
2414 (UInt8
*)mkextHeader
+ mkextPlistOffset
,
2416 mkextPlistCompressedSize
, mkextPlistFullSize
);
2417 if (!mkextPlistUncompressedData
) {
2420 mkextPlistDataBuffer
= (const char *)
2421 mkextPlistUncompressedData
->getBytesNoCopy();
2423 mkextPlistDataBuffer
= (const char *)mkextHeader
+ mkextPlistOffset
;
2426 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2428 parsedXML
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
);
2430 mkextPlist
= OSDynamicCast(OSDictionary
, parsedXML
);
2433 const char * errorCString
= "(unknown error)";
2435 if (errorString
&& errorString
->getCStringNoCopy()) {
2436 errorCString
= errorString
->getCStringNoCopy();
2437 } else if (parsedXML
) {
2438 errorCString
= "not a dictionary";
2440 OSKextLog(/* kext */ NULL
,
2441 kOSKextLogErrorLevel
|
2442 kOSKextLogArchiveFlag
,
2443 "Error unserializing mkext plist: %s.", errorCString
);
2447 /* If the caller needs the plist, hand it back and retain it.
2448 * (This function releases it at the end.)
2450 if (mkextPlistOut
) {
2451 *mkextPlistOut
= mkextPlist
;
2452 (*mkextPlistOut
)->retain();
2455 mkextInfoDictArray
= OSDynamicCast(OSArray
,
2456 mkextPlist
->getObject(kMKEXTInfoDictionariesKey
));
2457 if (!mkextInfoDictArray
) {
2458 OSKextLog(/* kext */ NULL
,
2459 kOSKextLogErrorLevel
|
2460 kOSKextLogArchiveFlag
,
2461 "Mkext archive contains no kext info dictionaries.");
2465 count
= mkextInfoDictArray
->getCount();
2466 for (i
= 0; i
< count
; i
++) {
2467 OSDictionary
* infoDict
;
2470 infoDict
= OSDynamicCast(OSDictionary
,
2471 mkextInfoDictArray
->getObject(i
));
2473 /* Create the kext for the entry, then release it, because the
2474 * kext system keeps them around until explicitly removed.
2475 * Any creation/registration failures are already logged for us.
2477 OSKext
* newKext
= OSKext::withMkext2Info(infoDict
, mkextData
);
2478 OSSafeRelease(newKext
);
2481 /* Even if we didn't keep any kexts from the mkext, we may have a load
2482 * request to process, so we are successful (no errors occurred).
2484 result
= kOSReturnSuccess
;
2488 OSSafeRelease(parsedXML
);
2489 OSSafeRelease(mkextPlistUncompressedData
);
2490 OSSafeRelease(errorString
);
2495 /*********************************************************************
2496 *********************************************************************/
2499 OSKext::withMkext2Info(
2500 OSDictionary
* anInfoDict
,
2503 OSKext
* newKext
= new OSKext
;
2505 if (newKext
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) {
2513 /*********************************************************************
2514 *********************************************************************/
2516 OSKext::initWithMkext2Info(
2517 OSDictionary
* anInfoDict
,
2520 bool result
= false;
2521 OSString
* kextPath
= NULL
; // do not release
2522 OSNumber
* executableOffsetNum
= NULL
; // do not release
2523 OSCollectionIterator
* iterator
= NULL
; // must release
2524 OSData
* executable
= NULL
; // must release
2526 if (!super::init()) {
2530 /* Get the path. Don't look for an arch-specific path property.
2532 kextPath
= OSDynamicCast(OSString
,
2533 anInfoDict
->getObject(kMKEXTBundlePathKey
));
2535 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
2539 /* If we have a path to the executable, save it.
2541 executableRelPath
= OSDynamicCast(OSString
,
2542 anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
));
2543 if (executableRelPath
) {
2544 executableRelPath
->retain();
2547 /* Don't need the paths to be in the info dictionary any more.
2549 anInfoDict
->removeObject(kMKEXTBundlePathKey
);
2550 anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
);
2552 executableOffsetNum
= OSDynamicCast(OSNumber
,
2553 infoDict
->getObject(kMKEXTExecutableKey
));
2554 if (executableOffsetNum
) {
2555 executable
= createMkext2FileEntry(mkextData
,
2556 executableOffsetNum
, "executable");
2557 infoDict
->removeObject(kMKEXTExecutableKey
);
2561 if (!setExecutable(executable
, mkextData
, true)) {
2566 result
= registerIdentifier();
2570 OSSafeRelease(executable
);
2571 OSSafeRelease(iterator
);
2575 /*********************************************************************
2576 *********************************************************************/
2578 OSKext::createMkext2FileEntry(
2580 OSNumber
* offsetNum
,
2583 OSData
* result
= NULL
;
2584 MkextEntryRef entryRef
;
2585 uint8_t * mkextBuffer
= (uint8_t *)mkextData
->getBytesNoCopy();
2586 uint32_t entryOffset
= offsetNum
->unsigned32BitValue();
2588 result
= OSData::withCapacity(sizeof(entryRef
));
2593 entryRef
.mkext
= (mkext_basic_header
*)mkextBuffer
;
2594 entryRef
.fileinfo
= mkextBuffer
+ entryOffset
;
2595 if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) {
2596 OSSafeReleaseNULL(result
);
2603 kOSKextLogErrorLevel
|
2604 kOSKextLogArchiveFlag
,
2605 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2606 name
, getIdentifierCString());
2611 /*********************************************************************
2612 *********************************************************************/
2614 static void * z_alloc(void *, u_int items
, u_int size
);
2615 static void z_free(void *, void *ptr
);
2617 typedef struct z_mem
{
2618 uint32_t alloc_size
;
2623 * Space allocation and freeing routines for use by zlib routines.
2626 z_alloc(void * notused __unused
, u_int num_items
, u_int size
)
2628 void * result
= NULL
;
2629 z_mem
* zmem
= NULL
;
2631 uint64_t total
= ((uint64_t)num_items
) * ((uint64_t)size
);
2632 //Check for overflow due to multiplication
2633 if (total
> UINT32_MAX
){
2634 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
2635 notused
, num_items
, size
, num_items
, size
);
2638 uint64_t allocSize64
= total
+ ((uint64_t)sizeof(zmem
));
2639 //Check for overflow due to addition
2640 if (allocSize64
> UINT32_MAX
){
2641 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
2642 notused
, num_items
, size
, (uint32_t)total
, sizeof(zmem
));
2644 uint32_t allocSize
= (uint32_t)allocSize64
;
2646 zmem
= (z_mem
*)kalloc(allocSize
);
2650 zmem
->alloc_size
= allocSize
;
2651 result
= (void *)&(zmem
->data
);
2657 z_free(void * notused __unused
, void * ptr
)
2659 uint32_t * skipper
= (uint32_t *)ptr
- 1;
2660 z_mem
* zmem
= (z_mem
*)skipper
;
2661 kfree((void *)zmem
, zmem
->alloc_size
);
2667 OSKext::extractMkext2FileData(
2670 uint32_t compressedSize
,
2673 OSData
* result
= NULL
;
2675 OSData
* uncompressedData
= NULL
; // release on error
2677 uint8_t * uncompressedDataBuffer
= 0; // do not free
2678 unsigned long uncompressedSize
;
2680 bool zstream_inited
= false;
2683 /* If the file isn't compressed, we want to make a copy
2684 * so that we don't have the tie to the larger mkext file buffer any more.
2686 if (!compressedSize
) {
2687 uncompressedData
= OSData::withBytes(data
, fullSize
);
2688 // xxx - no check for failure?
2689 result
= uncompressedData
;
2693 if (KERN_SUCCESS
!= kmem_alloc(kernel_map
,
2694 (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
)) {
2696 /* How's this for cheesy? The kernel is only asked to extract
2697 * kext plists so we tailor the log messages.
2701 kOSKextLogErrorLevel
|
2702 kOSKextLogArchiveFlag
,
2703 "Allocation failure extracting %s from mkext.", name
);
2706 kOSKextLogErrorLevel
|
2707 kOSKextLogArchiveFlag
,
2708 "Allocation failure extracting %s from mkext for kext %s.",
2709 name
, getIdentifierCString());
2714 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
);
2715 if (!uncompressedData
) {
2718 kOSKextLogErrorLevel
|
2719 kOSKextLogArchiveFlag
,
2720 "Allocation failure extracting %s from mkext.", name
);
2723 kOSKextLogErrorLevel
|
2724 kOSKextLogArchiveFlag
,
2725 "Allocation failure extracting %s from mkext for kext %s.",
2726 name
, getIdentifierCString());
2730 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
2734 kOSKextLogDetailLevel
|
2735 kOSKextLogArchiveFlag
,
2736 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2737 name
, compressedSize
, fullSize
);
2740 kOSKextLogDetailLevel
|
2741 kOSKextLogArchiveFlag
,
2742 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2743 getIdentifierCString(), name
, compressedSize
, fullSize
);
2746 bzero(&zstream
, sizeof(zstream
));
2747 zstream
.next_in
= (UInt8
*)data
;
2748 zstream
.avail_in
= compressedSize
;
2750 zstream
.next_out
= uncompressedDataBuffer
;
2751 zstream
.avail_out
= fullSize
;
2753 zstream
.zalloc
= z_alloc
;
2754 zstream
.zfree
= z_free
;
2756 zlib_result
= inflateInit(&zstream
);
2757 if (Z_OK
!= zlib_result
) {
2760 kOSKextLogErrorLevel
|
2761 kOSKextLogArchiveFlag
,
2762 "Mkext error; zlib inflateInit failed (%d) for %s.",
2766 kOSKextLogErrorLevel
|
2767 kOSKextLogArchiveFlag
,
2768 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2769 getIdentifierCString(), zlib_result
, name
);
2773 zstream_inited
= true;
2776 zlib_result
= inflate(&zstream
, Z_FINISH
);
2778 if (zlib_result
== Z_STREAM_END
|| zlib_result
== Z_OK
) {
2779 uncompressedSize
= zstream
.total_out
;
2783 kOSKextLogErrorLevel
|
2784 kOSKextLogArchiveFlag
,
2785 "Mkext error; zlib inflate failed (%d) for %s.",
2789 kOSKextLogErrorLevel
|
2790 kOSKextLogArchiveFlag
,
2791 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
2792 getIdentifierCString(), zlib_result
, name
);
2796 kOSKextLogErrorLevel
|
2797 kOSKextLogArchiveFlag
,
2798 "zlib error: %s.", zstream
.msg
);
2803 if (uncompressedSize
!= fullSize
) {
2806 kOSKextLogErrorLevel
|
2807 kOSKextLogArchiveFlag
,
2808 "Mkext error; zlib inflate discrepancy for %s, "
2809 "uncompressed size != original size.", name
);
2812 kOSKextLogErrorLevel
|
2813 kOSKextLogArchiveFlag
,
2814 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
2815 "uncompressed size != original size.",
2816 getIdentifierCString(), name
);
2821 result
= uncompressedData
;
2824 /* Don't bother checking return, nothing we can do on fail.
2826 if (zstream_inited
) inflateEnd(&zstream
);
2829 OSSafeRelease(uncompressedData
);
2835 /*********************************************************************
2836 *********************************************************************/
2839 OSKext::loadFromMkext(
2840 OSKextLogSpec clientLogFilter
,
2842 uint32_t mkextBufferLength
,
2844 uint32_t * logInfoLengthOut
)
2846 OSReturn result
= kOSReturnError
;
2847 OSReturn tempResult
= kOSReturnError
;
2849 OSData
* mkextData
= NULL
; // must release
2850 OSDictionary
* mkextPlist
= NULL
; // must release
2852 OSArray
* logInfoArray
= NULL
; // must release
2853 OSSerialize
* serializer
= NULL
; // must release
2855 OSString
* predicate
= NULL
; // do not release
2856 OSDictionary
* requestArgs
= NULL
; // do not release
2858 OSString
* kextIdentifier
= NULL
; // do not release
2859 OSNumber
* startKextExcludeNum
= NULL
; // do not release
2860 OSNumber
* startMatchingExcludeNum
= NULL
; // do not release
2861 OSBoolean
* delayAutounloadBool
= NULL
; // do not release
2862 OSArray
* personalityNames
= NULL
; // do not release
2864 /* Default values for these two options: regular autounload behavior,
2865 * load all kexts, send no personalities.
2867 Boolean delayAutounload
= false;
2868 OSKextExcludeLevel startKextExcludeLevel
= kOSKextExcludeNone
;
2869 OSKextExcludeLevel startMatchingExcludeLevel
= kOSKextExcludeAll
;
2871 IORecursiveLockLock(sKextLock
);
2875 *logInfoLengthOut
= 0;
2878 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
2880 OSKextLog(/* kext */ NULL
,
2881 kOSKextLogDebugLevel
|
2883 "Received kext load request from user space.");
2885 /* Regardless of processing, the fact that we have gotten here means some
2886 * user-space program is up and talking to us, so we'll switch our kext
2887 * registration to reflect that.
2889 if (!sUserLoadsActive
) {
2890 OSKextLog(/* kext */ NULL
,
2891 kOSKextLogProgressLevel
|
2892 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
2893 "Switching to late startup (user-space) kext loading policy.");
2895 sUserLoadsActive
= true;
2898 if (!sLoadEnabled
) {
2899 OSKextLog(/* kext */ NULL
,
2900 kOSKextLogErrorLevel
|
2902 "Kext loading is disabled.");
2903 result
= kOSKextReturnDisabled
;
2907 /* Note that we do not set a dealloc function on this OSData
2908 * object! No references to it can remain after the loadFromMkext()
2909 * call since we are in a MIG function, and will vm_deallocate()
2912 mkextData
= OSData::withBytesNoCopy(mkextBuffer
,
2915 OSKextLog(/* kext */ NULL
,
2916 kOSKextLogErrorLevel
|
2917 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
2918 "Failed to create wrapper for kext load request.");
2919 result
= kOSKextReturnNoMemory
;
2923 result
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
);
2924 if (result
!= kOSReturnSuccess
) {
2925 OSKextLog(/* kext */ NULL
,
2926 kOSKextLogErrorLevel
|
2928 "Failed to read kext load request.");
2932 predicate
= _OSKextGetRequestPredicate(mkextPlist
);
2933 if (!predicate
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) {
2934 OSKextLog(/* kext */ NULL
,
2935 kOSKextLogErrorLevel
|
2937 "Received kext load request with no predicate; skipping.");
2938 result
= kOSKextReturnInvalidArgument
;
2942 requestArgs
= OSDynamicCast(OSDictionary
,
2943 mkextPlist
->getObject(kKextRequestArgumentsKey
));
2944 if (!requestArgs
|| !requestArgs
->getCount()) {
2945 OSKextLog(/* kext */ NULL
,
2946 kOSKextLogErrorLevel
|
2948 "Received kext load request with no arguments.");
2949 result
= kOSKextReturnInvalidArgument
;
2953 kextIdentifier
= OSDynamicCast(OSString
,
2954 requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
));
2955 if (!kextIdentifier
) {
2956 OSKextLog(/* kext */ NULL
,
2957 kOSKextLogErrorLevel
|
2959 "Received kext load request with no kext identifier.");
2960 result
= kOSKextReturnInvalidArgument
;
2964 startKextExcludeNum
= OSDynamicCast(OSNumber
,
2965 requestArgs
->getObject(kKextRequestArgumentStartExcludeKey
));
2966 startMatchingExcludeNum
= OSDynamicCast(OSNumber
,
2967 requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
));
2968 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
2969 requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
));
2970 personalityNames
= OSDynamicCast(OSArray
,
2971 requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
));
2973 if (delayAutounloadBool
) {
2974 delayAutounload
= delayAutounloadBool
->getValue();
2976 if (startKextExcludeNum
) {
2977 startKextExcludeLevel
= startKextExcludeNum
->unsigned8BitValue();
2979 if (startMatchingExcludeNum
) {
2980 startMatchingExcludeLevel
= startMatchingExcludeNum
->unsigned8BitValue();
2983 OSKextLog(/* kext */ NULL
,
2984 kOSKextLogProgressLevel
|
2986 "Received request from user space to load kext %s.",
2987 kextIdentifier
->getCStringNoCopy());
2989 /* Load the kext, with no deferral, since this is a load from outside
2991 * xxx - Would like a better way to handle the default values for the
2992 * xxx - start/match opt args.
2994 result
= OSKext::loadKextWithIdentifier(
2996 /* allowDefer */ false,
2998 startKextExcludeLevel
,
2999 startMatchingExcludeLevel
,
3001 if (result
!= kOSReturnSuccess
) {
3004 /* If the load came down from kextd, it will shortly inform IOCatalogue
3005 * for matching via a separate IOKit calldown.
3010 /* Gather up the collected log messages for user space. Any
3011 * error messages past this call will not make it up as log messages
3012 * but will be in the system log.
3014 logInfoArray
= OSKext::clearUserSpaceLogFilter();
3016 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
3017 tempResult
= OSKext::serializeLogInfo(logInfoArray
,
3018 logInfoOut
, logInfoLengthOut
);
3019 if (tempResult
!= kOSReturnSuccess
) {
3020 result
= tempResult
;
3024 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3026 /* Note: mkextDataObject will have been retained by every kext w/an
3027 * executable in it. That should all have been flushed out at the
3028 * and of the load operation, but you never know....
3030 if (mkextData
&& mkextData
->getRetainCount() > 1) {
3031 OSKextLog(/* kext */ NULL
,
3032 kOSKextLogErrorLevel
|
3033 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3034 "Kext load request buffer from user space still retained by a kext; "
3035 "probable memory leak.");
3038 IORecursiveLockUnlock(sKextLock
);
3040 OSSafeRelease(mkextData
);
3041 OSSafeRelease(mkextPlist
);
3042 OSSafeRelease(serializer
);
3043 OSSafeRelease(logInfoArray
);
3048 /*********************************************************************
3049 *********************************************************************/
3052 OSKext::serializeLogInfo(
3053 OSArray
* logInfoArray
,
3055 uint32_t * logInfoLengthOut
)
3057 OSReturn result
= kOSReturnError
;
3058 char * buffer
= NULL
;
3059 kern_return_t kmem_result
= KERN_FAILURE
;
3060 OSSerialize
* serializer
= NULL
; // must release; reused
3061 char * logInfo
= NULL
; // returned by reference
3062 uint32_t logInfoLength
= 0;
3064 if (!logInfoArray
|| !logInfoOut
|| !logInfoLengthOut
) {
3065 OSKextLog(/* kext */ NULL
,
3066 kOSKextLogErrorLevel
|
3068 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3069 /* Bad programmer. */
3070 result
= kOSKextReturnInvalidArgument
;
3074 serializer
= OSSerialize::withCapacity(0);
3076 OSKextLog(/* kext */ NULL
,
3077 kOSKextLogErrorLevel
|
3079 "Failed to create serializer on log info for request from user space.");
3080 /* Incidental error; we're going to (try to) allow the request
3081 * itself to succeed. */
3084 if (!logInfoArray
->serialize(serializer
)) {
3085 OSKextLog(/* kext */ NULL
,
3086 kOSKextLogErrorLevel
|
3088 "Failed to serialize log info for request from user space.");
3089 /* Incidental error; we're going to (try to) allow the request
3090 * itself to succeed. */
3092 logInfo
= serializer
->text();
3093 logInfoLength
= serializer
->getLength();
3095 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
, round_page(logInfoLength
));
3096 if (kmem_result
!= KERN_SUCCESS
) {
3097 OSKextLog(/* kext */ NULL
,
3098 kOSKextLogErrorLevel
|
3100 "Failed to copy log info for request from user space.");
3101 /* Incidental error; we're going to (try to) allow the request
3104 /* 11981737 - clear uninitialized data in last page */
3105 bzero((void *)(buffer
+ logInfoLength
),
3106 (round_page(logInfoLength
) - logInfoLength
));
3107 memcpy(buffer
, logInfo
, logInfoLength
);
3108 *logInfoOut
= buffer
;
3109 *logInfoLengthOut
= logInfoLength
;
3113 result
= kOSReturnSuccess
;
3115 OSSafeRelease(serializer
);
3120 #pragma mark Instance Management Methods
3122 /*********************************************************************
3123 *********************************************************************/
3125 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
)
3127 OSKext
* foundKext
= NULL
;
3129 IORecursiveLockLock(sKextLock
);
3130 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3132 foundKext
->retain();
3134 IORecursiveLockUnlock(sKextLock
);
3139 /*********************************************************************
3140 *********************************************************************/
3142 OSKext::lookupKextWithIdentifier(OSString
* kextIdentifier
)
3144 return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy());
3147 /*********************************************************************
3148 *********************************************************************/
3150 OSKext::lookupKextWithLoadTag(uint32_t aTag
)
3152 OSKext
* foundKext
= NULL
; // returned
3155 IORecursiveLockLock(sKextLock
);
3157 count
= sLoadedKexts
->getCount();
3158 for (i
= 0; i
< count
; i
++) {
3159 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3160 if (thisKext
->getLoadTag() == aTag
) {
3161 foundKext
= thisKext
;
3162 foundKext
->retain();
3168 IORecursiveLockUnlock(sKextLock
);
3173 /*********************************************************************
3174 *********************************************************************/
3176 OSKext::lookupKextWithAddress(vm_address_t address
)
3178 OSKext
* foundKext
= NULL
; // returned
3181 IORecursiveLockLock(sKextLock
);
3183 count
= sLoadedKexts
->getCount();
3184 for (i
= 0; i
< count
; i
++) {
3185 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3186 if (thisKext
->linkedExecutable
) {
3187 vm_address_t kext_start
=
3188 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy();
3189 vm_address_t kext_end
= kext_start
+
3190 thisKext
->linkedExecutable
->getLength();
3192 if ((kext_start
<= address
) && (address
< kext_end
)) {
3193 foundKext
= thisKext
;
3194 foundKext
->retain();
3201 IORecursiveLockUnlock(sKextLock
);
3206 /*********************************************************************
3207 *********************************************************************/
3209 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
)
3211 bool result
= false;
3212 OSKext
* foundKext
= NULL
; // returned
3214 IORecursiveLockLock(sKextLock
);
3216 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3217 if (foundKext
&& foundKext
->isLoaded()) {
3221 IORecursiveLockUnlock(sKextLock
);
3226 /*********************************************************************
3227 * xxx - should spawn a separate thread so a kext can safely have
3228 * xxx - itself unloaded.
3229 *********************************************************************/
3234 bool terminateServicesAndRemovePersonalitiesFlag
)
3236 OSReturn result
= kOSKextReturnInUse
;
3237 OSKext
* checkKext
= NULL
; // do not release
3239 int macCheckResult
= 0;
3240 kauth_cred_t cred
= NULL
;
3243 IORecursiveLockLock(sKextLock
);
3245 /* If the kext has no identifier, it failed to init
3246 * so isn't in sKextsByID and it isn't loaded.
3248 if (!aKext
->getIdentifier()) {
3249 result
= kOSReturnSuccess
;
3253 checkKext
= OSDynamicCast(OSKext
,
3254 sKextsByID
->getObject(aKext
->getIdentifier()));
3255 if (checkKext
!= aKext
) {
3256 result
= kOSKextReturnNotFound
;
3260 if (aKext
->isLoaded()) {
3262 if (current_task() != kernel_task
) {
3263 cred
= kauth_cred_get_with_ref();
3264 macCheckResult
= mac_kext_check_unload(cred
, aKext
->getIdentifierCString());
3265 kauth_cred_unref(&cred
);
3268 if (macCheckResult
!= 0) {
3269 result
= kOSReturnError
;
3271 kOSKextLogErrorLevel
|
3272 kOSKextLogKextBookkeepingFlag
,
3273 "Failed to remove kext %s (MAC policy error 0x%x).",
3274 aKext
->getIdentifierCString(), macCheckResult
);
3279 /* If we are terminating, send the request to the IOCatalogue
3280 * (which will actually call us right back but that's ok we have
3281 * a recursive lock don't you know) but do not ask the IOCatalogue
3282 * to call back with an unload, we'll do that right here.
3284 if (terminateServicesAndRemovePersonalitiesFlag
) {
3285 result
= gIOCatalogue
->terminateDriversForModule(
3286 aKext
->getIdentifierCString(), /* unload */ false);
3287 if (result
!= kOSReturnSuccess
) {
3289 kOSKextLogErrorLevel
|
3290 kOSKextLogKextBookkeepingFlag
,
3291 "Can't remove kext %s; services failed to terminate - 0x%x.",
3292 aKext
->getIdentifierCString(), result
);
3297 result
= aKext
->unload();
3298 if (result
!= kOSReturnSuccess
) {
3303 /* Remove personalities as requested. This is a bit redundant for a loaded
3304 * kext as IOCatalogue::terminateDriversForModule() removes driver
3305 * personalities, but it doesn't restart matching, which we always want
3306 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3309 if (terminateServicesAndRemovePersonalitiesFlag
) {
3310 aKext
->removePersonalitiesFromCatalog();
3314 kOSKextLogProgressLevel
|
3315 kOSKextLogKextBookkeepingFlag
,
3316 "Removing kext %s.",
3317 aKext
->getIdentifierCString());
3319 sKextsByID
->removeObject(aKext
->getIdentifier());
3320 result
= kOSReturnSuccess
;
3323 IORecursiveLockUnlock(sKextLock
);
3327 /*********************************************************************
3328 *********************************************************************/
3331 OSKext::removeKextWithIdentifier(
3332 const char * kextIdentifier
,
3333 bool terminateServicesAndRemovePersonalitiesFlag
)
3335 OSReturn result
= kOSReturnError
;
3337 IORecursiveLockLock(sKextLock
);
3339 OSKext
* aKext
= OSDynamicCast(OSKext
,
3340 sKextsByID
->getObject(kextIdentifier
));
3342 result
= kOSKextReturnNotFound
;
3343 OSKextLog(/* kext */ NULL
,
3344 kOSKextLogErrorLevel
|
3345 kOSKextLogKextBookkeepingFlag
,
3346 "Can't remove kext %s - not found.",
3351 result
= OSKext::removeKext(aKext
,
3352 terminateServicesAndRemovePersonalitiesFlag
);
3355 IORecursiveLockUnlock(sKextLock
);
3360 /*********************************************************************
3361 *********************************************************************/
3364 OSKext::removeKextWithLoadTag(
3365 OSKextLoadTag loadTag
,
3366 bool terminateServicesAndRemovePersonalitiesFlag
)
3368 OSReturn result
= kOSReturnError
;
3369 OSKext
* foundKext
= NULL
;
3372 IORecursiveLockLock(sKextLock
);
3374 count
= sLoadedKexts
->getCount();
3375 for (i
= 0; i
< count
; i
++) {
3376 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3377 if (thisKext
->loadTag
== loadTag
) {
3378 foundKext
= thisKext
;
3384 result
= kOSKextReturnNotFound
;
3385 OSKextLog(/* kext */ NULL
,
3386 kOSKextLogErrorLevel
|
3387 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
3388 "Can't remove kext with load tag %d - not found.",
3393 result
= OSKext::removeKext(foundKext
,
3394 terminateServicesAndRemovePersonalitiesFlag
);
3397 IORecursiveLockUnlock(sKextLock
);
3402 /*********************************************************************
3403 *********************************************************************/
3405 OSKext::copyKexts(void)
3407 OSDictionary
* result
;
3409 IORecursiveLockLock(sKextLock
);
3410 result
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection());
3411 IORecursiveLockUnlock(sKextLock
);
3416 /*********************************************************************
3417 *********************************************************************/
3418 #define BOOTER_KEXT_PREFIX "Driver-"
3420 typedef struct _DeviceTreeBuffer
{
3423 } _DeviceTreeBuffer
;
3425 /*********************************************************************
3426 * Create a dictionary of excluded kexts from the given booter data.
3427 *********************************************************************/
3430 OSKext::createExcludeListFromBooterData(
3431 OSDictionary
* theDictionary
,
3432 OSCollectionIterator
* theIterator
)
3434 OSString
* deviceTreeName
= NULL
; // do not release
3435 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not release
3436 char * booterDataPtr
= NULL
; // do not release
3437 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not release
3438 char * infoDictAddr
= NULL
; // do not release
3439 OSObject
* parsedXML
= NULL
; // must release
3440 OSDictionary
* theInfoDict
= NULL
; // do not release
3442 theIterator
->reset();
3444 /* look for AppleKextExcludeList.kext */
3445 while ( (deviceTreeName
=
3446 OSDynamicCast(OSString
, theIterator
->getNextObject())) ) {
3448 const char * devTreeNameCString
;
3449 OSData
* deviceTreeEntry
;
3450 OSString
* myBundleID
; // do not release
3452 OSSafeReleaseNULL(parsedXML
);
3455 OSDynamicCast(OSData
, theDictionary
->getObject(deviceTreeName
));
3456 if (!deviceTreeEntry
) {
3460 /* Make sure it is a kext */
3461 devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
3462 if (strncmp(devTreeNameCString
, BOOTER_KEXT_PREFIX
,
3463 (sizeof(BOOTER_KEXT_PREFIX
) - 1)) != 0) {
3465 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3466 "\"%s\" not a kext",
3467 devTreeNameCString
);
3471 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
3472 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
3473 if (!deviceTreeBuffer
) {
3477 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
3478 if (!booterDataPtr
) {
3482 kextFileInfo
= (_BooterKextFileInfo
*) booterDataPtr
;
3483 if (!kextFileInfo
->infoDictPhysAddr
||
3484 !kextFileInfo
->infoDictLength
) {
3488 infoDictAddr
= (char *)
3489 ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
3490 if (!infoDictAddr
) {
3494 parsedXML
= OSUnserializeXML(infoDictAddr
);
3499 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
3505 OSDynamicCast(OSString
,
3506 theInfoDict
->getObject(kCFBundleIdentifierKey
));
3508 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3510 /* get copy of exclusion list dictionary */
3511 OSDictionary
* myTempDict
; // do not free
3513 myTempDict
= OSDynamicCast(
3515 theInfoDict
->getObject("OSKextExcludeList"));
3517 IORecursiveLockLock(sKextLock
);
3519 /* get rid of old exclusion list */
3520 if (sExcludeListByID
) {
3521 sExcludeListByID
->flushCollection();
3522 OSSafeRelease(sExcludeListByID
);
3524 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3525 IORecursiveLockUnlock(sKextLock
);
3530 } // while ( (deviceTreeName = ...) )
3532 OSSafeReleaseNULL(parsedXML
);
3536 /*********************************************************************
3537 * Create a dictionary of excluded kexts from the given prelink
3538 * info (kernelcache).
3539 *********************************************************************/
3542 OSKext::createExcludeListFromPrelinkInfo( OSArray
* theInfoArray
)
3544 OSDictionary
* myInfoDict
= NULL
; // do not release
3545 OSString
* myBundleID
; // do not release
3548 /* Find com.apple.driver.KextExcludeList. */
3549 for (i
= 0; i
< theInfoArray
->getCount(); i
++) {
3550 myInfoDict
= OSDynamicCast(OSDictionary
, theInfoArray
->getObject(i
));
3555 OSDynamicCast(OSString
,
3556 myInfoDict
->getObject(kCFBundleIdentifierKey
));
3558 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3559 // get copy of exclude list dictionary
3560 OSDictionary
* myTempDict
; // do not free
3561 myTempDict
= OSDynamicCast(OSDictionary
,
3562 myInfoDict
->getObject("OSKextExcludeList"));
3564 IORecursiveLockLock(sKextLock
);
3565 // get rid of old exclude list
3566 if (sExcludeListByID
) {
3567 sExcludeListByID
->flushCollection();
3568 OSSafeRelease(sExcludeListByID
);
3571 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3572 IORecursiveLockUnlock(sKextLock
);
3576 } // for (i = 0; i < theInfoArray->getCount()...
3582 #pragma mark Accessors
3584 /*********************************************************************
3585 *********************************************************************/
3587 OSKext::getIdentifier(void)
3592 /*********************************************************************
3593 * A kext must have a bundle identifier to even survive initialization;
3594 * this is guaranteed to exist past then.
3595 *********************************************************************/
3597 OSKext::getIdentifierCString(void)
3599 return bundleID
->getCStringNoCopy();
3602 /*********************************************************************
3603 *********************************************************************/
3605 OSKext::getVersion(void)
3610 /*********************************************************************
3611 *********************************************************************/
3613 OSKext::getCompatibleVersion(void)
3615 return compatibleVersion
;
3618 /*********************************************************************
3619 *********************************************************************/
3621 OSKext::isLibrary(void)
3623 return (getCompatibleVersion() > 0);
3626 /*********************************************************************
3627 *********************************************************************/
3629 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
)
3631 if ((compatibleVersion
> -1 && version
> -1) &&
3632 (compatibleVersion
<= version
&& aVersion
<= version
)) {
3638 /*********************************************************************
3639 *********************************************************************/
3641 OSKext::declaresExecutable(void)
3643 return (getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
);
3646 /*********************************************************************
3647 *********************************************************************/
3649 OSKext::getExecutable(void)
3651 OSData
* result
= NULL
;
3652 OSData
* extractedExecutable
= NULL
; // must release
3653 OSData
* mkextExecutableRef
= NULL
; // do not release
3655 result
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
));
3660 mkextExecutableRef
= OSDynamicCast(OSData
,
3661 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
));
3663 if (mkextExecutableRef
) {
3665 MkextEntryRef
* mkextEntryRef
= (MkextEntryRef
*)
3666 mkextExecutableRef
->getBytesNoCopy();
3667 uint32_t mkextVersion
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
);
3668 if (mkextVersion
== MKEXT_VERS_2
) {
3669 mkext2_file_entry
* fileinfo
=
3670 (mkext2_file_entry
*)mkextEntryRef
->fileinfo
;
3671 uint32_t compressedSize
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
);
3672 uint32_t fullSize
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
);
3673 extractedExecutable
= extractMkext2FileData(
3674 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable",
3675 compressedSize
, fullSize
);
3677 OSKextLog(this, kOSKextLogErrorLevel
|
3678 kOSKextLogArchiveFlag
,
3679 "Kext %s - unknown mkext version 0x%x for executable.",
3680 getIdentifierCString(), mkextVersion
);
3683 /* Regardless of success, remove the mkext executable,
3684 * and drop one reference on the mkext. (setExecutable() does not
3685 * replace, it removes, or panics if asked to replace.)
3687 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
3688 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
3690 if (extractedExecutable
&& extractedExecutable
->getLength()) {
3691 if (!setExecutable(extractedExecutable
)) {
3694 result
= extractedExecutable
;
3702 OSSafeRelease(extractedExecutable
);
3707 /*********************************************************************
3708 *********************************************************************/
3710 OSKext::isInterface(void)
3712 return flags
.interface
;
3715 /*********************************************************************
3716 *********************************************************************/
3718 OSKext::isKernel(void)
3720 return (this == sKernelKext
);
3723 /*********************************************************************
3724 *********************************************************************/
3726 OSKext::isKernelComponent(void)
3728 return flags
.kernelComponent
? true : false;
3731 /*********************************************************************
3732 *********************************************************************/
3734 OSKext::isExecutable(void)
3736 return (!isKernel() && !isInterface() && declaresExecutable());
3739 /*********************************************************************
3740 * We might want to check this recursively for all dependencies,
3741 * since a subtree of dependencies could get loaded before we hit
3742 * a dependency that isn't safe-boot-loadable.
3744 * xxx - Might want to return false if OSBundleEnableKextLogging or
3745 * OSBundleDebugLevel
3746 * or IOKitDebug is nonzero too (we used to do that, but I don't see
3747 * the point except it's usually development drivers, which might
3748 * cause panics on startup, that have those properties). Heh; could
3749 * use a "kx" boot-arg!
3750 *********************************************************************/
3752 OSKext::isLoadableInSafeBoot(void)
3754 bool result
= false;
3755 OSString
* required
= NULL
; // do not release
3762 required
= OSDynamicCast(OSString
,
3763 getPropertyForHostArch(kOSBundleRequiredKey
));
3767 if (required
->isEqualTo(kOSBundleRequiredRoot
) ||
3768 required
->isEqualTo(kOSBundleRequiredLocalRoot
) ||
3769 required
->isEqualTo(kOSBundleRequiredNetworkRoot
) ||
3770 required
->isEqualTo(kOSBundleRequiredSafeBoot
) ||
3771 required
->isEqualTo(kOSBundleRequiredConsole
)) {
3780 /*********************************************************************
3781 *********************************************************************/
3783 OSKext::isPrelinked(void)
3785 return flags
.prelinked
? true : false;
3788 /*********************************************************************
3789 *********************************************************************/
3790 bool OSKext::isLoaded(void)
3792 return flags
.loaded
? true : false;
3795 /*********************************************************************
3796 *********************************************************************/
3798 OSKext::isStarted(void)
3800 return flags
.started
? true : false;
3803 /*********************************************************************
3804 *********************************************************************/
3806 OSKext::isCPPInitialized(void)
3808 return flags
.CPPInitialized
;
3811 /*********************************************************************
3812 *********************************************************************/
3814 OSKext::setCPPInitialized(bool initialized
)
3816 flags
.CPPInitialized
= initialized
;
3819 /*********************************************************************
3820 *********************************************************************/
3822 OSKext::getLoadTag(void)
3827 /*********************************************************************
3828 *********************************************************************/
3829 void OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
)
3831 if (linkedExecutable
) {
3832 *loadSize
= linkedExecutable
->getLength();
3834 /* If we have a kmod_info struct, calculated the wired size
3835 * from that. Otherwise it's the full load size.
3838 *wiredSize
= *loadSize
- kmod_info
->hdr_size
;
3840 *wiredSize
= *loadSize
;
3849 /*********************************************************************
3850 *********************************************************************/
3852 OSKext::copyUUID(void)
3854 OSData
* result
= NULL
;
3855 OSData
* theExecutable
= NULL
; // do not release
3856 const kernel_mach_header_t
* header
= NULL
;
3857 const struct load_command
* load_cmd
= NULL
;
3858 const struct uuid_command
* uuid_cmd
= NULL
;
3861 /* An interface kext doesn't have a linked executable with an LC_UUID,
3862 * we create one when it's linked.
3864 if (interfaceUUID
) {
3865 result
= interfaceUUID
;
3870 /* For real kexts, try to get the UUID from the linked executable,
3871 * or if is hasn't been linked yet, the unrelocated executable.
3873 theExecutable
= linkedExecutable
;
3874 if (!theExecutable
) {
3875 theExecutable
= getExecutable();
3877 if (!theExecutable
) {
3881 header
= (const kernel_mach_header_t
*)theExecutable
->getBytesNoCopy();
3882 load_cmd
= (const struct load_command
*)&header
[1];
3884 if (header
->magic
!= MH_MAGIC_KERNEL
) {
3886 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3887 "%s: bad header %p",
3893 for (i
= 0; i
< header
->ncmds
; i
++) {
3894 if (load_cmd
->cmd
== LC_UUID
) {
3895 uuid_cmd
= (struct uuid_command
*)load_cmd
;
3896 result
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
));
3899 load_cmd
= (struct load_command
*)((caddr_t
)load_cmd
+ load_cmd
->cmdsize
);
3906 /*********************************************************************
3907 *********************************************************************/
3909 #if defined (__x86_64__)
3910 #define ARCHNAME "x86_64"
3912 #error architecture not supported
3915 #define ARCH_SEPARATOR_CHAR '_'
3917 static char * makeHostArchKey(const char * key
, uint32_t * keySizeOut
)
3919 char * result
= NULL
;
3920 uint32_t keyLength
= strlen(key
);
3923 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
3925 keySize
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
);
3926 result
= (char *)kalloc(keySize
);
3930 strlcpy(result
, key
, keySize
);
3931 result
[keyLength
++] = ARCH_SEPARATOR_CHAR
;
3932 result
[keyLength
] = '\0';
3933 strlcat(result
, ARCHNAME
, keySize
);
3934 *keySizeOut
= keySize
;
3940 /*********************************************************************
3941 *********************************************************************/
3943 OSKext::getPropertyForHostArch(const char * key
)
3945 OSObject
* result
= NULL
; // do not release
3946 uint32_t hostArchKeySize
= 0;
3947 char * hostArchKey
= NULL
; // must kfree
3949 if (!key
|| !infoDict
) {
3953 /* Some properties are not allowed to be arch-variant:
3954 * - Any CFBundle... property.
3955 * - OSBundleIsInterface.
3956 * - OSKernelResource.
3958 if (STRING_HAS_PREFIX(key
, "OS") ||
3959 STRING_HAS_PREFIX(key
, "IO")) {
3961 hostArchKey
= makeHostArchKey(key
, &hostArchKeySize
);
3963 OSKextLog(/* kext (this isn't about a kext) */ NULL
,
3964 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3965 "Allocation failure.");
3968 result
= infoDict
->getObject(hostArchKey
);
3972 result
= infoDict
->getObject(key
);
3976 if (hostArchKey
) kfree(hostArchKey
, hostArchKeySize
);
3981 #pragma mark Load/Start/Stop/Unload
3984 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
3986 /*********************************************************************
3987 * sExcludeListByID is a dictionary with keys / values of:
3988 * key = bundleID string of kext we will not allow to load
3989 * value = version string(s) of the kext that is to be denied loading.
3990 * The version strings can be comma delimited. For example if kext
3991 * com.foocompany.fookext has two versions that we want to deny
3992 * loading then the version strings might look like:
3994 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
3995 * not load the kext.
3997 * Value may also be in the form of "LE 2.0.0" (version numbers
3998 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
3999 * number less than 2.0.0 will not load)
4001 * NOTE - we cannot use the characters "<=" or "<" because we have code
4002 * that serializes plists and treats '<' as a special character.
4003 *********************************************************************/
4005 OSKext::isInExcludeList(void)
4007 OSString
* versionString
= NULL
; // do not release
4008 char * versionCString
= NULL
; // do not free
4010 boolean_t wantLessThan
= false;
4011 boolean_t wantLessThanEqualTo
= false;
4014 if (!sExcludeListByID
) {
4017 /* look up by bundleID in our exclude list and if found get version
4018 * string (or strings) that we will not allow to load
4020 versionString
= OSDynamicCast(OSString
, sExcludeListByID
->getObject(bundleID
));
4021 if (!versionString
) {
4025 /* parse version strings */
4026 versionCString
= (char *) versionString
->getCStringNoCopy();
4028 /* look for "LT" or "LE" form of version string, must be in first two
4031 if (*versionCString
== 'L' && *(versionCString
+ 1) == 'T') {
4032 wantLessThan
= true;
4035 else if (*versionCString
== 'L' && *(versionCString
+ 1) == 'E') {
4036 wantLessThanEqualTo
= true;
4040 for (i
= 0; *versionCString
!= 0x00; versionCString
++) {
4041 /* skip whitespace */
4042 if (isWhiteSpace(*versionCString
)) {
4046 /* peek ahead for version string separator or null terminator */
4047 if (*(versionCString
+ 1) == ',' || *(versionCString
+ 1) == 0x00) {
4049 /* OK, we have a version string */
4050 myBuffer
[i
++] = *versionCString
;
4053 OSKextVersion excludeVers
;
4054 excludeVers
= OSKextParseVersionString(myBuffer
);
4056 if (wantLessThanEqualTo
) {
4057 if (version
<= excludeVers
) {
4061 else if (wantLessThan
) {
4062 if (version
< excludeVers
) {
4066 else if ( version
== excludeVers
) {
4070 /* reset for the next (if any) version string */
4072 wantLessThan
= false;
4073 wantLessThanEqualTo
= false;
4076 /* save valid version character */
4077 myBuffer
[i
++] = *versionCString
;
4079 /* make sure bogus version string doesn't overrun local buffer */
4080 if ( i
>= sizeof(myBuffer
) ) {
4089 /*********************************************************************
4090 *********************************************************************/
4093 OSKext::loadKextWithIdentifier(
4094 const char * kextIdentifierCString
,
4095 Boolean allowDeferFlag
,
4096 Boolean delayAutounloadFlag
,
4097 OSKextExcludeLevel startOpt
,
4098 OSKextExcludeLevel startMatchingOpt
,
4099 OSArray
* personalityNames
)
4101 OSReturn result
= kOSReturnError
;
4102 OSString
* kextIdentifier
= NULL
; // must release
4104 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
4105 if (!kextIdentifier
) {
4106 result
= kOSKextReturnNoMemory
;
4109 result
= OSKext::loadKextWithIdentifier(kextIdentifier
,
4110 allowDeferFlag
, delayAutounloadFlag
,
4111 startOpt
, startMatchingOpt
, personalityNames
);
4114 OSSafeRelease(kextIdentifier
);
4118 /*********************************************************************
4119 *********************************************************************/
4121 OSKext::loadKextWithIdentifier(
4122 OSString
* kextIdentifier
,
4123 Boolean allowDeferFlag
,
4124 Boolean delayAutounloadFlag
,
4125 OSKextExcludeLevel startOpt
,
4126 OSKextExcludeLevel startMatchingOpt
,
4127 OSArray
* personalityNames
)
4129 OSReturn result
= kOSReturnError
;
4130 OSReturn pingResult
= kOSReturnError
;
4131 OSKext
* theKext
= NULL
; // do not release
4132 OSDictionary
* loadRequest
= NULL
; // must release
4133 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4135 IORecursiveLockLock(sKextLock
);
4137 if (!kextIdentifier
) {
4138 result
= kOSKextReturnInvalidArgument
;
4142 OSKext::recordIdentifierRequest(kextIdentifier
);
4144 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
4146 if (!allowDeferFlag
) {
4147 OSKextLog(/* kext */ NULL
,
4148 kOSKextLogErrorLevel
|
4150 "Can't load kext %s - not found.",
4151 kextIdentifier
->getCStringNoCopy());
4155 if (!sKernelRequestsEnabled
) {
4157 kOSKextLogErrorLevel
|
4159 "Can't load kext %s - requests to user space are disabled.",
4160 kextIdentifier
->getCStringNoCopy());
4161 result
= kOSKextReturnDisabled
;
4165 /* Create a new request unless one is already sitting
4166 * in sKernelRequests for this bundle identifier
4168 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4169 if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4170 result
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
,
4172 if (result
!= kOSReturnSuccess
) {
4175 if (!_OSKextSetRequestArgument(loadRequest
,
4176 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
4178 result
= kOSKextReturnNoMemory
;
4181 if (!sKernelRequests
->setObject(loadRequest
)) {
4182 result
= kOSKextReturnNoMemory
;
4186 if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4187 result
= kOSKextReturnNoMemory
;
4192 kOSKextLogDebugLevel
|
4194 "Kext %s not found; queued load request to user space.",
4195 kextIdentifier
->getCStringNoCopy());
4198 pingResult
= OSKext::pingKextd();
4199 if (pingResult
== kOSKextReturnDisabled
) {
4200 OSKextLog(/* kext */ NULL
,
4201 ((sPrelinkBoot
) ? kOSKextLogDebugLevel
: kOSKextLogErrorLevel
) |
4203 "Kext %s might not load - kextd is currently unavailable.",
4204 kextIdentifier
->getCStringNoCopy());
4207 result
= kOSKextReturnDeferred
;
4211 result
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
);
4213 if (result
!= kOSReturnSuccess
) {
4215 kOSKextLogErrorLevel
|
4217 "Failed to load kext %s (error 0x%x).",
4218 kextIdentifier
->getCStringNoCopy(), (int)result
);
4220 OSKext::removeKext(theKext
,
4221 /* terminateService/removePersonalities */ true);
4225 if (delayAutounloadFlag
) {
4227 kOSKextLogProgressLevel
|
4228 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4229 "Setting delayed autounload for %s.",
4230 kextIdentifier
->getCStringNoCopy());
4231 theKext
->flags
.delayAutounload
= 1;
4235 OSSafeRelease(loadRequest
);
4236 OSSafeRelease(kextIdentifierSymbol
);
4238 IORecursiveLockUnlock(sKextLock
);
4243 /*********************************************************************
4244 *********************************************************************/
4247 OSKext::recordIdentifierRequest(
4248 OSString
* kextIdentifier
)
4250 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4253 if (!sAllKextLoadIdentifiers
|| !kextIdentifier
) {
4257 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4258 if (!kextIdentifierSymbol
) {
4259 // xxx - this is really a basic alloc failure
4264 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4265 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4268 // xxx - need to find a way to associate this whole func w/the kext
4269 OSKextLog(/* kext */ NULL
,
4270 // xxx - check level
4271 kOSKextLogStepLevel
|
4272 kOSKextLogArchiveFlag
,
4273 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4274 kextIdentifier
->getCStringNoCopy());
4280 OSKextLog(/* kext */ NULL
,
4281 kOSKextLogErrorLevel
|
4282 kOSKextLogArchiveFlag
,
4283 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4284 kextIdentifier
->getCStringNoCopy());
4286 OSSafeRelease(kextIdentifierSymbol
);
4290 /*********************************************************************
4291 *********************************************************************/
4294 OSKextExcludeLevel startOpt
,
4295 OSKextExcludeLevel startMatchingOpt
,
4296 OSArray
* personalityNames
)
4298 OSReturn result
= kOSReturnError
;
4299 kern_return_t kxldResult
;
4300 OSKextExcludeLevel dependenciesStartOpt
= startOpt
;
4301 OSKextExcludeLevel dependenciesStartMatchingOpt
= startMatchingOpt
;
4302 unsigned int i
, count
;
4303 Boolean alreadyLoaded
= false;
4304 OSKext
* lastLoadedKext
= NULL
;
4306 if (isInExcludeList()) {
4308 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
|
4310 "Kext %s is in exclude list, not loadable",
4311 getIdentifierCString());
4313 result
= kOSKextReturnNotLoadable
;
4318 alreadyLoaded
= true;
4319 result
= kOSReturnSuccess
;
4322 kOSKextLogDebugLevel
|
4323 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4324 "Kext %s is already loaded.",
4325 getIdentifierCString());
4330 if (current_task() != kernel_task
) {
4331 int macCheckResult
= 0;
4332 kauth_cred_t cred
= NULL
;
4334 cred
= kauth_cred_get_with_ref();
4335 macCheckResult
= mac_kext_check_load(cred
, getIdentifierCString());
4336 kauth_cred_unref(&cred
);
4338 if (macCheckResult
!= 0) {
4339 result
= kOSReturnError
;
4341 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4342 "Failed to load kext %s (MAC policy error 0x%x).",
4343 getIdentifierCString(), macCheckResult
);
4349 if (!sLoadEnabled
) {
4351 kOSKextLogErrorLevel
|
4353 "Kext loading is disabled (attempt to load kext %s).",
4354 getIdentifierCString());
4355 result
= kOSKextReturnDisabled
;
4359 /* If we've pushed the next available load tag to the invalid value,
4360 * we can't load any more kexts.
4362 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4364 kOSKextLogErrorLevel
|
4366 "Can't load kext %s - no more load tags to assign.",
4367 getIdentifierCString());
4368 result
= kOSKextReturnNoResources
;
4372 /* This is a bit of a hack, because we shouldn't be handling
4373 * personalities within the load function.
4375 if (!declaresExecutable()) {
4376 result
= kOSReturnSuccess
;
4380 /* Are we in safe boot?
4382 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4384 kOSKextLogErrorLevel
|
4386 "Can't load kext %s - not loadable during safe boot.",
4387 getIdentifierCString());
4388 result
= kOSKextReturnBootLevel
;
4393 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4395 getIdentifierCString());
4397 if (!sKxldContext
) {
4398 kxldResult
= kxld_create_context(&sKxldContext
, &kern_allocate
,
4399 &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,
4400 /* cputype */ 0, /* cpusubtype */ 0);
4403 kOSKextLogErrorLevel
|
4404 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4405 "Can't load kext %s - failed to create link context.",
4406 getIdentifierCString());
4407 result
= kOSKextReturnNoMemory
;
4412 /* We only need to resolve dependencies once for the whole graph, but
4413 * resolveDependencies will just return if there's no work to do, so it's
4414 * safe to call it more than once.
4416 if (!resolveDependencies()) {
4417 // xxx - check resolveDependencies() for log msg
4419 kOSKextLogErrorLevel
|
4420 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4421 "Can't load kext %s - failed to resolve library dependencies.",
4422 getIdentifierCString());
4423 result
= kOSKextReturnDependencies
;
4427 /* If we are excluding just the kext being loaded now (and not its
4428 * dependencies), drop the exclusion level to none so dependencies
4429 * start and/or add their personalities.
4431 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4432 dependenciesStartOpt
= kOSKextExcludeNone
;
4435 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4436 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4439 /* Load the dependencies, recursively.
4441 count
= getNumDependencies();
4442 for (i
= 0; i
< count
; i
++) {
4443 OSKext
* dependency
= OSDynamicCast(OSKext
,
4444 dependencies
->getObject(i
));
4445 if (dependency
== NULL
) {
4447 kOSKextLogErrorLevel
|
4448 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4449 "Internal error loading kext %s; dependency disappeared.",
4450 getIdentifierCString());
4451 result
= kOSKextReturnInternalError
;
4455 /* Dependencies must be started accorting to the opt,
4456 * but not given the personality names of the main kext.
4458 result
= dependency
->load(dependenciesStartOpt
,
4459 dependenciesStartMatchingOpt
,
4460 /* personalityNames */ NULL
);
4461 if (result
!= KERN_SUCCESS
) {
4463 kOSKextLogErrorLevel
|
4464 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4465 "Dependency %s of kext %s failed to load.",
4466 dependency
->getIdentifierCString(),
4467 getIdentifierCString());
4469 OSKext::removeKext(dependency
,
4470 /* terminateService/removePersonalities */ true);
4471 result
= kOSKextReturnDependencyLoadError
;
4477 result
= loadExecutable();
4478 if (result
!= KERN_SUCCESS
) {
4482 flags
.loaded
= true;
4484 /* Add the kext to the list of loaded kexts and update the kmod_info
4485 * struct to point to that of the last loaded kext (which is the way
4486 * it's always been done, though I'd rather do them in order now).
4488 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
4489 sLoadedKexts
->setObject(this);
4491 /* Keep the kernel itself out of the kmod list.
4493 if (lastLoadedKext
->isKernel()) {
4494 lastLoadedKext
= NULL
;
4497 if (lastLoadedKext
) {
4498 kmod_info
->next
= lastLoadedKext
->kmod_info
;
4501 notifyKextLoadObservers(this, kmod_info
);
4503 /* Make the global kmod list point at the just-loaded kext. Note that the
4504 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4505 * although we do report it in kextstat these days by using the newer
4506 * OSArray of loaded kexts, which does contain it.
4508 * (The OSKext object representing the kernel doesn't even have a kmod_info
4509 * struct, though I suppose we could stick a pointer to it from the
4510 * static struct in OSRuntime.cpp.)
4514 /* Save the list of loaded kexts in case we panic.
4516 OSKext::saveLoadedKextPanicList();
4518 if (isExecutable()) {
4519 OSKext::updateLoadedKextSummaries();
4520 savePanicString(/* isLoading */ true);
4523 registerWithDTrace();
4525 jettisonLinkeditSegment();
4526 #endif /* CONFIG_DTRACE */
4530 if (isExecutable() && !flags
.started
) {
4531 if (startOpt
== kOSKextExcludeNone
) {
4533 if (result
!= kOSReturnSuccess
) {
4535 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4536 "Kext %s start failed (result 0x%x).",
4537 getIdentifierCString(), result
);
4538 result
= kOSKextReturnStartStopError
;
4543 /* If not excluding matching, send the personalities to the kernel.
4544 * This never affects the result of the load operation.
4545 * This is a bit of a hack, because we shouldn't be handling
4546 * personalities within the load function.
4548 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
4549 result
= sendPersonalitiesToCatalog(true, personalityNames
);
4554 /* More hack! If the kext doesn't declare an executable, even if we
4555 * "loaded" it, we have to remove any personalities naming it, or we'll
4556 * never see the registry go quiet. Errors here do not count for the
4557 * load operation itself.
4559 * Note that in every other regard it's perfectly ok for a kext to
4560 * not declare an executable and serve only as a package for personalities
4561 * naming another kext, so we do have to allow such kexts to be "loaded"
4562 * so that those other personalities get added & matched.
4564 if (!declaresExecutable()) {
4566 kOSKextLogStepLevel
| kOSKextLogLoadFlag
,
4567 "Kext %s has no executable; removing any personalities naming it.",
4568 getIdentifierCString());
4569 removePersonalitiesFromCatalog();
4572 if (result
!= kOSReturnSuccess
) {
4574 kOSKextLogErrorLevel
|
4576 "Kext %s failed to load (0x%x).",
4577 getIdentifierCString(), (int)result
);
4578 } else if (!alreadyLoaded
) {
4580 kOSKextLogProgressLevel
|
4583 getIdentifierCString());
4585 queueKextNotification(kKextRequestPredicateLoadNotification
,
4586 OSDynamicCast(OSString
, bundleID
));
4591 /*********************************************************************
4593 *********************************************************************/
4594 static char * strdup(const char * string
)
4596 char * result
= NULL
;
4603 size
= 1 + strlen(string
);
4604 result
= (char *)kalloc(size
);
4609 memcpy(result
, string
, size
);
4615 /*********************************************************************
4617 *********************************************************************/
4619 OSKext::slidePrelinkedExecutable()
4621 OSReturn result
= kOSKextReturnBadData
;
4622 kernel_mach_header_t
* mh
= NULL
;
4623 kernel_segment_command_t
* seg
= NULL
;
4624 kernel_segment_command_t
* linkeditSeg
= NULL
;
4625 kernel_section_t
* sec
= NULL
;
4626 char * linkeditBase
= NULL
;
4627 bool haveLinkeditBase
= false;
4628 char * relocBase
= NULL
;
4629 bool haveRelocBase
= false;
4630 struct dysymtab_command
* dysymtab
= NULL
;
4631 struct symtab_command
* symtab
= NULL
;
4632 kernel_nlist_t
* sym
= NULL
;
4633 struct relocation_info
* reloc
= NULL
;
4636 vm_offset_t new_kextsize
;
4638 if (linkedExecutable
== NULL
|| vm_kernel_slide
== 0) {
4639 result
= kOSReturnSuccess
;
4643 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4645 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4649 seg
->vmaddr
+= vm_kernel_slide
;
4651 #if KASLR_KEXT_DEBUG
4652 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
4654 (unsigned long)VM_KERNEL_UNSLIDE(seg
->vmaddr
),
4655 (unsigned long)seg
->vmaddr
);
4658 if (!haveRelocBase
) {
4659 relocBase
= (char *) seg
->vmaddr
;
4660 haveRelocBase
= true;
4662 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
4663 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
4664 haveLinkeditBase
= true;
4667 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4668 sec
->addr
+= vm_kernel_slide
;
4670 #if KASLR_KEXT_DEBUG
4671 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
4673 (unsigned long)VM_KERNEL_UNSLIDE(sec
->addr
),
4674 (unsigned long)sec
->addr
);
4679 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
4681 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
4683 if (symtab
!= NULL
) {
4684 /* Some pseudo-kexts have symbol tables without segments.
4686 if (symtab
->nsyms
> 0 && haveLinkeditBase
) {
4687 sym
= (kernel_nlist_t
*) (linkeditBase
+ symtab
->symoff
);
4688 for (i
= 0; i
< symtab
->nsyms
; i
++) {
4689 if (sym
[i
].n_type
& N_STAB
) {
4692 sym
[i
].n_value
+= vm_kernel_slide
;
4694 #if KASLR_KEXT_DEBUG
4695 #define MAX_SYMS_TO_LOG 5
4696 if ( i
< MAX_SYMS_TO_LOG
) {
4697 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
4698 (unsigned long)VM_KERNEL_UNSLIDE(sym
[i
].n_value
),
4699 (unsigned long)sym
[i
].n_value
);
4706 if (dysymtab
!= NULL
) {
4707 if (dysymtab
->nextrel
> 0) {
4709 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4711 "Sliding kext %s: External relocations found.",
4712 getIdentifierCString());
4716 if (dysymtab
->nlocrel
> 0) {
4717 if (!haveLinkeditBase
) {
4719 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4721 "Sliding kext %s: No linkedit segment.",
4722 getIdentifierCString());
4726 if (!haveRelocBase
) {
4728 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4731 "Sliding kext %s: No writable segments.",
4733 "Sliding kext %s: No segments.",
4735 getIdentifierCString());
4739 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
4740 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
4742 for (i
= 0; i
< dysymtab
->nlocrel
; i
++) {
4743 if ( reloc
[i
].r_extern
!= 0
4744 || reloc
[i
].r_type
!= 0
4745 || reloc
[i
].r_length
!= (sizeof(void *) == 8 ? 3 : 2)
4748 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4750 "Sliding kext %s: Unexpected relocation found.",
4751 getIdentifierCString());
4754 if (reloc
[i
].r_pcrel
!= 0) {
4757 *((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)) += vm_kernel_slide
;
4759 #if KASLR_KEXT_DEBUG
4760 #define MAX_DYSYMS_TO_LOG 5
4761 if ( i
< MAX_DYSYMS_TO_LOG
) {
4762 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
4763 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
))),
4764 (unsigned long)*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)));
4769 /* We should free these relocations, not just delete the reference to them.
4770 * <rdar://problem/10535549> Free relocations from PIE kexts.
4772 new_kextsize
= round_page(kmod_info
->size
- reloc_size
);
4774 if ((kmod_info
->size
- new_kextsize
) > PAGE_SIZE
) {
4775 vm_offset_t endofkext
= kmod_info
->address
+ kmod_info
->size
;
4776 vm_offset_t new_endofkext
= kmod_info
->address
+ new_kextsize
;
4777 vm_offset_t endofrelocInfo
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
);
4778 int bytes_remaining
= endofkext
- endofrelocInfo
;
4779 OSData
* new_osdata
= NULL
;
4781 /* fix up symbol offsets if they are after the dsymtab local relocs */
4783 if (dysymtab
->locreloff
< symtab
->symoff
){
4784 symtab
->symoff
-= reloc_size
;
4786 if (dysymtab
->locreloff
< symtab
->stroff
) {
4787 symtab
->stroff
-= reloc_size
;
4790 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
4791 dysymtab
->extreloff
-= reloc_size
;
4794 /* move data behind reloc info down to new offset */
4795 if (endofrelocInfo
< endofkext
) {
4796 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
4799 /* Create a new OSData for the smaller kext object and reflect
4800 * new linkedit segment size.
4802 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
4803 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
4805 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
4807 /* Fix up kmod info and linkedExecutable.
4809 kmod_info
->size
= new_kextsize
;
4811 new_osdata
->setDeallocFunction(osdata_kext_free
);
4813 new_osdata
->setDeallocFunction(osdata_phys_free
);
4815 linkedExecutable
->setDeallocFunction(NULL
);
4816 linkedExecutable
->release();
4817 linkedExecutable
= new_osdata
;
4820 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
4822 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
4826 dysymtab
->nlocrel
= 0;
4827 dysymtab
->locreloff
= 0;
4831 result
= kOSReturnSuccess
;
4836 /*********************************************************************
4837 * called only by load()
4838 *********************************************************************/
4840 OSKext::loadExecutable()
4842 OSReturn result
= kOSReturnError
;
4843 kern_return_t kxldResult
;
4844 KXLDDependency
* kxlddeps
= NULL
; // must kfree
4845 uint32_t num_kxlddeps
= 0;
4846 OSArray
* linkDependencies
= NULL
; // must release
4847 uint32_t numDirectDependencies
= 0;
4848 uint32_t num_kmod_refs
= 0;
4849 struct mach_header
** kxldHeaderPtr
= NULL
; // do not free
4850 struct mach_header
* kxld_header
= NULL
; // xxx - need to free here?
4851 OSData
* theExecutable
= NULL
; // do not release
4852 OSString
* versString
= NULL
; // do not release
4853 const char * versCString
= NULL
; // do not free
4854 const char * string
= NULL
; // do not free
4857 /* We need the version string for a variety of bits below.
4859 versString
= OSDynamicCast(OSString
,
4860 getPropertyForHostArch(kCFBundleVersionKey
));
4864 versCString
= versString
->getCStringNoCopy();
4866 if (isKernelComponent()) {
4867 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
4869 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
4871 kOSKextLogErrorLevel
|
4873 "Kernel component %s has incorrect version %s; "
4875 getIdentifierCString(),
4876 versCString
, KERNEL6_VERSION
);
4877 result
= kOSKextReturnInternalError
;
4879 } else if (strcmp(versCString
, osrelease
)) {
4881 kOSKextLogErrorLevel
|
4883 "Kernel component %s has incorrect version %s; "
4885 getIdentifierCString(),
4886 versCString
, osrelease
);
4887 result
= kOSKextReturnInternalError
;
4893 if (isPrelinked()) {
4894 result
= slidePrelinkedExecutable();
4895 if (result
!= kOSReturnSuccess
) {
4901 theExecutable
= getExecutable();
4902 if (!theExecutable
) {
4903 if (declaresExecutable()) {
4905 kOSKextLogErrorLevel
|
4907 "Can't load kext %s - executable is missing.",
4908 getIdentifierCString());
4909 result
= kOSKextReturnValidation
;
4915 if (isInterface()) {
4916 OSData
*executableCopy
= OSData::withData(theExecutable
);
4917 setLinkedExecutable(executableCopy
);
4918 executableCopy
->release();
4922 numDirectDependencies
= getNumDependencies();
4924 if (flags
.hasBleedthrough
) {
4925 linkDependencies
= dependencies
;
4926 linkDependencies
->retain();
4928 linkDependencies
= OSArray::withArray(dependencies
);
4929 if (!linkDependencies
) {
4931 kOSKextLogErrorLevel
|
4932 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4933 "Can't allocate link dependencies to load kext %s.",
4934 getIdentifierCString());
4938 for (i
= 0; i
< numDirectDependencies
; ++i
) {
4939 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
4940 dependencies
->getObject(i
));
4941 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
4945 num_kxlddeps
= linkDependencies
->getCount();
4946 if (!num_kxlddeps
) {
4948 kOSKextLogErrorLevel
|
4949 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4950 "Can't load kext %s - it has no library dependencies.",
4951 getIdentifierCString());
4955 kxlddeps
= (KXLDDependency
*)kalloc(num_kxlddeps
* sizeof(*kxlddeps
));
4958 kOSKextLogErrorLevel
|
4959 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4960 "Can't allocate link context to load kext %s.",
4961 getIdentifierCString());
4964 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
4966 for (i
= 0; i
< num_kxlddeps
; ++i
) {
4967 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
4969 if (dependency
->isInterface()) {
4970 OSKext
*interfaceTargetKext
= NULL
;
4971 OSData
* interfaceTarget
= NULL
;
4973 if (dependency
->isKernelComponent()) {
4974 interfaceTargetKext
= sKernelKext
;
4975 interfaceTarget
= sKernelKext
->linkedExecutable
;
4977 interfaceTargetKext
= OSDynamicCast(OSKext
,
4978 dependency
->dependencies
->getObject(0));
4980 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
4983 if (!interfaceTarget
) {
4988 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
4989 * it will be useful to have them in the debugger.
4990 * strdup() failing isn't critical right here so we don't check that.
4992 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
4993 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
4994 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
4996 kxlddeps
[i
].interface
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
4997 kxlddeps
[i
].interface_size
= dependency
->linkedExecutable
->getLength();
4998 kxlddeps
[i
].interface_name
= strdup(dependency
->getIdentifierCString());
5000 kxlddeps
[i
].kext
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5001 kxlddeps
[i
].kext_size
= dependency
->linkedExecutable
->getLength();
5002 kxlddeps
[i
].kext_name
= strdup(dependency
->getIdentifierCString());
5005 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
5008 kxldHeaderPtr
= &kxld_header
;
5012 kOSKextLogExplicitLevel
|
5013 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5014 "Kext %s - calling kxld_link_file:\n"
5015 " kxld_context: %p\n"
5016 " executable: %p executable_length: %d\n"
5018 " kxld_dependencies: %p num_dependencies: %d\n"
5019 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5020 getIdentifierCString(), sKxldContext
,
5021 theExecutable
->getBytesNoCopy(), theExecutable
->getLength(),
5022 this, kxlddeps
, num_kxlddeps
,
5023 kxldHeaderPtr
, &kmod_info
);
5026 /* After this call, the linkedExecutable instance variable
5029 kxldResult
= kxld_link_file(sKxldContext
,
5030 (u_char
*)theExecutable
->getBytesNoCopy(),
5031 theExecutable
->getLength(),
5032 getIdentifierCString(), this, kxlddeps
, num_kxlddeps
,
5033 (u_char
**)kxldHeaderPtr
, (kxld_addr_t
*)&kmod_info
);
5035 if (kxldResult
!= KERN_SUCCESS
) {
5036 // xxx - add kxldResult here?
5038 kOSKextLogErrorLevel
|
5040 "Can't load kext %s - link failed.",
5041 getIdentifierCString());
5042 result
= kOSKextReturnLinkError
;
5046 /* We've written data & instructions into kernel memory, so flush the data
5047 * cache and invalidate the instruction cache.
5048 * I/D caches are coherent on x86
5050 #if !defined(__i386__) && !defined(__x86_64__)
5051 flush_dcache(kmod_info
->address
, kmod_info
->size
, false);
5052 invalidate_icache(kmod_info
->address
, kmod_info
->size
, false);
5056 if (isInterface()) {
5058 /* Whip up a fake kmod_info entry for the interface kext.
5060 kmod_info
= (kmod_info_t
*)kalloc(sizeof(kmod_info_t
));
5062 result
= KERN_MEMORY_ERROR
;
5066 /* A pseudokext has almost nothing in its kmod_info struct.
5068 bzero(kmod_info
, sizeof(kmod_info_t
));
5070 kmod_info
->info_version
= KMOD_INFO_VERSION
;
5072 /* An interface kext doesn't have a linkedExecutable, so save a
5073 * copy of the UUID out of the original executable via copyUUID()
5074 * while we still have the original executable.
5076 interfaceUUID
= copyUUID();
5079 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5080 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5082 /* Stamp the bundle ID and version from the OSKext over anything
5083 * resident inside the kmod_info.
5085 string
= getIdentifierCString();
5086 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5088 string
= versCString
;
5089 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5091 /* Add the dependencies' kmod_info structs as kmod_references.
5093 num_kmod_refs
= getNumDependencies();
5094 if (num_kmod_refs
) {
5095 kmod_info
->reference_list
= (kmod_reference_t
*)kalloc(
5096 num_kmod_refs
* sizeof(kmod_reference_t
));
5097 if (!kmod_info
->reference_list
) {
5098 result
= KERN_MEMORY_ERROR
;
5101 bzero(kmod_info
->reference_list
,
5102 num_kmod_refs
* sizeof(kmod_reference_t
));
5103 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5104 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5105 OSKext
* refKext
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
));
5106 ref
->info
= refKext
->kmod_info
;
5107 ref
->info
->reference_count
++;
5109 if (refIndex
+ 1 < num_kmod_refs
) {
5110 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5115 if (!isInterface() && linkedExecutable
) {
5117 kOSKextLogProgressLevel
|
5119 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5121 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5122 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5123 (unsigned)kmod_info
->id
);
5126 result
= setVMProtections();
5127 if (result
!= KERN_SUCCESS
) {
5131 result
= kOSReturnSuccess
;
5134 OSSafeRelease(linkDependencies
);
5136 /* Clear up locally allocated dependency info.
5138 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5141 if (kxlddeps
[i
].kext_name
) {
5142 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5143 kfree(kxlddeps
[i
].kext_name
, size
);
5145 if (kxlddeps
[i
].interface_name
) {
5146 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5147 kfree(kxlddeps
[i
].interface_name
, size
);
5150 if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5152 /* We no longer need the unrelocated executable (which the linker
5153 * has altered anyhow).
5155 setExecutable(NULL
);
5157 if (result
!= kOSReturnSuccess
) {
5159 kOSKextLogErrorLevel
|
5161 "Failed to load executable for kext %s.",
5162 getIdentifierCString());
5164 if (kmod_info
&& kmod_info
->reference_list
) {
5165 kfree(kmod_info
->reference_list
,
5166 num_kmod_refs
* sizeof(kmod_reference_t
));
5168 if (isInterface()) {
5169 kfree(kmod_info
, sizeof(kmod_info_t
));
5172 if (linkedExecutable
) {
5173 linkedExecutable
->release();
5174 linkedExecutable
= NULL
;
5181 /*********************************************************************
5182 * The linkedit segment is used by the kext linker for dependency
5183 * resolution, and by dtrace for probe initialization. We can free it
5184 * for non-library kexts, since no kexts depend on non-library kexts
5185 * by definition, once dtrace has been initialized.
5186 *********************************************************************/
5188 OSKext::jettisonLinkeditSegment(void)
5190 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5191 kernel_segment_command_t
* linkedit
= NULL
;
5193 vm_size_t linkeditsize
, kextsize
;
5194 OSData
* data
= NULL
;
5196 /* 16K_XXX: To Remove */
5197 /* We don't currently guarantee alignment greater than 4KB for kext
5198 * segments, so we cannot always jettison __LINKEDIT cleanly, so let
5201 if (!TEST_PAGE_SIZE_4K
)
5205 /* We can free symbol tables for all embedded kexts because we don't
5206 * support runtime kext linking.
5208 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5210 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5215 /* Find the linkedit segment. If it's not the last segment, then freeing
5216 * it will fragment the kext into multiple VM regions, which OSKext is not
5217 * designed to handle, so we'll have to skip it.
5219 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5224 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5225 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
))
5230 /* Create a new OSData for the smaller kext object.
5232 linkeditsize
= round_page(linkedit
->vmsize
);
5233 kextsize
= kmod_info
->size
- linkeditsize
;
5234 start
= linkedit
->vmaddr
;
5236 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5241 /* Fix the kmod info and linkedExecutable.
5243 kmod_info
->size
= kextsize
;
5246 data
->setDeallocFunction(osdata_kext_free
);
5248 data
->setDeallocFunction(osdata_phys_free
);
5250 linkedExecutable
->setDeallocFunction(NULL
);
5251 linkedExecutable
->release();
5252 linkedExecutable
= data
;
5253 flags
.jettisonLinkeditSeg
= 1;
5255 /* Free the linkedit segment.
5258 kext_free(start
, linkeditsize
);
5260 ml_static_mfree(start
, linkeditsize
);
5267 /*********************************************************************
5268 *********************************************************************/
5270 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5272 if (linkedExecutable
) {
5273 panic("Attempt to set linked executable on kext "
5274 "that already has one (%s).\n",
5275 getIdentifierCString());
5277 linkedExecutable
= anExecutable
;
5278 linkedExecutable
->retain();
5283 /*********************************************************************
5284 * Go through all loaded kexts and tell them to register with dtrace.
5285 * The instance method only registers if necessary.
5286 *********************************************************************/
5289 OSKext::registerKextsWithDTrace(void)
5291 uint32_t count
= sLoadedKexts
->getCount();
5294 IORecursiveLockLock(sKextLock
);
5296 for (i
= 0; i
< count
; i
++) {
5297 OSKext
* thisKext
= NULL
; // do not release
5299 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5300 if (!thisKext
|| !thisKext
->isExecutable()) {
5304 thisKext
->registerWithDTrace();
5307 IORecursiveLockUnlock(sKextLock
);
5313 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5314 extern int (*dtrace_modunload
)(struct kmod_info
*);
5317 /*********************************************************************
5318 *********************************************************************/
5320 OSKext::registerWithDTrace(void)
5322 /* Register kext with dtrace. A dtrace_modload failure should not
5323 * prevent a kext from loading, so we ignore the return code.
5325 if (!flags
.dtraceInitialized
&& (dtrace_modload
!= NULL
)) {
5326 uint32_t modflag
= 0;
5327 OSObject
* forceInit
= getPropertyForHostArch("OSBundleForceDTraceInit");
5328 if (forceInit
== kOSBooleanTrue
) {
5329 modflag
|= KMOD_DTRACE_FORCE_INIT
;
5332 (void)(*dtrace_modload
)(kmod_info
, modflag
);
5333 flags
.dtraceInitialized
= true;
5334 jettisonLinkeditSegment();
5338 /*********************************************************************
5339 *********************************************************************/
5341 OSKext::unregisterWithDTrace(void)
5343 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5344 * prevent a kext from loading, so we ignore the return code.
5346 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
5347 (void)(*dtrace_modunload
)(kmod_info
);
5348 flags
.dtraceInitialized
= false;
5352 #endif /* CONFIG_DTRACE */
5355 /*********************************************************************
5356 * called only by loadExecutable()
5357 *********************************************************************/
5358 #if !VM_MAPPED_KEXTS
5359 #error Unrecognized architecture
5361 static inline kern_return_t
5364 vm_map_offset_t start
,
5365 vm_map_offset_t end
,
5369 if (start
== end
) { // 10538581
5370 return(KERN_SUCCESS
);
5372 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
5375 static inline kern_return_t
5378 vm_map_offset_t start
,
5379 vm_map_offset_t end
,
5380 vm_prot_t access_type
,
5381 boolean_t user_wire
)
5383 return vm_map_wire(map
, start
, end
, access_type
, user_wire
);
5388 OSKext::setVMProtections(void)
5390 vm_map_t kext_map
= NULL
;
5391 kernel_segment_command_t
* seg
= NULL
;
5392 vm_map_offset_t start
= 0;
5393 vm_map_offset_t end
= 0;
5394 OSReturn result
= kOSReturnError
;
5396 if (!kmod_info
->address
&& !kmod_info
->size
) {
5397 result
= kOSReturnSuccess
;
5401 /* Get the kext's vm map */
5402 kext_map
= kext_get_vm_map(kmod_info
);
5404 result
= KERN_MEMORY_ERROR
;
5408 /* Protect the headers as read-only; they do not need to be wired */
5409 result
= OSKext_protect(kext_map
, kmod_info
->address
,
5410 kmod_info
->address
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
);
5411 if (result
!= KERN_SUCCESS
) {
5415 /* Set the VM protections and wire down each of the segments */
5416 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5418 start
= round_page(seg
->vmaddr
);
5419 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
5421 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
5422 if (result
!= KERN_SUCCESS
) {
5424 kOSKextLogErrorLevel
|
5426 "Kext %s failed to set maximum VM protections "
5427 "for segment %s - 0x%x.",
5428 getIdentifierCString(), seg
->segname
, (int)result
);
5432 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5433 if (result
!= KERN_SUCCESS
) {
5435 kOSKextLogErrorLevel
|
5437 "Kext %s failed to set initial VM protections "
5438 "for segment %s - 0x%x.",
5439 getIdentifierCString(), seg
->segname
, (int)result
);
5443 if (segmentShouldBeWired(seg
)) {
5444 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5445 if (result
!= KERN_SUCCESS
) {
5450 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5457 /*********************************************************************
5458 *********************************************************************/
5460 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
5462 return (sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
)));
5465 /*********************************************************************
5466 *********************************************************************/
5468 OSKext::validateKextMapping(bool startFlag
)
5470 OSReturn result
= kOSReturnError
;
5471 const char * whichOp
= startFlag
? "start" : "stop";
5472 kern_return_t kern_result
= 0;
5473 vm_map_t kext_map
= NULL
;
5474 kernel_segment_command_t
* seg
= NULL
;
5475 mach_vm_address_t address
= 0;
5476 mach_vm_size_t size
= 0;
5478 mach_msg_type_number_t count
;
5479 vm_region_submap_short_info_data_64_t info
;
5481 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
5482 bzero(&info
, sizeof(info
));
5484 // xxx - do we need a distinct OSReturn value for these or is "bad data"
5485 // xxx - sufficient?
5487 /* Verify that the kmod_info and start/stop pointers are non-NULL.
5491 kOSKextLogErrorLevel
|
5493 "Kext %s - NULL kmod_info pointer.",
5494 getIdentifierCString());
5495 result
= kOSKextReturnBadData
;
5500 address
= (mach_vm_address_t
)kmod_info
->start
;
5502 address
= (mach_vm_address_t
)kmod_info
->stop
;
5507 kOSKextLogErrorLevel
|
5509 "Kext %s - NULL module %s pointer.",
5510 getIdentifierCString(), whichOp
);
5511 result
= kOSKextReturnBadData
;
5515 kext_map
= kext_get_vm_map(kmod_info
);
5516 depth
= (kernel_map
== kext_map
) ? 1 : 2;
5518 /* Verify that the start/stop function lies within the kext's address range.
5520 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
5521 kmod_info
->address
+ kmod_info
->size
<= address
)
5524 kOSKextLogErrorLevel
|
5526 "Kext %s module %s pointer is outside of kext range "
5527 "(%s %p - kext at %p-%p)..",
5528 getIdentifierCString(),
5531 (void *)VM_KERNEL_UNSLIDE(address
),
5532 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5533 (void *)(VM_KERNEL_UNSLIDE(kmod_info
->address
) + kmod_info
->size
));
5534 result
= kOSKextReturnBadData
;
5538 /* Only do these checks before calling the start function;
5539 * If anything goes wrong with the mapping while the kext is running,
5540 * we'll likely have panicked well before any attempt to stop the kext.
5544 /* Verify that the start/stop function is executable.
5546 kern_result
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
,
5547 (vm_region_recurse_info_t
)&info
, &count
);
5548 if (kern_result
!= KERN_SUCCESS
) {
5550 kOSKextLogErrorLevel
|
5552 "Kext %s - bad %s pointer %p.",
5553 getIdentifierCString(),
5554 whichOp
, (void *)VM_KERNEL_UNSLIDE(address
));
5555 result
= kOSKextReturnBadData
;
5560 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
5562 kOSKextLogErrorLevel
|
5564 "Kext %s - memory region containing module %s function "
5565 "is not executable.",
5566 getIdentifierCString(), whichOp
);
5567 result
= kOSKextReturnBadData
;
5572 /* Verify that the kext's segments are backed by physical memory.
5574 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5576 if (!verifySegmentMapping(seg
)) {
5577 result
= kOSKextReturnBadData
;
5581 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5586 result
= kOSReturnSuccess
;
5591 /*********************************************************************
5592 *********************************************************************/
5594 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
5596 mach_vm_address_t address
= 0;
5598 if (!segmentShouldBeWired(seg
)) return true;
5600 for (address
= seg
->vmaddr
;
5601 address
< round_page(seg
->vmaddr
+ seg
->vmsize
);
5602 address
+= PAGE_SIZE
)
5604 if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) {
5606 kOSKextLogErrorLevel
|
5608 "Kext %s - page %p is not backed by physical memory.",
5609 getIdentifierCString(),
5618 /*********************************************************************
5619 *********************************************************************/
5621 OSKext::start(bool startDependenciesFlag
)
5623 OSReturn result
= kOSReturnError
;
5624 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
5625 unsigned int i
, count
;
5626 void * kmodStartData
= NULL
;
5628 if (isStarted() || isInterface() || isKernelComponent()) {
5629 result
= kOSReturnSuccess
;
5635 kOSKextLogErrorLevel
|
5637 "Attempt to start nonloaded kext %s.",
5638 getIdentifierCString());
5639 result
= kOSKextReturnInvalidArgument
;
5643 if (!sLoadEnabled
) {
5645 kOSKextLogErrorLevel
|
5647 "Kext loading is disabled (attempt to start kext %s).",
5648 getIdentifierCString());
5649 result
= kOSKextReturnDisabled
;
5653 result
= validateKextMapping(/* start? */ true);
5654 if (result
!= kOSReturnSuccess
) {
5658 startfunc
= kmod_info
->start
;
5660 count
= getNumDependencies();
5661 for (i
= 0; i
< count
; i
++) {
5662 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
5663 if (dependency
== NULL
) {
5665 kOSKextLogErrorLevel
|
5667 "Kext %s start - internal error, dependency disappeared.",
5668 getIdentifierCString());
5671 if (!dependency
->isStarted()) {
5672 if (startDependenciesFlag
) {
5673 OSReturn dependencyResult
=
5674 dependency
->start(startDependenciesFlag
);
5675 if (dependencyResult
!= KERN_SUCCESS
) {
5677 kOSKextLogErrorLevel
|
5679 "Kext %s start - dependency %s failed to start (error 0x%x).",
5680 getIdentifierCString(),
5681 dependency
->getIdentifierCString(),
5687 kOSKextLogErrorLevel
|
5689 "Not starting %s - dependency %s not started yet.",
5690 getIdentifierCString(),
5691 dependency
->getIdentifierCString());
5692 result
= kOSKextReturnStartStopError
; // xxx - make new return?
5699 kOSKextLogDetailLevel
|
5701 "Kext %s calling module start function.",
5702 getIdentifierCString());
5706 #if !CONFIG_STATIC_CPPINIT
5707 result
= OSRuntimeInitializeCPP(kmod_info
, NULL
);
5708 if (result
== KERN_SUCCESS
) {
5712 kmodStartData
= GetAppleTEXTHashForKext(this, this->infoDict
);
5715 if (kmodStartData
) {
5717 kOSKextLogErrorLevel
|
5718 kOSKextLogGeneralFlag
,
5719 "Kext %s calling module start function. kmodStartData %p. arch %s",
5720 getIdentifierCString(), kmodStartData
, ARCHNAME
);
5723 #endif // CONFIG_KEC_FIPS
5725 result
= startfunc(kmod_info
, kmodStartData
);
5727 #if !CONFIG_STATIC_CPPINIT
5728 if (result
!= KERN_SUCCESS
) {
5729 (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
);
5736 /* On success overlap the setting of started/starting. On failure just
5739 if (result
== KERN_SUCCESS
) {
5742 // xxx - log start error from kernel?
5744 kOSKextLogProgressLevel
|
5746 "Kext %s is now started.",
5747 getIdentifierCString());
5749 invokeOrCancelRequestCallbacks(
5750 /* result not actually used */ kOSKextReturnStartStopError
,
5751 /* invokeFlag */ false);
5753 kOSKextLogProgressLevel
|
5755 "Kext %s did not start (return code 0x%x).",
5756 getIdentifierCString(), result
);
5763 /*********************************************************************
5764 *********************************************************************/
5766 bool OSKext::canUnloadKextWithIdentifier(
5767 OSString
* kextIdentifier
,
5768 bool checkClassesFlag
)
5770 bool result
= false;
5771 OSKext
* aKext
= NULL
; // do not release
5773 IORecursiveLockLock(sKextLock
);
5775 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
5778 goto finish
; // can't unload what's not loaded
5781 if (aKext
->isLoaded()) {
5782 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
5785 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
5793 IORecursiveLockUnlock(sKextLock
);
5797 /*********************************************************************
5798 *********************************************************************/
5802 OSReturn result
= kOSReturnError
;
5803 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
5805 if (!isStarted() || isInterface()) {
5806 result
= kOSReturnSuccess
;
5812 kOSKextLogErrorLevel
|
5814 "Attempt to stop nonloaded kext %s.",
5815 getIdentifierCString());
5816 result
= kOSKextReturnInvalidArgument
;
5820 /* Refuse to stop if we have clients or instances. It is up to
5821 * the caller to make sure those aren't true.
5823 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
5825 kOSKextLogErrorLevel
|
5827 "Kext %s - C++ instances; can't stop.",
5828 getIdentifierCString());
5829 result
= kOSKextReturnInUse
;
5833 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
5836 kOSKextLogErrorLevel
|
5838 "Kext %s - has references (linkage or tracking object); "
5840 getIdentifierCString());
5841 result
= kOSKextReturnInUse
;
5845 /* Note: If validateKextMapping fails on the stop & unload path,
5846 * we are in serious trouble and a kernel panic is likely whether
5847 * we stop & unload the kext or not.
5849 result
= validateKextMapping(/* start? */ false);
5850 if (result
!= kOSReturnSuccess
) {
5854 stopfunc
= kmod_info
->stop
;
5857 kOSKextLogDetailLevel
|
5859 "Kext %s calling module stop function.",
5860 getIdentifierCString());
5864 result
= stopfunc(kmod_info
, /* userData */ NULL
);
5865 #if !CONFIG_STATIC_CPPINIT
5866 if (result
== KERN_SUCCESS
) {
5867 result
= OSRuntimeFinalizeCPP(kmod_info
, NULL
);
5873 if (result
== KERN_SUCCESS
) {
5877 kOSKextLogDetailLevel
|
5879 "Kext %s is now stopped and ready to unload.",
5880 getIdentifierCString());
5883 kOSKextLogErrorLevel
|
5885 "Kext %s did not stop (return code 0x%x).",
5886 getIdentifierCString(), result
);
5887 result
= kOSKextReturnStartStopError
;
5895 /*********************************************************************
5896 *********************************************************************/
5898 OSKext::unload(void)
5900 OSReturn result
= kOSReturnError
;
5902 uint32_t num_kmod_refs
= 0;
5904 if (!sUnloadEnabled
) {
5906 kOSKextLogErrorLevel
|
5908 "Kext unloading is disabled (%s).",
5909 this->getIdentifierCString());
5911 result
= kOSKextReturnDisabled
;
5915 /* Refuse to unload if we have clients or instances. It is up to
5916 * the caller to make sure those aren't true.
5918 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
5919 // xxx - Don't log under errors? this is more of an info thing
5921 kOSKextLogErrorLevel
|
5922 kOSKextLogKextBookkeepingFlag
,
5923 "Can't unload kext %s; outstanding references (linkage or tracking object).",
5924 getIdentifierCString());
5925 result
= kOSKextReturnInUse
;
5929 if (hasOSMetaClassInstances()) {
5931 kOSKextLogErrorLevel
|
5932 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
5933 "Can't unload kext %s; classes have instances:",
5934 getIdentifierCString());
5935 reportOSMetaClassInstances(kOSKextLogErrorLevel
|
5936 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
);
5937 result
= kOSKextReturnInUse
;
5942 result
= kOSReturnSuccess
;
5946 if (isKernelComponent()) {
5947 result
= kOSKextReturnInvalidArgument
;
5951 /* Note that the kext is unloading before running any code that
5952 * might be in the kext (request callbacks, module stop function).
5953 * We will deny certain requests made against a kext in the process
5956 flags
.unloading
= 1;
5958 /* Update the string describing the last kext to unload in case we panic.
5960 savePanicString(/* isLoading */ false);
5964 if (result
!= KERN_SUCCESS
) {
5966 kOSKextLogErrorLevel
|
5968 "Kext %s can't unload - module stop returned 0x%x.",
5969 getIdentifierCString(), (unsigned)result
);
5970 result
= kOSKextReturnStartStopError
;
5976 kOSKextLogProgressLevel
|
5978 "Kext %s unloading.",
5979 getIdentifierCString());
5981 /* Even if we don't call the stop function, we want to be sure we
5982 * have no OSMetaClass references before unloading the kext executable
5983 * from memory. OSMetaClasses may have pointers into the kext executable
5984 * and that would cause a panic on OSKext::free() when metaClasses is freed.
5987 metaClasses
->flushCollection();
5990 /* Remove the kext from the list of loaded kexts, patch the gap
5991 * in the kmod_info_t linked list, and reset "kmod" to point to the
5992 * last loaded kext that isn't the fake kernel kext (sKernelKext).
5994 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
5995 if (index
!= (unsigned int)-1) {
5997 sLoadedKexts
->removeObject(index
);
5999 OSKext
* nextKext
= OSDynamicCast(OSKext
,
6000 sLoadedKexts
->getObject(index
));
6004 OSKext
* gapKext
= OSDynamicCast(OSKext
,
6005 sLoadedKexts
->getObject(index
- 1));
6007 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
6009 } else /* index == 0 */ {
6010 nextKext
->kmod_info
->next
= NULL
;
6014 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
6015 if (lastKext
&& !lastKext
->isKernel()) {
6016 kmod
= lastKext
->kmod_info
;
6018 kmod
= NULL
; // clear the global kmod variable
6022 /* Clear out the kmod references that we're keeping for compatibility
6023 * with current panic backtrace code & kgmacros.
6024 * xxx - will want to update those bits sometime and remove this.
6026 num_kmod_refs
= getNumDependencies();
6027 if (num_kmod_refs
&& kmod_info
&& kmod_info
->reference_list
) {
6028 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
6029 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
6030 ref
->info
->reference_count
--;
6032 kfree(kmod_info
->reference_list
,
6033 num_kmod_refs
* sizeof(kmod_reference_t
));
6037 unregisterWithDTrace();
6038 #endif /* CONFIG_DTRACE */
6040 notifyKextUnloadObservers(this);
6042 /* Unwire and free the linked executable.
6044 if (linkedExecutable
) {
6046 if (!isInterface()) {
6047 kernel_segment_command_t
*seg
= NULL
;
6048 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6052 kOSKextLogErrorLevel
|
6054 "Failed to free kext %s; couldn't find the kext map.",
6055 getIdentifierCString());
6056 result
= kOSKextReturnInternalError
;
6061 kOSKextLogProgressLevel
|
6063 "Kext %s unwiring and unmapping linked executable.",
6064 getIdentifierCString());
6066 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6068 if (segmentShouldBeWired(seg
)) {
6069 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6070 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6071 if (result
!= KERN_SUCCESS
) {
6073 kOSKextLogErrorLevel
|
6075 "Failed to unwire kext %s.",
6076 getIdentifierCString());
6077 result
= kOSKextReturnInternalError
;
6082 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6086 OSSafeReleaseNULL(linkedExecutable
);
6089 /* An interface kext has a fake kmod_info that was allocated,
6090 * so we have to free it.
6092 if (isInterface()) {
6093 kfree(kmod_info
, sizeof(kmod_info_t
));
6098 flags
.loaded
= false;
6099 flushDependencies();
6101 /* save a copy of the bundle ID for us to check when deciding to
6102 * rebuild the kernel cache file. If a kext was already in the kernel
6103 * cache and unloaded then later loaded we do not need to rebuild the
6104 * kernel cache. 9055303
6106 if (isPrelinked()) {
6107 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6108 IORecursiveLockLock(sKextLock
);
6109 if (sUnloadedPrelinkedKexts
) {
6110 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6112 IORecursiveLockUnlock(sKextLock
);
6117 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6118 "Kext %s unloaded.", getIdentifierCString());
6120 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6121 OSDynamicCast(OSString
, bundleID
));
6124 OSKext::saveLoadedKextPanicList();
6125 OSKext::updateLoadedKextSummaries();
6127 flags
.unloading
= 0;
6131 /*********************************************************************
6132 * Assumes sKextLock is held.
6133 *********************************************************************/
6136 OSKext::queueKextNotification(
6137 const char * notificationName
,
6138 OSString
* kextIdentifier
)
6140 OSReturn result
= kOSReturnError
;
6141 OSDictionary
* loadRequest
= NULL
; // must release
6143 if (!kextIdentifier
) {
6144 result
= kOSKextReturnInvalidArgument
;
6148 /* Create a new request unless one is already sitting
6149 * in sKernelRequests for this bundle identifier
6151 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6152 if (result
!= kOSReturnSuccess
) {
6155 if (!_OSKextSetRequestArgument(loadRequest
,
6156 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6158 result
= kOSKextReturnNoMemory
;
6161 if (!sKernelRequests
->setObject(loadRequest
)) {
6162 result
= kOSKextReturnNoMemory
;
6166 /* We might want to only queue the notification if kextd is active,
6167 * but that wouldn't work for embedded. Note that we don't care if
6168 * the ping immediately succeeds here so don't do anything with the
6169 * result of this call.
6171 OSKext::pingKextd();
6173 result
= kOSReturnSuccess
;
6176 OSSafeRelease(loadRequest
);
6181 /*********************************************************************
6182 *********************************************************************/
6184 _OSKextConsiderDestroyingLinkContext(
6185 __unused thread_call_param_t p0
,
6186 __unused thread_call_param_t p1
)
6188 /* Take multiple locks in the correct order.
6190 IORecursiveLockLock(sKextLock
);
6191 IORecursiveLockLock(sKextInnerLock
);
6193 /* The first time we destroy the kxldContext is in the first
6194 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6195 * before calling this function. Thereafter any call to this function
6196 * will actually destroy the context.
6198 if (sConsiderUnloadsCalled
&& sKxldContext
) {
6199 kxld_destroy_context(sKxldContext
);
6200 sKxldContext
= NULL
;
6203 /* Free the thread_call that was allocated to execute this function.
6205 if (sDestroyLinkContextThread
) {
6206 if (!thread_call_free(sDestroyLinkContextThread
)) {
6207 OSKextLog(/* kext */ NULL
,
6208 kOSKextLogErrorLevel
|
6209 kOSKextLogGeneralFlag
,
6210 "thread_call_free() failed for kext link context.");
6212 sDestroyLinkContextThread
= 0;
6215 IORecursiveLockUnlock(sKextInnerLock
);
6216 IORecursiveLockUnlock(sKextLock
);
6221 /*********************************************************************
6222 * Destroying the kxldContext requires checking variables under both
6223 * sKextInnerLock and sKextLock, so we do it on a separate thread
6224 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6225 * call relationship.
6227 * This function must be invoked with sKextInnerLock held.
6228 * Do not call any function that takes sKextLock here!
6229 *********************************************************************/
6232 OSKext::considerDestroyingLinkContext(void)
6234 IORecursiveLockLock(sKextInnerLock
);
6236 /* If we have already queued a thread to destroy the link context,
6237 * don't bother resetting; that thread will take care of it.
6239 if (sDestroyLinkContextThread
) {
6243 /* The function to be invoked in the thread will deallocate
6244 * this thread_call, so don't share it around.
6246 sDestroyLinkContextThread
= thread_call_allocate(
6247 &_OSKextConsiderDestroyingLinkContext
, 0);
6248 if (!sDestroyLinkContextThread
) {
6249 OSKextLog(/* kext */ NULL
,
6250 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
| kOSKextLogLinkFlag
,
6251 "Can't create thread to destroy kext link context.");
6255 thread_call_enter(sDestroyLinkContextThread
);
6258 IORecursiveLockUnlock(sKextInnerLock
);
6263 #pragma mark Autounload
6265 /*********************************************************************
6266 * This is a static method because the kext will be deallocated if it
6268 *********************************************************************/
6271 OSKext::autounloadKext(OSKext
* aKext
)
6273 OSReturn result
= kOSKextReturnInUse
;
6275 /* Check for external references to this kext (usu. dependents),
6276 * instances of defined classes (or classes derived from them),
6277 * outstanding requests.
6279 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
6280 !aKext
->flags
.autounloadEnabled
||
6281 aKext
->isKernelComponent()) {
6286 /* Skip a delay-autounload kext, once.
6288 if (aKext
->flags
.delayAutounload
) {
6290 kOSKextLogProgressLevel
|
6291 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6292 "Kext %s has delayed autounload set; skipping and clearing flag.",
6293 aKext
->getIdentifierCString());
6294 aKext
->flags
.delayAutounload
= 0;
6298 if (aKext
->hasOSMetaClassInstances() ||
6299 aKext
->countRequestCallbacks()) {
6303 result
= OSKext::removeKext(aKext
);
6309 /*********************************************************************
6310 *********************************************************************/
6312 _OSKextConsiderUnloads(
6313 __unused thread_call_param_t p0
,
6314 __unused thread_call_param_t p1
)
6316 bool didUnload
= false;
6317 unsigned int count
, i
;
6319 /* Take multiple locks in the correct order
6320 * (note also sKextSummaries lock further down).
6322 IORecursiveLockLock(sKextLock
);
6323 IORecursiveLockLock(sKextInnerLock
);
6325 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6327 /* If the system is powering down, don't try to unload anything.
6333 OSKextLog(/* kext */ NULL
,
6334 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6335 "Checking for unused kexts to autounload.");
6338 * Remove any request callbacks marked as stale,
6339 * and mark as stale any currently in flight.
6341 count
= sRequestCallbackRecords
->getCount();
6345 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
6346 sRequestCallbackRecords
->getObject(i
));
6347 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
6348 callbackRecord
->getObject(kKextRequestStaleKey
));
6350 if (stale
== kOSBooleanTrue
) {
6351 OSKext::invokeRequestCallback(callbackRecord
,
6352 kOSKextReturnTimeout
);
6354 callbackRecord
->setObject(kKextRequestStaleKey
,
6361 * Make multiple passes through the array of loaded kexts until
6362 * we don't unload any. This handles unwinding of dependency
6363 * chains. We have to go *backwards* through the array because
6364 * kexts are removed from it when unloaded, and we cannot make
6365 * a copy or we'll mess up the retain counts we rely on to
6366 * check whether a kext will unload. If only we could have
6367 * nonretaining collections like CF has....
6372 count
= sLoadedKexts
->getCount();
6376 OSKext
* thisKext
= OSDynamicCast(OSKext
,
6377 sLoadedKexts
->getObject(i
));
6378 didUnload
|= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
6381 } while (didUnload
);
6384 sConsiderUnloadsPending
= false;
6385 sConsiderUnloadsExecuted
= true;
6387 (void) OSKext::considerRebuildOfPrelinkedKernel();
6389 IORecursiveLockUnlock(sKextInnerLock
);
6390 IORecursiveLockUnlock(sKextLock
);
6395 /*********************************************************************
6396 * Do not call any function that takes sKextLock here!
6397 *********************************************************************/
6398 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
6402 IORecursiveLockLock(sKextInnerLock
);
6404 if (!sUnloadCallout
) {
6405 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, 0);
6408 /* we only reset delay value for unloading if we already have something
6409 * pending. rescheduleOnlyFlag should not start the count down.
6411 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
6415 thread_call_cancel(sUnloadCallout
);
6416 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
6417 clock_interval_to_deadline(sConsiderUnloadDelay
,
6418 1000 * 1000 * 1000, &when
);
6420 OSKextLog(/* kext */ NULL
,
6421 kOSKextLogProgressLevel
|
6423 "%scheduling %sscan for unused kexts in %lu seconds.",
6424 sConsiderUnloadsPending
? "Res" : "S",
6425 sConsiderUnloadsCalled
? "" : "initial ",
6426 (unsigned long)sConsiderUnloadDelay
);
6428 sConsiderUnloadsPending
= true;
6429 thread_call_enter_delayed(sUnloadCallout
, when
);
6433 /* The kxld context should be reused throughout boot. We mark the end of
6434 * period as the first time considerUnloads() is called, and we destroy
6435 * the first kxld context in that function. Afterwards, it will be
6436 * destroyed in flushNonloadedKexts.
6438 if (!sConsiderUnloadsCalled
) {
6439 sConsiderUnloadsCalled
= true;
6440 OSKext::considerDestroyingLinkContext();
6443 IORecursiveLockUnlock(sKextInnerLock
);
6447 /*********************************************************************
6448 * Do not call any function that takes sKextLock here!
6449 *********************************************************************/
6452 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
)
6454 IORecursiveLockLock(sKextInnerLock
);
6456 /* If the system is going to sleep, cancel the reaper thread timer,
6457 * and note that we're in a sleep state in case it just fired but hasn't
6458 * taken the lock yet. If we are coming back from sleep, just
6459 * clear the sleep flag; IOService's normal operation will cause
6460 * unloads to be considered soon enough.
6462 if (messageType
== kIOMessageSystemWillSleep
) {
6463 if (sUnloadCallout
) {
6464 thread_call_cancel(sUnloadCallout
);
6466 sSystemSleep
= true;
6467 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
6468 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
6469 sSystemSleep
= false;
6470 clock_get_uptime(&sLastWakeTime
);
6472 IORecursiveLockUnlock(sKextInnerLock
);
6474 return kIOReturnSuccess
;
6481 #pragma mark Prelinked Kernel
6483 /*********************************************************************
6484 * Do not access sConsiderUnloads... variables other than
6485 * sConsiderUnloadsExecuted in this function. They are guarded by a
6487 *********************************************************************/
6490 OSKext::considerRebuildOfPrelinkedKernel(void)
6492 static bool requestedPrelink
= false;
6493 OSReturn checkResult
= kOSReturnError
;
6494 OSDictionary
* prelinkRequest
= NULL
; // must release
6495 OSCollectionIterator
* kextIterator
= NULL
; // must release
6496 const OSSymbol
* thisID
= NULL
; // do not release
6497 bool doRebuild
= false;
6498 AbsoluteTime my_abstime
;
6502 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
6503 if (requestedPrelink
|| !sPrelinkBoot
) {
6507 /* no direct return from this point */
6508 IORecursiveLockLock(sKextLock
);
6510 /* We need to wait for kextd to get up and running with unloads already done
6511 * and any new startup kexts loaded.
6513 if (!sConsiderUnloadsExecuted
||
6514 !sDeferredLoadSucceeded
) {
6518 /* we really only care about boot / system start up related kexts so bail
6519 * if we're here after REBUILD_MAX_TIME.
6521 if (!_OSKextInPrelinkRebuildWindow()) {
6522 OSKextLog(/* kext */ NULL
,
6523 kOSKextLogArchiveFlag
,
6524 "%s prebuild rebuild has expired",
6526 requestedPrelink
= true;
6530 /* we do not want to trigger a rebuild if we get here too close to waking
6531 * up. (see radar 10233768)
6533 IORecursiveLockLock(sKextInnerLock
);
6535 clock_get_uptime(&my_abstime
);
6536 delta_secs
= MINIMUM_WAKEUP_SECONDS
+ 1;
6537 if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) {
6538 SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
);
6539 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
6540 delta_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
6542 IORecursiveLockUnlock(sKextInnerLock
);
6544 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
6545 /* too close to time of last wake from sleep */
6548 requestedPrelink
= true;
6550 /* Now it's time to see if we have a reason to rebuild. We may have done
6551 * some loads and unloads but the kernel cache didn't actually change.
6552 * We will rebuild if any kext is not marked prelinked AND is not in our
6553 * list of prelinked kexts that got unloaded. (see radar 9055303)
6555 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
6556 if (!kextIterator
) {
6560 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
6561 OSKext
* thisKext
; // do not release
6563 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
6564 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
6568 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
6571 /* kext is loaded and was not in current kernel cache so let's rebuild
6574 OSKextLog(/* kext */ NULL
,
6575 kOSKextLogArchiveFlag
,
6576 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
6577 thisKext
->bundleID
->getCStringNoCopy());
6580 sUnloadedPrelinkedKexts
->flushCollection();
6586 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
6588 if (checkResult
!= kOSReturnSuccess
) {
6592 if (!sKernelRequests
->setObject(prelinkRequest
)) {
6596 OSKext::pingKextd();
6599 IORecursiveLockUnlock(sKextLock
);
6600 OSSafeRelease(prelinkRequest
);
6601 OSSafeRelease(kextIterator
);
6607 #pragma mark Dependencies
6609 /*********************************************************************
6610 *********************************************************************/
6612 OSKext::resolveDependencies(
6613 OSArray
* loopStack
)
6615 bool result
= false;
6616 OSArray
* localLoopStack
= NULL
; // must release
6617 bool addedToLoopStack
= false;
6618 OSDictionary
* libraries
= NULL
; // do not release
6619 OSCollectionIterator
* libraryIterator
= NULL
; // must release
6620 OSString
* libraryID
= NULL
; // do not release
6621 OSString
* infoString
= NULL
; // do not release
6622 OSString
* readableString
= NULL
; // do not release
6623 OSKext
* libraryKext
= NULL
; // do not release
6624 bool hasRawKernelDependency
= false;
6625 bool hasKernelDependency
= false;
6626 bool hasKPIDependency
= false;
6627 bool hasPrivateKPIDependency
= false;
6630 /* A kernel component will automatically have this flag set,
6631 * and a loaded kext should also have it set (as should all its
6632 * loaded dependencies).
6634 if (flags
.hasAllDependencies
) {
6639 /* Check for loops in the dependency graph.
6642 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
6644 kOSKextLogErrorLevel
|
6645 kOSKextLogDependenciesFlag
,
6646 "Kext %s has a dependency loop; can't resolve dependencies.",
6647 getIdentifierCString());
6652 kOSKextLogStepLevel
|
6653 kOSKextLogDependenciesFlag
,
6654 "Kext %s resolving dependencies.",
6655 getIdentifierCString());
6657 loopStack
= OSArray::withCapacity(6); // any small capacity will do
6660 kOSKextLogErrorLevel
|
6661 kOSKextLogDependenciesFlag
,
6662 "Kext %s can't create bookkeeping stack to resolve dependencies.",
6663 getIdentifierCString());
6666 localLoopStack
= loopStack
;
6668 if (!loopStack
->setObject(this)) {
6670 kOSKextLogErrorLevel
|
6671 kOSKextLogDependenciesFlag
,
6672 "Kext %s - internal error resolving dependencies.",
6673 getIdentifierCString());
6676 addedToLoopStack
= true;
6678 /* Purge any existing kexts in the dependency list and start over.
6680 flushDependencies();
6683 kOSKextLogErrorLevel
|
6684 kOSKextLogDependenciesFlag
,
6685 "Kext %s - internal error resolving dependencies.",
6686 getIdentifierCString());
6689 libraries
= OSDynamicCast(OSDictionary
,
6690 getPropertyForHostArch(kOSBundleLibrariesKey
));
6691 if (libraries
== NULL
|| libraries
->getCount() == 0) {
6693 kOSKextLogErrorLevel
|
6694 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6695 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
6696 getIdentifierCString(), kOSBundleLibrariesKey
);
6700 /* Make a new array to hold the dependencies (flush freed the old one).
6702 dependencies
= OSArray::withCapacity(libraries
->getCount());
6703 if (!dependencies
) {
6705 kOSKextLogErrorLevel
|
6706 kOSKextLogDependenciesFlag
,
6707 "Kext %s - can't allocate dependencies array.",
6708 getIdentifierCString());
6712 // xxx - compat: We used to add an implicit dependency on kernel 6.0
6713 // xxx - compat: if none were declared.
6715 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
6716 if (!libraryIterator
) {
6718 kOSKextLogErrorLevel
|
6719 kOSKextLogDependenciesFlag
,
6720 "Kext %s - can't allocate dependencies iterator.",
6721 getIdentifierCString());
6725 while ((libraryID
= OSDynamicCast(OSString
,
6726 libraryIterator
->getNextObject()))) {
6728 const char * library_id
= libraryID
->getCStringNoCopy();
6730 OSString
* libraryVersion
= OSDynamicCast(OSString
,
6731 libraries
->getObject(libraryID
));
6732 if (libraryVersion
== NULL
) {
6734 kOSKextLogErrorLevel
|
6735 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6736 "Kext %s - illegal type in OSBundleLibraries.",
6737 getIdentifierCString());
6741 OSKextVersion libraryVers
=
6742 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
6743 if (libraryVers
== -1) {
6745 kOSKextLogErrorLevel
|
6746 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6747 "Kext %s - invalid library version %s.",
6748 getIdentifierCString(),
6749 libraryVersion
->getCStringNoCopy());
6753 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
6754 if (libraryKext
== NULL
) {
6756 kOSKextLogErrorLevel
|
6757 kOSKextLogDependenciesFlag
,
6758 "Kext %s - library kext %s not found.",
6759 getIdentifierCString(), library_id
);
6763 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
6765 kOSKextLogErrorLevel
|
6766 kOSKextLogDependenciesFlag
,
6767 "Kext %s - library kext %s not compatible "
6768 "with requested version %s.",
6769 getIdentifierCString(), library_id
,
6770 libraryVersion
->getCStringNoCopy());
6774 /* If a nonprelinked library somehow got into the mix for a
6775 * prelinked kext, at any point in the chain, we must fail
6776 * because the prelinked relocs for the library will be all wrong.
6778 if (this->isPrelinked() &&
6779 libraryKext
->declaresExecutable() &&
6780 !libraryKext
->isPrelinked()) {
6783 kOSKextLogErrorLevel
|
6784 kOSKextLogDependenciesFlag
,
6785 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
6786 getIdentifierCString(), library_id
,
6787 libraryVersion
->getCStringNoCopy());
6791 if (!libraryKext
->resolveDependencies(loopStack
)) {
6795 /* Add the library directly only if it has an executable to link.
6796 * Otherwise it's just used to collect other dependencies, so put
6797 * *its* dependencies on the list for this kext.
6799 // xxx - We are losing info here; would like to make fake entries or
6800 // xxx - keep these in the dependency graph for loaded kexts.
6801 // xxx - I really want to make kernel components not a special case!
6802 if (libraryKext
->declaresExecutable() ||
6803 libraryKext
->isInterface()) {
6805 if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) {
6806 dependencies
->setObject(libraryKext
);
6809 kOSKextLogDetailLevel
|
6810 kOSKextLogDependenciesFlag
,
6811 "Kext %s added dependency %s.",
6812 getIdentifierCString(),
6813 libraryKext
->getIdentifierCString());
6816 int numLibDependencies
= libraryKext
->getNumDependencies();
6817 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
6820 if (numLibDependencies
) {
6821 // xxx - this msg level should be 1 lower than the per-kext one
6823 kOSKextLogDetailLevel
|
6824 kOSKextLogDependenciesFlag
,
6825 "Kext %s pulling %d dependencies from codeless library %s.",
6826 getIdentifierCString(),
6828 libraryKext
->getIdentifierCString());
6830 for (index
= 0; index
< numLibDependencies
; index
++) {
6831 OSKext
* thisLibDependency
= OSDynamicCast(OSKext
,
6832 libraryDependencies
->getObject(index
));
6833 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) {
6834 dependencies
->setObject(thisLibDependency
);
6836 kOSKextLogDetailLevel
|
6837 kOSKextLogDependenciesFlag
,
6838 "Kext %s added dependency %s from codeless library %s.",
6839 getIdentifierCString(),
6840 thisLibDependency
->getIdentifierCString(),
6841 libraryKext
->getIdentifierCString());
6846 if ((strlen(library_id
) == strlen(KERNEL_LIB
)) &&
6847 0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) {
6849 hasRawKernelDependency
= true;
6850 } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) {
6851 hasKernelDependency
= true;
6852 } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) {
6853 hasKPIDependency
= true;
6854 if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) {
6855 hasPrivateKPIDependency
= true;
6860 if (hasRawKernelDependency
) {
6862 kOSKextLogErrorLevel
|
6863 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6864 "Error - kext %s declares a dependency on %s, which is not permitted.",
6865 getIdentifierCString(), KERNEL_LIB
);
6869 if (hasKernelDependency
) {
6871 kOSKextLogErrorLevel
|
6872 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6873 "Error - kext %s declares %s dependencies. "
6874 "Only %s* dependencies are supported for 64-bit kexts.",
6875 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
6878 if (!hasKPIDependency
) {
6880 kOSKextLogWarningLevel
|
6881 kOSKextLogDependenciesFlag
,
6882 "Warning - kext %s declares no %s* dependencies. "
6883 "If it uses any KPIs, the link may fail with undefined symbols.",
6884 getIdentifierCString(), KPI_LIB_PREFIX
);
6886 #else /* __LP64__ */
6887 // xxx - will change to flatly disallow "kernel" dependencies at some point
6888 // xxx - is it invalid to do both "com.apple.kernel" and any
6889 // xxx - "com.apple.kernel.*"?
6891 if (hasKernelDependency
&& hasKPIDependency
) {
6893 kOSKextLogWarningLevel
|
6894 kOSKextLogDependenciesFlag
,
6895 "Warning - kext %s has immediate dependencies on both "
6896 "%s* and %s* components; use only one style.",
6897 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
6900 if (!hasKernelDependency
&& !hasKPIDependency
) {
6901 // xxx - do we want to use validation flag for these too?
6903 kOSKextLogWarningLevel
|
6904 kOSKextLogDependenciesFlag
,
6905 "Warning - %s declares no kernel dependencies; using %s.",
6906 getIdentifierCString(), KERNEL6_LIB
);
6907 OSKext
* kernelKext
= OSDynamicCast(OSKext
,
6908 sKextsByID
->getObject(KERNEL6_LIB
));
6910 dependencies
->setObject(kernelKext
);
6913 kOSKextLogErrorLevel
|
6914 kOSKextLogDependenciesFlag
,
6915 "Error - Library %s not found for %s.",
6916 KERNEL6_LIB
, getIdentifierCString());
6920 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
6921 * its indirect dependencies to simulate old-style linking. XXX - Should
6922 * check for duplicates.
6924 if (!hasKPIDependency
) {
6927 flags
.hasBleedthrough
= true;
6929 count
= getNumDependencies();
6931 /* We add to the dependencies array in this loop, but do not iterate
6932 * past its original count.
6934 for (i
= 0; i
< count
; i
++) {
6935 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
6936 dependencies
->getObject(i
));
6937 dependencyKext
->addBleedthroughDependencies(dependencies
);
6940 #endif /* __LP64__ */
6942 if (hasPrivateKPIDependency
) {
6943 bool hasApplePrefix
= false;
6944 bool infoCopyrightIsValid
= false;
6945 bool readableCopyrightIsValid
= false;
6947 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
6950 infoString
= OSDynamicCast(OSString
,
6951 getPropertyForHostArch("CFBundleGetInfoString"));
6953 infoCopyrightIsValid
=
6954 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
6957 readableString
= OSDynamicCast(OSString
,
6958 getPropertyForHostArch("NSHumanReadableCopyright"));
6959 if (readableString
) {
6960 readableCopyrightIsValid
=
6961 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
6964 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
6966 kOSKextLogErrorLevel
|
6967 kOSKextLogDependenciesFlag
,
6968 "Error - kext %s declares a dependency on %s. "
6969 "Only Apple kexts may declare a dependency on %s.",
6970 getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
);
6976 flags
.hasAllDependencies
= 1;
6980 if (addedToLoopStack
) {
6981 count
= loopStack
->getCount();
6982 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
6983 loopStack
->removeObject(count
- 1);
6986 kOSKextLogErrorLevel
|
6987 kOSKextLogDependenciesFlag
,
6988 "Kext %s - internal error resolving dependencies.",
6989 getIdentifierCString());
6993 if (result
&& localLoopStack
) {
6995 kOSKextLogStepLevel
|
6996 kOSKextLogDependenciesFlag
,
6997 "Kext %s successfully resolved dependencies.",
6998 getIdentifierCString());
7001 OSSafeRelease(localLoopStack
);
7002 OSSafeRelease(libraryIterator
);
7007 /*********************************************************************
7008 *********************************************************************/
7010 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
7012 bool result
= false;
7013 unsigned int dependencyIndex
, dependencyCount
;
7015 dependencyCount
= getNumDependencies();
7017 for (dependencyIndex
= 0;
7018 dependencyIndex
< dependencyCount
;
7019 dependencyIndex
++) {
7021 OSKext
* dependency
= OSDynamicCast(OSKext
,
7022 dependencies
->getObject(dependencyIndex
));
7025 kOSKextLogErrorLevel
|
7026 kOSKextLogDependenciesFlag
,
7027 "Kext %s - internal error propagating compatibility dependencies.",
7028 getIdentifierCString());
7031 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7032 anArray
->setObject(dependency
);
7034 dependency
->addBleedthroughDependencies(anArray
);
7043 /*********************************************************************
7044 *********************************************************************/
7046 OSKext::flushDependencies(bool forceFlag
)
7048 bool result
= false;
7050 /* Only clear the dependencies if the kext isn't loaded;
7051 * we need the info for loaded kexts to track references.
7053 if (!isLoaded() || forceFlag
) {
7055 // xxx - check level
7057 kOSKextLogProgressLevel
|
7058 kOSKextLogDependenciesFlag
,
7059 "Kext %s flushing dependencies.",
7060 getIdentifierCString());
7061 OSSafeReleaseNULL(dependencies
);
7064 if (!isKernelComponent()) {
7065 flags
.hasAllDependencies
= 0;
7073 /*********************************************************************
7074 *********************************************************************/
7076 OSKext::getNumDependencies(void)
7078 if (!dependencies
) {
7081 return dependencies
->getCount();
7084 /*********************************************************************
7085 *********************************************************************/
7087 OSKext::getDependencies(void)
7089 return dependencies
;
7093 #pragma mark OSMetaClass Support
7095 /*********************************************************************
7096 *********************************************************************/
7099 OSMetaClass
* aClass
,
7100 uint32_t numClasses
)
7102 OSReturn result
= kOSMetaClassNoInsKModSet
;
7105 metaClasses
= OSSet::withCapacity(numClasses
);
7111 if (metaClasses
->containsObject(aClass
)) {
7113 kOSKextLogWarningLevel
|
7115 "Notice - kext %s has already registered class %s.",
7116 getIdentifierCString(),
7117 aClass
->getClassName());
7118 result
= kOSReturnSuccess
;
7122 if (!metaClasses
->setObject(aClass
)) {
7126 kOSKextLogDetailLevel
|
7128 "Kext %s registered class %s.",
7129 getIdentifierCString(),
7130 aClass
->getClassName());
7133 if (!flags
.autounloadEnabled
) {
7134 const OSMetaClass
* metaScan
= NULL
; // do not release
7136 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7137 if (metaScan
== OSTypeID(IOService
)) {
7140 kOSKextLogProgressLevel
|
7142 "Kext %s has IOService subclass %s; enabling autounload.",
7143 getIdentifierCString(),
7144 aClass
->getClassName());
7146 flags
.autounloadEnabled
= 1;
7152 notifyAddClassObservers(this, aClass
, flags
);
7154 result
= kOSReturnSuccess
;
7157 if (result
!= kOSReturnSuccess
) {
7159 kOSKextLogErrorLevel
|
7161 "Kext %s failed to register class %s.",
7162 getIdentifierCString(),
7163 aClass
->getClassName());
7169 /*********************************************************************
7170 *********************************************************************/
7172 OSKext::removeClass(
7173 OSMetaClass
* aClass
)
7175 OSReturn result
= kOSMetaClassNoKModSet
;
7181 if (!metaClasses
->containsObject(aClass
)) {
7183 kOSKextLogWarningLevel
|
7185 "Notice - kext %s asked to unregister unknown class %s.",
7186 getIdentifierCString(),
7187 aClass
->getClassName());
7188 result
= kOSReturnSuccess
;
7193 kOSKextLogDetailLevel
|
7195 "Kext %s unregistering class %s.",
7196 getIdentifierCString(),
7197 aClass
->getClassName());
7199 metaClasses
->removeObject(aClass
);
7201 notifyRemoveClassObservers(this, aClass
, flags
);
7203 result
= kOSReturnSuccess
;
7206 if (result
!= kOSReturnSuccess
) {
7208 kOSKextLogErrorLevel
|
7210 "Failed to unregister kext %s class %s.",
7211 getIdentifierCString(),
7212 aClass
->getClassName());
7217 /*********************************************************************
7218 *********************************************************************/
7220 OSKext::getMetaClasses(void)
7225 /*********************************************************************
7226 *********************************************************************/
7228 OSKext::hasOSMetaClassInstances(void)
7230 bool result
= false;
7231 OSCollectionIterator
* classIterator
= NULL
; // must release
7232 OSMetaClass
* checkClass
= NULL
; // do not release
7238 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7239 if (!classIterator
) {
7240 // xxx - log alloc failure?
7243 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7244 if (checkClass
->getInstanceCount()) {
7252 OSSafeRelease(classIterator
);
7256 /*********************************************************************
7257 *********************************************************************/
7260 OSKext::reportOSMetaClassInstances(
7261 const char * kextIdentifier
,
7262 OSKextLogSpec msgLogSpec
)
7264 OSKext
* theKext
= NULL
; // must release
7266 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
7271 theKext
->reportOSMetaClassInstances(msgLogSpec
);
7273 OSSafeRelease(theKext
);
7277 /*********************************************************************
7278 *********************************************************************/
7280 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
7282 OSCollectionIterator
* classIterator
= NULL
; // must release
7283 OSMetaClass
* checkClass
= NULL
; // do not release
7289 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7290 if (!classIterator
) {
7293 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7294 if (checkClass
->getInstanceCount()) {
7297 " Kext %s class %s has %d instance%s.",
7298 getIdentifierCString(),
7299 checkClass
->getClassName(),
7300 checkClass
->getInstanceCount(),
7301 checkClass
->getInstanceCount() == 1 ? "" : "s");
7306 OSSafeRelease(classIterator
);
7311 #pragma mark User-Space Requests
7313 /*********************************************************************
7314 * XXX - this function is a big ugly mess
7315 *********************************************************************/
7318 OSKext::handleRequest(
7319 host_priv_t hostPriv
,
7320 OSKextLogSpec clientLogFilter
,
7321 char * requestBuffer
,
7322 uint32_t requestLength
,
7323 char ** responseOut
,
7324 uint32_t * responseLengthOut
,
7326 uint32_t * logInfoLengthOut
)
7328 OSReturn result
= kOSReturnError
;
7329 kern_return_t kmem_result
= KERN_FAILURE
;
7331 char * response
= NULL
; // returned by reference
7332 uint32_t responseLength
= 0;
7334 OSObject
* parsedXML
= NULL
; // must release
7335 OSDictionary
* requestDict
= NULL
; // do not release
7336 OSString
* errorString
= NULL
; // must release
7338 OSObject
* responseObject
= NULL
; // must release
7340 OSSerialize
* serializer
= NULL
; // must release
7342 OSArray
* logInfoArray
= NULL
; // must release
7344 OSString
* predicate
= NULL
; // do not release
7345 OSString
* kextIdentifier
= NULL
; // do not release
7346 OSArray
* kextIdentifiers
= NULL
; // do not release
7347 OSKext
* theKext
= NULL
; // do not release
7348 OSBoolean
* boolArg
= NULL
; // do not release
7350 IORecursiveLockLock(sKextLock
);
7353 *responseOut
= NULL
;
7354 *responseLengthOut
= 0;
7358 *logInfoLengthOut
= 0;
7361 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
7363 /* XML must be nul-terminated.
7365 if (requestBuffer
[requestLength
- 1] != '\0') {
7366 OSKextLog(/* kext */ NULL
,
7367 kOSKextLogErrorLevel
|
7369 "Invalid request from user space (not nul-terminated).");
7370 result
= kOSKextReturnBadData
;
7373 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
7375 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
7378 const char * errorCString
= "(unknown error)";
7380 if (errorString
&& errorString
->getCStringNoCopy()) {
7381 errorCString
= errorString
->getCStringNoCopy();
7382 } else if (parsedXML
) {
7383 errorCString
= "not a dictionary";
7385 OSKextLog(/* kext */ NULL
,
7386 kOSKextLogErrorLevel
|
7388 "Error unserializing request from user space: %s.",
7390 result
= kOSKextReturnSerialization
;
7394 predicate
= _OSKextGetRequestPredicate(requestDict
);
7396 OSKextLog(/* kext */ NULL
,
7397 kOSKextLogErrorLevel
|
7399 "Recieved kext request from user space with no predicate.");
7400 result
= kOSKextReturnInvalidArgument
;
7404 OSKextLog(/* kext */ NULL
,
7405 kOSKextLogDebugLevel
|
7407 "Received '%s' request from user space.",
7408 predicate
->getCStringNoCopy());
7410 result
= kOSKextReturnNotPrivileged
;
7411 if (hostPriv
== HOST_PRIV_NULL
) {
7412 /* must be root to use these kext requests */
7413 if (predicate
->isEqualTo(kKextRequestPredicateUnload
) ||
7414 predicate
->isEqualTo(kKextRequestPredicateStart
) ||
7415 predicate
->isEqualTo(kKextRequestPredicateStop
) ||
7416 predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
) ||
7417 predicate
->isEqualTo(kKextRequestPredicateSendResource
) ) {
7418 OSKextLog(/* kext */ NULL
,
7419 kOSKextLogErrorLevel
|
7421 "Access Failure - must be root user.");
7426 /* Get common args in anticipation of use.
7428 kextIdentifier
= OSDynamicCast(OSString
, _OSKextGetRequestArgument(
7429 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7430 kextIdentifiers
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument(
7431 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7432 if (kextIdentifier
) {
7433 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
7435 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
7436 requestDict
, kKextRequestArgumentValueKey
));
7438 result
= kOSKextReturnInvalidArgument
;
7440 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
7441 if (!kextIdentifier
) {
7442 OSKextLog(/* kext */ NULL
,
7443 kOSKextLogErrorLevel
|
7445 "Invalid arguments to kext start request.");
7446 } else if (!theKext
) {
7447 OSKextLog(/* kext */ NULL
,
7448 kOSKextLogErrorLevel
|
7450 "Kext %s not found for start request.",
7451 kextIdentifier
->getCStringNoCopy());
7452 result
= kOSKextReturnNotFound
;
7454 result
= theKext
->start();
7457 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
7458 if (!kextIdentifier
) {
7459 OSKextLog(/* kext */ NULL
,
7460 kOSKextLogErrorLevel
|
7462 "Invalid arguments to kext stop request.");
7463 } else if (!theKext
) {
7464 OSKextLog(/* kext */ NULL
,
7465 kOSKextLogErrorLevel
|
7467 "Kext %s not found for stop request.",
7468 kextIdentifier
->getCStringNoCopy());
7469 result
= kOSKextReturnNotFound
;
7471 result
= theKext
->stop();
7474 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
7475 if (!kextIdentifier
) {
7476 OSKextLog(/* kext */ NULL
,
7477 kOSKextLogErrorLevel
|
7479 "Invalid arguments to kext unload request.");
7480 } else if (!theKext
) {
7481 OSKextLog(/* kext */ NULL
,
7482 kOSKextLogErrorLevel
|
7484 "Kext %s not found for unload request.",
7485 kextIdentifier
->getCStringNoCopy());
7486 result
= kOSKextReturnNotFound
;
7488 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
7489 _OSKextGetRequestArgument(requestDict
,
7490 kKextRequestArgumentTerminateIOServicesKey
));
7491 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
7494 } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
7495 result
= OSKext::dispatchResource(requestDict
);
7497 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
7498 OSBoolean
* delayAutounloadBool
= NULL
;
7499 OSObject
* infoKeysRaw
= NULL
;
7500 OSArray
* infoKeys
= NULL
;
7501 uint32_t infoKeysCount
= 0;
7503 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
7504 _OSKextGetRequestArgument(requestDict
,
7505 kKextRequestArgumentDelayAutounloadKey
));
7507 /* If asked to delay autounload, reset the timer if it's currently set.
7508 * (That is, don't schedule an unload if one isn't already pending.
7510 if (delayAutounloadBool
== kOSBooleanTrue
) {
7511 OSKext::considerUnloads(/* rescheduleOnly? */ true);
7514 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
7515 kKextRequestArgumentInfoKeysKey
);
7516 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
7517 if (infoKeysRaw
&& !infoKeys
) {
7518 OSKextLog(/* kext */ NULL
,
7519 kOSKextLogErrorLevel
|
7521 "Invalid arguments to kext info request.");
7526 infoKeysCount
= infoKeys
->getCount();
7527 for (uint32_t i
= 0; i
< infoKeysCount
; i
++) {
7528 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) {
7529 OSKextLog(/* kext */ NULL
,
7530 kOSKextLogErrorLevel
|
7532 "Invalid arguments to kext info request.");
7538 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
7539 if (!responseObject
) {
7540 result
= kOSKextReturnInternalError
;
7542 OSKextLog(/* kext */ NULL
,
7543 kOSKextLogDebugLevel
|
7545 "Returning loaded kext info.");
7546 result
= kOSReturnSuccess
;
7548 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) {
7550 /* Hand the current sKernelRequests array to the caller
7551 * (who must release it), and make a new one.
7553 responseObject
= sKernelRequests
;
7554 sKernelRequests
= OSArray::withCapacity(0);
7555 sPostedKextLoadIdentifiers
->flushCollection();
7556 OSKextLog(/* kext */ NULL
,
7557 kOSKextLogDebugLevel
|
7559 "Returning kernel requests.");
7560 result
= kOSReturnSuccess
;
7562 } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) {
7564 /* Return the set of all requested bundle identifiers */
7565 responseObject
= sAllKextLoadIdentifiers
;
7566 responseObject
->retain();
7567 OSKextLog(/* kext */ NULL
,
7568 kOSKextLogDebugLevel
|
7570 "Returning load requests.");
7571 result
= kOSReturnSuccess
;
7574 OSKextLog(/* kext */ NULL
,
7575 kOSKextLogDebugLevel
|
7577 "Received '%s' invalid request from user space.",
7578 predicate
->getCStringNoCopy());
7583 * Now we have handle the request, or not. Gather up the response & logging
7584 * info to ship to user space.
7587 /* Note: Nothing in OSKext is supposed to retain requestDict,
7588 * but you never know....
7590 if (requestDict
->getRetainCount() > 1) {
7591 OSKextLog(/* kext */ NULL
,
7592 kOSKextLogWarningLevel
|
7594 "Request from user space still retained by a kext; "
7595 "probable memory leak.");
7598 if (responseOut
&& responseObject
) {
7599 serializer
= OSSerialize::withCapacity(0);
7601 result
= kOSKextReturnNoMemory
;
7605 if (!responseObject
->serialize(serializer
)) {
7606 OSKextLog(/* kext */ NULL
,
7607 kOSKextLogGeneralFlag
| kOSKextLogErrorLevel
,
7608 "Failed to serialize response to request from user space.");
7609 result
= kOSKextReturnSerialization
;
7613 response
= (char *)serializer
->text();
7614 responseLength
= serializer
->getLength();
7617 if (responseOut
&& response
) {
7620 /* This kmem_alloc sets the return value of the function.
7622 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
,
7623 round_page(responseLength
));
7624 if (kmem_result
!= KERN_SUCCESS
) {
7625 OSKextLog(/* kext */ NULL
,
7626 kOSKextLogErrorLevel
|
7628 "Failed to copy response to request from user space.");
7629 result
= kmem_result
;
7632 /* 11981737 - clear uninitialized data in last page */
7633 bzero((void *)(buffer
+ responseLength
),
7634 (round_page(responseLength
) - responseLength
));
7635 memcpy(buffer
, response
, responseLength
);
7636 *responseOut
= buffer
;
7637 *responseLengthOut
= responseLength
;
7643 /* Gather up the collected log messages for user space. Any messages
7644 * messages past this call will not make it up as log messages but
7645 * will be in the system log. Note that we ignore the return of the
7646 * serialize; it has no bearing on the operation at hand even if we
7647 * fail to get the log messages.
7649 logInfoArray
= OSKext::clearUserSpaceLogFilter();
7651 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
7652 (void)OSKext::serializeLogInfo(logInfoArray
,
7653 logInfoOut
, logInfoLengthOut
);
7656 IORecursiveLockUnlock(sKextLock
);
7658 OSSafeRelease(parsedXML
);
7659 OSSafeRelease(errorString
);
7660 OSSafeRelease(responseObject
);
7661 OSSafeRelease(serializer
);
7662 OSSafeRelease(logInfoArray
);
7667 /*********************************************************************
7668 *********************************************************************/
7671 OSKext::copyLoadedKextInfo(
7672 OSArray
* kextIdentifiers
,
7675 OSDictionary
* result
= NULL
;
7676 OSDictionary
* kextInfo
= NULL
; // must release
7678 uint32_t idCount
= 0;
7679 uint32_t idIndex
= 0;
7681 IORecursiveLockLock(sKextLock
);
7683 /* Empty list of bundle ids is equivalent to no list (get all).
7685 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
7686 kextIdentifiers
= NULL
;
7687 } else if (kextIdentifiers
) {
7688 idCount
= kextIdentifiers
->getCount();
7693 if (infoKeys
&& !infoKeys
->getCount()) {
7697 count
= sLoadedKexts
->getCount();
7698 result
= OSDictionary::withCapacity(count
);
7702 for (i
= 0; i
< count
; i
++) {
7703 OSKext
* thisKext
= NULL
; // do not release
7704 Boolean includeThis
= true;
7707 kextInfo
->release();
7710 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
7715 /* Skip current kext if we have a list of bundle IDs and
7716 * it isn't in the list.
7718 if (kextIdentifiers
) {
7719 const OSString
* thisKextID
= thisKext
->getIdentifier();
7721 includeThis
= false;
7723 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
7724 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
7725 kextIdentifiers
->getObject(idIndex
));
7726 if (thisKextID
->isEqualTo(thisRequestID
)) {
7737 kextInfo
= thisKext
->copyInfo(infoKeys
);
7739 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
7744 IORecursiveLockUnlock(sKextLock
);
7746 if (kextInfo
) kextInfo
->release();
7751 /*********************************************************************
7752 * Any info that needs to do allocations must goto finish on alloc
7753 * failure. Info that is just a lookup should just not set the object
7754 * if the info does not exist.
7755 *********************************************************************/
7756 #define _OSKextLoadInfoDictCapacity (12)
7759 OSKext::copyInfo(OSArray
* infoKeys
)
7761 OSDictionary
* result
= NULL
;
7762 bool success
= false;
7763 OSData
* headerData
= NULL
; // must release
7764 OSNumber
* cpuTypeNumber
= NULL
; // must release
7765 OSNumber
* cpuSubtypeNumber
= NULL
; // must release
7766 OSString
* versionString
= NULL
; // do not release
7767 uint32_t executablePathCStringSize
= 0;
7768 char * executablePathCString
= NULL
; // must release
7769 OSString
* executablePathString
= NULL
; // must release
7770 OSData
* uuid
= NULL
; // must release
7771 OSNumber
* scratchNumber
= NULL
; // must release
7772 OSArray
* dependencyLoadTags
= NULL
; // must release
7773 OSCollectionIterator
* metaClassIterator
= NULL
; // must release
7774 OSArray
* metaClassInfo
= NULL
; // must release
7775 OSDictionary
* metaClassDict
= NULL
; // must release
7776 OSMetaClass
* thisMetaClass
= NULL
; // do not release
7777 OSString
* metaClassName
= NULL
; // must release
7778 OSString
* superclassName
= NULL
; // must release
7781 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
7787 /* Empty keys means no keys, but NULL is quicker to check.
7789 if (infoKeys
&& !infoKeys
->getCount()) {
7793 /* Headers, CPU type, and CPU subtype.
7796 _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) ||
7797 _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) ||
7798 _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
))
7801 if (linkedExecutable
&& !isInterface()) {
7803 kernel_mach_header_t
*kext_mach_hdr
= (kernel_mach_header_t
*)
7804 linkedExecutable
->getBytesNoCopy();
7806 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) {
7807 kernel_mach_header_t
* temp_kext_mach_hdr
;
7808 struct load_command
* lcp
;
7810 headerData
= OSData::withBytes(kext_mach_hdr
,
7811 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
7816 // unslide any vmaddrs we return to userspace - 10726716
7817 temp_kext_mach_hdr
= (kernel_mach_header_t
*)
7818 headerData
->getBytesNoCopy();
7819 if (temp_kext_mach_hdr
== NULL
) {
7823 lcp
= (struct load_command
*) (temp_kext_mach_hdr
+ 1);
7824 for (i
= 0; i
< temp_kext_mach_hdr
->ncmds
; i
++) {
7825 if (lcp
->cmd
== LC_SEGMENT_KERNEL
) {
7826 kernel_segment_command_t
* segp
;
7827 kernel_section_t
* secp
;
7829 segp
= (kernel_segment_command_t
*) lcp
;
7830 // 10543468 - if we jettisoned __LINKEDIT clear size info
7831 if (flags
.jettisonLinkeditSeg
) {
7832 if (strncmp(segp
->segname
, SEG_LINKEDIT
, sizeof(segp
->segname
)) == 0) {
7839 OSKextLog(/* kext */ NULL
,
7840 kOSKextLogErrorLevel
|
7841 kOSKextLogGeneralFlag
,
7842 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
7843 __FUNCTION__
, segp
->segname
, segp
->vmaddr
,
7844 VM_KERNEL_UNSLIDE(segp
->vmaddr
),
7845 segp
->vmsize
, segp
->nsects
);
7847 segp
->vmaddr
= VM_KERNEL_UNSLIDE(segp
->vmaddr
);
7849 for (secp
= firstsect(segp
); secp
!= NULL
; secp
= nextsect(segp
, secp
)) {
7850 secp
->addr
= VM_KERNEL_UNSLIDE(secp
->addr
);
7853 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
7855 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
7858 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) {
7859 cpuTypeNumber
= OSNumber::withNumber(
7860 (uint64_t) kext_mach_hdr
->cputype
,
7861 8 * sizeof(kext_mach_hdr
->cputype
));
7862 if (!cpuTypeNumber
) {
7865 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
7868 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
7869 cpuSubtypeNumber
= OSNumber::withNumber(
7870 (uint64_t) kext_mach_hdr
->cpusubtype
,
7871 8 * sizeof(kext_mach_hdr
->cpusubtype
));
7872 if (!cpuSubtypeNumber
) {
7875 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
7880 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
7882 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
7886 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
7887 versionString
= OSDynamicCast(OSString
,
7888 getPropertyForHostArch(kCFBundleVersionKey
));
7889 if (versionString
) {
7890 result
->setObject(kCFBundleVersionKey
, versionString
);
7894 /* OSBundleCompatibleVersion.
7896 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
7897 versionString
= OSDynamicCast(OSString
,
7898 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
7899 if (versionString
) {
7900 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
7906 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
7908 result
->setObject(kOSBundlePathKey
, path
);
7913 /* OSBundleExecutablePath.
7915 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
7916 if (path
&& executableRelPath
) {
7918 uint32_t pathLength
= path
->getLength(); // gets incremented below
7920 // +1 for slash, +1 for \0
7921 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
7923 executablePathCString
= (char *)kalloc((executablePathCStringSize
) *
7924 sizeof(char)); // +1 for \0
7925 if (!executablePathCString
) {
7928 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
7929 executablePathCStringSize
);
7930 executablePathCString
[pathLength
++] = '/';
7931 executablePathCString
[pathLength
++] = '\0';
7932 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
7933 executablePathCStringSize
);
7935 executablePathString
= OSString::withCString(executablePathCString
);
7937 if (!executablePathCString
) {
7941 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
7945 /* UUID, if the kext has one.
7947 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
7950 result
->setObject(kOSBundleUUIDKey
, uuid
);
7955 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
7957 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSKernelResourceKey
)) {
7958 result
->setObject(kOSKernelResourceKey
,
7959 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
7962 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
7963 result
->setObject(kOSBundleIsInterfaceKey
,
7964 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
7967 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
7968 result
->setObject(kOSBundlePrelinkedKey
,
7969 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
7972 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
7973 result
->setObject(kOSBundleStartedKey
,
7974 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
7979 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
7980 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
7981 /* numBits */ 8 * sizeof(loadTag
));
7982 if (!scratchNumber
) {
7985 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
7986 OSSafeReleaseNULL(scratchNumber
);
7989 /* LoadAddress, LoadSize.
7992 _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) ||
7993 _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) ||
7994 _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
))
7996 if (isInterface() || linkedExecutable
) {
7997 /* These go to userspace via serialization, so we don't want any doubts
8000 uint64_t loadAddress
= 0;
8001 uint32_t loadSize
= 0;
8002 uint32_t wiredSize
= 0;
8004 /* Interfaces always report 0 load address & size.
8005 * Just the way they roll.
8007 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
8008 * xxx - shouldn't have one!
8010 if (linkedExecutable
/* && !isInterface() */) {
8011 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
8012 loadAddress
= VM_KERNEL_UNSLIDE(loadAddress
);
8013 loadSize
= linkedExecutable
->getLength();
8015 /* If we have a kmod_info struct, calculated the wired size
8016 * from that. Otherwise it's the full load size.
8019 wiredSize
= loadSize
- kmod_info
->hdr_size
;
8021 wiredSize
= loadSize
;
8025 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
8026 scratchNumber
= OSNumber::withNumber(
8027 (unsigned long long)(loadAddress
),
8028 /* numBits */ 8 * sizeof(loadAddress
));
8029 if (!scratchNumber
) {
8032 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
8033 OSSafeReleaseNULL(scratchNumber
);
8035 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
8036 scratchNumber
= OSNumber::withNumber(
8037 (unsigned long long)(loadSize
),
8038 /* numBits */ 8 * sizeof(loadSize
));
8039 if (!scratchNumber
) {
8042 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
8043 OSSafeReleaseNULL(scratchNumber
);
8045 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
8046 scratchNumber
= OSNumber::withNumber(
8047 (unsigned long long)(wiredSize
),
8048 /* numBits */ 8 * sizeof(wiredSize
));
8049 if (!scratchNumber
) {
8052 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
8053 OSSafeReleaseNULL(scratchNumber
);
8058 /* OSBundleDependencies. In descending order for
8059 * easy compatibility with kextstat(8).
8061 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
8062 if ((count
= getNumDependencies())) {
8063 dependencyLoadTags
= OSArray::withCapacity(count
);
8064 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
8068 OSKext
* dependency
= OSDynamicCast(OSKext
,
8069 dependencies
->getObject(i
));
8071 OSSafeReleaseNULL(scratchNumber
);
8076 scratchNumber
= OSNumber::withNumber(
8077 (unsigned long long)dependency
->getLoadTag(),
8078 /* numBits*/ 8 * sizeof(loadTag
));
8079 if (!scratchNumber
) {
8082 dependencyLoadTags
->setObject(scratchNumber
);
8087 OSSafeReleaseNULL(scratchNumber
);
8089 /* OSBundleMetaClasses.
8091 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) {
8092 if (metaClasses
&& metaClasses
->getCount()) {
8093 metaClassIterator
= OSCollectionIterator::withCollection(metaClasses
);
8094 metaClassInfo
= OSArray::withCapacity(metaClasses
->getCount());
8095 if (!metaClassIterator
|| !metaClassInfo
) {
8098 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
8100 while ( (thisMetaClass
= OSDynamicCast(OSMetaClass
,
8101 metaClassIterator
->getNextObject())) ) {
8103 OSSafeReleaseNULL(metaClassDict
);
8104 OSSafeReleaseNULL(scratchNumber
);
8105 OSSafeReleaseNULL(metaClassName
);
8106 OSSafeReleaseNULL(superclassName
);
8108 metaClassDict
= OSDictionary::withCapacity(3);
8109 if (!metaClassDict
) {
8113 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
8114 if (thisMetaClass
->getSuperClass()) {
8115 superclassName
= OSString::withCString(
8116 thisMetaClass
->getSuperClass()->getClassName());
8118 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
8119 8 * sizeof(unsigned int));
8121 /* Bail if any of the essentials is missing. The root class lacks a superclass,
8124 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
8128 metaClassInfo
->setObject(metaClassDict
);
8129 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
8130 if (superclassName
) {
8131 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
8133 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
8138 /* OSBundleRetainCount.
8140 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
8141 OSSafeReleaseNULL(scratchNumber
);
8143 int kextRetainCount
= getRetainCount() - 1;
8147 scratchNumber
= OSNumber::withNumber(
8148 (int)kextRetainCount
,
8149 /* numBits*/ 8 * sizeof(int));
8150 if (scratchNumber
) {
8151 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
8159 OSSafeRelease(headerData
);
8160 OSSafeRelease(cpuTypeNumber
);
8161 OSSafeRelease(cpuSubtypeNumber
);
8162 OSSafeRelease(executablePathString
);
8163 if (executablePathString
) kfree(executablePathCString
, executablePathCStringSize
);
8164 OSSafeRelease(uuid
);
8165 OSSafeRelease(scratchNumber
);
8166 OSSafeRelease(dependencyLoadTags
);
8167 OSSafeRelease(metaClassIterator
);
8168 OSSafeRelease(metaClassInfo
);
8169 OSSafeRelease(metaClassDict
);
8170 OSSafeRelease(metaClassName
);
8171 OSSafeRelease(superclassName
);
8173 OSSafeReleaseNULL(result
);
8178 /*********************************************************************
8179 *********************************************************************/
8182 OSKext::requestResource(
8183 const char * kextIdentifierCString
,
8184 const char * resourceNameCString
,
8185 OSKextRequestResourceCallback callback
,
8187 OSKextRequestTag
* requestTagOut
)
8189 OSReturn result
= kOSReturnError
;
8190 OSKext
* callbackKext
= NULL
; // must release (looked up)
8192 OSKextRequestTag requestTag
= -1;
8193 OSNumber
* requestTagNum
= NULL
; // must release
8195 OSDictionary
* requestDict
= NULL
; // must release
8196 OSString
* kextIdentifier
= NULL
; // must release
8197 OSString
* resourceName
= NULL
; // must release
8199 OSDictionary
* callbackRecord
= NULL
; // must release
8200 OSData
* callbackWrapper
= NULL
; // must release
8202 OSData
* contextWrapper
= NULL
; // must release
8204 IORecursiveLockLock(sKextLock
);
8206 if (requestTagOut
) {
8207 *requestTagOut
= kOSKextRequestTagInvalid
;
8210 /* If requests to user space are disabled, don't go any further */
8211 if (!sKernelRequestsEnabled
) {
8212 OSKextLog(/* kext */ NULL
,
8213 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8214 "Can't request resource %s for %s - requests to user space are disabled.",
8215 resourceNameCString
,
8216 kextIdentifierCString
);
8217 result
= kOSKextReturnDisabled
;
8221 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
8222 result
= kOSKextReturnInvalidArgument
;
8226 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
8227 if (!callbackKext
) {
8228 OSKextLog(/* kext */ NULL
,
8229 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8230 "Resource request has bad callback address.");
8231 result
= kOSKextReturnInvalidArgument
;
8234 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
8235 OSKextLog(/* kext */ NULL
,
8236 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8237 "Resource request callback is in a kext that is not started.");
8238 result
= kOSKextReturnInvalidArgument
;
8242 /* Do not allow any new requests to be made on a kext that is unloading.
8244 if (callbackKext
->flags
.stopping
) {
8245 result
= kOSKextReturnStopping
;
8249 /* If we're wrapped the next available request tag around to the negative
8250 * numbers, we can't service any more requests.
8252 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
8253 OSKextLog(/* kext */ NULL
,
8254 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8255 "No more request tags available; restart required.");
8256 result
= kOSKextReturnNoResources
;
8259 requestTag
= sNextRequestTag
++;
8261 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
8263 if (result
!= kOSReturnSuccess
) {
8267 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
8268 resourceName
= OSString::withCString(resourceNameCString
);
8269 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
8270 8 * sizeof(requestTag
));
8271 if (!kextIdentifier
||
8274 !_OSKextSetRequestArgument(requestDict
,
8275 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
8276 !_OSKextSetRequestArgument(requestDict
,
8277 kKextRequestArgumentNameKey
, resourceName
) ||
8278 !_OSKextSetRequestArgument(requestDict
,
8279 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
8281 result
= kOSKextReturnNoMemory
;
8285 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
8286 if (!callbackRecord
) {
8287 result
= kOSKextReturnNoMemory
;
8290 // we validate callback address at call time
8291 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
8293 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
8295 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
8296 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
8298 result
= kOSKextReturnNoMemory
;
8303 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
8304 kKextRequestArgumentContextKey
, contextWrapper
)) {
8306 result
= kOSKextReturnNoMemory
;
8311 /* Only post the requests after all the other potential failure points
8314 if (!sKernelRequests
->setObject(requestDict
) ||
8315 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
8317 result
= kOSKextReturnNoMemory
;
8321 OSKext::pingKextd();
8323 result
= kOSReturnSuccess
;
8324 if (requestTagOut
) {
8325 *requestTagOut
= requestTag
;
8330 /* If we didn't succeed, yank the request & callback
8331 * from their holding arrays.
8333 if (result
!= kOSReturnSuccess
) {
8336 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
8337 if (index
!= (unsigned int)-1) {
8338 sKernelRequests
->removeObject(index
);
8340 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
8341 if (index
!= (unsigned int)-1) {
8342 sRequestCallbackRecords
->removeObject(index
);
8346 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8348 IORecursiveLockUnlock(sKextLock
);
8350 if (callbackKext
) callbackKext
->release();
8351 if (requestTagNum
) requestTagNum
->release();
8353 if (requestDict
) requestDict
->release();
8354 if (kextIdentifier
) kextIdentifier
->release();
8355 if (resourceName
) resourceName
->release();
8357 if (callbackRecord
) callbackRecord
->release();
8358 if (callbackWrapper
) callbackWrapper
->release();
8359 if (contextWrapper
) contextWrapper
->release();
8364 /*********************************************************************
8365 * Assumes sKextLock is held.
8366 *********************************************************************/
8369 OSKext::dequeueCallbackForRequestTag(
8370 OSKextRequestTag requestTag
,
8371 OSDictionary
** callbackRecordOut
)
8373 OSReturn result
= kOSReturnError
;
8374 OSNumber
* requestTagNum
= NULL
; // must release
8376 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
8377 8 * sizeof(requestTag
));
8378 if (!requestTagNum
) {
8382 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
8386 OSSafeRelease(requestTagNum
);
8391 /*********************************************************************
8392 * Assumes sKextLock is held.
8393 *********************************************************************/
8396 OSKext::dequeueCallbackForRequestTag(
8397 OSNumber
* requestTagNum
,
8398 OSDictionary
** callbackRecordOut
)
8400 OSReturn result
= kOSKextReturnInvalidArgument
;
8401 OSDictionary
* callbackRecord
= NULL
; // retain if matched!
8402 OSNumber
* callbackTagNum
= NULL
; // do not release
8403 unsigned int count
, i
;
8405 result
= kOSReturnError
;
8406 count
= sRequestCallbackRecords
->getCount();
8407 for (i
= 0; i
< count
; i
++) {
8408 callbackRecord
= OSDynamicCast(OSDictionary
,
8409 sRequestCallbackRecords
->getObject(i
));
8410 if (!callbackRecord
) {
8414 /* If we don't find a tag, we basically have a leak here. Maybe
8415 * we should just remove it.
8417 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
8418 callbackRecord
, kKextRequestArgumentRequestTagKey
));
8419 if (!callbackTagNum
) {
8423 /* We could be even more paranoid and check that all the incoming
8424 * args match what's in the callback record.
8426 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
8427 if (callbackRecordOut
) {
8428 *callbackRecordOut
= callbackRecord
;
8429 callbackRecord
->retain();
8431 sRequestCallbackRecords
->removeObject(i
);
8432 result
= kOSReturnSuccess
;
8436 result
= kOSKextReturnNotFound
;
8442 /*********************************************************************
8443 * Assumes sKextLock is held.
8444 *********************************************************************/
8447 OSKext::dispatchResource(OSDictionary
* requestDict
)
8449 OSReturn result
= kOSReturnError
;
8450 OSDictionary
* callbackRecord
= NULL
; // must release
8451 OSNumber
* requestTag
= NULL
; // do not release
8452 OSNumber
* requestResult
= NULL
; // do not release
8453 OSData
* dataObj
= NULL
; // do not release
8454 uint32_t dataLength
= 0;
8455 const void * dataPtr
= NULL
; // do not free
8456 OSData
* callbackWrapper
= NULL
; // do not release
8457 OSKextRequestResourceCallback callback
= NULL
;
8458 OSData
* contextWrapper
= NULL
; // do not release
8459 void * context
= NULL
; // do not free
8460 OSKext
* callbackKext
= NULL
; // must release (looked up)
8462 /* Get the args from the request. Right now we need the tag
8463 * to look up the callback record, and the result for invoking the callback.
8465 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
8466 kKextRequestArgumentRequestTagKey
));
8467 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
8468 kKextRequestArgumentResultKey
));
8469 if (!requestTag
|| !requestResult
) {
8470 result
= kOSKextReturnInvalidArgument
;
8474 /* Look for a callback record matching this request's tag.
8476 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
8477 if (result
!= kOSReturnSuccess
) {
8482 * Get the context pointer of the callback record (if there is one).
8484 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
8485 kKextRequestArgumentContextKey
));
8486 context
= _OSKextExtractPointer(contextWrapper
);
8487 if (contextWrapper
&& !context
) {
8491 callbackWrapper
= OSDynamicCast(OSData
,
8492 _OSKextGetRequestArgument(callbackRecord
,
8493 kKextRequestArgumentCallbackKey
));
8494 callback
= (OSKextRequestResourceCallback
)
8495 _OSKextExtractPointer(callbackWrapper
);
8500 /* Check for a data obj. We might not have one and that's ok, that means
8501 * we didn't find the requested resource, and we still have to tell the
8502 * caller that via the callback.
8504 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
8505 kKextRequestArgumentValueKey
));
8507 dataPtr
= dataObj
->getBytesNoCopy();
8508 dataLength
= dataObj
->getLength();
8511 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
8512 if (!callbackKext
) {
8513 OSKextLog(/* kext */ NULL
,
8514 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8515 "Can't invoke callback for resource request; ");
8518 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
8519 OSKextLog(/* kext */ NULL
,
8520 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8521 "Can't invoke kext resource callback; ");
8525 (void)callback(requestTag
->unsigned32BitValue(),
8526 (OSReturn
)requestResult
->unsigned32BitValue(),
8527 dataPtr
, dataLength
, context
);
8529 result
= kOSReturnSuccess
;
8532 if (callbackKext
) callbackKext
->release();
8533 if (callbackRecord
) callbackRecord
->release();
8538 /*********************************************************************
8539 *********************************************************************/
8542 OSKext::invokeRequestCallback(
8543 OSDictionary
* callbackRecord
,
8544 OSReturn callbackResult
)
8546 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
8547 OSNumber
* resultNum
= NULL
; // must release
8553 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
8554 8 * sizeof(callbackResult
));
8559 /* Insert the result into the callback record and dispatch it as if it
8560 * were the reply coming down from user space.
8562 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
8565 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
8566 /* This removes the pending callback record.
8568 OSKext::dispatchResource(callbackRecord
);
8572 if (resultNum
) resultNum
->release();
8576 /*********************************************************************
8577 * Assumes sKextLock is held.
8578 *********************************************************************/
8581 OSKext::cancelRequest(
8582 OSKextRequestTag requestTag
,
8585 OSReturn result
= kOSKextReturnNoMemory
;
8586 OSDictionary
* callbackRecord
= NULL
; // must release
8587 OSData
* contextWrapper
= NULL
; // do not release
8589 IORecursiveLockLock(sKextLock
);
8590 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
8592 IORecursiveLockUnlock(sKextLock
);
8594 if (result
== kOSReturnSuccess
&& contextOut
) {
8595 contextWrapper
= OSDynamicCast(OSData
,
8596 _OSKextGetRequestArgument(callbackRecord
,
8597 kKextRequestArgumentContextKey
));
8598 *contextOut
= _OSKextExtractPointer(contextWrapper
);
8601 if (callbackRecord
) callbackRecord
->release();
8606 /*********************************************************************
8607 * Assumes sKextLock is held.
8608 *********************************************************************/
8610 OSKext::invokeOrCancelRequestCallbacks(
8611 OSReturn callbackResult
,
8614 unsigned int count
, i
;
8616 count
= sRequestCallbackRecords
->getCount();
8623 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
8624 sRequestCallbackRecords
->getObject(i
));
8629 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
8630 _OSKextGetRequestArgument(request
,
8631 kKextRequestArgumentCallbackKey
));
8633 if (!callbackWrapper
) {
8634 sRequestCallbackRecords
->removeObject(i
);
8638 vm_address_t callbackAddress
= (vm_address_t
)
8639 _OSKextExtractPointer(callbackWrapper
);
8641 if ((kmod_info
->address
<= callbackAddress
) &&
8642 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
8645 /* This removes the callback record.
8647 invokeRequestCallback(request
, callbackResult
);
8649 sRequestCallbackRecords
->removeObject(i
);
8658 /*********************************************************************
8659 * Assumes sKextLock is held.
8660 *********************************************************************/
8662 OSKext::countRequestCallbacks(void)
8664 uint32_t result
= 0;
8665 unsigned int count
, i
;
8667 count
= sRequestCallbackRecords
->getCount();
8674 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
8675 sRequestCallbackRecords
->getObject(i
));
8680 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
8681 _OSKextGetRequestArgument(request
,
8682 kKextRequestArgumentCallbackKey
));
8684 if (!callbackWrapper
) {
8688 vm_address_t callbackAddress
= (vm_address_t
)
8689 _OSKextExtractPointer(callbackWrapper
);
8691 if ((kmod_info
->address
<= callbackAddress
) &&
8692 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
8702 /*********************************************************************
8703 *********************************************************************/
8704 static OSReturn
_OSKextCreateRequest(
8705 const char * predicate
,
8706 OSDictionary
** requestP
)
8708 OSReturn result
= kOSKextReturnNoMemory
;
8709 OSDictionary
* request
= NULL
; // must release on error
8711 request
= OSDictionary::withCapacity(2);
8715 result
= _OSDictionarySetCStringValue(request
,
8716 kKextRequestPredicateKey
, predicate
);
8717 if (result
!= kOSReturnSuccess
) {
8720 result
= kOSReturnSuccess
;
8723 if (result
!= kOSReturnSuccess
) {
8724 if (request
) request
->release();
8726 *requestP
= request
;
8732 /*********************************************************************
8733 *********************************************************************/
8734 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
8736 return OSDynamicCast(OSString
,
8737 requestDict
->getObject(kKextRequestPredicateKey
));
8740 /*********************************************************************
8741 *********************************************************************/
8742 static OSObject
* _OSKextGetRequestArgument(
8743 OSDictionary
* requestDict
,
8744 const char * argName
)
8746 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
8747 requestDict
->getObject(kKextRequestArgumentsKey
));
8749 return args
->getObject(argName
);
8754 /*********************************************************************
8755 *********************************************************************/
8756 static bool _OSKextSetRequestArgument(
8757 OSDictionary
* requestDict
,
8758 const char * argName
,
8761 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
8762 requestDict
->getObject(kKextRequestArgumentsKey
));
8764 args
= OSDictionary::withCapacity(2);
8768 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
8772 return args
->setObject(argName
, value
);
8778 /*********************************************************************
8779 *********************************************************************/
8780 static void * _OSKextExtractPointer(OSData
* wrapper
)
8782 void * result
= NULL
;
8783 const void * resultPtr
= NULL
;
8788 resultPtr
= wrapper
->getBytesNoCopy();
8789 result
= *(void **)resultPtr
;
8794 /*********************************************************************
8795 *********************************************************************/
8796 static OSReturn
_OSDictionarySetCStringValue(
8797 OSDictionary
* dict
,
8799 const char * cValue
)
8801 OSReturn result
= kOSKextReturnNoMemory
;
8802 const OSSymbol
* key
= NULL
; // must release
8803 OSString
* value
= NULL
; // must release
8805 key
= OSSymbol::withCString(cKey
);
8806 value
= OSString::withCString(cValue
);
8807 if (!key
|| !value
) {
8810 if (dict
->setObject(key
, value
)) {
8811 result
= kOSReturnSuccess
;
8815 if (key
) key
->release();
8816 if (value
) value
->release();
8821 /*********************************************************************
8822 *********************************************************************/
8823 static bool _OSArrayContainsCString(
8825 const char * cString
)
8827 bool result
= false;
8828 const OSSymbol
* symbol
= NULL
;
8831 if (!array
|| !cString
) {
8835 symbol
= OSSymbol::withCStringNoCopy(cString
);
8840 count
= array
->getCount();
8841 for (i
= 0; i
< count
; i
++) {
8842 OSObject
* thisObject
= array
->getObject(i
);
8843 if (symbol
->isEqualTo(thisObject
)) {
8850 if (symbol
) symbol
->release();
8854 /*********************************************************************
8855 * We really only care about boot / system start up related kexts.
8856 * We return true if we're less than REBUILD_MAX_TIME since start up,
8857 * otherwise return false.
8858 *********************************************************************/
8859 bool _OSKextInPrelinkRebuildWindow(void)
8861 static bool outside_the_window
= false;
8862 AbsoluteTime my_abstime
;
8866 if (outside_the_window
) {
8869 clock_get_uptime(&my_abstime
);
8870 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
8871 my_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
8872 if (my_secs
> REBUILD_MAX_TIME
) {
8873 outside_the_window
= true;
8879 /*********************************************************************
8880 *********************************************************************/
8881 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
8883 int unLoadedCount
, i
;
8884 bool result
= false;
8886 IORecursiveLockLock(sKextLock
);
8888 if (sUnloadedPrelinkedKexts
== NULL
) {
8891 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
8892 if (unLoadedCount
== 0) {
8896 for (i
= 0; i
< unLoadedCount
; i
++) {
8897 const OSSymbol
* myBundleID
; // do not release
8899 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
8900 if (!myBundleID
) continue;
8901 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
8907 IORecursiveLockUnlock(sKextLock
);
8912 #pragma mark Personalities (IOKit Drivers)
8914 /*********************************************************************
8915 *********************************************************************/
8918 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
8920 OSArray
* result
= NULL
; // returned
8921 OSCollectionIterator
* kextIterator
= NULL
; // must release
8922 OSArray
* personalities
= NULL
; // must release
8923 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
8925 OSString
* kextID
= NULL
; // do not release
8926 OSKext
* theKext
= NULL
; // do not release
8928 IORecursiveLockLock(sKextLock
);
8930 /* Let's conservatively guess that any given kext has around 3
8931 * personalities for now.
8933 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
8938 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
8939 if (!kextIterator
) {
8943 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
8944 if (personalitiesIterator
) {
8945 personalitiesIterator
->release();
8946 personalitiesIterator
= NULL
;
8948 if (personalities
) {
8949 personalities
->release();
8950 personalities
= NULL
;
8953 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
8954 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
8955 personalities
= theKext
->copyPersonalitiesArray();
8956 if (!personalities
) {
8959 result
->merge(personalities
);
8961 // xxx - check for better place to put this log msg
8963 kOSKextLogWarningLevel
|
8965 "Kext %s is not loadable during safe boot; "
8966 "omitting its personalities.",
8967 theKext
->getIdentifierCString());
8973 IORecursiveLockUnlock(sKextLock
);
8975 if (kextIterator
) kextIterator
->release();
8976 if (personalitiesIterator
) personalitiesIterator
->release();
8977 if (personalities
) personalities
->release();
8982 /*********************************************************************
8983 *********************************************************************/
8986 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
8988 int numPersonalities
= 0;
8990 OSKextLog(/* kext */ NULL
,
8991 kOSKextLogStepLevel
|
8993 "Sending all eligible registered kexts' personalities "
8994 "to the IOCatalogue %s.",
8995 startMatching
? "and starting matching" : "but not starting matching");
8997 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
8998 /* filterSafeBootFlag */ true);
9000 if (personalities
) {
9001 gIOCatalogue
->addDrivers(personalities
, startMatching
);
9002 numPersonalities
= personalities
->getCount();
9003 personalities
->release();
9006 OSKextLog(/* kext */ NULL
,
9007 kOSKextLogStepLevel
|
9009 "%d kext personalit%s sent to the IOCatalogue; %s.",
9010 numPersonalities
, numPersonalities
> 0 ? "ies" : "y",
9011 startMatching
? "matching started" : "matching not started");
9015 /*********************************************************************
9016 * Do not make a deep copy, just convert the IOKitPersonalities dict
9017 * to an array for sending to the IOCatalogue.
9018 *********************************************************************/
9020 OSKext::copyPersonalitiesArray(void)
9022 OSArray
* result
= NULL
;
9023 OSDictionary
* personalities
= NULL
; // do not release
9024 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
9026 OSString
* personalityName
= NULL
; // do not release
9027 OSString
* personalityBundleIdentifier
= NULL
; // do not release
9029 personalities
= OSDynamicCast(OSDictionary
,
9030 getPropertyForHostArch(kIOKitPersonalitiesKey
));
9031 if (!personalities
) {
9035 result
= OSArray::withCapacity(personalities
->getCount());
9040 personalitiesIterator
=
9041 OSCollectionIterator::withCollection(personalities
);
9042 if (!personalitiesIterator
) {
9045 while ((personalityName
= OSDynamicCast(OSString
,
9046 personalitiesIterator
->getNextObject()))) {
9048 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
9049 personalities
->getObject(personalityName
));
9052 * If the personality doesn't have a CFBundleIdentifier, or if it
9053 * differs from the kext's, insert the kext's ID so we can find it.
9054 * The publisher ID is used to remove personalities from bundles
9057 personalityBundleIdentifier
= OSDynamicCast(OSString
,
9058 personality
->getObject(kCFBundleIdentifierKey
));
9060 if (!personalityBundleIdentifier
) {
9061 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
9062 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
9063 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
9066 result
->setObject(personality
);
9070 if (personalitiesIterator
) personalitiesIterator
->release();
9075 /*********************************************************************
9076 Might want to change this to a bool return?
9077 *********************************************************************/
9079 OSKext::sendPersonalitiesToCatalog(
9081 OSArray
* personalityNames
)
9083 OSReturn result
= kOSReturnSuccess
;
9084 OSArray
* personalitiesToSend
= NULL
; // must release
9085 OSDictionary
* kextPersonalities
= NULL
; // do not release
9088 if (!sLoadEnabled
) {
9090 kOSKextLogErrorLevel
|
9092 "Kext loading is disabled (attempt to start matching for kext %s).",
9093 getIdentifierCString());
9094 result
= kOSKextReturnDisabled
;
9098 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
9100 kOSKextLogErrorLevel
|
9102 "Kext %s is not loadable during safe boot; "
9103 "not sending personalities to the IOCatalogue.",
9104 getIdentifierCString());
9105 result
= kOSKextReturnNotLoadable
;
9109 if (!personalityNames
|| !personalityNames
->getCount()) {
9110 personalitiesToSend
= copyPersonalitiesArray();
9112 kextPersonalities
= OSDynamicCast(OSDictionary
,
9113 getPropertyForHostArch(kIOKitPersonalitiesKey
));
9114 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
9118 personalitiesToSend
= OSArray::withCapacity(0);
9119 if (!personalitiesToSend
) {
9120 result
= kOSKextReturnNoMemory
;
9123 count
= personalityNames
->getCount();
9124 for (i
= 0; i
< count
; i
++) {
9125 OSString
* name
= OSDynamicCast(OSString
,
9126 personalityNames
->getObject(i
));
9130 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
9131 kextPersonalities
->getObject(name
));
9133 personalitiesToSend
->setObject(personality
);
9137 if (personalitiesToSend
) {
9138 unsigned numPersonalities
= personalitiesToSend
->getCount();
9140 kOSKextLogStepLevel
|
9142 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
9143 getIdentifierCString(),
9145 numPersonalities
> 1 ? "ies" : "y",
9146 startMatching
? " and starting matching" : " but not starting matching");
9147 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
9150 if (personalitiesToSend
) {
9151 personalitiesToSend
->release();
9156 /*********************************************************************
9157 * xxx - We should allow removing the kext's declared personalities,
9158 * xxx - even with other bundle identifiers.
9159 *********************************************************************/
9161 OSKext::removePersonalitiesFromCatalog(void)
9163 OSDictionary
* personality
= NULL
; // do not release
9165 personality
= OSDictionary::withCapacity(1);
9169 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
9172 kOSKextLogStepLevel
|
9174 "Kext %s removing all personalities naming it from the IOCatalogue.",
9175 getIdentifierCString());
9177 /* Have the IOCatalog remove all personalities matching this kext's
9178 * bundle ID and trigger matching anew.
9180 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
9183 if (personality
) personality
->release();
9190 #pragma mark Logging
9192 /*********************************************************************
9193 * Do not call any function that takes sKextLock here!
9194 *********************************************************************/
9197 OSKext::setUserSpaceLogFilter(
9198 OSKextLogSpec newUserLogFilter
,
9201 OSKextLogSpec result
;
9202 bool allocError
= false;
9204 /* Do not call any function that takes sKextLoggingLock during
9205 * this critical block. That means do logging after.
9207 IOLockLock(sKextLoggingLock
);
9209 result
= sUserSpaceKextLogFilter
;
9210 sUserSpaceKextLogFilter
= newUserLogFilter
;
9212 if (newUserLogFilter
&& captureFlag
&&
9213 !sUserSpaceLogSpecArray
&& !sUserSpaceLogMessageArray
) {
9215 // xxx - do some measurements for a good initial capacity?
9216 sUserSpaceLogSpecArray
= OSArray::withCapacity(0);
9217 sUserSpaceLogMessageArray
= OSArray::withCapacity(0);
9219 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
9220 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
9221 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
9226 IOLockUnlock(sKextLoggingLock
);
9228 /* If the config flag itself is changing, log the state change
9229 * going both ways, before setting up the user-space log arrays,
9230 * so that this is only logged in the kernel.
9232 if (result
!= newUserLogFilter
) {
9233 OSKextLog(/* kext */ NULL
,
9234 kOSKextLogDebugLevel
|
9235 kOSKextLogGeneralFlag
,
9236 "User-space log flags changed from 0x%x to 0x%x.",
9237 result
, newUserLogFilter
);
9240 OSKextLog(/* kext */ NULL
,
9241 kOSKextLogErrorLevel
|
9242 kOSKextLogGeneralFlag
,
9243 "Failed to allocate user-space log message arrays.");
9249 /*********************************************************************
9250 * Do not call any function that takes sKextLock here!
9251 *********************************************************************/
9254 OSKext::clearUserSpaceLogFilter(void)
9256 OSArray
* result
= NULL
;
9257 OSKextLogSpec oldLogFilter
;
9258 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
9260 /* Do not call any function that takes sKextLoggingLock during
9261 * this critical block. That means do logging after.
9263 IOLockLock(sKextLoggingLock
);
9265 result
= OSArray::withCapacity(2);
9267 result
->setObject(sUserSpaceLogSpecArray
);
9268 result
->setObject(sUserSpaceLogMessageArray
);
9270 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
9271 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
9273 oldLogFilter
= sUserSpaceKextLogFilter
;
9274 sUserSpaceKextLogFilter
= newLogFilter
;
9276 IOLockUnlock(sKextLoggingLock
);
9278 /* If the config flag itself is changing, log the state change
9279 * going both ways, after tearing down the user-space log
9280 * arrays, so this is only logged within the kernel.
9282 if (oldLogFilter
!= newLogFilter
) {
9283 OSKextLog(/* kext */ NULL
,
9284 kOSKextLogDebugLevel
|
9285 kOSKextLogGeneralFlag
,
9286 "User-space log flags changed from 0x%x to 0x%x.",
9287 oldLogFilter
, newLogFilter
);
9294 /*********************************************************************
9295 * Do not call any function that takes sKextLock here!
9296 *********************************************************************/
9299 OSKext::getUserSpaceLogFilter(void)
9301 OSKextLogSpec result
;
9303 IOLockLock(sKextLoggingLock
);
9304 result
= sUserSpaceKextLogFilter
;
9305 IOLockUnlock(sKextLoggingLock
);
9310 /*********************************************************************
9311 * This function is called by OSMetaClass during kernel C++ setup.
9312 * Be careful what you access here; assume only OSKext::initialize()
9315 * Do not call any function that takes sKextLock here!
9316 *********************************************************************/
9317 #define VTRESET "\033[0m"
9319 #define VTBOLD "\033[1m"
9320 #define VTUNDER "\033[4m"
9322 #define VTRED "\033[31m"
9323 #define VTGREEN "\033[32m"
9324 #define VTYELLOW "\033[33m"
9325 #define VTBLUE "\033[34m"
9326 #define VTMAGENTA "\033[35m"
9327 #define VTCYAN "\033[36m"
9329 inline const char * colorForFlags(OSKextLogSpec flags
)
9331 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
9334 case kOSKextLogErrorLevel
:
9335 return VTRED VTBOLD
;
9337 case kOSKextLogWarningLevel
:
9340 case kOSKextLogBasicLevel
:
9341 return VTYELLOW VTUNDER
;
9343 case kOSKextLogProgressLevel
:
9346 case kOSKextLogStepLevel
:
9349 case kOSKextLogDetailLevel
:
9352 case kOSKextLogDebugLevel
:
9362 inline bool logSpecMatch(
9363 OSKextLogSpec msgLogSpec
,
9364 OSKextLogSpec logFilter
)
9366 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
9367 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
9368 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
9370 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
9371 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
9372 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
9374 /* Explicit messages always get logged.
9376 if (msgLevel
== kOSKextLogExplicitLevel
) {
9380 /* Warnings and errors are logged regardless of the flags.
9382 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
9386 /* A verbose message that isn't for a logging-enabled kext and isn't global
9387 * does *not* get logged.
9389 if (!msgKextGlobal
&& !filterKextGlobal
) {
9393 /* Warnings and errors are logged regardless of the flags.
9394 * All other messages must fit the flags and
9395 * have a level at or below the filter.
9398 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
9409 OSKextLogSpec msgLogSpec
,
9410 const char * format
, ...)
9414 va_start(argList
, format
);
9415 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
9422 OSKextLogSpec msgLogSpec
,
9423 const char * format
,
9426 extern int disableConsoleOutput
;
9428 bool logForKernel
= false;
9429 bool logForUser
= false;
9431 char stackBuffer
[120];
9432 uint32_t length
= 0;
9433 char * allocBuffer
= NULL
; // must kfree
9434 OSNumber
* logSpecNum
= NULL
; // must release
9435 OSString
* logString
= NULL
; // must release
9436 char * buffer
= stackBuffer
; // do not free
9438 IOLockLock(sKextLoggingLock
);
9440 /* Set the kext/global bit in the message spec if we have no
9441 * kext or if the kext requests logging.
9443 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
9444 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
9447 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
9448 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
9449 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
9452 if (! (logForKernel
|| logForUser
) ) {
9456 /* No goto from here until past va_end()!
9458 va_copy(argList
, srcArgList
);
9459 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
9462 if (length
+ 1 >= sizeof(stackBuffer
)) {
9463 allocBuffer
= (char *)kalloc((length
+ 1) * sizeof(char));
9468 /* No goto from here until past va_end()!
9470 va_copy(argList
, srcArgList
);
9471 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
9474 buffer
= allocBuffer
;
9477 /* If user space wants the log message, queue it up.
9479 if (logForUser
&& sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
9480 logSpecNum
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
));
9481 logString
= OSString::withCString(buffer
);
9482 if (logSpecNum
&& logString
) {
9483 sUserSpaceLogSpecArray
->setObject(logSpecNum
);
9484 sUserSpaceLogMessageArray
->setObject(logString
);
9488 /* Always log messages from the kernel according to the kernel's
9493 /* If we are in console mode and have a custom log filter,
9494 * colorize the log message.
9496 if (!disableConsoleOutput
&& sBootArgLogFilterFound
) {
9497 const char * color
= ""; // do not free
9498 color
= colorForFlags(msgLogSpec
);
9499 printf("%s%s%s\n", colorForFlags(msgLogSpec
),
9500 buffer
, color
[0] ? VTRESET
: "");
9502 printf("%s\n", buffer
);
9507 IOLockUnlock(sKextLoggingLock
);
9510 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
9512 OSSafeRelease(logString
);
9513 OSSafeRelease(logSpecNum
);
9517 #if KASLR_IOREG_DEBUG
9519 #define IOLOG_INDENT( the_indention ) \
9522 for ( i = 0; i < (the_indention); i++ ) { \
9527 extern vm_offset_t vm_kernel_stext
;
9528 extern vm_offset_t vm_kernel_etext
;
9529 extern mach_vm_offset_t kext_alloc_base
;
9530 extern mach_vm_offset_t kext_alloc_max
;
9532 bool ScanForAddrInObject(OSObject
* theObject
,
9535 bool ScanForAddrInObject(OSObject
* theObject
,
9538 const OSMetaClass
* myTypeID
;
9539 OSCollectionIterator
* myIter
;
9542 bool myResult
= false;
9544 if ( theObject
== NULL
) {
9545 IOLog("%s: theObject is NULL \n",
9550 myTypeID
= OSTypeIDInst(theObject
);
9552 if ( myTypeID
== OSTypeID(OSDictionary
) ) {
9553 OSDictionary
* myDictionary
;
9555 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
9556 myIter
= OSCollectionIterator::withCollection( myDictionary
);
9557 if ( myIter
== NULL
)
9561 while ( (myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject())) ) {
9564 myValue
= myDictionary
->getObject(myKey
);
9565 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
9567 // if we ever get a true result return true
9569 IOLOG_INDENT(indent
);
9570 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
9575 else if ( myTypeID
== OSTypeID(OSArray
) ) {
9578 myArray
= OSDynamicCast(OSArray
, theObject
);
9579 myIter
= OSCollectionIterator::withCollection(myArray
);
9580 if ( myIter
== NULL
)
9584 while ( (myValue
= myIter
->getNextObject()) ) {
9586 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
9588 // if we ever get a true result return true
9590 IOLOG_INDENT(indent
);
9591 IOLog("OSArray: \n");
9596 else if ( myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
) ) {
9598 // should we look for addresses in strings?
9600 else if ( myTypeID
== OSTypeID(OSData
) ) {
9606 myDataObj
= OSDynamicCast(OSData
, theObject
);
9607 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
9608 myLen
= myDataObj
->getLength();
9610 if (myPtrPtr
&& myLen
&& myLen
> 7) {
9612 int myPtrCount
= (myLen
/ sizeof(void *));
9614 for (i
= 0; i
< myPtrCount
; i
++) {
9615 UInt64 numberValue
= (UInt64
) *(myPtrPtr
);
9617 if ( kext_alloc_max
!= 0 &&
9618 numberValue
>= kext_alloc_base
&&
9619 numberValue
< kext_alloc_max
) {
9621 OSKext
* myKext
= NULL
; // must release (looked up)
9622 // IOLog("found OSData %p in kext map %p to %p \n",
9624 // (void *) kext_alloc_base,
9625 // (void *) kext_alloc_max);
9627 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) *(myPtrPtr
) );
9629 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
9631 myKext
->getIdentifierCString());
9636 if ( vm_kernel_etext
!= 0 &&
9637 numberValue
>= vm_kernel_stext
&&
9638 numberValue
< vm_kernel_etext
) {
9639 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
9641 (void *) vm_kernel_stext
,
9642 (void *) vm_kernel_etext
);
9649 else if ( myTypeID
== OSTypeID(OSBoolean
) ) {
9651 // do nothing here...
9653 else if ( myTypeID
== OSTypeID(OSNumber
) ) {
9655 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
9657 UInt64 numberValue
= number
->unsigned64BitValue();
9659 if ( kext_alloc_max
!= 0 &&
9660 numberValue
>= kext_alloc_base
&&
9661 numberValue
< kext_alloc_max
) {
9663 OSKext
* myKext
= NULL
; // must release (looked up)
9664 IOLog("found OSNumber in kext map %p to %p \n",
9665 (void *) kext_alloc_base
,
9666 (void *) kext_alloc_max
);
9667 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
9669 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) numberValue
);
9671 IOLog("found in kext \"%s\" \n",
9672 myKext
->getIdentifierCString());
9678 if ( vm_kernel_etext
!= 0 &&
9679 numberValue
>= vm_kernel_stext
&&
9680 numberValue
< vm_kernel_etext
) {
9681 IOLog("found OSNumber in kernel text segment %p to %p \n",
9682 (void *) vm_kernel_stext
,
9683 (void *) vm_kernel_etext
);
9684 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
9690 const OSMetaClass
* myMetaClass
= NULL
;
9692 myMetaClass
= theObject
->getMetaClass();
9693 if ( myMetaClass
) {
9694 IOLog("class %s \n", myMetaClass
->getClassName() );
9697 IOLog("Unknown object \n" );
9704 #endif // KASLR_KEXT_DEBUG
9709 #pragma mark Backtrace Dump & kmod_get_info() support
9711 /*********************************************************************
9712 * This function must be safe to call in panic context.
9713 *********************************************************************/
9716 OSKext::printKextsInBacktrace(
9719 int (* printf_func
)(const char *fmt
, ...),
9723 addr64_t summary_page
= 0;
9724 addr64_t last_summary_page
= 0;
9725 bool found_kmod
= false;
9729 IOLockLock(sKextSummariesLock
);
9732 if (!gLoadedKextSummaries
) {
9733 (*printf_func
)(" can't perform kext scan: no kext summary");
9737 summary_page
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
);
9738 last_summary_page
= round_page(summary_page
+ sLoadedKextSummariesAllocSize
);
9739 for (; summary_page
< last_summary_page
; summary_page
+= PAGE_SIZE
) {
9740 if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) {
9741 (*printf_func
)(" can't perform kext scan: "
9742 "missing kext summary page %p", summary_page
);
9747 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
9748 OSKextLoadedKextSummary
* summary
;
9750 summary
= gLoadedKextSummaries
->summaries
+ i
;
9751 if (!summary
->address
) {
9755 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
9760 (*printf_func
)(" Kernel Extensions in backtrace:\n");
9764 printSummary(summary
, printf_func
, doUnslide
);
9769 IOLockUnlock(sKextSummariesLock
);
9775 /*********************************************************************
9776 * This function must be safe to call in panic context.
9777 *********************************************************************/
9780 OSKext::summaryIsInBacktrace(
9781 OSKextLoadedKextSummary
* summary
,
9787 for (i
= 0; i
< cnt
; i
++) {
9788 vm_offset_t kscan_addr
= addr
[i
];
9789 if ((kscan_addr
>= summary
->address
) &&
9790 (kscan_addr
< (summary
->address
+ summary
->size
)))
9799 /*********************************************************************
9800 * scan list of loaded kext summaries looking for a load address match and if
9801 * found return the UUID C string. If not found then set empty string.
9802 *********************************************************************/
9803 static void findSummaryUUID(
9805 uuid_string_t uuid
);
9807 static void findSummaryUUID(
9813 uuid
[0] = 0x00; // default to no UUID
9815 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
9816 OSKextLoadedKextSummary
* summary
;
9818 summary
= gLoadedKextSummaries
->summaries
+ i
;
9820 if (summary
->loadTag
== tag_ID
) {
9821 (void) uuid_unparse(summary
->uuid
, uuid
);
9828 /*********************************************************************
9829 * This function must be safe to call in panic context.
9830 *********************************************************************/
9831 void OSKext::printSummary(
9832 OSKextLoadedKextSummary
* summary
,
9833 int (* printf_func
)(const char *fmt
, ...),
9836 kmod_reference_t
* kmod_ref
= NULL
;
9838 char version
[kOSKextVersionMaxLength
];
9841 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
9842 strlcpy(version
, "unknown version", sizeof(version
));
9844 (void) uuid_unparse(summary
->uuid
, uuid
);
9847 tmpAddr
= VM_KERNEL_UNSLIDE(summary
->address
);
9850 tmpAddr
= summary
->address
;
9852 (*printf_func
)(" %s(%s)[%s]@0x%llx->0x%llx\n",
9853 summary
->name
, version
, uuid
,
9854 tmpAddr
, tmpAddr
+ summary
->size
- 1);
9856 /* print dependency info */
9857 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
9859 kmod_ref
= kmod_ref
->next
) {
9860 kmod_info_t
* rinfo
;
9862 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) {
9863 (*printf_func
)(" kmod dependency scan stopped "
9864 "due to missing dependency page: %p\n", kmod_ref
);
9867 rinfo
= kmod_ref
->info
;
9869 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) {
9870 (*printf_func
)(" kmod dependency scan stopped "
9871 "due to missing kmod page: %p\n", rinfo
);
9875 if (!rinfo
->address
) {
9876 continue; // skip fake entries for built-ins
9879 /* locate UUID in gLoadedKextSummaries */
9880 findSummaryUUID(rinfo
->id
, uuid
);
9883 tmpAddr
= VM_KERNEL_UNSLIDE(rinfo
->address
);
9886 tmpAddr
= rinfo
->address
;
9888 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
9889 rinfo
->name
, rinfo
->version
, uuid
, tmpAddr
);
9895 /*******************************************************************************
9896 * substitute() looks at an input string (a pointer within a larger buffer)
9897 * for a match to a substring, and on match it writes the marker & substitution
9898 * character to an output string, updating the scan (from) and
9899 * output (to) indexes as appropriate.
9900 *******************************************************************************/
9901 static int substitute(
9902 const char * scan_string
,
9904 uint32_t * to_index
,
9905 uint32_t * from_index
,
9906 const char * substring
,
9910 /* string_out must be at least KMOD_MAX_NAME bytes.
9914 const char * scan_string
,
9916 uint32_t * to_index
,
9917 uint32_t * from_index
,
9918 const char * substring
,
9922 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
9924 /* On a substring match, append the marker (if there is one) and then
9925 * the substitution character, updating the output (to) index accordingly.
9926 * Then update the input (from) length by the length of the substring
9927 * that got replaced.
9929 if (!strncmp(scan_string
, substring
, substring_length
)) {
9931 string_out
[(*to_index
)++] = marker
;
9933 string_out
[(*to_index
)++] = substitution
;
9934 (*from_index
) += substring_length
;
9940 /*******************************************************************************
9941 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
9942 * KMOD_MAX_NAME characters and performs various substitutions of common
9943 * prefixes & substrings as defined by tables in kext_panic_report.h.
9944 *******************************************************************************/
9945 static void compactIdentifier(
9946 const char * identifier
,
9947 char * identifier_out
,
9948 char ** identifier_out_end
);
9952 const char * identifier
,
9953 char * identifier_out
,
9954 char ** identifier_out_end
)
9956 uint32_t from_index
, to_index
;
9957 uint32_t scan_from_index
= 0;
9958 uint32_t scan_to_index
= 0;
9959 subs_entry_t
* subs_entry
= NULL
;
9962 from_index
= to_index
= 0;
9963 identifier_out
[0] = '\0';
9965 /* Replace certain identifier prefixes with shorter @+character sequences.
9966 * Check the return value of substitute() so we only replace the prefix.
9968 for (subs_entry
= &kext_identifier_prefix_subs
[0];
9969 subs_entry
->substring
&& !did_sub
;
9972 did_sub
= substitute(identifier
, identifier_out
,
9973 &scan_to_index
, &scan_from_index
,
9974 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
9978 /* Now scan through the identifier looking for the common substrings
9979 * and replacing them with shorter !+character sequences via substitute().
9981 for (/* see above */;
9982 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
9985 const char * scan_string
= &identifier
[scan_from_index
];
9989 if (scan_from_index
) {
9990 for (subs_entry
= &kext_identifier_substring_subs
[0];
9991 subs_entry
->substring
&& !did_sub
;
9994 did_sub
= substitute(scan_string
, identifier_out
,
9995 &scan_to_index
, &scan_from_index
,
9996 subs_entry
->substring
, '!', subs_entry
->substitute
);
10000 /* If we didn't substitute, copy the input character to the output.
10003 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
10007 identifier_out
[scan_to_index
] = '\0';
10008 if (identifier_out_end
) {
10009 *identifier_out_end
= &identifier_out
[scan_to_index
];
10015 /*******************************************************************************
10016 * assemble_identifier_and_version() adds to a string buffer a compacted
10017 * bundle identifier followed by a version string.
10018 *******************************************************************************/
10020 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
10022 static int assemble_identifier_and_version(
10023 kmod_info_t
* kmod_info
,
10024 char * identPlusVers
,
10028 assemble_identifier_and_version(
10029 kmod_info_t
* kmod_info
,
10030 char * identPlusVers
,
10035 compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
);
10036 result
= strnlen(identPlusVers
, KMOD_MAX_NAME
- 1);
10037 identPlusVers
[result
++] = '\t'; // increment for real char
10038 identPlusVers
[result
] = '\0'; // don't increment for nul char
10039 result
= strlcat(identPlusVers
, kmod_info
->version
, bufSize
);
10040 if (result
>= bufSize
) {
10041 identPlusVers
[bufSize
- 1] = '\0';
10042 result
= bufSize
- 1;
10048 /*******************************************************************************
10049 * Assumes sKextLock is held.
10050 *******************************************************************************/
10053 OSKext::saveLoadedKextPanicListTyped(
10054 const char * prefix
,
10058 uint32_t list_size
)
10061 unsigned int count
, i
;
10063 count
= sLoadedKexts
->getCount();
10070 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
10071 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
10073 uint32_t identPlusVersLength
;
10075 char identPlusVers
[2*KMOD_MAX_NAME
];
10078 printf("OSKext::saveLoadedKextPanicListTyped - "
10079 "NULL kext in loaded kext list; continuing\n");
10084 printf("OSKext::saveLoadedKextPanicListTyped - "
10085 "Kext type cast failed in loaded kext list; continuing\n");
10089 /* Skip all built-in kexts.
10091 if (theKext
->isKernelComponent()) {
10095 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
10097 /* Filter for kmod name (bundle identifier).
10099 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
10100 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
10104 /* Filter for libraries (kexts that have a compatible version).
10106 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
10107 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
10113 !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) {
10115 printf("kext scan stopped due to missing kmod_info page: %p\n",
10120 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
10122 sizeof(identPlusVers
));
10123 if (!identPlusVersLength
) {
10124 printf("error saving loaded kext info\n");
10128 /* make sure everything fits and we null terminate.
10130 tempLen
= strlcat(paniclist
, identPlusVers
, list_size
);
10131 if (tempLen
>= list_size
) {
10132 // panic list is full, keep it and null terminate
10133 paniclist
[list_size
- 1] = 0x00;
10137 tempLen
= strlcat(paniclist
, "\n", list_size
);
10138 if (tempLen
>= list_size
) {
10139 // panic list is full, keep it and null terminate
10140 paniclist
[list_size
- 1] = 0x00;
10152 /*********************************************************************
10153 *********************************************************************/
10156 OSKext::saveLoadedKextPanicList(void)
10158 char * newlist
= NULL
;
10159 uint32_t newlist_size
= 0;
10161 newlist_size
= KEXT_PANICLIST_SIZE
;
10162 newlist
= (char *)kalloc(newlist_size
);
10165 OSKextLog(/* kext */ NULL
,
10166 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
10167 "Couldn't allocate kext panic log buffer.");
10173 // non-"com.apple." kexts
10174 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
10175 /* libs? */ -1, newlist
, newlist_size
) != 0) {
10179 // "com.apple." nonlibrary kexts
10180 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10181 /* libs? */ 0, newlist
, newlist_size
) != 0) {
10185 // "com.apple." library kexts
10186 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10187 /* libs? */ 1, newlist
, newlist_size
) != 0) {
10192 if (loaded_kext_paniclist
) {
10193 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
10195 loaded_kext_paniclist
= newlist
;
10197 loaded_kext_paniclist_size
= newlist_size
;
10201 kfree(newlist
, newlist_size
);
10206 /*********************************************************************
10207 * Assumes sKextLock is held.
10208 *********************************************************************/
10210 OSKext::savePanicString(bool isLoading
)
10215 return; // do not goto finish here b/c of lock
10218 len
= assemble_identifier_and_version( kmod_info
,
10219 (isLoading
) ? last_loaded_str_buf
: last_unloaded_str_buf
,
10220 (isLoading
) ? sizeof(last_loaded_str_buf
) : sizeof(last_unloaded_str_buf
) );
10222 printf("error saving unloaded kext info\n");
10227 last_loaded_strlen
= len
;
10228 last_loaded_address
= (void *)kmod_info
->address
;
10229 last_loaded_size
= kmod_info
->size
;
10230 clock_get_uptime(&last_loaded_timestamp
);
10232 last_unloaded_strlen
= len
;
10233 last_unloaded_address
= (void *)kmod_info
->address
;
10234 last_unloaded_size
= kmod_info
->size
;
10235 clock_get_uptime(&last_unloaded_timestamp
);
10242 /*********************************************************************
10243 *********************************************************************/
10246 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
10248 if (last_loaded_strlen
) {
10249 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
10250 AbsoluteTime_to_scalar(&last_loaded_timestamp
),
10251 last_loaded_strlen
, last_loaded_str_buf
,
10252 last_loaded_address
, last_loaded_size
);
10255 if (last_unloaded_strlen
) {
10256 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
10257 AbsoluteTime_to_scalar(&last_unloaded_timestamp
),
10258 last_unloaded_strlen
, last_unloaded_str_buf
,
10259 last_unloaded_address
, last_unloaded_size
);
10262 printf_func("loaded kexts:\n");
10263 if (loaded_kext_paniclist
&&
10264 pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) &&
10265 loaded_kext_paniclist
[0]) {
10267 printf_func("%.*s",
10268 strnlen(loaded_kext_paniclist
, loaded_kext_paniclist_size
),
10269 loaded_kext_paniclist
);
10271 printf_func("(none)\n");
10276 /*********************************************************************
10277 * Assumes sKextLock is held.
10278 *********************************************************************/
10281 OSKext::updateLoadedKextSummaries(void)
10283 kern_return_t result
= KERN_FAILURE
;
10284 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
10285 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
10287 vm_map_offset_t start
, end
;
10288 size_t summarySize
= 0;
10294 #if DEVELOPMENT || DEBUG
10295 if (IORecursiveLockHaveLock(sKextLock
) == false) {
10296 panic("sKextLock must be held");
10300 IOLockLock(sKextSummariesLock
);
10302 count
= sLoadedKexts
->getCount();
10303 for (i
= 0, maxKexts
= 0; i
< count
; ++i
) {
10304 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10305 maxKexts
+= (aKext
&& aKext
->isExecutable());
10308 if (!maxKexts
) goto finish
;
10309 if (maxKexts
< kOSKextTypicalLoadCount
) maxKexts
= kOSKextTypicalLoadCount
;
10311 /* Calculate the size needed for the new summary headers.
10314 size
= sizeof(*gLoadedKextSummaries
);
10315 size
+= maxKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
10316 size
= round_page(size
);
10318 if (gLoadedKextSummaries
== NULL
|| sLoadedKextSummariesAllocSize
< size
) {
10319 if (gLoadedKextSummaries
) {
10320 kmem_free(kernel_map
,
10321 (vm_offset_t
)gLoadedKextSummaries
,
10322 sLoadedKextSummariesAllocSize
);
10323 gLoadedKextSummaries
= NULL
;
10324 sLoadedKextSummariesAllocSize
= 0;
10326 result
= kmem_alloc(kernel_map
,
10327 (vm_offset_t
*)&summaryHeaderAlloc
,
10329 if (result
!= KERN_SUCCESS
) goto finish
;
10330 summaryHeader
= summaryHeaderAlloc
;
10331 summarySize
= size
;
10334 summaryHeader
= gLoadedKextSummaries
;
10335 summarySize
= sLoadedKextSummariesAllocSize
;
10337 start
= (vm_map_offset_t
) summaryHeader
;
10338 end
= start
+ summarySize
;
10339 result
= vm_map_protect(kernel_map
,
10344 if (result
!= KERN_SUCCESS
) goto finish
;
10347 /* Populate the summary header.
10350 bzero(summaryHeader
, summarySize
);
10351 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
10352 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
10354 /* Populate each kext summary.
10357 count
= sLoadedKexts
->getCount();
10358 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
10359 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10360 if (!aKext
|| !aKext
->isExecutable()) {
10364 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
10365 summaryHeader
->numSummaries
++;
10368 /* Write protect the buffer and move it into place.
10371 start
= (vm_map_offset_t
) summaryHeader
;
10372 end
= start
+ summarySize
;
10374 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_READ
, FALSE
);
10375 if (result
!= KERN_SUCCESS
) goto finish
;
10377 gLoadedKextSummaries
= summaryHeader
;
10378 sLoadedKextSummariesAllocSize
= summarySize
;
10379 summaryHeaderAlloc
= NULL
;
10381 /* Call the magic breakpoint function through a static function pointer so
10382 * the compiler can't optimize the function away.
10384 if (sLoadedKextSummariesUpdated
) (*sLoadedKextSummariesUpdated
)();
10387 IOLockUnlock(sKextSummariesLock
);
10389 /* If we had to allocate a new buffer but failed to generate the summaries,
10392 if (summaryHeaderAlloc
) {
10393 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
10399 /*********************************************************************
10400 *********************************************************************/
10402 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
10406 strlcpy(summary
->name
, getIdentifierCString(),
10407 sizeof(summary
->name
));
10411 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
10412 OSSafeRelease(uuid
);
10415 summary
->address
= kmod_info
->address
;
10416 summary
->size
= kmod_info
->size
;
10417 summary
->version
= getVersion();
10418 summary
->loadTag
= kmod_info
->id
;
10419 summary
->flags
= 0;
10420 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
10425 /*********************************************************************
10426 *********************************************************************/
10428 #if CONFIG_KEC_FIPS
10431 #pragma mark Kernel External Components for FIPS compliance
10434 /*********************************************************************
10435 * Kernel External Components for FIPS compliance (KEC_FIPS)
10436 *********************************************************************/
10438 GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
)
10440 AppleTEXTHash_t my_ath
= {1, 0, NULL
};
10441 AppleTEXTHash_t
* my_athp
= NULL
; // do not release
10442 OSDictionary
* textHashDict
= NULL
; // do not release
10443 OSData
* segmentHash
= NULL
; // do not release
10445 if (theKext
== NULL
|| theInfoDict
== NULL
) {
10449 textHashDict
= OSDynamicCast(OSDictionary
, theInfoDict
->getObject(kAppleTextHashesKey
));
10450 if (textHashDict
== NULL
) {
10454 segmentHash
= OSDynamicCast(OSData
,
10455 textHashDict
->getObject(ARCHNAME
));
10456 if (segmentHash
== NULL
) {
10460 // KEC_FIPS type kexts never unload so we don't have to clean up our
10462 if (kmem_alloc(kernel_map
, (vm_offset_t
*) &my_athp
,
10463 sizeof(AppleTEXTHash_t
)) != KERN_SUCCESS
) {
10467 memcpy(my_athp
, &my_ath
, sizeof(my_ath
));
10468 my_athp
->ath_length
= segmentHash
->getLength();
10469 if (my_athp
->ath_length
> 0) {
10470 my_athp
->ath_hash
= (void *)segmentHash
->getBytesNoCopy();
10475 kOSKextLogErrorLevel
|
10476 kOSKextLogGeneralFlag
,
10477 "Kext %s ath_version %d ath_length %d ath_hash %p",
10478 theKext
->getIdentifierCString(),
10479 my_athp
->ath_version
,
10480 my_athp
->ath_length
,
10481 my_athp
->ath_hash
);
10484 return( (void *) my_athp
);
10487 #endif // CONFIG_KEC_FIPS