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 /* A typical Snow Leopard system has a bit under 120 kexts loaded.
128 * Use this number to create containers.
130 #define kOSKextTypicalLoadCount (120)
132 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
133 * A loaded kext will no dependents or external retains will have 2 retains.
135 #define kOSKextMinRetainCount (1)
136 #define kOSKextMinLoadedRetainCount (2)
139 * Strings and substrings used in dependency resolution.
141 #define APPLE_KEXT_PREFIX "com.apple."
142 #define KERNEL_LIB "com.apple.kernel"
144 #define PRIVATE_KPI "com.apple.kpi.private"
146 /* Version for compatbility pseudokexts (com.apple.kernel.*),
147 * compatible back to v6.0.
149 #define KERNEL6_LIB "com.apple.kernel.6.0"
150 #define KERNEL6_VERSION "7.9.9"
152 #define KERNEL_LIB_PREFIX "com.apple.kernel."
153 #define KPI_LIB_PREFIX "com.apple.kpi."
155 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0)
157 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
158 #define MINIMUM_WAKEUP_SECONDS (30)
160 /*********************************************************************
161 * infoDict keys for internally-stored data. Saves on ivar slots for
162 * objects we don't keep around past boot time or during active load.
163 *********************************************************************/
165 /* A usable, uncompressed file is stored under this key.
167 #define _kOSKextExecutableKey "_OSKextExecutable"
169 /* An indirect reference to the executable file from an mkext
170 * is stored under this key.
172 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference"
174 /* If the file is contained in a larger buffer laid down by the booter or
175 * sent from user space, the OSKext stores that OSData under this key so that
176 * references are properly tracked. This is always an mkext, right now.
178 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
181 #pragma mark Typedefs
183 /*********************************************************************
185 *********************************************************************/
187 /*********************************************************************
188 * MkextEntryRef describes the contents of an OSData object
189 * referencing a file entry from an mkext so that we can uncompress
190 * (if necessary) and extract it on demand.
192 * It contains the mkextVersion in case we ever wind up supporting
193 * multiple mkext formats. Mkext format 1 is officially retired as of
195 *********************************************************************/
196 typedef struct MkextEntryRef
{
197 mkext_basic_header
* mkext
; // beginning of whole mkext file
198 void * fileinfo
; // mkext2_file_entry or equiv; see mkext.h
202 #pragma mark Global and static Module Variables
204 /*********************************************************************
205 * Global & static variables, used to keep track of kexts.
206 *********************************************************************/
208 static bool sPrelinkBoot
= false;
209 static bool sSafeBoot
= false;
210 static bool sKeepSymbols
= false;
212 /*********************************************************************
213 * sKextLock is the principal lock for OSKext, and guards all static
214 * and global variables not owned by other locks (declared further
215 * below). It must be taken by any entry-point method or function,
216 * including internal functions called on scheduled threads.
218 * sKextLock and sKextInnerLock are recursive due to multiple functions
219 * that are called both externally and internally. The other locks are
222 * Which locks are taken depends on what they protect, but if more than
223 * one must be taken, they must always be locked in this order
224 * (and unlocked in reverse order) to prevent deadlocks:
228 * 3. sKextSummariesLock
229 * 4. sKextLoggingLock
231 static IORecursiveLock
* sKextLock
= NULL
;
233 static OSDictionary
* sKextsByID
= NULL
;
234 static OSDictionary
* sExcludeListByID
= NULL
;
235 static OSArray
* sLoadedKexts
= NULL
;
236 static OSArray
* sUnloadedPrelinkedKexts
= NULL
;
238 // Requests to kextd waiting to be picked up.
239 static OSArray
* sKernelRequests
= NULL
;
240 // Identifier of kext load requests in sKernelRequests
241 static OSSet
* sPostedKextLoadIdentifiers
= NULL
;
242 static OSArray
* sRequestCallbackRecords
= NULL
;
244 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
245 static OSSet
* sAllKextLoadIdentifiers
= NULL
;
246 static KXLDContext
* sKxldContext
= NULL
;
247 static uint32_t sNextLoadTag
= 0;
248 static uint32_t sNextRequestTag
= 0;
250 static bool sUserLoadsActive
= false;
251 static bool sKextdActive
= false;
252 static bool sDeferredLoadSucceeded
= false;
253 static bool sConsiderUnloadsExecuted
= false;
256 static bool sKernelRequestsEnabled
= false;
258 static bool sKernelRequestsEnabled
= true;
260 static bool sLoadEnabled
= true;
261 static bool sUnloadEnabled
= true;
263 /*********************************************************************
264 * Stuff for the OSKext representing the kernel itself.
266 static OSKext
* sKernelKext
= NULL
;
268 /* Set up a fake kmod_info struct for the kernel.
269 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
270 * before OSKext is initialized; that call only needs the name
271 * and address to be set correctly.
273 * We don't do much else with the kerne's kmod_info; we never
274 * put it into the kmod list, never adjust the reference count,
275 * and never have kernel components reference it.
276 * For that matter, we don't do much with kmod_info structs
277 * at all anymore! We just keep them filled in for gdb and
278 * binary compability.
280 kmod_info_t g_kernel_kmod_info
= {
282 /* info_version */ KMOD_INFO_VERSION
,
283 /* id */ 0, // loadTag: kernel is always 0
284 /* name */ kOSKextKernelIdentifier
, // bundle identifier
285 /* version */ "0", // filled in in OSKext::initialize()
286 /* reference_count */ -1, // never adjusted; kernel never unloads
287 /* reference_list */ NULL
,
289 /* size */ 0, // filled in in OSKext::initialize()
296 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
297 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
298 // misc_protos.h, db_low_trace.c, kgmacros
299 // 'kmod' is a holdover from the old kmod system, we can't rename it.
300 kmod_info_t
* kmod
= NULL
;
302 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
305 static char * loaded_kext_paniclist
= NULL
;
306 static uint32_t loaded_kext_paniclist_size
= 0;
307 static uint32_t loaded_kext_paniclist_length
= 0;
309 AbsoluteTime last_loaded_timestamp
;
310 static char last_loaded_str
[2*KMOD_MAX_NAME
];
311 static u_long last_loaded_strlen
= 0;
312 static void * last_loaded_address
= NULL
;
313 static u_long last_loaded_size
= 0;
315 AbsoluteTime last_unloaded_timestamp
;
316 static char last_unloaded_str
[2*KMOD_MAX_NAME
];
317 static u_long last_unloaded_strlen
= 0;
318 static void * last_unloaded_address
= NULL
;
319 static u_long last_unloaded_size
= 0;
321 /*********************************************************************
322 * sKextInnerLock protects against cross-calls with IOService and
323 * IOCatalogue, and owns the variables declared immediately below.
325 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
327 * When both sKextLock and sKextInnerLock need to be taken,
328 * always lock sKextLock first and unlock it second. Never take both
329 * locks in an entry point to OSKext; if you need to do so, you must
330 * spawn an independent thread to avoid potential deadlocks for threads
331 * calling into OSKext.
333 static IORecursiveLock
* sKextInnerLock
= NULL
;
335 static bool sAutounloadEnabled
= true;
336 static bool sConsiderUnloadsCalled
= false;
337 static bool sConsiderUnloadsPending
= false;
339 static unsigned int sConsiderUnloadDelay
= 60; // seconds
340 static thread_call_t sUnloadCallout
= 0;
341 static thread_call_t sDestroyLinkContextThread
= 0; // one-shot, one-at-a-time thread
342 static bool sSystemSleep
= false; // true when system going to sleep
343 static AbsoluteTime sLastWakeTime
; // last time we woke up
345 /*********************************************************************
346 * Backtraces can be printed at various times so we need a tight lock
347 * on data used for that. sKextSummariesLock protects the variables
348 * declared immediately below.
350 * gLoadedKextSummaries is accessed by other modules, but only during
351 * a panic so the lock isn't needed then.
353 * gLoadedKextSummaries has the "used" attribute in order to ensure
354 * that it remains visible even when we are performing extremely
355 * aggressive optimizations, as it is needed to allow the debugger
356 * to automatically parse the list of loaded kexts.
358 static IOLock
* sKextSummariesLock
= NULL
;
360 void (*sLoadedKextSummariesUpdated
)(void) = OSKextLoadedKextSummariesUpdated
;
361 OSKextLoadedKextSummaryHeader
* gLoadedKextSummaries
__attribute__((used
)) = NULL
;
362 static size_t sLoadedKextSummariesAllocSize
= 0;
363 OSKextLoadedKextSummaryHeader
* sPrevLoadedKextSummaries
= NULL
;
364 static size_t sPrevLoadedKextSummariesAllocSize
= 0;
367 /*********************************************************************
368 * sKextLoggingLock protects the logging variables declared immediately below.
370 static IOLock
* sKextLoggingLock
= NULL
;
372 static const OSKextLogSpec kDefaultKernelLogFilter
= kOSKextLogBasicLevel
|
373 kOSKextLogVerboseFlagsMask
;
374 static OSKextLogSpec sKernelLogFilter
= kDefaultKernelLogFilter
;
375 static bool sBootArgLogFilterFound
= false;
376 SYSCTL_UINT(_debug
, OID_AUTO
, kextlog
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &sKernelLogFilter
,
377 sKernelLogFilter
, "kernel kext logging");
379 static OSKextLogSpec sUserSpaceKextLogFilter
= kOSKextLogSilentFilter
;
380 static OSArray
* sUserSpaceLogSpecArray
= NULL
;
381 static OSArray
* sUserSpaceLogMessageArray
= NULL
;
384 * End scope for sKextInnerLock-protected variables.
385 *********************************************************************/
388 #pragma mark OSData callbacks (need to move to OSData)
390 /*********************************************************************
391 * C functions used for callbacks.
392 *********************************************************************/
394 void osdata_kmem_free(void * ptr
, unsigned int length
) {
395 kmem_free(kernel_map
, (vm_address_t
)ptr
, length
);
399 void osdata_phys_free(void * ptr
, unsigned int length
) {
400 ml_static_mfree((vm_offset_t
)ptr
, length
);
404 void osdata_vm_deallocate(void * ptr
, unsigned int length
)
406 (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
);
410 void osdata_kext_free(void * ptr
, unsigned int length
)
412 (void)kext_free((vm_offset_t
)ptr
, length
);
418 #pragma mark KXLD Allocation Callback
420 /*********************************************************************
421 * KXLD Allocation Callback
422 *********************************************************************/
426 KXLDAllocateFlags
* flags
,
429 vm_address_t result
= 0; // returned
430 kern_return_t mach_result
= KERN_FAILURE
;
431 bool success
= false;
432 OSKext
* theKext
= (OSKext
*)user_data
;
433 u_long roundSize
= round_page(size
);
434 OSData
* linkBuffer
= NULL
; // must release
436 mach_result
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
);
437 if (mach_result
!= KERN_SUCCESS
) {
439 kOSKextLogErrorLevel
|
440 kOSKextLogGeneralFlag
,
441 "Can't allocate kernel memory to link %s.",
442 theKext
->getIdentifierCString());
446 /* Create an OSData wrapper for the allocated buffer.
448 linkBuffer
= OSData::withBytesNoCopy((void *)result
, roundSize
);
451 kOSKextLogErrorLevel
|
452 kOSKextLogGeneralFlag
,
453 "Can't allocate linked executable wrapper for %s.",
454 theKext
->getIdentifierCString());
457 linkBuffer
->setDeallocFunction(osdata_kext_free
);
459 kOSKextLogProgressLevel
|
460 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
461 "Allocated link buffer for kext %s at %p (%lu bytes).",
462 theKext
->getIdentifierCString(),
463 (void *)result
, (unsigned long)roundSize
);
465 theKext
->setLinkedExecutable(linkBuffer
);
467 *flags
= kKxldAllocateWritable
;
471 if (!success
&& result
) {
472 kext_free(result
, roundSize
);
476 OSSafeRelease(linkBuffer
);
478 return (kxld_addr_t
)result
;
481 /*********************************************************************
482 *********************************************************************/
485 KXLDLogSubsystem subsystem
,
491 OSKext
*theKext
= (OSKext
*) user_data
;
492 OSKextLogSpec logSpec
= 0;
495 case kKxldLogLinking
:
496 logSpec
|= kOSKextLogLinkFlag
;
498 case kKxldLogPatching
:
499 logSpec
|= kOSKextLogPatchFlag
;
504 case kKxldLogExplicit
:
505 logSpec
|= kOSKextLogExplicitLevel
;
508 logSpec
|= kOSKextLogErrorLevel
;
511 logSpec
|= kOSKextLogWarningLevel
;
514 logSpec
|= kOSKextLogProgressLevel
;
517 logSpec
|= kOSKextLogDetailLevel
;
520 logSpec
|= kOSKextLogDebugLevel
;
524 OSKextVLog(theKext
, logSpec
, format
, argList
);
528 #pragma mark IOStatistics defines
533 #define notifyKextLoadObservers(kext, kmod_info) \
535 IOStatistics::onKextLoad(kext, kmod_info); \
538 #define notifyKextUnloadObservers(kext) \
540 IOStatistics::onKextUnload(kext); \
543 #define notifyAddClassObservers(kext, addedClass, flags) \
545 IOStatistics::onClassAdded(kext, addedClass); \
548 #define notifyRemoveClassObservers(kext, removedClass, flags) \
550 IOStatistics::onClassRemoved(kext, removedClass); \
555 #define notifyKextLoadObservers(kext, kmod_info)
556 #define notifyKextUnloadObservers(kext)
557 #define notifyAddClassObservers(kext, addedClass, flags)
558 #define notifyRemoveClassObservers(kext, removedClass, flags)
560 #endif /* IOKITSTATS */
563 #pragma mark Module Config (Startup & Shutdown)
565 /*********************************************************************
566 * Module Config (Class Definition & Class Methods)
567 *********************************************************************/
568 #define super OSObject
569 OSDefineMetaClassAndStructors(OSKext
, OSObject
)
571 /*********************************************************************
572 *********************************************************************/
575 OSKext::initialize(void)
577 OSData
* kernelExecutable
= NULL
; // do not release
578 u_char
* kernelStart
= NULL
; // do not free
579 size_t kernelLength
= 0;
580 OSString
* scratchString
= NULL
; // must release
581 IORegistryEntry
* registryRoot
= NULL
; // do not release
582 OSNumber
* kernelCPUType
= NULL
; // must release
583 OSNumber
* kernelCPUSubtype
= NULL
; // must release
584 OSKextLogSpec bootLogFilter
= kOSKextLogSilentFilter
;
585 bool setResult
= false;
586 uint64_t * timestamp
= 0;
587 char bootArgBuffer
[16]; // for PE_parse_boot_argn w/strings
589 /* This must be the first thing allocated. Everything else grabs this lock.
591 sKextLock
= IORecursiveLockAlloc();
592 sKextInnerLock
= IORecursiveLockAlloc();
593 sKextSummariesLock
= IOLockAlloc();
594 sKextLoggingLock
= IOLockAlloc();
596 assert(sKextInnerLock
);
597 assert(sKextSummariesLock
);
598 assert(sKextLoggingLock
);
600 sKextsByID
= OSDictionary::withCapacity(kOSKextTypicalLoadCount
);
601 sLoadedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
);
602 sUnloadedPrelinkedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
/ 10);
603 sKernelRequests
= OSArray::withCapacity(0);
604 sPostedKextLoadIdentifiers
= OSSet::withCapacity(0);
605 sAllKextLoadIdentifiers
= OSSet::withCapacity(kOSKextTypicalLoadCount
);
606 sRequestCallbackRecords
= OSArray::withCapacity(0);
607 assert(sKextsByID
&& sLoadedKexts
&& sKernelRequests
&&
608 sPostedKextLoadIdentifiers
&& sAllKextLoadIdentifiers
&&
609 sRequestCallbackRecords
&& sUnloadedPrelinkedKexts
);
611 /* Read the log flag boot-args and set the log flags.
613 if (PE_parse_boot_argn("kextlog", &bootLogFilter
, sizeof(bootLogFilter
))) {
614 sBootArgLogFilterFound
= true;
615 sKernelLogFilter
= bootLogFilter
;
616 // log this if any flags are set
617 OSKextLog(/* kext */ NULL
,
618 kOSKextLogBasicLevel
|
620 "Kernel kext log filter 0x%x per kextlog boot arg.",
621 (unsigned)sKernelLogFilter
);
624 sSafeBoot
= PE_parse_boot_argn("-x", bootArgBuffer
,
625 sizeof(bootArgBuffer
)) ? true : false;
628 OSKextLog(/* kext */ NULL
,
629 kOSKextLogWarningLevel
|
630 kOSKextLogGeneralFlag
,
631 "SAFE BOOT DETECTED - "
632 "only valid OSBundleRequired kexts will be loaded.");
635 PE_parse_boot_argn("keepsyms", &sKeepSymbols
, sizeof(sKeepSymbols
));
637 /* Set up an OSKext instance to represent the kernel itself.
639 sKernelKext
= new OSKext
;
642 kernelStart
= (u_char
*)&_mh_execute_header
;
643 kernelLength
= getlastaddr() - (vm_offset_t
)kernelStart
;
644 kernelExecutable
= OSData::withBytesNoCopy(
645 kernelStart
, kernelLength
);
646 assert(kernelExecutable
);
649 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu \n",
650 (unsigned long)kernelStart
,
651 (unsigned long)getlastaddr(),
655 sKernelKext
->loadTag
= sNextLoadTag
++; // the kernel is load tag 0
656 sKernelKext
->bundleID
= OSSymbol::withCString(kOSKextKernelIdentifier
);
658 sKernelKext
->version
= OSKextParseVersionString(osrelease
);
659 sKernelKext
->compatibleVersion
= sKernelKext
->version
;
660 sKernelKext
->linkedExecutable
= kernelExecutable
;
662 sKernelKext
->flags
.hasAllDependencies
= 1;
663 sKernelKext
->flags
.kernelComponent
= 1;
664 sKernelKext
->flags
.prelinked
= 0;
665 sKernelKext
->flags
.loaded
= 1;
666 sKernelKext
->flags
.started
= 1;
667 sKernelKext
->flags
.CPPInitialized
= 0;
668 sKernelKext
->flags
.jettisonLinkeditSeg
= 0;
670 sKernelKext
->kmod_info
= &g_kernel_kmod_info
;
671 strlcpy(g_kernel_kmod_info
.version
, osrelease
,
672 sizeof(g_kernel_kmod_info
.version
));
673 g_kernel_kmod_info
.size
= kernelLength
;
674 g_kernel_kmod_info
.id
= sKernelKext
->loadTag
;
676 /* Cons up an info dict, so we don't have to have special-case
679 sKernelKext
->infoDict
= OSDictionary::withCapacity(5);
680 assert(sKernelKext
->infoDict
);
681 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
,
682 sKernelKext
->bundleID
);
684 setResult
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
,
688 scratchString
= OSString::withCStringNoCopy(osrelease
);
689 assert(scratchString
);
690 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
,
693 OSSafeReleaseNULL(scratchString
);
695 scratchString
= OSString::withCStringNoCopy("mach_kernel");
696 assert(scratchString
);
697 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
,
700 OSSafeReleaseNULL(scratchString
);
702 /* Add the kernel kext to the bookkeeping dictionaries. Note that
703 * the kernel kext doesn't have a kmod_info struct. copyInfo()
704 * gathers info from other places anyhow.
706 setResult
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
);
708 setResult
= sLoadedKexts
->setObject(sKernelKext
);
710 sKernelKext
->release();
712 registryRoot
= IORegistryEntry::getRegistryRoot();
713 kernelCPUType
= OSNumber::withNumber(
714 (long long unsigned int)_mh_execute_header
.cputype
,
715 8 * sizeof(_mh_execute_header
.cputype
));
716 kernelCPUSubtype
= OSNumber::withNumber(
717 (long long unsigned int)_mh_execute_header
.cpusubtype
,
718 8 * sizeof(_mh_execute_header
.cpusubtype
));
719 assert(registryRoot
&& kernelCPUSubtype
&& kernelCPUType
);
721 registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
);
722 registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
);
724 OSSafeRelease(kernelCPUType
);
725 OSSafeRelease(kernelCPUSubtype
);
727 timestamp
= __OSAbsoluteTimePtr(&last_loaded_timestamp
);
729 timestamp
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
);
731 timestamp
= __OSAbsoluteTimePtr(&sLastWakeTime
);
734 OSKextLog(/* kext */ NULL
,
735 kOSKextLogProgressLevel
|
736 kOSKextLogGeneralFlag
,
737 "Kext system initialized.");
739 notifyKextLoadObservers(sKernelKext
, sKernelKext
->kmod_info
);
744 /*********************************************************************
745 * This could be in OSKextLib.cpp but we need to hold a lock
746 * while removing all the segments and sKextLock will do.
747 *********************************************************************/
750 OSKext::removeKextBootstrap(void)
752 OSReturn result
= kOSReturnError
;
754 static bool alreadyDone
= false;
756 const char * dt_kernel_header_name
= "Kernel-__HEADER";
757 const char * dt_kernel_symtab_name
= "Kernel-__SYMTAB";
758 kernel_mach_header_t
* dt_mach_header
= NULL
;
759 int dt_mach_header_size
= 0;
760 struct symtab_command
* dt_symtab
= NULL
;
761 int dt_symtab_size
= 0;
764 kernel_segment_command_t
* seg_to_remove
= NULL
;
767 /* This must be the very first thing done by this function.
769 IORecursiveLockLock(sKextLock
);
771 /* If we already did this, it's a success.
774 result
= kOSReturnSuccess
;
778 OSKextLog(/* kext */ NULL
,
779 kOSKextLogProgressLevel
|
780 kOSKextLogGeneralFlag
,
781 "Jettisoning kext bootstrap segments.");
784 * Dispose of unnecessary stuff that the booter didn't need to load.
786 dt_result
= IODTGetLoaderInfo(dt_kernel_header_name
,
787 (void **)&dt_mach_header
, &dt_mach_header_size
);
788 if (dt_result
== 0 && dt_mach_header
) {
789 IODTFreeLoaderInfo(dt_kernel_header_name
, (void *)dt_mach_header
,
790 round_page_32(dt_mach_header_size
));
792 dt_result
= IODTGetLoaderInfo(dt_kernel_symtab_name
,
793 (void **)&dt_symtab
, &dt_symtab_size
);
794 if (dt_result
== 0 && dt_symtab
) {
795 IODTFreeLoaderInfo(dt_kernel_symtab_name
, (void *)dt_symtab
,
796 round_page_32(dt_symtab_size
));
800 * KLD bootstrap segment.
802 // xxx - should rename KLD segment
803 seg_to_remove
= getsegbyname("__KLD");
805 OSRuntimeUnloadCPPForSegment(seg_to_remove
);
808 #if __i386__ || __x86_64__
809 /* On x86, use the mapping data from the segment load command to
810 * unload KLD directly.
811 * This may invalidate any assumptions about "avail_start"
812 * defining the lower bound for valid physical addresses.
814 if (seg_to_remove
&& seg_to_remove
->vmaddr
&& seg_to_remove
->vmsize
) {
815 // 04/18/11 - gab: <rdar://problem/9236163>
816 // overwrite memory occupied by KLD segment with random data before
818 read_random((void *) seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
819 ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
825 seg_to_remove
= NULL
;
828 * Prelinked kernel's symtab (if there is one).
830 kernel_section_t
* sect
;
831 sect
= getsectbyname("__PRELINK", "__symtab");
832 if (sect
&& sect
->addr
&& sect
->size
) {
833 ml_static_mfree(sect
->addr
, sect
->size
);
836 seg_to_remove
= (kernel_segment_command_t
*)getsegbyname("__LINKEDIT");
838 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
839 * pageable, unless keepsyms is set. To do that, we have to copy it from
840 * its booter-allocated memory, free the booter memory, reallocate proper
841 * managed memory, then copy the segment back in.
845 kern_return_t mem_result
;
846 void *seg_copy
= NULL
;
847 void *seg_data
= NULL
;
848 vm_map_offset_t seg_offset
= 0;
849 vm_map_offset_t seg_copy_offset
= 0;
850 vm_map_size_t seg_length
= 0;
852 seg_data
= (void *) seg_to_remove
->vmaddr
;
853 seg_offset
= (vm_map_offset_t
) seg_to_remove
->vmaddr
;
854 seg_length
= (vm_map_size_t
) seg_to_remove
->vmsize
;
856 /* Allocate space for the LINKEDIT copy.
858 mem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*) &seg_copy
,
860 if (mem_result
!= KERN_SUCCESS
) {
861 OSKextLog(/* kext */ NULL
,
862 kOSKextLogErrorLevel
|
863 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
864 "Can't copy __LINKEDIT segment for VM reassign.");
867 seg_copy_offset
= (vm_map_offset_t
) seg_copy
;
871 memcpy(seg_copy
, seg_data
, seg_length
);
873 /* Dump the booter memory.
875 ml_static_mfree(seg_offset
, seg_length
);
877 /* Set up the VM region.
879 mem_result
= vm_map_enter_mem_object(
882 seg_length
, /* mask */ 0,
883 VM_FLAGS_FIXED
| VM_FLAGS_OVERWRITE
,
885 (vm_object_offset_t
) 0,
887 /* cur_protection */ VM_PROT_READ
| VM_PROT_WRITE
,
888 /* max_protection */ VM_PROT_ALL
,
889 /* inheritance */ VM_INHERIT_DEFAULT
);
890 if ((mem_result
!= KERN_SUCCESS
) ||
891 (seg_offset
!= (vm_map_offset_t
) seg_data
))
893 OSKextLog(/* kext */ NULL
,
894 kOSKextLogErrorLevel
|
895 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
896 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
897 seg_data
, seg_length
, mem_result
);
903 memcpy(seg_data
, seg_copy
, seg_length
);
907 kmem_free(kernel_map
, seg_copy_offset
, seg_length
);
909 #else /* we are not CONFIG_KXLD */
910 #error CONFIG_KXLD is expected for this arch
913 * Dump the LINKEDIT segment, unless keepsyms is set.
916 const char *dt_segment_name
= "Kernel-__LINKEDIT";
917 if (0 == IODTGetLoaderInfo(dt_segment_name
,
918 &segment_paddress
, &segment_size
)) {
920 vm_offset_t vmaddr
= ml_static_ptovirt((vm_offset_t
)segment_paddress
);
921 bzero((void*)vmaddr
, segment_size
);
923 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
927 OSKextLog(/* kext */ NULL
,
928 kOSKextLogBasicLevel
|
929 kOSKextLogGeneralFlag
,
930 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
932 #endif /* CONFIG_KXLD */
934 seg_to_remove
= NULL
;
937 result
= kOSReturnSuccess
;
941 /* This must be the very last thing done before returning.
943 IORecursiveLockUnlock(sKextLock
);
948 /*********************************************************************
949 *********************************************************************/
951 OSKext::flushNonloadedKexts(
952 Boolean flushPrelinkedKexts
)
954 OSSet
* prelinkedKexts
= NULL
; // must release
955 OSCollectionIterator
* kextIterator
= NULL
; // must release
956 OSCollectionIterator
* prelinkIterator
= NULL
; // must release
957 const OSSymbol
* thisID
= NULL
; // do not release
958 OSKext
* thisKext
= NULL
; // do not release
961 IORecursiveLockLock(sKextLock
);
963 OSKextLog(/* kext */ NULL
,
964 kOSKextLogProgressLevel
|
965 kOSKextLogKextBookkeepingFlag
,
966 "Flushing nonloaded kexts and other unused data.");
968 OSKext::considerDestroyingLinkContext();
970 /* If we aren't flushing unused prelinked kexts, we have to put them
971 * aside while we flush everything else so make a container for them.
973 if (!flushPrelinkedKexts
) {
974 prelinkedKexts
= OSSet::withCapacity(0);
975 if (!prelinkedKexts
) {
980 /* Set aside prelinked kexts (in-use or not) and break
981 * any lingering inter-kext references for nonloaded kexts
982 * so they have min. retain counts.
984 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
989 while ((thisID
= OSDynamicCast(OSSymbol
,
990 kextIterator
->getNextObject()))) {
992 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
995 if (prelinkedKexts
&& thisKext
->isPrelinked()) {
996 prelinkedKexts
->setObject(thisKext
);
998 thisKext
->flushDependencies(/* forceIfLoaded */ false);
1002 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1004 sKextsByID
->flushCollection();
1006 /* Now put the loaded kexts back into the ID dictionary.
1008 count
= sLoadedKexts
->getCount();
1009 for (i
= 0; i
< count
; i
++) {
1010 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
1011 sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
);
1014 /* Finally, put back the prelinked kexts if we saved any.
1016 if (prelinkedKexts
) {
1017 prelinkIterator
= OSCollectionIterator::withCollection(prelinkedKexts
);
1018 if (!prelinkIterator
) {
1022 while ((thisKext
= OSDynamicCast(OSKext
,
1023 prelinkIterator
->getNextObject()))) {
1025 sKextsByID
->setObject(thisKext
->getIdentifierCString(),
1031 IORecursiveLockUnlock(sKextLock
);
1033 OSSafeRelease(prelinkedKexts
);
1034 OSSafeRelease(kextIterator
);
1035 OSSafeRelease(prelinkIterator
);
1040 /*********************************************************************
1041 *********************************************************************/
1044 OSKext::setKextdActive(Boolean active
)
1046 IORecursiveLockLock(sKextLock
);
1047 sKextdActive
= active
;
1048 if (sKernelRequests
->getCount()) {
1049 OSKext::pingKextd();
1051 IORecursiveLockUnlock(sKextLock
);
1056 /*********************************************************************
1057 * OSKextLib.cpp might need access to this someday but for now it's
1059 *********************************************************************/
1061 extern void ipc_port_release_send(ipc_port_t
);
1066 OSKext::pingKextd(void)
1068 OSReturn result
= kOSReturnError
;
1070 mach_port_t kextd_port
= IPC_PORT_NULL
;
1072 if (!sKextdActive
) {
1073 result
= kOSKextReturnDisabled
; // basically unavailable
1077 result
= host_get_kextd_port(host_priv_self(), &kextd_port
);
1078 if (result
!= KERN_SUCCESS
|| !IPC_PORT_VALID(kextd_port
)) {
1079 OSKextLog(/* kext */ NULL
,
1080 kOSKextLogErrorLevel
|
1082 "Can't get kextd port.");
1086 result
= kextd_ping(kextd_port
);
1087 if (result
!= KERN_SUCCESS
) {
1088 OSKextLog(/* kext */ NULL
,
1089 kOSKextLogErrorLevel
|
1091 "kextd ping failed (0x%x).", (int)result
);
1096 if (IPC_PORT_VALID(kextd_port
)) {
1097 ipc_port_release_send(kextd_port
);
1104 /*********************************************************************
1105 *********************************************************************/
1108 OSKext::setDeferredLoadSucceeded(Boolean succeeded
)
1110 IORecursiveLockLock(sKextLock
);
1111 sDeferredLoadSucceeded
= succeeded
;
1112 IORecursiveLockUnlock(sKextLock
);
1117 /*********************************************************************
1118 * Called from IOSystemShutdownNotification.
1119 *********************************************************************/
1122 OSKext::willShutdown(void)
1125 OSReturn checkResult
= kOSReturnError
;
1127 OSDictionary
* exitRequest
= NULL
; // must release
1129 IORecursiveLockLock(sKextLock
);
1131 OSKext::setLoadEnabled(false);
1132 OSKext::setUnloadEnabled(false);
1133 OSKext::setAutounloadsEnabled(false);
1134 OSKext::setKernelRequestsEnabled(false);
1137 OSKextLog(/* kext */ NULL
,
1138 kOSKextLogProgressLevel
|
1139 kOSKextLogGeneralFlag
,
1140 "System shutdown; requesting immediate kextd exit.");
1142 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
,
1144 if (checkResult
!= kOSReturnSuccess
) {
1147 if (!sKernelRequests
->setObject(exitRequest
)) {
1151 OSKext::pingKextd();
1156 IORecursiveLockUnlock(sKextLock
);
1158 OSSafeRelease(exitRequest
);
1162 /*********************************************************************
1163 *********************************************************************/
1166 OSKext::getLoadEnabled(void)
1170 IORecursiveLockLock(sKextLock
);
1171 result
= sLoadEnabled
;
1172 IORecursiveLockUnlock(sKextLock
);
1176 /*********************************************************************
1177 *********************************************************************/
1180 OSKext::setLoadEnabled(bool flag
)
1184 IORecursiveLockLock(sKextLock
);
1185 result
= sLoadEnabled
;
1186 sLoadEnabled
= (flag
? true : false);
1188 if (sLoadEnabled
!= result
) {
1189 OSKextLog(/* kext */ NULL
,
1190 kOSKextLogBasicLevel
|
1192 "Kext loading now %sabled.", sLoadEnabled
? "en" : "dis");
1195 IORecursiveLockUnlock(sKextLock
);
1200 /*********************************************************************
1201 *********************************************************************/
1204 OSKext::getUnloadEnabled(void)
1208 IORecursiveLockLock(sKextLock
);
1209 result
= sUnloadEnabled
;
1210 IORecursiveLockUnlock(sKextLock
);
1214 /*********************************************************************
1215 *********************************************************************/
1218 OSKext::setUnloadEnabled(bool flag
)
1222 IORecursiveLockLock(sKextLock
);
1223 result
= sUnloadEnabled
;
1224 sUnloadEnabled
= (flag
? true : false);
1225 IORecursiveLockUnlock(sKextLock
);
1227 if (sUnloadEnabled
!= result
) {
1228 OSKextLog(/* kext */ NULL
,
1229 kOSKextLogBasicLevel
|
1230 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1231 "Kext unloading now %sabled.", sUnloadEnabled
? "en" : "dis");
1237 /*********************************************************************
1238 * Do not call any function that takes sKextLock here!
1239 *********************************************************************/
1242 OSKext::getAutounloadEnabled(void)
1246 IORecursiveLockLock(sKextInnerLock
);
1247 result
= sAutounloadEnabled
? true : false;
1248 IORecursiveLockUnlock(sKextInnerLock
);
1252 /*********************************************************************
1253 * Do not call any function that takes sKextLock here!
1254 *********************************************************************/
1257 OSKext::setAutounloadsEnabled(bool flag
)
1261 IORecursiveLockLock(sKextInnerLock
);
1263 result
= sAutounloadEnabled
;
1264 sAutounloadEnabled
= (flag
? true : false);
1265 if (!sAutounloadEnabled
&& sUnloadCallout
) {
1266 thread_call_cancel(sUnloadCallout
);
1269 if (sAutounloadEnabled
!= result
) {
1270 OSKextLog(/* kext */ NULL
,
1271 kOSKextLogBasicLevel
|
1272 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1273 "Kext autounloading now %sabled.",
1274 sAutounloadEnabled
? "en" : "dis");
1277 IORecursiveLockUnlock(sKextInnerLock
);
1282 /*********************************************************************
1283 *********************************************************************/
1284 /* instance method operating on OSKext field */
1286 OSKext::setAutounloadEnabled(bool flag
)
1288 bool result
= flags
.autounloadEnabled
? true : false;
1289 flags
.autounloadEnabled
= flag
? 1 : 0;
1291 if (result
!= (flag
? true : false)) {
1293 kOSKextLogProgressLevel
|
1294 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
1295 "Autounloading for kext %s now %sabled.",
1296 getIdentifierCString(),
1297 flags
.autounloadEnabled
? "en" : "dis");
1302 /*********************************************************************
1303 *********************************************************************/
1306 OSKext::setKernelRequestsEnabled(bool flag
)
1310 IORecursiveLockLock(sKextLock
);
1311 result
= sKernelRequestsEnabled
;
1312 sKernelRequestsEnabled
= flag
? true : false;
1314 if (sKernelRequestsEnabled
!= result
) {
1315 OSKextLog(/* kext */ NULL
,
1316 kOSKextLogBasicLevel
|
1317 kOSKextLogGeneralFlag
,
1318 "Kernel requests now %sabled.",
1319 sKernelRequestsEnabled
? "en" : "dis");
1321 IORecursiveLockUnlock(sKextLock
);
1325 /*********************************************************************
1326 *********************************************************************/
1329 OSKext::getKernelRequestsEnabled(void)
1333 IORecursiveLockLock(sKextLock
);
1334 result
= sKernelRequestsEnabled
;
1335 IORecursiveLockUnlock(sKextLock
);
1340 #pragma mark Kext Life Cycle
1342 /*********************************************************************
1343 *********************************************************************/
1345 OSKext::withPrelinkedInfoDict(
1346 OSDictionary
* anInfoDict
)
1348 OSKext
* newKext
= new OSKext
;
1350 if (newKext
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
)) {
1358 /*********************************************************************
1359 *********************************************************************/
1361 OSKext::initWithPrelinkedInfoDict(
1362 OSDictionary
* anInfoDict
)
1364 bool result
= false;
1365 OSString
* kextPath
= NULL
; // do not release
1366 OSNumber
* addressNum
= NULL
; // reused; do not release
1367 OSNumber
* lengthNum
= NULL
; // reused; do not release
1368 void * data
= NULL
; // do not free
1369 void * srcData
= NULL
; // do not free
1370 OSData
* prelinkedExecutable
= NULL
; // must release
1371 uint32_t length
= 0; // reused
1373 if (!super::init()) {
1377 /* Get the path. Don't look for an arch-specific path property.
1379 kextPath
= OSDynamicCast(OSString
,
1380 anInfoDict
->getObject(kPrelinkBundlePathKey
));
1382 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
1385 #if KASLR_KEXT_DEBUG
1386 IOLog("kaslr: kext %s \n", getIdentifierCString());
1389 /* Also get the executable's bundle-relative path if present.
1390 * Don't look for an arch-specific path property.
1392 executableRelPath
= OSDynamicCast(OSString
,
1393 anInfoDict
->getObject(kPrelinkExecutableRelativePathKey
));
1394 if (executableRelPath
) {
1395 executableRelPath
->retain();
1398 /* Don't need the paths to be in the info dictionary any more.
1400 anInfoDict
->removeObject(kPrelinkBundlePathKey
);
1401 anInfoDict
->removeObject(kPrelinkExecutableRelativePathKey
);
1403 /* Create an OSData wrapper around the linked executable.
1405 addressNum
= OSDynamicCast(OSNumber
,
1406 anInfoDict
->getObject(kPrelinkExecutableLoadKey
));
1408 lengthNum
= OSDynamicCast(OSNumber
,
1409 anInfoDict
->getObject(kPrelinkExecutableSizeKey
));
1412 kOSKextLogErrorLevel
|
1413 kOSKextLogArchiveFlag
,
1414 "Kext %s can't find prelinked kext executable size.",
1415 getIdentifierCString());
1419 data
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1420 length
= (uint32_t) (lengthNum
->unsigned32BitValue());
1422 #if KASLR_KEXT_DEBUG
1423 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1424 (unsigned long)VM_KERNEL_UNSLIDE(data
),
1425 (unsigned long)data
,
1429 anInfoDict
->removeObject(kPrelinkExecutableLoadKey
);
1430 anInfoDict
->removeObject(kPrelinkExecutableSizeKey
);
1432 /* If the kext's load address differs from its source address, allocate
1433 * space in the kext map at the load address and copy the kext over.
1435 addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
));
1437 srcData
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1439 #if KASLR_KEXT_DEBUG
1440 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1441 (unsigned long)VM_KERNEL_UNSLIDE(srcData
),
1442 (unsigned long)srcData
);
1445 if (data
!= srcData
) {
1447 kern_return_t alloc_result
;
1449 alloc_result
= kext_alloc((vm_offset_t
*)&data
, length
, /* fixed */ TRUE
);
1450 if (alloc_result
!= KERN_SUCCESS
) {
1452 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1453 "Failed to allocate space for prelinked kext %s.",
1454 getIdentifierCString());
1457 memcpy(data
, srcData
, length
);
1460 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1461 "Error: prelinked kext %s - source and load addresses "
1462 "differ on ILP32 architecture.",
1463 getIdentifierCString());
1465 #endif /* __LP64__ */
1468 anInfoDict
->removeObject(kPrelinkExecutableSourceKey
);
1471 prelinkedExecutable
= OSData::withBytesNoCopy(data
, length
);
1472 if (!prelinkedExecutable
) {
1474 kOSKextLogErrorLevel
|
1475 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
1476 "Kext %s failed to create executable wrapper.",
1477 getIdentifierCString());
1482 prelinkedExecutable
->setDeallocFunction(osdata_kext_free
);
1484 prelinkedExecutable
->setDeallocFunction(osdata_phys_free
);
1486 setLinkedExecutable(prelinkedExecutable
);
1487 addressNum
= OSDynamicCast(OSNumber
,
1488 anInfoDict
->getObject(kPrelinkKmodInfoKey
));
1491 kOSKextLogErrorLevel
|
1492 kOSKextLogArchiveFlag
,
1493 "Kext %s can't find prelinked kext kmod_info address.",
1494 getIdentifierCString());
1498 if (addressNum
->unsigned64BitValue() != 0) {
1499 kmod_info
= (kmod_info_t
*) (intptr_t) (addressNum
->unsigned64BitValue() + vm_kernel_slide
);
1500 kmod_info
->address
+= vm_kernel_slide
;
1501 #if KASLR_KEXT_DEBUG
1502 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1503 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
),
1504 (unsigned long)kmod_info
);
1505 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1506 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
1507 (unsigned long)kmod_info
->address
);
1511 anInfoDict
->removeObject(kPrelinkKmodInfoKey
);
1514 /* If the plist has a UUID for an interface, save that off.
1516 if (isInterface()) {
1517 interfaceUUID
= OSDynamicCast(OSData
,
1518 anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
));
1519 if (interfaceUUID
) {
1520 interfaceUUID
->retain();
1521 anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
);
1525 flags
.prelinked
= true;
1527 /* If we created a kext from prelink info,
1528 * we must be booting from a prelinked kernel.
1530 sPrelinkBoot
= true;
1532 result
= registerIdentifier();
1535 OSSafeRelease(prelinkedExecutable
);
1540 /*********************************************************************
1541 *********************************************************************/
1543 OSKext::withBooterData(
1544 OSString
* deviceTreeName
,
1545 OSData
* booterData
)
1547 OSKext
* newKext
= new OSKext
;
1549 if (newKext
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) {
1557 /*********************************************************************
1558 *********************************************************************/
1559 typedef struct _BooterKextFileInfo
{
1560 uint32_t infoDictPhysAddr
;
1561 uint32_t infoDictLength
;
1562 uint32_t executablePhysAddr
;
1563 uint32_t executableLength
;
1564 uint32_t bundlePathPhysAddr
;
1565 uint32_t bundlePathLength
;
1566 } _BooterKextFileInfo
;
1569 OSKext::initWithBooterData(
1570 OSString
* deviceTreeName
,
1571 OSData
* booterData
)
1573 bool result
= false;
1574 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not free
1575 char * infoDictAddr
= NULL
; // do not free
1576 void * executableAddr
= NULL
; // do not free
1577 char * bundlePathAddr
= NULL
; // do not free
1579 OSObject
* parsedXML
= NULL
; // must release
1580 OSDictionary
* theInfoDict
= NULL
; // do not release
1581 OSString
* kextPath
= NULL
; // must release
1582 OSString
* errorString
= NULL
; // must release
1583 OSData
* executable
= NULL
; // must release
1585 if (!super::init()) {
1589 kextFileInfo
= (_BooterKextFileInfo
*)booterData
->getBytesNoCopy();
1590 if (!kextFileInfo
) {
1592 kOSKextLogErrorLevel
|
1593 kOSKextLogGeneralFlag
,
1594 "No booter-provided data for kext device tree entry %s.",
1595 deviceTreeName
->getCStringNoCopy());
1599 /* The info plist must exist or we can't read the kext.
1601 if (!kextFileInfo
->infoDictPhysAddr
|| !kextFileInfo
->infoDictLength
) {
1603 kOSKextLogErrorLevel
|
1604 kOSKextLogGeneralFlag
,
1605 "No kext info dictionary for booter device tree entry %s.",
1606 deviceTreeName
->getCStringNoCopy());
1610 infoDictAddr
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
1611 if (!infoDictAddr
) {
1613 kOSKextLogErrorLevel
|
1614 kOSKextLogGeneralFlag
,
1615 "Can't translate physical address 0x%x of kext info dictionary "
1616 "for device tree entry %s.",
1617 (int)kextFileInfo
->infoDictPhysAddr
,
1618 deviceTreeName
->getCStringNoCopy());
1622 parsedXML
= OSUnserializeXML(infoDictAddr
, &errorString
);
1624 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
1627 const char * errorCString
= "(unknown error)";
1629 if (errorString
&& errorString
->getCStringNoCopy()) {
1630 errorCString
= errorString
->getCStringNoCopy();
1631 } else if (parsedXML
) {
1632 errorCString
= "not a dictionary";
1635 kOSKextLogErrorLevel
|
1636 kOSKextLogGeneralFlag
,
1637 "Error unserializing info dictionary for device tree entry %s: %s.",
1638 deviceTreeName
->getCStringNoCopy(), errorCString
);
1642 /* A bundle path is not mandatory.
1644 if (kextFileInfo
->bundlePathPhysAddr
&& kextFileInfo
->bundlePathLength
) {
1645 bundlePathAddr
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
);
1646 if (!bundlePathAddr
) {
1648 kOSKextLogErrorLevel
|
1649 kOSKextLogGeneralFlag
,
1650 "Can't translate physical address 0x%x of kext bundle path "
1651 "for device tree entry %s.",
1652 (int)kextFileInfo
->bundlePathPhysAddr
,
1653 deviceTreeName
->getCStringNoCopy());
1656 bundlePathAddr
[kextFileInfo
->bundlePathLength
-1] = '\0'; // just in case!
1658 kextPath
= OSString::withCString(bundlePathAddr
);
1661 kOSKextLogErrorLevel
|
1662 kOSKextLogGeneralFlag
,
1663 "Failed to create wrapper for device tree entry %s kext path %s.",
1664 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
);
1669 if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) {
1673 /* An executable is not mandatory.
1675 if (kextFileInfo
->executablePhysAddr
&& kextFileInfo
->executableLength
) {
1676 executableAddr
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
);
1677 if (!executableAddr
) {
1679 kOSKextLogErrorLevel
|
1680 kOSKextLogGeneralFlag
,
1681 "Can't translate physical address 0x%x of kext executable "
1682 "for device tree entry %s.",
1683 (int)kextFileInfo
->executablePhysAddr
,
1684 deviceTreeName
->getCStringNoCopy());
1688 executable
= OSData::withBytesNoCopy(executableAddr
,
1689 kextFileInfo
->executableLength
);
1692 kOSKextLogErrorLevel
|
1693 kOSKextLogGeneralFlag
,
1694 "Failed to create executable wrapper for device tree entry %s.",
1695 deviceTreeName
->getCStringNoCopy());
1699 /* A kext with an executable needs to retain the whole booterData
1700 * object to keep the executable in memory.
1702 if (!setExecutable(executable
, booterData
)) {
1704 kOSKextLogErrorLevel
|
1705 kOSKextLogGeneralFlag
,
1706 "Failed to set kext executable for device tree entry %s.",
1707 deviceTreeName
->getCStringNoCopy());
1712 result
= registerIdentifier();
1715 OSSafeRelease(parsedXML
);
1716 OSSafeRelease(kextPath
);
1717 OSSafeRelease(errorString
);
1718 OSSafeRelease(executable
);
1723 /*********************************************************************
1724 *********************************************************************/
1726 OSKext::registerIdentifier(void)
1728 bool result
= false;
1729 OSKext
* existingKext
= NULL
; // do not release
1730 bool existingIsLoaded
= false;
1731 bool existingIsPrelinked
= false;
1732 OSKextVersion newVersion
= -1;
1733 OSKextVersion existingVersion
= -1;
1734 char newVersionCString
[kOSKextVersionMaxLength
];
1735 char existingVersionCString
[kOSKextVersionMaxLength
];
1736 OSData
* newUUID
= NULL
; // must release
1737 OSData
* existingUUID
= NULL
; // must release
1739 IORecursiveLockLock(sKextLock
);
1741 /* Get the new kext's version for checks & log messages.
1743 newVersion
= getVersion();
1744 OSKextVersionGetString(newVersion
, newVersionCString
,
1745 kOSKextVersionMaxLength
);
1747 /* If we don't have an existing kext with this identifier,
1748 * just record the new kext and we're done!
1750 existingKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
));
1751 if (!existingKext
) {
1752 sKextsByID
->setObject(bundleID
, this);
1757 /* Get the existing kext's version for checks & log messages.
1759 existingVersion
= existingKext
->getVersion();
1760 OSKextVersionGetString(existingVersion
,
1761 existingVersionCString
, kOSKextVersionMaxLength
);
1763 existingIsLoaded
= existingKext
->isLoaded();
1764 existingIsPrelinked
= existingKext
->isPrelinked();
1766 /* If we have a kext with this identifier that's already loaded/prelinked,
1767 * we can't use the new one, but let's be really thorough and check how
1768 * the two are related for a precise diagnostic log message.
1770 * Note that user space can't find out about nonloaded prelinked kexts,
1771 * so in this case we log a message when new & existing are equivalent
1772 * at the step rather than warning level, because we are always going
1773 * be getting a copy of the kext in the user load request mkext.
1775 if (existingIsLoaded
|| existingIsPrelinked
) {
1776 bool sameVersion
= (newVersion
== existingVersion
);
1777 bool sameExecutable
= true; // assume true unless we have UUIDs
1779 /* Only get the UUID if the existing kext is loaded. Doing so
1780 * might have to uncompress an mkext executable and we shouldn't
1781 * take that hit when neither kext is loaded.
1783 newUUID
= copyUUID();
1784 existingUUID
= existingKext
->copyUUID();
1786 /* I'm entirely too paranoid about checking equivalence of executables,
1787 * but I remember nasty problems with it in the past.
1789 * - If we have UUIDs for both kexts, compare them.
1790 * - If only one kext has a UUID, they're definitely different.
1792 if (newUUID
&& existingUUID
) {
1793 sameExecutable
= newUUID
->isEqualTo(existingUUID
);
1794 } else if (newUUID
|| existingUUID
) {
1795 sameExecutable
= false;
1798 if (!newUUID
&& !existingUUID
) {
1800 /* If there are no UUIDs, we can't really tell that the executables
1801 * are *different* without a lot of work; the loaded kext's
1802 * unrelocated executable is no longer around (and we never had it
1803 * in-kernel for a prelinked kext). We certainly don't want to do
1804 * a whole fake link for the new kext just to compare, either.
1807 OSKextVersionGetString(version
, newVersionCString
,
1808 sizeof(newVersionCString
));
1810 kOSKextLogWarningLevel
|
1811 kOSKextLogKextBookkeepingFlag
,
1812 "Notice - new kext %s, v%s matches %s kext "
1813 "but can't determine if executables are the same (no UUIDs).",
1814 getIdentifierCString(),
1816 (existingIsLoaded
? "loaded" : "prelinked"));
1819 if (sameVersion
&& sameExecutable
) {
1821 (existingIsLoaded
? kOSKextLogWarningLevel
: kOSKextLogStepLevel
) |
1822 kOSKextLogKextBookkeepingFlag
,
1823 "Refusing new kext %s, v%s: a %s copy is already present "
1824 "(same version and executable).",
1825 getIdentifierCString(), newVersionCString
,
1826 (existingIsLoaded
? "loaded" : "prelinked"));
1829 /* This condition is significant so log it under warnings.
1832 kOSKextLogWarningLevel
|
1833 kOSKextLogKextBookkeepingFlag
,
1834 "Refusing new kext %s, v%s: already have %s v%s.",
1835 getIdentifierCString(),
1837 (existingIsLoaded
? "loaded" : "prelinked"),
1838 existingVersionCString
);
1840 /* This condition is significant so log it under warnings.
1843 kOSKextLogWarningLevel
| kOSKextLogKextBookkeepingFlag
,
1844 "Refusing new kext %s, v%s: a %s copy with a different "
1845 "executable UUID is already present.",
1846 getIdentifierCString(), newVersionCString
,
1847 (existingIsLoaded
? "loaded" : "prelinked"));
1851 } /* if (existingIsLoaded || existingIsPrelinked) */
1853 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
1854 * user loads are happening or if we're still in early boot. User agents are
1855 * supposed to resolve dependencies topside and include only the exact
1856 * kexts needed; so we always accept the new kext (in fact we should never
1857 * see an older unloaded copy hanging around).
1859 if (sUserLoadsActive
) {
1860 sKextsByID
->setObject(bundleID
, this);
1864 kOSKextLogStepLevel
|
1865 kOSKextLogKextBookkeepingFlag
,
1866 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
1867 getIdentifierCString(),
1868 existingVersionCString
,
1874 /* During early boot, the kext with the highest version always wins out.
1875 * Prelinked kernels will never hit this, but mkexts and booter-read
1876 * kexts might have duplicates.
1878 if (newVersion
> existingVersion
) {
1879 sKextsByID
->setObject(bundleID
, this);
1883 kOSKextLogStepLevel
|
1884 kOSKextLogKextBookkeepingFlag
,
1885 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
1886 existingVersionCString
,
1887 getIdentifierCString(),
1892 kOSKextLogStepLevel
|
1893 kOSKextLogKextBookkeepingFlag
,
1894 "Kext %s is already registered with a higher/same version (v%s); "
1895 "dropping newly-added (v%s).",
1896 getIdentifierCString(),
1897 existingVersionCString
,
1901 /* result has been set appropriately by now. */
1905 IORecursiveLockUnlock(sKextLock
);
1909 kOSKextLogStepLevel
|
1910 kOSKextLogKextBookkeepingFlag
,
1911 "Kext %s, v%s registered and available for loading.",
1912 getIdentifierCString(), newVersionCString
);
1915 OSSafeRelease(newUUID
);
1916 OSSafeRelease(existingUUID
);
1921 /*********************************************************************
1922 * Does the bare minimum validation to look up a kext.
1923 * All other validation is done on the spot as needed.
1924 **********************************************************************/
1926 OSKext::setInfoDictionaryAndPath(
1927 OSDictionary
* aDictionary
,
1930 bool result
= false;
1931 OSString
* bundleIDString
= NULL
; // do not release
1932 OSString
* versionString
= NULL
; // do not release
1933 OSString
* compatibleVersionString
= NULL
; // do not release
1934 const char * versionCString
= NULL
; // do not free
1935 const char * compatibleVersionCString
= NULL
; // do not free
1936 OSBoolean
* scratchBool
= NULL
; // do not release
1937 OSDictionary
* scratchDict
= NULL
; // do not release
1940 panic("Attempt to set info dictionary on a kext "
1941 "that already has one (%s).",
1942 getIdentifierCString());
1945 if (!aDictionary
|| !OSDynamicCast(OSDictionary
, aDictionary
)) {
1949 infoDict
= aDictionary
;
1952 /* Check right away if the info dictionary has any log flags.
1954 scratchBool
= OSDynamicCast(OSBoolean
,
1955 getPropertyForHostArch(kOSBundleEnableKextLoggingKey
));
1956 if (scratchBool
== kOSBooleanTrue
) {
1957 flags
.loggingEnabled
= 1;
1960 /* The very next thing to get is the bundle identifier. Unlike
1961 * in user space, a kext with no bundle identifier gets axed
1964 bundleIDString
= OSDynamicCast(OSString
,
1965 getPropertyForHostArch(kCFBundleIdentifierKey
));
1966 if (!bundleIDString
) {
1968 kOSKextLogErrorLevel
|
1969 kOSKextLogValidationFlag
,
1970 "CFBundleIdentifier missing/invalid type in kext %s.",
1971 aPath
? aPath
->getCStringNoCopy() : "(unknown)");
1974 bundleID
= OSSymbol::withString(bundleIDString
);
1977 kOSKextLogErrorLevel
|
1978 kOSKextLogValidationFlag
,
1979 "Can't copy bundle identifier as symbol for kext %s.",
1980 bundleIDString
->getCStringNoCopy());
1984 /* Save the path if we got one (it should always be available but it's
1985 * just something nice to have for bookkeeping).
1993 * Minimal validation to initialize. We'll do other validation on the spot.
1995 if (bundleID
->getLength() >= KMOD_MAX_NAME
) {
1997 kOSKextLogErrorLevel
|
1998 kOSKextLogValidationFlag
,
1999 "Kext %s error - CFBundleIdentifier over max length %d.",
2000 getIdentifierCString(), KMOD_MAX_NAME
- 1);
2004 version
= compatibleVersion
= -1;
2006 versionString
= OSDynamicCast(OSString
,
2007 getPropertyForHostArch(kCFBundleVersionKey
));
2008 if (!versionString
) {
2010 kOSKextLogErrorLevel
|
2011 kOSKextLogValidationFlag
,
2012 "Kext %s error - CFBundleVersion missing/invalid type.",
2013 getIdentifierCString());
2016 versionCString
= versionString
->getCStringNoCopy();
2017 version
= OSKextParseVersionString(versionCString
);
2020 kOSKextLogErrorLevel
|
2021 kOSKextLogValidationFlag
,
2022 "Kext %s error - CFBundleVersion bad value '%s'.",
2023 getIdentifierCString(), versionCString
);
2027 compatibleVersion
= -1; // set to illegal value for kexts that don't have
2029 compatibleVersionString
= OSDynamicCast(OSString
,
2030 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
2031 if (compatibleVersionString
) {
2032 compatibleVersionCString
= compatibleVersionString
->getCStringNoCopy();
2033 compatibleVersion
= OSKextParseVersionString(compatibleVersionCString
);
2034 if (compatibleVersion
< 0) {
2036 kOSKextLogErrorLevel
|
2037 kOSKextLogValidationFlag
,
2038 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2039 getIdentifierCString(), compatibleVersionCString
);
2043 if (compatibleVersion
> version
) {
2045 kOSKextLogErrorLevel
|
2046 kOSKextLogValidationFlag
,
2047 "Kext %s error - %s %s > %s %s (must be <=).",
2048 getIdentifierCString(),
2049 kOSBundleCompatibleVersionKey
, compatibleVersionCString
,
2050 kCFBundleVersionKey
, versionCString
);
2055 /* Check to see if this kext is in exclude list */
2056 if ( isInExcludeList() ) {
2058 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
2059 "Kext %s is in exclude list, not loadable",
2060 getIdentifierCString());
2064 /* Set flags for later use if the infoDict gets flushed. We only
2065 * check for true values, not false ones(!)
2067 scratchBool
= OSDynamicCast(OSBoolean
,
2068 getPropertyForHostArch(kOSBundleIsInterfaceKey
));
2069 if (scratchBool
== kOSBooleanTrue
) {
2070 flags
.interface
= 1;
2073 scratchBool
= OSDynamicCast(OSBoolean
,
2074 getPropertyForHostArch(kOSKernelResourceKey
));
2075 if (scratchBool
== kOSBooleanTrue
) {
2076 flags
.kernelComponent
= 1;
2077 flags
.interface
= 1; // xxx - hm. the kernel itself isn't an interface...
2080 /* A kernel component has one implicit dependency on the kernel.
2082 flags
.hasAllDependencies
= 1;
2085 /* Make sure common string values in personalities are uniqued to OSSymbols.
2087 scratchDict
= OSDynamicCast(OSDictionary
,
2088 getPropertyForHostArch(kIOKitPersonalitiesKey
));
2090 uniquePersonalityProperties(scratchDict
);
2100 /*********************************************************************
2101 * Not used for prelinked kernel boot as there is no unrelocated
2103 *********************************************************************/
2105 OSKext::setExecutable(
2106 OSData
* anExecutable
,
2107 OSData
* externalData
,
2108 bool externalDataIsMkext
)
2110 bool result
= false;
2111 const char * executableKey
= NULL
; // do not free
2113 if (!anExecutable
) {
2114 infoDict
->removeObject(_kOSKextExecutableKey
);
2115 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
2116 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
2121 if (infoDict
->getObject(_kOSKextExecutableKey
) ||
2122 infoDict
->getObject(_kOSKextMkextExecutableReferenceKey
)) {
2124 panic("Attempt to set an executable on a kext "
2125 "that already has one (%s).",
2126 getIdentifierCString());
2130 if (externalDataIsMkext
) {
2131 executableKey
= _kOSKextMkextExecutableReferenceKey
;
2133 executableKey
= _kOSKextExecutableKey
;
2137 infoDict
->setObject(executableKey
, anExecutable
);
2139 infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
);
2149 /*********************************************************************
2150 *********************************************************************/
2152 uniqueStringPlistProperty(OSDictionary
* dict
, const char * key
)
2154 OSString
* stringValue
= NULL
; // do not release
2155 const OSSymbol
* symbolValue
= NULL
; // must release
2157 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2162 symbolValue
= OSSymbol::withString(stringValue
);
2167 dict
->setObject(key
, symbolValue
);
2170 if (symbolValue
) symbolValue
->release();
2175 /*********************************************************************
2176 *********************************************************************/
2178 uniqueStringPlistProperty(OSDictionary
* dict
, const OSString
* key
)
2180 OSString
* stringValue
= NULL
; // do not release
2181 const OSSymbol
* symbolValue
= NULL
; // must release
2183 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2188 symbolValue
= OSSymbol::withString(stringValue
);
2193 dict
->setObject(key
, symbolValue
);
2196 if (symbolValue
) symbolValue
->release();
2201 /*********************************************************************
2202 * Replace common personality property values with uniqued instances
2203 * to save on wired memory.
2204 *********************************************************************/
2207 OSKext::uniquePersonalityProperties(OSDictionary
* personalityDict
)
2209 /* Properties every personality has.
2211 uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKey
);
2212 uniqueStringPlistProperty(personalityDict
, kIOProviderClassKey
);
2213 uniqueStringPlistProperty(personalityDict
, gIOClassKey
);
2215 /* Other commonly used properties.
2217 uniqueStringPlistProperty(personalityDict
, gIOMatchCategoryKey
);
2218 uniqueStringPlistProperty(personalityDict
, gIOResourceMatchKey
);
2219 uniqueStringPlistProperty(personalityDict
, gIOUserClientClassKey
);
2221 uniqueStringPlistProperty(personalityDict
, "HIDDefaultBehavior");
2222 uniqueStringPlistProperty(personalityDict
, "HIDPointerAccelerationType");
2223 uniqueStringPlistProperty(personalityDict
, "HIDRemoteControlType");
2224 uniqueStringPlistProperty(personalityDict
, "HIDScrollAccelerationType");
2225 uniqueStringPlistProperty(personalityDict
, "IOPersonalityPublisher");
2226 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect");
2227 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect Location");
2228 uniqueStringPlistProperty(personalityDict
, "Vendor");
2229 uniqueStringPlistProperty(personalityDict
, "Vendor Identification");
2230 uniqueStringPlistProperty(personalityDict
, "Vendor Name");
2231 uniqueStringPlistProperty(personalityDict
, "bConfigurationValue");
2232 uniqueStringPlistProperty(personalityDict
, "bInterfaceNumber");
2233 uniqueStringPlistProperty(personalityDict
, "idProduct");
2238 /*********************************************************************
2239 *********************************************************************/
2244 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2247 OSSafeRelease(infoDict
);
2248 OSSafeRelease(bundleID
);
2249 OSSafeRelease(path
);
2250 OSSafeRelease(executableRelPath
);
2251 OSSafeRelease(dependencies
);
2252 OSSafeRelease(linkedExecutable
);
2253 OSSafeRelease(metaClasses
);
2254 OSSafeRelease(interfaceUUID
);
2256 if (isInterface() && kmod_info
) {
2257 kfree(kmod_info
, sizeof(kmod_info_t
));
2265 #pragma mark Mkext files
2267 /*********************************************************************
2268 *********************************************************************/
2270 OSKext::readMkextArchive(OSData
* mkextData
,
2271 uint32_t * checksumPtr
)
2273 OSReturn result
= kOSKextReturnBadData
;
2274 uint32_t mkextLength
= 0;
2275 mkext_header
* mkextHeader
= 0; // do not free
2276 uint32_t mkextVersion
= 0;
2278 /* Note default return of kOSKextReturnBadData above.
2280 mkextLength
= mkextData
->getLength();
2281 if (mkextLength
< sizeof(mkext_basic_header
)) {
2282 OSKextLog(/* kext */ NULL
,
2283 kOSKextLogErrorLevel
|
2284 kOSKextLogArchiveFlag
,
2285 "Mkext archive too small to be valid.");
2289 mkextHeader
= (mkext_header
*)mkextData
->getBytesNoCopy();
2291 if (MKEXT_GET_MAGIC(mkextHeader
) != MKEXT_MAGIC
||
2292 MKEXT_GET_SIGNATURE(mkextHeader
) != MKEXT_SIGN
) {
2293 OSKextLog(/* kext */ NULL
,
2294 kOSKextLogErrorLevel
|
2295 kOSKextLogArchiveFlag
,
2296 "Mkext archive has invalid magic or signature.");
2300 if (MKEXT_GET_LENGTH(mkextHeader
) != mkextLength
) {
2301 OSKextLog(/* kext */ NULL
,
2302 kOSKextLogErrorLevel
|
2303 kOSKextLogArchiveFlag
,
2304 "Mkext archive recorded length doesn't match actual file length.");
2308 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2310 if (mkextVersion
== MKEXT_VERS_2
) {
2311 result
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
);
2312 } else if (mkextVersion
== MKEXT_VERS_1
) {
2313 result
= OSKext::readMkext1Archive(mkextData
, checksumPtr
);
2315 OSKextLog(/* kext */ NULL
,
2316 kOSKextLogErrorLevel
|
2317 kOSKextLogArchiveFlag
,
2318 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
);
2319 result
= kOSKextReturnUnsupported
;
2326 /*********************************************************************
2327 * Assumes magic, signature, version, length have been checked.
2329 * Doesn't do as much bounds-checking as it should, but we're dropping
2330 * mkext1 support from the kernel for SnowLeopard soon.
2332 * Should keep track of all kexts created so far, and if we hit a
2333 * fatal error halfway through, remove those kexts. If we've dropped
2334 * an older version that had already been read, whoops! Might want to
2335 * add a level of buffering?
2336 *********************************************************************/
2339 OSKext::readMkext1Archive(
2341 uint32_t * checksumPtr
)
2343 OSReturn result
= kOSReturnError
;
2344 uint32_t mkextLength
;
2345 mkext1_header
* mkextHeader
= 0; // do not free
2346 void * mkextEnd
= 0; // do not free
2347 uint32_t mkextVersion
;
2348 uint8_t * crc_address
= 0;
2350 uint32_t numKexts
= 0;
2352 OSData
* infoDictDataObject
= NULL
; // must release
2353 OSObject
* parsedXML
= NULL
; // must release
2354 OSDictionary
* infoDict
= NULL
; // do not release
2355 OSString
* errorString
= NULL
; // must release
2356 OSData
* mkextExecutableInfo
= NULL
; // must release
2357 OSKext
* theKext
= NULL
; // must release
2359 mkextLength
= mkextData
->getLength();
2360 mkextHeader
= (mkext1_header
*)mkextData
->getBytesNoCopy();
2361 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2362 mkextVersion
= OSSwapBigToHostInt32(mkextHeader
->version
);
2364 crc_address
= (u_int8_t
*)&mkextHeader
->version
;
2365 checksum
= mkext_adler32(crc_address
,
2366 (uintptr_t)mkextHeader
+
2367 OSSwapBigToHostInt32(mkextHeader
->length
) - (uintptr_t)crc_address
);
2369 if (OSSwapBigToHostInt32(mkextHeader
->adler32
) != checksum
) {
2370 OSKextLog(/* kext */ NULL
,
2371 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2372 "Kext archive has a bad checksum.");
2373 result
= kOSKextReturnBadData
;
2378 *checksumPtr
= checksum
;
2381 /* Check that the CPU type & subtype match that of the running kernel. */
2382 if (OSSwapBigToHostInt32(mkextHeader
->cputype
) != (UInt32
)CPU_TYPE_ANY
) {
2383 if ((UInt32
)_mh_execute_header
.cputype
!=
2384 OSSwapBigToHostInt32(mkextHeader
->cputype
)) {
2386 OSKextLog(/* kext */ NULL
,
2387 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2388 "Kext archive doesn't contain software "
2389 "for this computer's CPU type.");
2390 result
= kOSKextReturnArchNotFound
;
2395 numKexts
= OSSwapBigToHostInt32(mkextHeader
->numkexts
);
2397 for (uint32_t i
= 0; i
< numKexts
; i
++) {
2399 OSSafeReleaseNULL(infoDictDataObject
);
2400 OSSafeReleaseNULL(infoDict
);
2401 OSSafeReleaseNULL(mkextExecutableInfo
);
2402 OSSafeReleaseNULL(errorString
);
2403 OSSafeReleaseNULL(theKext
);
2405 mkext_kext
* kextEntry
= &mkextHeader
->kext
[i
];
2406 mkext_file
* infoDictPtr
= &kextEntry
->plist
;
2407 mkext_file
* executablePtr
= &kextEntry
->module;
2408 if (kextEntry
>= mkextEnd
) {
2409 OSKextLog(/* kext */ NULL
,
2410 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2411 "Mkext file overrun.");
2412 result
= kOSKextReturnBadData
;
2416 /* Note that we're pretty tolerant of errors in individual entries.
2417 * As long as we can keep processing, we do.
2419 infoDictDataObject
= OSKext::extractMkext1Entry(
2420 mkextHeader
, infoDictPtr
);
2421 if (!infoDictDataObject
) {
2422 OSKextLog(/* kext */ NULL
,
2423 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2424 "Can't uncompress info dictionary "
2425 "from mkext archive entry %d.", i
);
2429 parsedXML
= OSUnserializeXML(
2430 (const char *)infoDictDataObject
->getBytesNoCopy(),
2433 infoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
2436 const char * errorCString
= "(unknown error)";
2438 if (errorString
&& errorString
->getCStringNoCopy()) {
2439 errorCString
= errorString
->getCStringNoCopy();
2440 } else if (parsedXML
) {
2441 errorCString
= "not a dictionary";
2443 OSKextLog(/* kext */ NULL
,
2444 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2445 "Error: Can't read XML property list "
2446 "for mkext archive entry %d: %s.", i
, errorCString
);
2450 theKext
= new OSKext
;
2452 OSKextLog(/* kext */ NULL
,
2453 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2454 "Kext allocation failure.");
2459 * Prepare an entry to hold the mkext entry info for the
2460 * compressed binary module, if there is one. If all four fields
2461 * of the module entry are zero, there isn't one.
2463 if ((OSSwapBigToHostInt32(executablePtr
->offset
) ||
2464 OSSwapBigToHostInt32(executablePtr
->compsize
) ||
2465 OSSwapBigToHostInt32(executablePtr
->realsize
) ||
2466 OSSwapBigToHostInt32(executablePtr
->modifiedsecs
))) {
2468 MkextEntryRef entryRef
;
2470 mkextExecutableInfo
= OSData::withCapacity(sizeof(entryRef
));
2471 if (!mkextExecutableInfo
) {
2472 panic("Error: Couldn't allocate data object "
2473 "for mkext archive entry %d.\n", i
);
2476 entryRef
.mkext
= (mkext_basic_header
*)mkextHeader
;
2477 entryRef
.fileinfo
= (uint8_t *)executablePtr
;
2478 if (!mkextExecutableInfo
->appendBytes(&entryRef
,
2479 sizeof(entryRef
))) {
2481 OSKextLog(/* kext */ NULL
,
2482 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2483 "Couldn't record executable info "
2484 "for mkext archive entry %d.", i
);
2485 // we might hit a load error later but oh well
2486 // xxx - should probably remove theKext
2492 /* Init can fail because of a data/runtime error, or because the
2493 * kext is a dup. Either way, we don't care here.
2495 if (!theKext
->initWithMkext1Info(infoDict
, mkextExecutableInfo
,
2498 // theKext is released at the top of the loop or in the finish block
2502 /* If we got even one kext out of the mkext archive,
2503 * we have successfully read the archive, in that we
2504 * have data references into its mapped memory.
2506 result
= kOSReturnSuccess
;
2511 OSSafeRelease(infoDictDataObject
);
2512 OSSafeRelease(parsedXML
);
2513 OSSafeRelease(errorString
);
2514 OSSafeRelease(mkextExecutableInfo
);
2515 OSSafeRelease(theKext
);
2520 /*********************************************************************
2521 *********************************************************************/
2523 OSKext::initWithMkext1Info(
2524 OSDictionary
* anInfoDict
,
2525 OSData
* executableWrapper
,
2528 bool result
= false;
2530 // mkext1 doesn't allow for path (might stuff in info dict)
2531 if (!setInfoDictionaryAndPath(anInfoDict
, /* path */ NULL
)) {
2535 if (!registerIdentifier()) {
2539 if (!setExecutable(executableWrapper
, mkextData
, true)) {
2547 /* If we can't init, remove the kext from the lookup dictionary.
2548 * This is safe to call in init because there's an implicit retain.
2551 OSKext::removeKext(this, /* removePersonalities? */ false);
2557 /*********************************************************************
2558 * xxx - this should take the input data length
2559 *********************************************************************/
2562 OSKext::extractMkext1Entry(
2563 const void * mkextFileBase
,
2566 OSData
* result
= NULL
;
2567 OSData
* uncompressedData
= NULL
; // release on error
2568 const char * errmsg
= NULL
;
2570 mkext_file
* fileinfo
;
2571 uint8_t * uncompressedDataBuffer
= 0; // do not free (panic on alloc. fail)
2572 size_t uncompressed_size
= 0;
2573 kern_return_t kern_result
;
2575 fileinfo
= (mkext_file
*)entry
;
2577 size_t offset
= OSSwapBigToHostInt32(fileinfo
->offset
);
2578 size_t compressed_size
= OSSwapBigToHostInt32(fileinfo
->compsize
);
2579 size_t expected_size
= OSSwapBigToHostInt32(fileinfo
->realsize
);
2581 // Add 1 for '\0' to terminate XML string (for plists)
2582 // (we really should have the archive format include that).
2583 size_t alloc_size
= expected_size
+ 1;
2584 time_t modifiedsecs
= OSSwapBigToHostInt32(fileinfo
->modifiedsecs
);
2586 /* If these four fields are zero there's no file, but it's up to
2587 * the calling context to decide if that's an error.
2589 if (offset
== 0 && compressed_size
== 0 &&
2590 expected_size
== 0 && modifiedsecs
== 0) {
2594 kern_result
= kmem_alloc(kernel_map
,
2595 (vm_offset_t
*)&uncompressedDataBuffer
,
2597 if (kern_result
!= KERN_SUCCESS
) {
2602 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
,
2604 if (uncompressedData
== NULL
) {
2605 /* No need to free uncompressedDataBuffer here, either. */
2609 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
2611 /* Do the decompression if necessary. Note that even if the file isn't
2612 * compressed, we want to make a copy so that we don't have the tie to
2613 * the larger mkext file buffer any more.
2614 * xxx - need to detect decompression overflow too
2616 if (compressed_size
!= 0) {
2617 errmsg
= "OSKext::uncompressMkext - "
2618 "uncompressed file shorter than expected";
2619 uncompressed_size
= decompress_lzss(uncompressedDataBuffer
,
2621 ((uint8_t *)mkextFileBase
) + offset
,
2623 if (uncompressed_size
!= expected_size
) {
2627 memcpy(uncompressedDataBuffer
,
2628 ((uint8_t *)mkextFileBase
) + offset
,
2632 // Add a terminating nul character in case the data is XML.
2633 // (we really should have the archive format include that).
2634 uncompressedDataBuffer
[expected_size
] = '\0';
2636 result
= uncompressedData
;
2641 OSKextLog(/* kext */ NULL
,
2642 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2645 if (uncompressedData
) {
2646 uncompressedData
->release();
2652 /*********************************************************************
2653 * Assumes magic, signature, version, length have been checked.
2654 * xxx - need to add further bounds checking for each file entry
2656 * Should keep track of all kexts created so far, and if we hit a
2657 * fatal error halfway through, remove those kexts. If we've dropped
2658 * an older version that had already been read, whoops! Might want to
2659 * add a level of buffering?
2660 *********************************************************************/
2663 OSKext::readMkext2Archive(
2665 OSDictionary
** mkextPlistOut
,
2666 uint32_t * checksumPtr
)
2668 OSReturn result
= kOSReturnError
;
2669 uint32_t mkextLength
;
2670 mkext2_header
* mkextHeader
= NULL
; // do not free
2671 void * mkextEnd
= NULL
; // do not free
2672 uint32_t mkextVersion
;
2673 uint8_t * crc_address
= NULL
;
2675 uint32_t mkextPlistOffset
;
2676 uint32_t mkextPlistCompressedSize
;
2677 char * mkextPlistEnd
= NULL
; // do not free
2678 uint32_t mkextPlistFullSize
;
2679 OSString
* errorString
= NULL
; // must release
2680 OSData
* mkextPlistUncompressedData
= NULL
; // must release
2681 const char * mkextPlistDataBuffer
= NULL
; // do not free
2682 OSObject
* parsedXML
= NULL
; // must release
2683 OSDictionary
* mkextPlist
= NULL
; // do not release
2684 OSArray
* mkextInfoDictArray
= NULL
; // do not release
2687 mkextLength
= mkextData
->getLength();
2688 mkextHeader
= (mkext2_header
*)mkextData
->getBytesNoCopy();
2689 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2690 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2692 crc_address
= (u_int8_t
*)&mkextHeader
->version
;
2693 checksum
= mkext_adler32(crc_address
,
2694 (uintptr_t)mkextHeader
+
2695 MKEXT_GET_LENGTH(mkextHeader
) - (uintptr_t)crc_address
);
2697 if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) {
2698 OSKextLog(/* kext */ NULL
,
2699 kOSKextLogErrorLevel
|
2700 kOSKextLogArchiveFlag
,
2701 "Mkext archive has bad checksum.");
2702 result
= kOSKextReturnBadData
;
2707 *checksumPtr
= checksum
;
2710 /* Check that the CPU type & subtype match that of the running kernel. */
2711 if (MKEXT_GET_CPUTYPE(mkextHeader
) == (UInt32
)CPU_TYPE_ANY
) {
2712 OSKextLog(/* kext */ NULL
,
2713 kOSKextLogErrorLevel
|
2714 kOSKextLogArchiveFlag
,
2715 "Mkext archive must have a specific CPU type.");
2716 result
= kOSKextReturnBadData
;
2719 if ((UInt32
)_mh_execute_header
.cputype
!=
2720 MKEXT_GET_CPUTYPE(mkextHeader
)) {
2722 OSKextLog(/* kext */ NULL
,
2723 kOSKextLogErrorLevel
|
2724 kOSKextLogArchiveFlag
,
2725 "Mkext archive does not match the running kernel's CPU type.");
2726 result
= kOSKextReturnArchNotFound
;
2731 mkextPlistOffset
= MKEXT2_GET_PLIST(mkextHeader
);
2732 mkextPlistCompressedSize
= MKEXT2_GET_PLIST_COMPSIZE(mkextHeader
);
2733 mkextPlistEnd
= (char *)mkextHeader
+ mkextPlistOffset
+
2734 mkextPlistCompressedSize
;
2735 if (mkextPlistEnd
> mkextEnd
) {
2736 OSKextLog(/* kext */ NULL
,
2737 kOSKextLogErrorLevel
|
2738 kOSKextLogArchiveFlag
,
2739 "Mkext archive file overrun.");
2740 result
= kOSKextReturnBadData
;
2743 mkextPlistFullSize
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
);
2744 if (mkextPlistCompressedSize
) {
2745 mkextPlistUncompressedData
= sKernelKext
->extractMkext2FileData(
2746 (UInt8
*)mkextHeader
+ mkextPlistOffset
,
2748 mkextPlistCompressedSize
, mkextPlistFullSize
);
2749 if (!mkextPlistUncompressedData
) {
2752 mkextPlistDataBuffer
= (const char *)
2753 mkextPlistUncompressedData
->getBytesNoCopy();
2755 mkextPlistDataBuffer
= (const char *)mkextHeader
+ mkextPlistOffset
;
2758 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2760 parsedXML
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
);
2762 mkextPlist
= OSDynamicCast(OSDictionary
, parsedXML
);
2765 const char * errorCString
= "(unknown error)";
2767 if (errorString
&& errorString
->getCStringNoCopy()) {
2768 errorCString
= errorString
->getCStringNoCopy();
2769 } else if (parsedXML
) {
2770 errorCString
= "not a dictionary";
2772 OSKextLog(/* kext */ NULL
,
2773 kOSKextLogErrorLevel
|
2774 kOSKextLogArchiveFlag
,
2775 "Error unserializing mkext plist: %s.", errorCString
);
2779 /* If the caller needs the plist, hand it back and retain it.
2780 * (This function releases it at the end.)
2782 if (mkextPlistOut
) {
2783 *mkextPlistOut
= mkextPlist
;
2784 (*mkextPlistOut
)->retain();
2787 mkextInfoDictArray
= OSDynamicCast(OSArray
,
2788 mkextPlist
->getObject(kMKEXTInfoDictionariesKey
));
2789 if (!mkextInfoDictArray
) {
2790 OSKextLog(/* kext */ NULL
,
2791 kOSKextLogErrorLevel
|
2792 kOSKextLogArchiveFlag
,
2793 "Mkext archive contains no kext info dictionaries.");
2797 count
= mkextInfoDictArray
->getCount();
2798 for (i
= 0; i
< count
; i
++) {
2799 OSDictionary
* infoDict
;
2802 infoDict
= OSDynamicCast(OSDictionary
,
2803 mkextInfoDictArray
->getObject(i
));
2805 /* Create the kext for the entry, then release it, because the
2806 * kext system keeps them around until explicitly removed.
2807 * Any creation/registration failures are already logged for us.
2809 OSKext
* newKext
= OSKext::withMkext2Info(infoDict
, mkextData
);
2810 OSSafeRelease(newKext
);
2813 /* Even if we didn't keep any kexts from the mkext, we may have a load
2814 * request to process, so we are successful (no errors occurred).
2816 result
= kOSReturnSuccess
;
2820 OSSafeRelease(parsedXML
);
2821 OSSafeRelease(mkextPlistUncompressedData
);
2822 OSSafeRelease(errorString
);
2827 /*********************************************************************
2828 *********************************************************************/
2831 OSKext::withMkext2Info(
2832 OSDictionary
* anInfoDict
,
2835 OSKext
* newKext
= new OSKext
;
2837 if (newKext
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) {
2845 /*********************************************************************
2846 *********************************************************************/
2848 OSKext::initWithMkext2Info(
2849 OSDictionary
* anInfoDict
,
2852 bool result
= false;
2853 OSString
* kextPath
= NULL
; // do not release
2854 OSNumber
* executableOffsetNum
= NULL
; // do not release
2855 OSCollectionIterator
* iterator
= NULL
; // must release
2856 OSData
* executable
= NULL
; // must release
2858 if (!super::init()) {
2862 /* Get the path. Don't look for an arch-specific path property.
2864 kextPath
= OSDynamicCast(OSString
,
2865 anInfoDict
->getObject(kMKEXTBundlePathKey
));
2867 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
2871 /* If we have a path to the executable, save it.
2873 executableRelPath
= OSDynamicCast(OSString
,
2874 anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
));
2875 if (executableRelPath
) {
2876 executableRelPath
->retain();
2879 /* Don't need the paths to be in the info dictionary any more.
2881 anInfoDict
->removeObject(kMKEXTBundlePathKey
);
2882 anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
);
2884 executableOffsetNum
= OSDynamicCast(OSNumber
,
2885 infoDict
->getObject(kMKEXTExecutableKey
));
2886 if (executableOffsetNum
) {
2887 executable
= createMkext2FileEntry(mkextData
,
2888 executableOffsetNum
, "executable");
2889 infoDict
->removeObject(kMKEXTExecutableKey
);
2893 if (!setExecutable(executable
, mkextData
, true)) {
2898 result
= registerIdentifier();
2902 OSSafeRelease(executable
);
2903 OSSafeRelease(iterator
);
2907 /*********************************************************************
2908 *********************************************************************/
2910 OSKext::createMkext2FileEntry(
2912 OSNumber
* offsetNum
,
2915 OSData
* result
= NULL
;
2916 MkextEntryRef entryRef
;
2917 uint8_t * mkextBuffer
= (uint8_t *)mkextData
->getBytesNoCopy();
2918 uint32_t entryOffset
= offsetNum
->unsigned32BitValue();
2920 result
= OSData::withCapacity(sizeof(entryRef
));
2925 entryRef
.mkext
= (mkext_basic_header
*)mkextBuffer
;
2926 entryRef
.fileinfo
= mkextBuffer
+ entryOffset
;
2927 if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) {
2928 OSSafeReleaseNULL(result
);
2935 kOSKextLogErrorLevel
|
2936 kOSKextLogArchiveFlag
,
2937 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2938 name
, getIdentifierCString());
2943 /*********************************************************************
2944 *********************************************************************/
2946 static void * z_alloc(void *, u_int items
, u_int size
);
2947 static void z_free(void *, void *ptr
);
2949 typedef struct z_mem
{
2950 uint32_t alloc_size
;
2955 * Space allocation and freeing routines for use by zlib routines.
2958 z_alloc(void * notused __unused
, u_int num_items
, u_int size
)
2960 void * result
= NULL
;
2961 z_mem
* zmem
= NULL
;
2962 uint32_t total
= num_items
* size
;
2963 uint32_t allocSize
= total
+ sizeof(zmem
);
2965 zmem
= (z_mem
*)kalloc(allocSize
);
2969 zmem
->alloc_size
= allocSize
;
2970 result
= (void *)&(zmem
->data
);
2976 z_free(void * notused __unused
, void * ptr
)
2978 uint32_t * skipper
= (uint32_t *)ptr
- 1;
2979 z_mem
* zmem
= (z_mem
*)skipper
;
2980 kfree((void *)zmem
, zmem
->alloc_size
);
2986 OSKext::extractMkext2FileData(
2989 uint32_t compressedSize
,
2992 OSData
* result
= NULL
;
2994 OSData
* uncompressedData
= NULL
; // release on error
2996 uint8_t * uncompressedDataBuffer
= 0; // do not free
2997 unsigned long uncompressedSize
;
2999 bool zstream_inited
= false;
3002 /* If the file isn't compressed, we want to make a copy
3003 * so that we don't have the tie to the larger mkext file buffer any more.
3005 if (!compressedSize
) {
3006 uncompressedData
= OSData::withBytes(data
, fullSize
);
3007 // xxx - no check for failure?
3008 result
= uncompressedData
;
3012 if (KERN_SUCCESS
!= kmem_alloc(kernel_map
,
3013 (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
)) {
3015 /* How's this for cheesy? The kernel is only asked to extract
3016 * kext plists so we tailor the log messages.
3020 kOSKextLogErrorLevel
|
3021 kOSKextLogArchiveFlag
,
3022 "Allocation failure extracting %s from mkext.", name
);
3025 kOSKextLogErrorLevel
|
3026 kOSKextLogArchiveFlag
,
3027 "Allocation failure extracting %s from mkext for kext %s.",
3028 name
, getIdentifierCString());
3033 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
);
3034 if (!uncompressedData
) {
3037 kOSKextLogErrorLevel
|
3038 kOSKextLogArchiveFlag
,
3039 "Allocation failure extracting %s from mkext.", name
);
3042 kOSKextLogErrorLevel
|
3043 kOSKextLogArchiveFlag
,
3044 "Allocation failure extracting %s from mkext for kext %s.",
3045 name
, getIdentifierCString());
3049 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
3053 kOSKextLogDetailLevel
|
3054 kOSKextLogArchiveFlag
,
3055 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3056 name
, compressedSize
, fullSize
);
3059 kOSKextLogDetailLevel
|
3060 kOSKextLogArchiveFlag
,
3061 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3062 getIdentifierCString(), name
, compressedSize
, fullSize
);
3065 bzero(&zstream
, sizeof(zstream
));
3066 zstream
.next_in
= (UInt8
*)data
;
3067 zstream
.avail_in
= compressedSize
;
3069 zstream
.next_out
= uncompressedDataBuffer
;
3070 zstream
.avail_out
= fullSize
;
3072 zstream
.zalloc
= z_alloc
;
3073 zstream
.zfree
= z_free
;
3075 zlib_result
= inflateInit(&zstream
);
3076 if (Z_OK
!= zlib_result
) {
3079 kOSKextLogErrorLevel
|
3080 kOSKextLogArchiveFlag
,
3081 "Mkext error; zlib inflateInit failed (%d) for %s.",
3085 kOSKextLogErrorLevel
|
3086 kOSKextLogArchiveFlag
,
3087 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3088 getIdentifierCString(), zlib_result
, name
);
3092 zstream_inited
= true;
3095 zlib_result
= inflate(&zstream
, Z_FINISH
);
3097 if (zlib_result
== Z_STREAM_END
|| zlib_result
== Z_OK
) {
3098 uncompressedSize
= zstream
.total_out
;
3102 kOSKextLogErrorLevel
|
3103 kOSKextLogArchiveFlag
,
3104 "Mkext error; zlib inflate failed (%d) for %s.",
3108 kOSKextLogErrorLevel
|
3109 kOSKextLogArchiveFlag
,
3110 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3111 getIdentifierCString(), zlib_result
, name
);
3115 kOSKextLogErrorLevel
|
3116 kOSKextLogArchiveFlag
,
3117 "zlib error: %s.", zstream
.msg
);
3122 if (uncompressedSize
!= fullSize
) {
3125 kOSKextLogErrorLevel
|
3126 kOSKextLogArchiveFlag
,
3127 "Mkext error; zlib inflate discrepancy for %s, "
3128 "uncompressed size != original size.", name
);
3131 kOSKextLogErrorLevel
|
3132 kOSKextLogArchiveFlag
,
3133 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3134 "uncompressed size != original size.",
3135 getIdentifierCString(), name
);
3140 result
= uncompressedData
;
3143 /* Don't bother checking return, nothing we can do on fail.
3145 if (zstream_inited
) inflateEnd(&zstream
);
3148 OSSafeRelease(uncompressedData
);
3154 /*********************************************************************
3155 *********************************************************************/
3158 OSKext::loadFromMkext(
3159 OSKextLogSpec clientLogFilter
,
3161 uint32_t mkextBufferLength
,
3163 uint32_t * logInfoLengthOut
)
3165 OSReturn result
= kOSReturnError
;
3166 OSReturn tempResult
= kOSReturnError
;
3168 OSData
* mkextData
= NULL
; // must release
3169 OSDictionary
* mkextPlist
= NULL
; // must release
3171 OSArray
* logInfoArray
= NULL
; // must release
3172 OSSerialize
* serializer
= NULL
; // must release
3174 OSString
* predicate
= NULL
; // do not release
3175 OSDictionary
* requestArgs
= NULL
; // do not release
3177 OSString
* kextIdentifier
= NULL
; // do not release
3178 OSNumber
* startKextExcludeNum
= NULL
; // do not release
3179 OSNumber
* startMatchingExcludeNum
= NULL
; // do not release
3180 OSBoolean
* delayAutounloadBool
= NULL
; // do not release
3181 OSArray
* personalityNames
= NULL
; // do not release
3183 /* Default values for these two options: regular autounload behavior,
3184 * load all kexts, send no personalities.
3186 Boolean delayAutounload
= false;
3187 OSKextExcludeLevel startKextExcludeLevel
= kOSKextExcludeNone
;
3188 OSKextExcludeLevel startMatchingExcludeLevel
= kOSKextExcludeAll
;
3190 IORecursiveLockLock(sKextLock
);
3194 *logInfoLengthOut
= 0;
3197 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
3199 OSKextLog(/* kext */ NULL
,
3200 kOSKextLogDebugLevel
|
3202 "Received kext load request from user space.");
3204 /* Regardless of processing, the fact that we have gotten here means some
3205 * user-space program is up and talking to us, so we'll switch our kext
3206 * registration to reflect that.
3208 if (!sUserLoadsActive
) {
3209 OSKextLog(/* kext */ NULL
,
3210 kOSKextLogProgressLevel
|
3211 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
3212 "Switching to late startup (user-space) kext loading policy.");
3214 sUserLoadsActive
= true;
3217 if (!sLoadEnabled
) {
3218 OSKextLog(/* kext */ NULL
,
3219 kOSKextLogErrorLevel
|
3221 "Kext loading is disabled.");
3222 result
= kOSKextReturnDisabled
;
3226 /* Note that we do not set a dealloc function on this OSData
3227 * object! No references to it can remain after the loadFromMkext()
3228 * call since we are in a MIG function, and will vm_deallocate()
3231 mkextData
= OSData::withBytesNoCopy(mkextBuffer
,
3234 OSKextLog(/* kext */ NULL
,
3235 kOSKextLogErrorLevel
|
3236 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3237 "Failed to create wrapper for kext load request.");
3238 result
= kOSKextReturnNoMemory
;
3242 result
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
);
3243 if (result
!= kOSReturnSuccess
) {
3244 OSKextLog(/* kext */ NULL
,
3245 kOSKextLogErrorLevel
|
3247 "Failed to read kext load request.");
3251 predicate
= _OSKextGetRequestPredicate(mkextPlist
);
3252 if (!predicate
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) {
3253 OSKextLog(/* kext */ NULL
,
3254 kOSKextLogErrorLevel
|
3256 "Received kext load request with no predicate; skipping.");
3257 result
= kOSKextReturnInvalidArgument
;
3261 requestArgs
= OSDynamicCast(OSDictionary
,
3262 mkextPlist
->getObject(kKextRequestArgumentsKey
));
3263 if (!requestArgs
|| !requestArgs
->getCount()) {
3264 OSKextLog(/* kext */ NULL
,
3265 kOSKextLogErrorLevel
|
3267 "Received kext load request with no arguments.");
3268 result
= kOSKextReturnInvalidArgument
;
3272 kextIdentifier
= OSDynamicCast(OSString
,
3273 requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
));
3274 if (!kextIdentifier
) {
3275 OSKextLog(/* kext */ NULL
,
3276 kOSKextLogErrorLevel
|
3278 "Received kext load request with no kext identifier.");
3279 result
= kOSKextReturnInvalidArgument
;
3283 startKextExcludeNum
= OSDynamicCast(OSNumber
,
3284 requestArgs
->getObject(kKextRequestArgumentStartExcludeKey
));
3285 startMatchingExcludeNum
= OSDynamicCast(OSNumber
,
3286 requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
));
3287 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
3288 requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
));
3289 personalityNames
= OSDynamicCast(OSArray
,
3290 requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
));
3292 if (delayAutounloadBool
) {
3293 delayAutounload
= delayAutounloadBool
->getValue();
3295 if (startKextExcludeNum
) {
3296 startKextExcludeLevel
= startKextExcludeNum
->unsigned8BitValue();
3298 if (startMatchingExcludeNum
) {
3299 startMatchingExcludeLevel
= startMatchingExcludeNum
->unsigned8BitValue();
3302 OSKextLog(/* kext */ NULL
,
3303 kOSKextLogProgressLevel
|
3305 "Received request from user space to load kext %s.",
3306 kextIdentifier
->getCStringNoCopy());
3308 /* Load the kext, with no deferral, since this is a load from outside
3310 * xxx - Would like a better way to handle the default values for the
3311 * xxx - start/match opt args.
3313 result
= OSKext::loadKextWithIdentifier(
3315 /* allowDefer */ false,
3317 startKextExcludeLevel
,
3318 startMatchingExcludeLevel
,
3320 if (result
!= kOSReturnSuccess
) {
3323 /* If the load came down from kextd, it will shortly inform IOCatalogue
3324 * for matching via a separate IOKit calldown.
3329 /* Gather up the collected log messages for user space. Any
3330 * error messages past this call will not make it up as log messages
3331 * but will be in the system log.
3333 logInfoArray
= OSKext::clearUserSpaceLogFilter();
3335 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
3336 tempResult
= OSKext::serializeLogInfo(logInfoArray
,
3337 logInfoOut
, logInfoLengthOut
);
3338 if (tempResult
!= kOSReturnSuccess
) {
3339 result
= tempResult
;
3343 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3345 /* Note: mkextDataObject will have been retained by every kext w/an
3346 * executable in it. That should all have been flushed out at the
3347 * and of the load operation, but you never know....
3349 if (mkextData
&& mkextData
->getRetainCount() > 1) {
3350 OSKextLog(/* kext */ NULL
,
3351 kOSKextLogErrorLevel
|
3352 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3353 "Kext load request buffer from user space still retained by a kext; "
3354 "probable memory leak.");
3357 IORecursiveLockUnlock(sKextLock
);
3359 OSSafeRelease(mkextData
);
3360 OSSafeRelease(mkextPlist
);
3361 OSSafeRelease(serializer
);
3362 OSSafeRelease(logInfoArray
);
3367 /*********************************************************************
3368 *********************************************************************/
3371 OSKext::serializeLogInfo(
3372 OSArray
* logInfoArray
,
3374 uint32_t * logInfoLengthOut
)
3376 OSReturn result
= kOSReturnError
;
3377 char * buffer
= NULL
;
3378 kern_return_t kmem_result
= KERN_FAILURE
;
3379 OSSerialize
* serializer
= NULL
; // must release; reused
3380 char * logInfo
= NULL
; // returned by reference
3381 uint32_t logInfoLength
= 0;
3383 if (!logInfoArray
|| !logInfoOut
|| !logInfoLengthOut
) {
3384 OSKextLog(/* kext */ NULL
,
3385 kOSKextLogErrorLevel
|
3387 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3388 /* Bad programmer. */
3389 result
= kOSKextReturnInvalidArgument
;
3393 serializer
= OSSerialize::withCapacity(0);
3395 OSKextLog(/* kext */ NULL
,
3396 kOSKextLogErrorLevel
|
3398 "Failed to create serializer on log info for request from user space.");
3399 /* Incidental error; we're going to (try to) allow the request
3400 * itself to succeed. */
3403 if (!logInfoArray
->serialize(serializer
)) {
3404 OSKextLog(/* kext */ NULL
,
3405 kOSKextLogErrorLevel
|
3407 "Failed to serialize log info for request from user space.");
3408 /* Incidental error; we're going to (try to) allow the request
3409 * itself to succeed. */
3411 logInfo
= serializer
->text();
3412 logInfoLength
= serializer
->getLength();
3414 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
, round_page(logInfoLength
));
3415 if (kmem_result
!= KERN_SUCCESS
) {
3416 OSKextLog(/* kext */ NULL
,
3417 kOSKextLogErrorLevel
|
3419 "Failed to copy log info for request from user space.");
3420 /* Incidental error; we're going to (try to) allow the request
3423 /* 11981737 - clear uninitialized data in last page */
3424 bzero((void *)(buffer
+ logInfoLength
),
3425 (round_page(logInfoLength
) - logInfoLength
));
3426 memcpy(buffer
, logInfo
, logInfoLength
);
3427 *logInfoOut
= buffer
;
3428 *logInfoLengthOut
= logInfoLength
;
3432 result
= kOSReturnSuccess
;
3434 OSSafeRelease(serializer
);
3439 #pragma mark Instance Management Methods
3441 /*********************************************************************
3442 *********************************************************************/
3444 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
)
3446 OSKext
* foundKext
= NULL
;
3448 IORecursiveLockLock(sKextLock
);
3449 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3451 foundKext
->retain();
3453 IORecursiveLockUnlock(sKextLock
);
3458 /*********************************************************************
3459 *********************************************************************/
3461 OSKext::lookupKextWithIdentifier(OSString
* kextIdentifier
)
3463 return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy());
3466 /*********************************************************************
3467 *********************************************************************/
3469 OSKext::lookupKextWithLoadTag(uint32_t aTag
)
3471 OSKext
* foundKext
= NULL
; // returned
3474 IORecursiveLockLock(sKextLock
);
3476 count
= sLoadedKexts
->getCount();
3477 for (i
= 0; i
< count
; i
++) {
3478 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3479 if (thisKext
->getLoadTag() == aTag
) {
3480 foundKext
= thisKext
;
3481 foundKext
->retain();
3487 IORecursiveLockUnlock(sKextLock
);
3492 /*********************************************************************
3493 *********************************************************************/
3495 OSKext::lookupKextWithAddress(vm_address_t address
)
3497 OSKext
* foundKext
= NULL
; // returned
3500 IORecursiveLockLock(sKextLock
);
3502 count
= sLoadedKexts
->getCount();
3503 for (i
= 0; i
< count
; i
++) {
3504 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3505 if (thisKext
->linkedExecutable
) {
3506 vm_address_t kext_start
=
3507 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy();
3508 vm_address_t kext_end
= kext_start
+
3509 thisKext
->linkedExecutable
->getLength();
3511 if ((kext_start
<= address
) && (address
< kext_end
)) {
3512 foundKext
= thisKext
;
3513 foundKext
->retain();
3520 IORecursiveLockUnlock(sKextLock
);
3525 /*********************************************************************
3526 *********************************************************************/
3528 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
)
3530 bool result
= false;
3531 OSKext
* foundKext
= NULL
; // returned
3533 IORecursiveLockLock(sKextLock
);
3535 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3536 if (foundKext
&& foundKext
->isLoaded()) {
3540 IORecursiveLockUnlock(sKextLock
);
3545 /*********************************************************************
3546 * xxx - should spawn a separate thread so a kext can safely have
3547 * xxx - itself unloaded.
3548 *********************************************************************/
3553 bool terminateServicesAndRemovePersonalitiesFlag
)
3555 OSReturn result
= kOSKextReturnInUse
;
3556 OSKext
* checkKext
= NULL
; // do not release
3558 int macCheckResult
= 0;
3559 kauth_cred_t cred
= NULL
;
3562 IORecursiveLockLock(sKextLock
);
3564 /* If the kext has no identifier, it failed to init
3565 * so isn't in sKextsByID and it isn't loaded.
3567 if (!aKext
->getIdentifier()) {
3568 result
= kOSReturnSuccess
;
3572 checkKext
= OSDynamicCast(OSKext
,
3573 sKextsByID
->getObject(aKext
->getIdentifier()));
3574 if (checkKext
!= aKext
) {
3575 result
= kOSKextReturnNotFound
;
3579 if (aKext
->isLoaded()) {
3581 if (current_task() != kernel_task
) {
3582 cred
= kauth_cred_get_with_ref();
3583 macCheckResult
= mac_kext_check_unload(cred
, aKext
->getIdentifierCString());
3584 kauth_cred_unref(&cred
);
3587 if (macCheckResult
!= 0) {
3588 result
= kOSReturnError
;
3590 kOSKextLogErrorLevel
|
3591 kOSKextLogKextBookkeepingFlag
,
3592 "Failed to remove kext %s (MAC policy error 0x%x).",
3593 aKext
->getIdentifierCString(), macCheckResult
);
3598 /* If we are terminating, send the request to the IOCatalogue
3599 * (which will actually call us right back but that's ok we have
3600 * a recursive lock don't you know) but do not ask the IOCatalogue
3601 * to call back with an unload, we'll do that right here.
3603 if (terminateServicesAndRemovePersonalitiesFlag
) {
3604 result
= gIOCatalogue
->terminateDriversForModule(
3605 aKext
->getIdentifierCString(), /* unload */ false);
3606 if (result
!= kOSReturnSuccess
) {
3608 kOSKextLogErrorLevel
|
3609 kOSKextLogKextBookkeepingFlag
,
3610 "Can't remove kext %s; services failed to terminate - 0x%x.",
3611 aKext
->getIdentifierCString(), result
);
3616 result
= aKext
->unload();
3617 if (result
!= kOSReturnSuccess
) {
3622 /* Remove personalities as requested. This is a bit redundant for a loaded
3623 * kext as IOCatalogue::terminateDriversForModule() removes driver
3624 * personalities, but it doesn't restart matching, which we always want
3625 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3628 if (terminateServicesAndRemovePersonalitiesFlag
) {
3629 aKext
->removePersonalitiesFromCatalog();
3633 kOSKextLogProgressLevel
|
3634 kOSKextLogKextBookkeepingFlag
,
3635 "Removing kext %s.",
3636 aKext
->getIdentifierCString());
3638 sKextsByID
->removeObject(aKext
->getIdentifier());
3639 result
= kOSReturnSuccess
;
3642 IORecursiveLockUnlock(sKextLock
);
3646 /*********************************************************************
3647 *********************************************************************/
3650 OSKext::removeKextWithIdentifier(
3651 const char * kextIdentifier
,
3652 bool terminateServicesAndRemovePersonalitiesFlag
)
3654 OSReturn result
= kOSReturnError
;
3656 IORecursiveLockLock(sKextLock
);
3658 OSKext
* aKext
= OSDynamicCast(OSKext
,
3659 sKextsByID
->getObject(kextIdentifier
));
3661 result
= kOSKextReturnNotFound
;
3662 OSKextLog(/* kext */ NULL
,
3663 kOSKextLogErrorLevel
|
3664 kOSKextLogKextBookkeepingFlag
,
3665 "Can't remove kext %s - not found.",
3670 result
= OSKext::removeKext(aKext
,
3671 terminateServicesAndRemovePersonalitiesFlag
);
3674 IORecursiveLockUnlock(sKextLock
);
3679 /*********************************************************************
3680 *********************************************************************/
3683 OSKext::removeKextWithLoadTag(
3684 OSKextLoadTag loadTag
,
3685 bool terminateServicesAndRemovePersonalitiesFlag
)
3687 OSReturn result
= kOSReturnError
;
3688 OSKext
* foundKext
= NULL
;
3691 IORecursiveLockLock(sKextLock
);
3693 count
= sLoadedKexts
->getCount();
3694 for (i
= 0; i
< count
; i
++) {
3695 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3696 if (thisKext
->loadTag
== loadTag
) {
3697 foundKext
= thisKext
;
3703 result
= kOSKextReturnNotFound
;
3704 OSKextLog(/* kext */ NULL
,
3705 kOSKextLogErrorLevel
|
3706 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
3707 "Can't remove kext with load tag %d - not found.",
3712 result
= OSKext::removeKext(foundKext
,
3713 terminateServicesAndRemovePersonalitiesFlag
);
3716 IORecursiveLockUnlock(sKextLock
);
3721 /*********************************************************************
3722 *********************************************************************/
3724 OSKext::copyKexts(void)
3726 OSDictionary
* result
;
3728 IORecursiveLockLock(sKextLock
);
3729 result
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection());
3730 IORecursiveLockUnlock(sKextLock
);
3735 /*********************************************************************
3736 *********************************************************************/
3737 #define BOOTER_KEXT_PREFIX "Driver-"
3739 typedef struct _DeviceTreeBuffer
{
3742 } _DeviceTreeBuffer
;
3744 /*********************************************************************
3745 * Create a dictionary of excluded kexts from the given booter data.
3746 *********************************************************************/
3749 OSKext::createExcludeListFromBooterData(
3750 OSDictionary
* theDictionary
,
3751 OSCollectionIterator
* theIterator
)
3753 OSString
* deviceTreeName
= NULL
; // do not release
3754 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not release
3755 char * booterDataPtr
= NULL
; // do not release
3756 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not release
3757 char * infoDictAddr
= NULL
; // do not release
3758 OSObject
* parsedXML
= NULL
; // must release
3759 OSDictionary
* theInfoDict
= NULL
; // do not release
3761 theIterator
->reset();
3763 /* look for AppleKextExcludeList.kext */
3764 while ( (deviceTreeName
=
3765 OSDynamicCast(OSString
, theIterator
->getNextObject())) ) {
3767 const char * devTreeNameCString
;
3768 OSData
* deviceTreeEntry
;
3769 OSString
* myBundleID
; // do not release
3771 OSSafeReleaseNULL(parsedXML
);
3774 OSDynamicCast(OSData
, theDictionary
->getObject(deviceTreeName
));
3775 if (!deviceTreeEntry
) {
3779 /* Make sure it is a kext */
3780 devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
3781 if (strncmp(devTreeNameCString
, BOOTER_KEXT_PREFIX
,
3782 (sizeof(BOOTER_KEXT_PREFIX
) - 1)) != 0) {
3784 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3785 "\"%s\" not a kext",
3786 devTreeNameCString
);
3790 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
3791 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
3792 if (!deviceTreeBuffer
) {
3796 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
3797 if (!booterDataPtr
) {
3801 kextFileInfo
= (_BooterKextFileInfo
*) booterDataPtr
;
3802 if (!kextFileInfo
->infoDictPhysAddr
||
3803 !kextFileInfo
->infoDictLength
) {
3807 infoDictAddr
= (char *)
3808 ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
3809 if (!infoDictAddr
) {
3813 parsedXML
= OSUnserializeXML(infoDictAddr
);
3818 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
3824 OSDynamicCast(OSString
,
3825 theInfoDict
->getObject(kCFBundleIdentifierKey
));
3827 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3829 /* get copy of exclusion list dictionary */
3830 OSDictionary
* myTempDict
; // do not free
3832 myTempDict
= OSDynamicCast(
3834 theInfoDict
->getObject("OSKextExcludeList"));
3836 IORecursiveLockLock(sKextLock
);
3838 /* get rid of old exclusion list */
3839 if (sExcludeListByID
) {
3840 sExcludeListByID
->flushCollection();
3841 OSSafeRelease(sExcludeListByID
);
3843 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3844 IORecursiveLockUnlock(sKextLock
);
3849 } // while ( (deviceTreeName = ...) )
3851 OSSafeReleaseNULL(parsedXML
);
3855 /*********************************************************************
3856 * Create a dictionary of excluded kexts from the given prelink
3857 * info (kernelcache).
3858 *********************************************************************/
3861 OSKext::createExcludeListFromPrelinkInfo( OSArray
* theInfoArray
)
3863 OSDictionary
* myInfoDict
= NULL
; // do not release
3864 OSString
* myBundleID
; // do not release
3867 /* Find com.apple.driver.KextExcludeList. */
3868 for (i
= 0; i
< theInfoArray
->getCount(); i
++) {
3869 myInfoDict
= OSDynamicCast(OSDictionary
, theInfoArray
->getObject(i
));
3874 OSDynamicCast(OSString
,
3875 myInfoDict
->getObject(kCFBundleIdentifierKey
));
3877 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3878 // get copy of exclude list dictionary
3879 OSDictionary
* myTempDict
; // do not free
3880 myTempDict
= OSDynamicCast(OSDictionary
,
3881 myInfoDict
->getObject("OSKextExcludeList"));
3883 IORecursiveLockLock(sKextLock
);
3884 // get rid of old exclude list
3885 if (sExcludeListByID
) {
3886 sExcludeListByID
->flushCollection();
3887 OSSafeRelease(sExcludeListByID
);
3890 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3891 IORecursiveLockUnlock(sKextLock
);
3895 } // for (i = 0; i < theInfoArray->getCount()...
3901 #pragma mark Accessors
3903 /*********************************************************************
3904 *********************************************************************/
3906 OSKext::getIdentifier(void)
3911 /*********************************************************************
3912 * A kext must have a bundle identifier to even survive initialization;
3913 * this is guaranteed to exist past then.
3914 *********************************************************************/
3916 OSKext::getIdentifierCString(void)
3918 return bundleID
->getCStringNoCopy();
3921 /*********************************************************************
3922 *********************************************************************/
3924 OSKext::getVersion(void)
3929 /*********************************************************************
3930 *********************************************************************/
3932 OSKext::getCompatibleVersion(void)
3934 return compatibleVersion
;
3937 /*********************************************************************
3938 *********************************************************************/
3940 OSKext::isLibrary(void)
3942 return (getCompatibleVersion() > 0);
3945 /*********************************************************************
3946 *********************************************************************/
3948 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
)
3950 if ((compatibleVersion
> -1 && version
> -1) &&
3951 (compatibleVersion
<= version
&& aVersion
<= version
)) {
3957 /*********************************************************************
3958 *********************************************************************/
3960 OSKext::declaresExecutable(void)
3962 return (getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
);
3965 /*********************************************************************
3966 *********************************************************************/
3968 OSKext::getExecutable(void)
3970 OSData
* result
= NULL
;
3971 OSData
* extractedExecutable
= NULL
; // must release
3972 OSData
* mkextExecutableRef
= NULL
; // do not release
3974 result
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
));
3979 mkextExecutableRef
= OSDynamicCast(OSData
,
3980 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
));
3982 if (mkextExecutableRef
) {
3984 MkextEntryRef
* mkextEntryRef
= (MkextEntryRef
*)
3985 mkextExecutableRef
->getBytesNoCopy();
3986 uint32_t mkextVersion
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
);
3987 if (mkextVersion
== MKEXT_VERS_2
) {
3988 mkext2_file_entry
* fileinfo
=
3989 (mkext2_file_entry
*)mkextEntryRef
->fileinfo
;
3990 uint32_t compressedSize
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
);
3991 uint32_t fullSize
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
);
3992 extractedExecutable
= extractMkext2FileData(
3993 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable",
3994 compressedSize
, fullSize
);
3995 } else if (mkextVersion
== MKEXT_VERS_1
) {
3996 extractedExecutable
= extractMkext1Entry(
3997 mkextEntryRef
->mkext
, mkextEntryRef
->fileinfo
);
3999 OSKextLog(this, kOSKextLogErrorLevel
|
4000 kOSKextLogArchiveFlag
,
4001 "Kext %s - unknown mkext version 0x%x for executable.",
4002 getIdentifierCString(), mkextVersion
);
4005 /* Regardless of success, remove the mkext executable,
4006 * and drop one reference on the mkext. (setExecutable() does not
4007 * replace, it removes, or panics if asked to replace.)
4009 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
4010 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
4012 if (extractedExecutable
&& extractedExecutable
->getLength()) {
4013 if (!setExecutable(extractedExecutable
)) {
4016 result
= extractedExecutable
;
4024 OSSafeRelease(extractedExecutable
);
4029 /*********************************************************************
4030 *********************************************************************/
4032 OSKext::isInterface(void)
4034 return flags
.interface
;
4037 /*********************************************************************
4038 *********************************************************************/
4040 OSKext::isKernel(void)
4042 return (this == sKernelKext
);
4045 /*********************************************************************
4046 *********************************************************************/
4048 OSKext::isKernelComponent(void)
4050 return flags
.kernelComponent
? true : false;
4053 /*********************************************************************
4054 *********************************************************************/
4056 OSKext::isExecutable(void)
4058 return (!isKernel() && !isInterface() && declaresExecutable());
4061 /*********************************************************************
4062 * We might want to check this recursively for all dependencies,
4063 * since a subtree of dependencies could get loaded before we hit
4064 * a dependency that isn't safe-boot-loadable.
4066 * xxx - Might want to return false if OSBundleEnableKextLogging or
4067 * OSBundleDebugLevel
4068 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4069 * the point except it's usually development drivers, which might
4070 * cause panics on startup, that have those properties). Heh; could
4071 * use a "kx" boot-arg!
4072 *********************************************************************/
4074 OSKext::isLoadableInSafeBoot(void)
4076 bool result
= false;
4077 OSString
* required
= NULL
; // do not release
4084 required
= OSDynamicCast(OSString
,
4085 getPropertyForHostArch(kOSBundleRequiredKey
));
4089 if (required
->isEqualTo(kOSBundleRequiredRoot
) ||
4090 required
->isEqualTo(kOSBundleRequiredLocalRoot
) ||
4091 required
->isEqualTo(kOSBundleRequiredNetworkRoot
) ||
4092 required
->isEqualTo(kOSBundleRequiredSafeBoot
) ||
4093 required
->isEqualTo(kOSBundleRequiredConsole
)) {
4102 /*********************************************************************
4103 *********************************************************************/
4105 OSKext::isPrelinked(void)
4107 return flags
.prelinked
? true : false;
4110 /*********************************************************************
4111 *********************************************************************/
4112 bool OSKext::isLoaded(void)
4114 return flags
.loaded
? true : false;
4117 /*********************************************************************
4118 *********************************************************************/
4120 OSKext::isStarted(void)
4122 return flags
.started
? true : false;
4125 /*********************************************************************
4126 *********************************************************************/
4128 OSKext::isCPPInitialized(void)
4130 return flags
.CPPInitialized
;
4133 /*********************************************************************
4134 *********************************************************************/
4136 OSKext::setCPPInitialized(bool initialized
)
4138 flags
.CPPInitialized
= initialized
;
4141 /*********************************************************************
4142 *********************************************************************/
4144 OSKext::getLoadTag(void)
4149 /*********************************************************************
4150 *********************************************************************/
4151 void OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
)
4153 if (linkedExecutable
) {
4154 *loadSize
= linkedExecutable
->getLength();
4156 /* If we have a kmod_info struct, calculated the wired size
4157 * from that. Otherwise it's the full load size.
4160 *wiredSize
= *loadSize
- kmod_info
->hdr_size
;
4162 *wiredSize
= *loadSize
;
4171 /*********************************************************************
4172 *********************************************************************/
4174 OSKext::copyUUID(void)
4176 OSData
* result
= NULL
;
4177 OSData
* theExecutable
= NULL
; // do not release
4178 const kernel_mach_header_t
* header
= NULL
;
4179 const struct load_command
* load_cmd
= NULL
;
4180 const struct uuid_command
* uuid_cmd
= NULL
;
4183 /* An interface kext doesn't have a linked executable with an LC_UUID,
4184 * we create one when it's linked.
4186 if (interfaceUUID
) {
4187 result
= interfaceUUID
;
4192 /* For real kexts, try to get the UUID from the linked executable,
4193 * or if is hasn't been linked yet, the unrelocated executable.
4195 theExecutable
= linkedExecutable
;
4196 if (!theExecutable
) {
4197 theExecutable
= getExecutable();
4199 if (!theExecutable
) {
4203 header
= (const kernel_mach_header_t
*)theExecutable
->getBytesNoCopy();
4204 load_cmd
= (const struct load_command
*)&header
[1];
4206 for (i
= 0; i
< header
->ncmds
; i
++) {
4207 if (load_cmd
->cmd
== LC_UUID
) {
4208 uuid_cmd
= (struct uuid_command
*)load_cmd
;
4209 result
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
));
4212 load_cmd
= (struct load_command
*)((caddr_t
)load_cmd
+ load_cmd
->cmdsize
);
4219 /*********************************************************************
4220 *********************************************************************/
4222 #if defined (__x86_64__)
4223 #define ARCHNAME "x86_64"
4225 #error architecture not supported
4228 #define ARCH_SEPARATOR_CHAR '_'
4230 static char * makeHostArchKey(const char * key
, uint32_t * keySizeOut
)
4232 char * result
= NULL
;
4233 uint32_t keyLength
= strlen(key
);
4236 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4238 keySize
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
);
4239 result
= (char *)kalloc(keySize
);
4243 strlcpy(result
, key
, keySize
);
4244 result
[keyLength
++] = ARCH_SEPARATOR_CHAR
;
4245 result
[keyLength
] = '\0';
4246 strlcat(result
, ARCHNAME
, keySize
);
4247 *keySizeOut
= keySize
;
4253 /*********************************************************************
4254 *********************************************************************/
4256 OSKext::getPropertyForHostArch(const char * key
)
4258 OSObject
* result
= NULL
; // do not release
4259 uint32_t hostArchKeySize
= 0;
4260 char * hostArchKey
= NULL
; // must kfree
4262 if (!key
|| !infoDict
) {
4266 /* Some properties are not allowed to be arch-variant:
4267 * - Any CFBundle... property.
4268 * - OSBundleIsInterface.
4269 * - OSKernelResource.
4271 if (STRING_HAS_PREFIX(key
, "OS") ||
4272 STRING_HAS_PREFIX(key
, "IO")) {
4274 hostArchKey
= makeHostArchKey(key
, &hostArchKeySize
);
4276 OSKextLog(/* kext (this isn't about a kext) */ NULL
,
4277 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4278 "Allocation failure.");
4281 result
= infoDict
->getObject(hostArchKey
);
4285 result
= infoDict
->getObject(key
);
4289 if (hostArchKey
) kfree(hostArchKey
, hostArchKeySize
);
4294 #pragma mark Load/Start/Stop/Unload
4297 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4299 /*********************************************************************
4300 * sExcludeListByID is a dictionary with keys / values of:
4301 * key = bundleID string of kext we will not allow to load
4302 * value = version string(s) of the kext that is to be denied loading.
4303 * The version strings can be comma delimited. For example if kext
4304 * com.foocompany.fookext has two versions that we want to deny
4305 * loading then the version strings might look like:
4307 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4308 * not load the kext.
4310 * Value may also be in the form of "LE 2.0.0" (version numbers
4311 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4312 * number less than 2.0.0 will not load)
4314 * NOTE - we cannot use the characters "<=" or "<" because we have code
4315 * that serializes plists and treats '<' as a special character.
4316 *********************************************************************/
4318 OSKext::isInExcludeList(void)
4320 OSString
* versionString
= NULL
; // do not release
4321 char * versionCString
= NULL
; // do not free
4323 boolean_t wantLessThan
= false;
4324 boolean_t wantLessThanEqualTo
= false;
4327 if (!sExcludeListByID
) {
4330 /* look up by bundleID in our exclude list and if found get version
4331 * string (or strings) that we will not allow to load
4333 versionString
= OSDynamicCast(OSString
, sExcludeListByID
->getObject(bundleID
));
4334 if (!versionString
) {
4338 /* parse version strings */
4339 versionCString
= (char *) versionString
->getCStringNoCopy();
4341 /* look for "LT" or "LE" form of version string, must be in first two
4344 if (*versionCString
== 'L' && *(versionCString
+ 1) == 'T') {
4345 wantLessThan
= true;
4348 else if (*versionCString
== 'L' && *(versionCString
+ 1) == 'E') {
4349 wantLessThanEqualTo
= true;
4353 for (i
= 0; *versionCString
!= 0x00; versionCString
++) {
4354 /* skip whitespace */
4355 if (isWhiteSpace(*versionCString
)) {
4359 /* peek ahead for version string separator or null terminator */
4360 if (*(versionCString
+ 1) == ',' || *(versionCString
+ 1) == 0x00) {
4362 /* OK, we have a version string */
4363 myBuffer
[i
++] = *versionCString
;
4366 OSKextVersion excludeVers
;
4367 excludeVers
= OSKextParseVersionString(myBuffer
);
4369 if (wantLessThanEqualTo
) {
4370 if (version
<= excludeVers
) {
4374 else if (wantLessThan
) {
4375 if (version
< excludeVers
) {
4379 else if ( version
== excludeVers
) {
4383 /* reset for the next (if any) version string */
4385 wantLessThan
= false;
4386 wantLessThanEqualTo
= false;
4389 /* save valid version character */
4390 myBuffer
[i
++] = *versionCString
;
4392 /* make sure bogus version string doesn't overrun local buffer */
4393 if ( i
>= sizeof(myBuffer
) ) {
4402 /*********************************************************************
4403 *********************************************************************/
4406 OSKext::loadKextWithIdentifier(
4407 const char * kextIdentifierCString
,
4408 Boolean allowDeferFlag
,
4409 Boolean delayAutounloadFlag
,
4410 OSKextExcludeLevel startOpt
,
4411 OSKextExcludeLevel startMatchingOpt
,
4412 OSArray
* personalityNames
)
4414 OSReturn result
= kOSReturnError
;
4415 OSString
* kextIdentifier
= NULL
; // must release
4417 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
4418 if (!kextIdentifier
) {
4419 result
= kOSKextReturnNoMemory
;
4422 result
= OSKext::loadKextWithIdentifier(kextIdentifier
,
4423 allowDeferFlag
, delayAutounloadFlag
,
4424 startOpt
, startMatchingOpt
, personalityNames
);
4427 OSSafeRelease(kextIdentifier
);
4431 /*********************************************************************
4432 *********************************************************************/
4434 OSKext::loadKextWithIdentifier(
4435 OSString
* kextIdentifier
,
4436 Boolean allowDeferFlag
,
4437 Boolean delayAutounloadFlag
,
4438 OSKextExcludeLevel startOpt
,
4439 OSKextExcludeLevel startMatchingOpt
,
4440 OSArray
* personalityNames
)
4442 OSReturn result
= kOSReturnError
;
4443 OSReturn pingResult
= kOSReturnError
;
4444 OSKext
* theKext
= NULL
; // do not release
4445 OSDictionary
* loadRequest
= NULL
; // must release
4446 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4448 int macCheckResult
= 0;
4449 kauth_cred_t cred
= NULL
;
4452 IORecursiveLockLock(sKextLock
);
4454 if (!kextIdentifier
) {
4455 result
= kOSKextReturnInvalidArgument
;
4459 OSKext::recordIdentifierRequest(kextIdentifier
);
4461 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
4463 if (!allowDeferFlag
) {
4464 OSKextLog(/* kext */ NULL
,
4465 kOSKextLogErrorLevel
|
4467 "Can't load kext %s - not found.",
4468 kextIdentifier
->getCStringNoCopy());
4472 if (!sKernelRequestsEnabled
) {
4474 kOSKextLogErrorLevel
|
4476 "Can't load kext %s - requests to user space are disabled.",
4477 kextIdentifier
->getCStringNoCopy());
4478 result
= kOSKextReturnDisabled
;
4482 /* Create a new request unless one is already sitting
4483 * in sKernelRequests for this bundle identifier
4485 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4486 if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4487 result
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
,
4489 if (result
!= kOSReturnSuccess
) {
4492 if (!_OSKextSetRequestArgument(loadRequest
,
4493 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
4495 result
= kOSKextReturnNoMemory
;
4498 if (!sKernelRequests
->setObject(loadRequest
)) {
4499 result
= kOSKextReturnNoMemory
;
4503 if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4504 result
= kOSKextReturnNoMemory
;
4509 kOSKextLogDebugLevel
|
4511 "Kext %s not found; queued load request to user space.",
4512 kextIdentifier
->getCStringNoCopy());
4515 pingResult
= OSKext::pingKextd();
4516 if (pingResult
== kOSKextReturnDisabled
) {
4517 OSKextLog(/* kext */ NULL
,
4518 ((sPrelinkBoot
) ? kOSKextLogDebugLevel
: kOSKextLogErrorLevel
) |
4520 "Kext %s might not load - kextd is currently unavailable.",
4521 kextIdentifier
->getCStringNoCopy());
4524 result
= kOSKextReturnDeferred
;
4529 if (current_task() != kernel_task
) {
4530 cred
= kauth_cred_get_with_ref();
4531 macCheckResult
= mac_kext_check_load(cred
, kextIdentifier
->getCStringNoCopy());
4532 kauth_cred_unref(&cred
);
4535 if (macCheckResult
!= 0) {
4536 result
= kOSReturnError
;
4539 kOSKextLogErrorLevel
|
4541 "Failed to load kext %s (MAC policy error 0x%x).",
4542 kextIdentifier
->getCStringNoCopy(), macCheckResult
);
4548 result
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
);
4550 if (result
!= kOSReturnSuccess
) {
4552 kOSKextLogErrorLevel
|
4554 "Failed to load kext %s (error 0x%x).",
4555 kextIdentifier
->getCStringNoCopy(), (int)result
);
4557 OSKext::removeKext(theKext
,
4558 /* terminateService/removePersonalities */ true);
4562 if (delayAutounloadFlag
) {
4564 kOSKextLogProgressLevel
|
4565 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4566 "Setting delayed autounload for %s.",
4567 kextIdentifier
->getCStringNoCopy());
4568 theKext
->flags
.delayAutounload
= 1;
4572 OSSafeRelease(loadRequest
);
4573 OSSafeRelease(kextIdentifierSymbol
);
4575 IORecursiveLockUnlock(sKextLock
);
4580 /*********************************************************************
4581 *********************************************************************/
4584 OSKext::recordIdentifierRequest(
4585 OSString
* kextIdentifier
)
4587 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4590 if (!sAllKextLoadIdentifiers
|| !kextIdentifier
) {
4594 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4595 if (!kextIdentifierSymbol
) {
4596 // xxx - this is really a basic alloc failure
4601 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4602 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4605 // xxx - need to find a way to associate this whole func w/the kext
4606 OSKextLog(/* kext */ NULL
,
4607 // xxx - check level
4608 kOSKextLogStepLevel
|
4609 kOSKextLogArchiveFlag
,
4610 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4611 kextIdentifier
->getCStringNoCopy());
4617 OSKextLog(/* kext */ NULL
,
4618 kOSKextLogErrorLevel
|
4619 kOSKextLogArchiveFlag
,
4620 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4621 kextIdentifier
->getCStringNoCopy());
4623 OSSafeRelease(kextIdentifierSymbol
);
4627 /*********************************************************************
4628 *********************************************************************/
4631 OSKextExcludeLevel startOpt
,
4632 OSKextExcludeLevel startMatchingOpt
,
4633 OSArray
* personalityNames
)
4635 OSReturn result
= kOSReturnError
;
4636 kern_return_t kxldResult
;
4637 OSKextExcludeLevel dependenciesStartOpt
= startOpt
;
4638 OSKextExcludeLevel dependenciesStartMatchingOpt
= startMatchingOpt
;
4639 unsigned int i
, count
;
4640 Boolean alreadyLoaded
= false;
4641 OSKext
* lastLoadedKext
= NULL
;
4643 if (isInExcludeList()) {
4645 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
|
4647 "Kext %s is in exclude list, not loadable",
4648 getIdentifierCString());
4650 result
= kOSKextReturnNotLoadable
;
4655 alreadyLoaded
= true;
4656 result
= kOSReturnSuccess
;
4659 kOSKextLogDebugLevel
|
4660 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4661 "Kext %s is already loaded.",
4662 getIdentifierCString());
4666 if (!sLoadEnabled
) {
4668 kOSKextLogErrorLevel
|
4670 "Kext loading is disabled (attempt to load kext %s).",
4671 getIdentifierCString());
4672 result
= kOSKextReturnDisabled
;
4676 /* If we've pushed the next available load tag to the invalid value,
4677 * we can't load any more kexts.
4679 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4681 kOSKextLogErrorLevel
|
4683 "Can't load kext %s - no more load tags to assign.",
4684 getIdentifierCString());
4685 result
= kOSKextReturnNoResources
;
4689 /* This is a bit of a hack, because we shouldn't be handling
4690 * personalities within the load function.
4692 if (!declaresExecutable()) {
4693 result
= kOSReturnSuccess
;
4697 /* Are we in safe boot?
4699 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4701 kOSKextLogErrorLevel
|
4703 "Can't load kext %s - not loadable during safe boot.",
4704 getIdentifierCString());
4705 result
= kOSKextReturnBootLevel
;
4710 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4712 getIdentifierCString());
4715 if (!sKxldContext
) {
4716 kxldResult
= kxld_create_context(&sKxldContext
, &kern_allocate
,
4717 &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,
4718 /* cputype */ 0, /* cpusubtype */ 0);
4721 kOSKextLogErrorLevel
|
4722 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4723 "Can't load kext %s - failed to create link context.",
4724 getIdentifierCString());
4725 result
= kOSKextReturnNoMemory
;
4730 /* We only need to resolve dependencies once for the whole graph, but
4731 * resolveDependencies will just return if there's no work to do, so it's
4732 * safe to call it more than once.
4734 if (!resolveDependencies()) {
4735 // xxx - check resolveDependencies() for log msg
4737 kOSKextLogErrorLevel
|
4738 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4739 "Can't load kext %s - failed to resolve library dependencies.",
4740 getIdentifierCString());
4741 result
= kOSKextReturnDependencies
;
4745 /* If we are excluding just the kext being loaded now (and not its
4746 * dependencies), drop the exclusion level to none so dependencies
4747 * start and/or add their personalities.
4749 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4750 dependenciesStartOpt
= kOSKextExcludeNone
;
4753 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4754 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4757 /* Load the dependencies, recursively.
4759 count
= getNumDependencies();
4760 for (i
= 0; i
< count
; i
++) {
4761 OSKext
* dependency
= OSDynamicCast(OSKext
,
4762 dependencies
->getObject(i
));
4763 if (dependency
== NULL
) {
4765 kOSKextLogErrorLevel
|
4766 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4767 "Internal error loading kext %s; dependency disappeared.",
4768 getIdentifierCString());
4769 result
= kOSKextReturnInternalError
;
4773 /* Dependencies must be started accorting to the opt,
4774 * but not given the personality names of the main kext.
4776 result
= dependency
->load(dependenciesStartOpt
,
4777 dependenciesStartMatchingOpt
,
4778 /* personalityNames */ NULL
);
4779 if (result
!= KERN_SUCCESS
) {
4781 kOSKextLogErrorLevel
|
4782 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4783 "Dependency %s of kext %s failed to load.",
4784 dependency
->getIdentifierCString(),
4785 getIdentifierCString());
4787 OSKext::removeKext(dependency
,
4788 /* terminateService/removePersonalities */ true);
4789 result
= kOSKextReturnDependencyLoadError
;
4795 result
= loadExecutable();
4796 if (result
!= KERN_SUCCESS
) {
4800 flags
.loaded
= true;
4802 /* Add the kext to the list of loaded kexts and update the kmod_info
4803 * struct to point to that of the last loaded kext (which is the way
4804 * it's always been done, though I'd rather do them in order now).
4806 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
4807 sLoadedKexts
->setObject(this);
4809 /* Keep the kernel itself out of the kmod list.
4811 if (lastLoadedKext
->isKernel()) {
4812 lastLoadedKext
= NULL
;
4815 if (lastLoadedKext
) {
4816 kmod_info
->next
= lastLoadedKext
->kmod_info
;
4819 notifyKextLoadObservers(this, kmod_info
);
4821 /* Make the global kmod list point at the just-loaded kext. Note that the
4822 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4823 * although we do report it in kextstat these days by using the newer
4824 * OSArray of loaded kexts, which does contain it.
4826 * (The OSKext object representing the kernel doesn't even have a kmod_info
4827 * struct, though I suppose we could stick a pointer to it from the
4828 * static struct in OSRuntime.cpp.)
4832 /* Save the list of loaded kexts in case we panic.
4834 OSKext::saveLoadedKextPanicList();
4836 if (isExecutable()) {
4837 OSKext::updateLoadedKextSummaries();
4838 savePanicString(/* isLoading */ true);
4841 registerWithDTrace();
4843 jettisonLinkeditSegment();
4844 #endif /* CONFIG_DTRACE */
4848 if (isExecutable() && !flags
.started
) {
4849 if (startOpt
== kOSKextExcludeNone
) {
4851 if (result
!= kOSReturnSuccess
) {
4853 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4854 "Kext %s start failed (result 0x%x).",
4855 getIdentifierCString(), result
);
4856 result
= kOSKextReturnStartStopError
;
4861 /* If not excluding matching, send the personalities to the kernel.
4862 * This never affects the result of the load operation.
4863 * This is a bit of a hack, because we shouldn't be handling
4864 * personalities within the load function.
4866 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
4867 result
= sendPersonalitiesToCatalog(true, personalityNames
);
4872 /* More hack! If the kext doesn't declare an executable, even if we
4873 * "loaded" it, we have to remove any personalities naming it, or we'll
4874 * never see the registry go quiet. Errors here do not count for the
4875 * load operation itself.
4877 * Note that in every other regard it's perfectly ok for a kext to
4878 * not declare an executable and serve only as a package for personalities
4879 * naming another kext, so we do have to allow such kexts to be "loaded"
4880 * so that those other personalities get added & matched.
4882 if (!declaresExecutable()) {
4884 kOSKextLogStepLevel
| kOSKextLogLoadFlag
,
4885 "Kext %s has no executable; removing any personalities naming it.",
4886 getIdentifierCString());
4887 removePersonalitiesFromCatalog();
4890 if (result
!= kOSReturnSuccess
) {
4892 kOSKextLogErrorLevel
|
4894 "Kext %s failed to load (0x%x).",
4895 getIdentifierCString(), (int)result
);
4896 } else if (!alreadyLoaded
) {
4898 kOSKextLogProgressLevel
|
4901 getIdentifierCString());
4903 queueKextNotification(kKextRequestPredicateLoadNotification
,
4904 OSDynamicCast(OSString
, bundleID
));
4909 /*********************************************************************
4911 *********************************************************************/
4912 static char * strdup(const char * string
)
4914 char * result
= NULL
;
4921 size
= 1 + strlen(string
);
4922 result
= (char *)kalloc(size
);
4927 memcpy(result
, string
, size
);
4933 /*********************************************************************
4935 *********************************************************************/
4937 OSKext::slidePrelinkedExecutable()
4939 OSReturn result
= kOSKextReturnBadData
;
4940 kernel_mach_header_t
* mh
= NULL
;
4941 kernel_segment_command_t
* seg
= NULL
;
4942 kernel_segment_command_t
* linkeditSeg
= NULL
;
4943 kernel_section_t
* sec
= NULL
;
4944 char * linkeditBase
= NULL
;
4945 bool haveLinkeditBase
= false;
4946 char * relocBase
= NULL
;
4947 bool haveRelocBase
= false;
4948 struct dysymtab_command
* dysymtab
= NULL
;
4949 struct symtab_command
* symtab
= NULL
;
4950 kernel_nlist_t
* sym
= NULL
;
4951 struct relocation_info
* reloc
= NULL
;
4954 vm_offset_t new_kextsize
;
4956 if (linkedExecutable
== NULL
|| vm_kernel_slide
== 0) {
4957 result
= kOSReturnSuccess
;
4961 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4963 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4967 seg
->vmaddr
+= vm_kernel_slide
;
4969 #if KASLR_KEXT_DEBUG
4970 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
4972 (unsigned long)VM_KERNEL_UNSLIDE(seg
->vmaddr
),
4973 (unsigned long)seg
->vmaddr
);
4976 if (!haveRelocBase
) {
4977 relocBase
= (char *) seg
->vmaddr
;
4978 haveRelocBase
= true;
4980 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
4981 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
4982 haveLinkeditBase
= true;
4985 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4986 sec
->addr
+= vm_kernel_slide
;
4988 #if KASLR_KEXT_DEBUG
4989 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
4991 (unsigned long)VM_KERNEL_UNSLIDE(sec
->addr
),
4992 (unsigned long)sec
->addr
);
4997 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
4999 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
5001 if (symtab
!= NULL
) {
5002 /* Some pseudo-kexts have symbol tables without segments.
5004 if (symtab
->nsyms
> 0 && haveLinkeditBase
) {
5005 sym
= (kernel_nlist_t
*) (linkeditBase
+ symtab
->symoff
);
5006 for (i
= 0; i
< symtab
->nsyms
; i
++) {
5007 if (sym
[i
].n_type
& N_STAB
) {
5010 sym
[i
].n_value
+= vm_kernel_slide
;
5012 #if KASLR_KEXT_DEBUG
5013 #define MAX_SYMS_TO_LOG 5
5014 if ( i
< MAX_SYMS_TO_LOG
) {
5015 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
5016 (unsigned long)VM_KERNEL_UNSLIDE(sym
[i
].n_value
),
5017 (unsigned long)sym
[i
].n_value
);
5024 if (dysymtab
!= NULL
) {
5025 if (dysymtab
->nextrel
> 0) {
5027 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5029 "Sliding kext %s: External relocations found.",
5030 getIdentifierCString());
5034 if (dysymtab
->nlocrel
> 0) {
5035 if (!haveLinkeditBase
) {
5037 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5039 "Sliding kext %s: No linkedit segment.",
5040 getIdentifierCString());
5044 if (!haveRelocBase
) {
5046 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5049 "Sliding kext %s: No writable segments.",
5051 "Sliding kext %s: No segments.",
5053 getIdentifierCString());
5057 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
5058 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
5060 for (i
= 0; i
< dysymtab
->nlocrel
; i
++) {
5061 if ( reloc
[i
].r_extern
!= 0
5062 || reloc
[i
].r_type
!= 0
5063 || reloc
[i
].r_length
!= (sizeof(void *) == 8 ? 3 : 2)
5066 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
5068 "Sliding kext %s: Unexpected relocation found.",
5069 getIdentifierCString());
5072 if (reloc
[i
].r_pcrel
!= 0) {
5075 *((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)) += vm_kernel_slide
;
5077 #if KASLR_KEXT_DEBUG
5078 #define MAX_DYSYMS_TO_LOG 5
5079 if ( i
< MAX_DYSYMS_TO_LOG
) {
5080 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
5081 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
))),
5082 (unsigned long)*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)));
5087 /* We should free these relocations, not just delete the reference to them.
5088 * <rdar://problem/10535549> Free relocations from PIE kexts.
5090 new_kextsize
= round_page(kmod_info
->size
- reloc_size
);
5092 if ((kmod_info
->size
- new_kextsize
) > PAGE_SIZE
) {
5093 vm_offset_t endofkext
= kmod_info
->address
+ kmod_info
->size
;
5094 vm_offset_t new_endofkext
= kmod_info
->address
+ new_kextsize
;
5095 vm_offset_t endofrelocInfo
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
);
5096 int bytes_remaining
= endofkext
- endofrelocInfo
;
5097 OSData
* new_osdata
= NULL
;
5099 /* fix up symbol offsets if they are after the dsymtab local relocs */
5101 if (dysymtab
->locreloff
< symtab
->symoff
){
5102 symtab
->symoff
-= reloc_size
;
5104 if (dysymtab
->locreloff
< symtab
->stroff
) {
5105 symtab
->stroff
-= reloc_size
;
5108 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
5109 dysymtab
->extreloff
-= reloc_size
;
5112 /* move data behind reloc info down to new offset */
5113 if (endofrelocInfo
< endofkext
) {
5114 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
5117 /* Create a new OSData for the smaller kext object and reflect
5118 * new linkedit segment size.
5120 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
5121 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
5123 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
5125 /* Fix up kmod info and linkedExecutable.
5127 kmod_info
->size
= new_kextsize
;
5129 new_osdata
->setDeallocFunction(osdata_kext_free
);
5131 new_osdata
->setDeallocFunction(osdata_phys_free
);
5133 linkedExecutable
->setDeallocFunction(NULL
);
5134 linkedExecutable
->release();
5135 linkedExecutable
= new_osdata
;
5138 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
5140 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
5144 dysymtab
->nlocrel
= 0;
5145 dysymtab
->locreloff
= 0;
5149 result
= kOSReturnSuccess
;
5154 /*********************************************************************
5155 * called only by load()
5156 *********************************************************************/
5158 OSKext::loadExecutable()
5160 OSReturn result
= kOSReturnError
;
5161 kern_return_t kxldResult
;
5162 KXLDDependency
* kxlddeps
= NULL
; // must kfree
5163 uint32_t num_kxlddeps
= 0;
5164 OSArray
* linkDependencies
= NULL
; // must release
5165 uint32_t numDirectDependencies
= 0;
5166 uint32_t num_kmod_refs
= 0;
5167 struct mach_header
** kxldHeaderPtr
= NULL
; // do not free
5168 struct mach_header
* kxld_header
= NULL
; // xxx - need to free here?
5169 OSData
* theExecutable
= NULL
; // do not release
5170 OSString
* versString
= NULL
; // do not release
5171 const char * versCString
= NULL
; // do not free
5172 const char * string
= NULL
; // do not free
5175 /* We need the version string for a variety of bits below.
5177 versString
= OSDynamicCast(OSString
,
5178 getPropertyForHostArch(kCFBundleVersionKey
));
5182 versCString
= versString
->getCStringNoCopy();
5184 if (isKernelComponent()) {
5185 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
5187 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
5189 kOSKextLogErrorLevel
|
5191 "Kernel component %s has incorrect version %s; "
5193 getIdentifierCString(),
5194 versCString
, KERNEL6_VERSION
);
5195 result
= kOSKextReturnInternalError
;
5197 } else if (strcmp(versCString
, osrelease
)) {
5199 kOSKextLogErrorLevel
|
5201 "Kernel component %s has incorrect version %s; "
5203 getIdentifierCString(),
5204 versCString
, osrelease
);
5205 result
= kOSKextReturnInternalError
;
5211 if (isPrelinked()) {
5212 result
= slidePrelinkedExecutable();
5213 if (result
!= kOSReturnSuccess
) {
5219 theExecutable
= getExecutable();
5220 if (!theExecutable
) {
5221 if (declaresExecutable()) {
5223 kOSKextLogErrorLevel
|
5225 "Can't load kext %s - executable is missing.",
5226 getIdentifierCString());
5227 result
= kOSKextReturnValidation
;
5233 if (isInterface()) {
5234 OSData
*executableCopy
= OSData::withData(theExecutable
);
5235 setLinkedExecutable(executableCopy
);
5236 executableCopy
->release();
5240 numDirectDependencies
= getNumDependencies();
5242 if (flags
.hasBleedthrough
) {
5243 linkDependencies
= dependencies
;
5244 linkDependencies
->retain();
5246 linkDependencies
= OSArray::withArray(dependencies
);
5247 if (!linkDependencies
) {
5249 kOSKextLogErrorLevel
|
5250 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5251 "Can't allocate link dependencies to load kext %s.",
5252 getIdentifierCString());
5256 for (i
= 0; i
< numDirectDependencies
; ++i
) {
5257 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
5258 dependencies
->getObject(i
));
5259 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
5263 num_kxlddeps
= linkDependencies
->getCount();
5264 if (!num_kxlddeps
) {
5266 kOSKextLogErrorLevel
|
5267 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
5268 "Can't load kext %s - it has no library dependencies.",
5269 getIdentifierCString());
5273 kxlddeps
= (KXLDDependency
*)kalloc(num_kxlddeps
* sizeof(*kxlddeps
));
5276 kOSKextLogErrorLevel
|
5277 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5278 "Can't allocate link context to load kext %s.",
5279 getIdentifierCString());
5282 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
5284 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5285 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
5287 if (dependency
->isInterface()) {
5288 OSKext
*interfaceTargetKext
= NULL
;
5289 OSData
* interfaceTarget
= NULL
;
5291 if (dependency
->isKernelComponent()) {
5292 interfaceTargetKext
= sKernelKext
;
5293 interfaceTarget
= sKernelKext
->linkedExecutable
;
5295 interfaceTargetKext
= OSDynamicCast(OSKext
,
5296 dependency
->dependencies
->getObject(0));
5298 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
5301 if (!interfaceTarget
) {
5306 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5307 * it will be useful to have them in the debugger.
5308 * strdup() failing isn't critical right here so we don't check that.
5310 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
5311 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
5312 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
5314 kxlddeps
[i
].interface
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5315 kxlddeps
[i
].interface_size
= dependency
->linkedExecutable
->getLength();
5316 kxlddeps
[i
].interface_name
= strdup(dependency
->getIdentifierCString());
5318 kxlddeps
[i
].kext
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5319 kxlddeps
[i
].kext_size
= dependency
->linkedExecutable
->getLength();
5320 kxlddeps
[i
].kext_name
= strdup(dependency
->getIdentifierCString());
5323 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
5326 kxldHeaderPtr
= &kxld_header
;
5330 kOSKextLogExplicitLevel
|
5331 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5332 "Kext %s - calling kxld_link_file:\n"
5333 " kxld_context: %p\n"
5334 " executable: %p executable_length: %d\n"
5336 " kxld_dependencies: %p num_dependencies: %d\n"
5337 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5338 getIdentifierCString(), sKxldContext
,
5339 theExecutable
->getBytesNoCopy(), theExecutable
->getLength(),
5340 this, kxlddeps
, num_kxlddeps
,
5341 kxldHeaderPtr
, &kmod_info
);
5344 /* After this call, the linkedExecutable instance variable
5347 kxldResult
= kxld_link_file(sKxldContext
,
5348 (u_char
*)theExecutable
->getBytesNoCopy(),
5349 theExecutable
->getLength(),
5350 getIdentifierCString(), this, kxlddeps
, num_kxlddeps
,
5351 (u_char
**)kxldHeaderPtr
, (kxld_addr_t
*)&kmod_info
);
5353 if (kxldResult
!= KERN_SUCCESS
) {
5354 // xxx - add kxldResult here?
5356 kOSKextLogErrorLevel
|
5358 "Can't load kext %s - link failed.",
5359 getIdentifierCString());
5360 result
= kOSKextReturnLinkError
;
5364 /* We've written data & instructions into kernel memory, so flush the data
5365 * cache and invalidate the instruction cache.
5366 * I/D caches are coherent on x86
5368 #if !defined(__i386__) && !defined(__x86_64__)
5369 flush_dcache(kmod_info
->address
, kmod_info
->size
, false);
5370 invalidate_icache(kmod_info
->address
, kmod_info
->size
, false);
5374 if (isInterface()) {
5376 /* Whip up a fake kmod_info entry for the interface kext.
5378 kmod_info
= (kmod_info_t
*)kalloc(sizeof(kmod_info_t
));
5380 result
= KERN_MEMORY_ERROR
;
5384 /* A pseudokext has almost nothing in its kmod_info struct.
5386 bzero(kmod_info
, sizeof(kmod_info_t
));
5388 kmod_info
->info_version
= KMOD_INFO_VERSION
;
5390 /* An interface kext doesn't have a linkedExecutable, so save a
5391 * copy of the UUID out of the original executable via copyUUID()
5392 * while we still have the original executable.
5394 interfaceUUID
= copyUUID();
5397 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5398 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5400 /* Stamp the bundle ID and version from the OSKext over anything
5401 * resident inside the kmod_info.
5403 string
= getIdentifierCString();
5404 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5406 string
= versCString
;
5407 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5409 /* Add the dependencies' kmod_info structs as kmod_references.
5411 num_kmod_refs
= getNumDependencies();
5412 if (num_kmod_refs
) {
5413 kmod_info
->reference_list
= (kmod_reference_t
*)kalloc(
5414 num_kmod_refs
* sizeof(kmod_reference_t
));
5415 if (!kmod_info
->reference_list
) {
5416 result
= KERN_MEMORY_ERROR
;
5419 bzero(kmod_info
->reference_list
,
5420 num_kmod_refs
* sizeof(kmod_reference_t
));
5421 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5422 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5423 OSKext
* refKext
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
));
5424 ref
->info
= refKext
->kmod_info
;
5425 ref
->info
->reference_count
++;
5427 if (refIndex
+ 1 < num_kmod_refs
) {
5428 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5433 if (!isInterface() && linkedExecutable
) {
5435 kOSKextLogProgressLevel
|
5437 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5439 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5440 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5441 (unsigned)kmod_info
->id
);
5444 result
= setVMProtections();
5445 if (result
!= KERN_SUCCESS
) {
5449 result
= kOSReturnSuccess
;
5452 OSSafeRelease(linkDependencies
);
5454 /* Clear up locally allocated dependency info.
5456 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5459 if (kxlddeps
[i
].kext_name
) {
5460 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5461 kfree(kxlddeps
[i
].kext_name
, size
);
5463 if (kxlddeps
[i
].interface_name
) {
5464 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5465 kfree(kxlddeps
[i
].interface_name
, size
);
5468 if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5470 /* We no longer need the unrelocated executable (which the linker
5471 * has altered anyhow).
5473 setExecutable(NULL
);
5475 if (result
!= kOSReturnSuccess
) {
5477 kOSKextLogErrorLevel
|
5479 "Failed to load executable for kext %s.",
5480 getIdentifierCString());
5482 if (kmod_info
&& kmod_info
->reference_list
) {
5483 kfree(kmod_info
->reference_list
,
5484 num_kmod_refs
* sizeof(kmod_reference_t
));
5486 if (isInterface()) {
5487 kfree(kmod_info
, sizeof(kmod_info_t
));
5490 if (linkedExecutable
) {
5491 linkedExecutable
->release();
5492 linkedExecutable
= NULL
;
5499 /*********************************************************************
5500 * The linkedit segment is used by the kext linker for dependency
5501 * resolution, and by dtrace for probe initialization. We can free it
5502 * for non-library kexts, since no kexts depend on non-library kexts
5503 * by definition, once dtrace has been initialized.
5504 *********************************************************************/
5506 OSKext::jettisonLinkeditSegment(void)
5508 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5509 kernel_segment_command_t
* linkedit
= NULL
;
5511 vm_size_t linkeditsize
, kextsize
;
5512 OSData
* data
= NULL
;
5515 /* We can free symbol tables for all embedded kexts because we don't
5516 * support runtime kext linking.
5518 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5520 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5525 /* Find the linkedit segment. If it's not the last segment, then freeing
5526 * it will fragment the kext into multiple VM regions, which OSKext is not
5527 * designed to handle, so we'll have to skip it.
5529 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5534 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5535 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
))
5540 /* Create a new OSData for the smaller kext object.
5542 linkeditsize
= round_page(linkedit
->vmsize
);
5543 kextsize
= kmod_info
->size
- linkeditsize
;
5544 start
= linkedit
->vmaddr
;
5546 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5551 /* Fix the kmod info and linkedExecutable.
5553 kmod_info
->size
= kextsize
;
5556 data
->setDeallocFunction(osdata_kext_free
);
5558 data
->setDeallocFunction(osdata_phys_free
);
5560 linkedExecutable
->setDeallocFunction(NULL
);
5561 linkedExecutable
->release();
5562 linkedExecutable
= data
;
5563 flags
.jettisonLinkeditSeg
= 1;
5565 /* Free the linkedit segment.
5568 kext_free(start
, linkeditsize
);
5570 ml_static_mfree(start
, linkeditsize
);
5577 /*********************************************************************
5578 *********************************************************************/
5580 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5582 if (linkedExecutable
) {
5583 panic("Attempt to set linked executable on kext "
5584 "that already has one (%s).\n",
5585 getIdentifierCString());
5587 linkedExecutable
= anExecutable
;
5588 linkedExecutable
->retain();
5593 /*********************************************************************
5594 * Go through all loaded kexts and tell them to register with dtrace.
5595 * The instance method only registers if necessary.
5596 *********************************************************************/
5599 OSKext::registerKextsWithDTrace(void)
5601 uint32_t count
= sLoadedKexts
->getCount();
5604 IORecursiveLockLock(sKextLock
);
5606 for (i
= 0; i
< count
; i
++) {
5607 OSKext
* thisKext
= NULL
; // do not release
5609 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5610 if (!thisKext
|| !thisKext
->isExecutable()) {
5614 thisKext
->registerWithDTrace();
5617 IORecursiveLockUnlock(sKextLock
);
5623 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5624 extern int (*dtrace_modunload
)(struct kmod_info
*);
5627 /*********************************************************************
5628 *********************************************************************/
5630 OSKext::registerWithDTrace(void)
5632 /* Register kext with dtrace. A dtrace_modload failure should not
5633 * prevent a kext from loading, so we ignore the return code.
5635 if (!flags
.dtraceInitialized
&& (dtrace_modload
!= NULL
)) {
5636 uint32_t modflag
= 0;
5637 OSObject
* forceInit
= getPropertyForHostArch("OSBundleForceDTraceInit");
5638 if (forceInit
== kOSBooleanTrue
) {
5639 modflag
|= KMOD_DTRACE_FORCE_INIT
;
5642 (void)(*dtrace_modload
)(kmod_info
, modflag
);
5643 flags
.dtraceInitialized
= true;
5644 jettisonLinkeditSegment();
5648 /*********************************************************************
5649 *********************************************************************/
5651 OSKext::unregisterWithDTrace(void)
5653 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5654 * prevent a kext from loading, so we ignore the return code.
5656 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
5657 (void)(*dtrace_modunload
)(kmod_info
);
5658 flags
.dtraceInitialized
= false;
5662 #endif /* CONFIG_DTRACE */
5665 /*********************************************************************
5666 * called only by loadExecutable()
5667 *********************************************************************/
5668 #if !VM_MAPPED_KEXTS
5669 #error Unrecognized architecture
5671 static inline kern_return_t
5674 vm_map_offset_t start
,
5675 vm_map_offset_t end
,
5679 if (start
== end
) { // 10538581
5680 return(KERN_SUCCESS
);
5682 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
5685 static inline kern_return_t
5688 vm_map_offset_t start
,
5689 vm_map_offset_t end
,
5690 vm_prot_t access_type
,
5691 boolean_t user_wire
)
5693 return vm_map_wire(map
, start
, end
, access_type
, user_wire
);
5698 OSKext::setVMProtections(void)
5700 vm_map_t kext_map
= NULL
;
5701 kernel_segment_command_t
* seg
= NULL
;
5702 vm_map_offset_t start
= 0;
5703 vm_map_offset_t end
= 0;
5704 OSReturn result
= kOSReturnError
;
5706 if (!kmod_info
->address
&& !kmod_info
->size
) {
5707 result
= kOSReturnSuccess
;
5711 /* Get the kext's vm map */
5712 kext_map
= kext_get_vm_map(kmod_info
);
5714 result
= KERN_MEMORY_ERROR
;
5718 /* Protect the headers as read-only; they do not need to be wired */
5719 result
= OSKext_protect(kext_map
, kmod_info
->address
,
5720 kmod_info
->address
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
);
5721 if (result
!= KERN_SUCCESS
) {
5725 /* Set the VM protections and wire down each of the segments */
5726 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5728 start
= round_page(seg
->vmaddr
);
5729 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
5731 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
5732 if (result
!= KERN_SUCCESS
) {
5734 kOSKextLogErrorLevel
|
5736 "Kext %s failed to set maximum VM protections "
5737 "for segment %s - 0x%x.",
5738 getIdentifierCString(), seg
->segname
, (int)result
);
5742 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5743 if (result
!= KERN_SUCCESS
) {
5745 kOSKextLogErrorLevel
|
5747 "Kext %s failed to set initial VM protections "
5748 "for segment %s - 0x%x.",
5749 getIdentifierCString(), seg
->segname
, (int)result
);
5753 if (segmentShouldBeWired(seg
)) {
5754 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5755 if (result
!= KERN_SUCCESS
) {
5760 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5767 /*********************************************************************
5768 *********************************************************************/
5770 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
5772 return (sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
)));
5775 /*********************************************************************
5776 *********************************************************************/
5778 OSKext::validateKextMapping(bool startFlag
)
5780 OSReturn result
= kOSReturnError
;
5781 const char * whichOp
= startFlag
? "start" : "stop";
5782 kern_return_t kern_result
= 0;
5783 vm_map_t kext_map
= NULL
;
5784 kernel_segment_command_t
* seg
= NULL
;
5785 mach_vm_address_t address
= 0;
5786 mach_vm_size_t size
= 0;
5788 mach_msg_type_number_t count
;
5789 vm_region_submap_short_info_data_64_t info
;
5791 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
5792 bzero(&info
, sizeof(info
));
5794 // xxx - do we need a distinct OSReturn value for these or is "bad data"
5795 // xxx - sufficient?
5797 /* Verify that the kmod_info and start/stop pointers are non-NULL.
5801 kOSKextLogErrorLevel
|
5803 "Kext %s - NULL kmod_info pointer.",
5804 getIdentifierCString());
5805 result
= kOSKextReturnBadData
;
5810 address
= (mach_vm_address_t
)kmod_info
->start
;
5812 address
= (mach_vm_address_t
)kmod_info
->stop
;
5817 kOSKextLogErrorLevel
|
5819 "Kext %s - NULL module %s pointer.",
5820 getIdentifierCString(), whichOp
);
5821 result
= kOSKextReturnBadData
;
5825 kext_map
= kext_get_vm_map(kmod_info
);
5826 depth
= (kernel_map
== kext_map
) ? 1 : 2;
5828 /* Verify that the start/stop function lies within the kext's address range.
5830 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
5831 kmod_info
->address
+ kmod_info
->size
<= address
)
5834 kOSKextLogErrorLevel
|
5836 "Kext %s module %s pointer is outside of kext range "
5837 "(%s %p - kext at %p-%p)..",
5838 getIdentifierCString(),
5841 (void *)VM_KERNEL_UNSLIDE(address
),
5842 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5843 (void *)(VM_KERNEL_UNSLIDE(kmod_info
->address
) + kmod_info
->size
));
5844 result
= kOSKextReturnBadData
;
5848 /* Only do these checks before calling the start function;
5849 * If anything goes wrong with the mapping while the kext is running,
5850 * we'll likely have panicked well before any attempt to stop the kext.
5854 /* Verify that the start/stop function is executable.
5856 kern_result
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
,
5857 (vm_region_recurse_info_t
)&info
, &count
);
5858 if (kern_result
!= KERN_SUCCESS
) {
5860 kOSKextLogErrorLevel
|
5862 "Kext %s - bad %s pointer %p.",
5863 getIdentifierCString(),
5864 whichOp
, (void *)VM_KERNEL_UNSLIDE(address
));
5865 result
= kOSKextReturnBadData
;
5870 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
5872 kOSKextLogErrorLevel
|
5874 "Kext %s - memory region containing module %s function "
5875 "is not executable.",
5876 getIdentifierCString(), whichOp
);
5877 result
= kOSKextReturnBadData
;
5882 /* Verify that the kext's segments are backed by physical memory.
5884 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5886 if (!verifySegmentMapping(seg
)) {
5887 result
= kOSKextReturnBadData
;
5891 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5896 result
= kOSReturnSuccess
;
5901 /*********************************************************************
5902 *********************************************************************/
5904 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
5906 mach_vm_address_t address
= 0;
5908 if (!segmentShouldBeWired(seg
)) return true;
5910 for (address
= seg
->vmaddr
;
5911 address
< round_page(seg
->vmaddr
+ seg
->vmsize
);
5912 address
+= PAGE_SIZE
)
5914 if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) {
5916 kOSKextLogErrorLevel
|
5918 "Kext %s - page %p is not backed by physical memory.",
5919 getIdentifierCString(),
5928 /*********************************************************************
5929 *********************************************************************/
5931 OSKext::start(bool startDependenciesFlag
)
5933 OSReturn result
= kOSReturnError
;
5934 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
5935 unsigned int i
, count
;
5936 void * kmodStartData
= NULL
;
5938 if (isStarted() || isInterface() || isKernelComponent()) {
5939 result
= kOSReturnSuccess
;
5945 kOSKextLogErrorLevel
|
5947 "Attempt to start nonloaded kext %s.",
5948 getIdentifierCString());
5949 result
= kOSKextReturnInvalidArgument
;
5953 if (!sLoadEnabled
) {
5955 kOSKextLogErrorLevel
|
5957 "Kext loading is disabled (attempt to start kext %s).",
5958 getIdentifierCString());
5959 result
= kOSKextReturnDisabled
;
5963 result
= validateKextMapping(/* start? */ true);
5964 if (result
!= kOSReturnSuccess
) {
5968 startfunc
= kmod_info
->start
;
5970 count
= getNumDependencies();
5971 for (i
= 0; i
< count
; i
++) {
5972 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
5973 if (dependency
== NULL
) {
5975 kOSKextLogErrorLevel
|
5977 "Kext %s start - internal error, dependency disappeared.",
5978 getIdentifierCString());
5981 if (!dependency
->isStarted()) {
5982 if (startDependenciesFlag
) {
5983 OSReturn dependencyResult
=
5984 dependency
->start(startDependenciesFlag
);
5985 if (dependencyResult
!= KERN_SUCCESS
) {
5987 kOSKextLogErrorLevel
|
5989 "Kext %s start - dependency %s failed to start (error 0x%x).",
5990 getIdentifierCString(),
5991 dependency
->getIdentifierCString(),
5997 kOSKextLogErrorLevel
|
5999 "Not starting %s - dependency %s not started yet.",
6000 getIdentifierCString(),
6001 dependency
->getIdentifierCString());
6002 result
= kOSKextReturnStartStopError
; // xxx - make new return?
6009 kOSKextLogDetailLevel
|
6011 "Kext %s calling module start function.",
6012 getIdentifierCString());
6016 #if !CONFIG_STATIC_CPPINIT
6017 result
= OSRuntimeInitializeCPP(kmod_info
, NULL
);
6018 if (result
== KERN_SUCCESS
) {
6022 kmodStartData
= GetAppleTEXTHashForKext(this, this->infoDict
);
6025 if (kmodStartData
) {
6027 kOSKextLogErrorLevel
|
6028 kOSKextLogGeneralFlag
,
6029 "Kext %s calling module start function. kmodStartData %p. arch %s",
6030 getIdentifierCString(), kmodStartData
, ARCHNAME
);
6033 #endif // CONFIG_KEC_FIPS
6035 result
= startfunc(kmod_info
, kmodStartData
);
6037 #if !CONFIG_STATIC_CPPINIT
6038 if (result
!= KERN_SUCCESS
) {
6039 (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6046 /* On success overlap the setting of started/starting. On failure just
6049 if (result
== KERN_SUCCESS
) {
6052 // xxx - log start error from kernel?
6054 kOSKextLogProgressLevel
|
6056 "Kext %s is now started.",
6057 getIdentifierCString());
6059 invokeOrCancelRequestCallbacks(
6060 /* result not actually used */ kOSKextReturnStartStopError
,
6061 /* invokeFlag */ false);
6063 kOSKextLogProgressLevel
|
6065 "Kext %s did not start (return code 0x%x).",
6066 getIdentifierCString(), result
);
6073 /*********************************************************************
6074 *********************************************************************/
6076 bool OSKext::canUnloadKextWithIdentifier(
6077 OSString
* kextIdentifier
,
6078 bool checkClassesFlag
)
6080 bool result
= false;
6081 OSKext
* aKext
= NULL
; // do not release
6083 IORecursiveLockLock(sKextLock
);
6085 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
6088 goto finish
; // can't unload what's not loaded
6091 if (aKext
->isLoaded()) {
6092 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
6095 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
6103 IORecursiveLockUnlock(sKextLock
);
6107 /*********************************************************************
6108 *********************************************************************/
6112 OSReturn result
= kOSReturnError
;
6113 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
6115 if (!isStarted() || isInterface()) {
6116 result
= kOSReturnSuccess
;
6122 kOSKextLogErrorLevel
|
6124 "Attempt to stop nonloaded kext %s.",
6125 getIdentifierCString());
6126 result
= kOSKextReturnInvalidArgument
;
6130 /* Refuse to stop if we have clients or instances. It is up to
6131 * the caller to make sure those aren't true.
6133 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6135 kOSKextLogErrorLevel
|
6137 "Kext %s - C++ instances; can't stop.",
6138 getIdentifierCString());
6139 result
= kOSKextReturnInUse
;
6143 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6146 kOSKextLogErrorLevel
|
6148 "Kext %s - has references (linkage or tracking object); "
6150 getIdentifierCString());
6151 result
= kOSKextReturnInUse
;
6155 /* Note: If validateKextMapping fails on the stop & unload path,
6156 * we are in serious trouble and a kernel panic is likely whether
6157 * we stop & unload the kext or not.
6159 result
= validateKextMapping(/* start? */ false);
6160 if (result
!= kOSReturnSuccess
) {
6164 stopfunc
= kmod_info
->stop
;
6167 kOSKextLogDetailLevel
|
6169 "Kext %s calling module stop function.",
6170 getIdentifierCString());
6174 result
= stopfunc(kmod_info
, /* userData */ NULL
);
6175 #if !CONFIG_STATIC_CPPINIT
6176 if (result
== KERN_SUCCESS
) {
6177 result
= OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6183 if (result
== KERN_SUCCESS
) {
6187 kOSKextLogDetailLevel
|
6189 "Kext %s is now stopped and ready to unload.",
6190 getIdentifierCString());
6193 kOSKextLogErrorLevel
|
6195 "Kext %s did not stop (return code 0x%x).",
6196 getIdentifierCString(), result
);
6197 result
= kOSKextReturnStartStopError
;
6205 /*********************************************************************
6206 *********************************************************************/
6208 OSKext::unload(void)
6210 OSReturn result
= kOSReturnError
;
6212 uint32_t num_kmod_refs
= 0;
6214 if (!sUnloadEnabled
) {
6216 kOSKextLogErrorLevel
|
6218 "Kext unloading is disabled (%s).",
6219 this->getIdentifierCString());
6221 result
= kOSKextReturnDisabled
;
6225 /* Refuse to unload if we have clients or instances. It is up to
6226 * the caller to make sure those aren't true.
6228 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6229 // xxx - Don't log under errors? this is more of an info thing
6231 kOSKextLogErrorLevel
|
6232 kOSKextLogKextBookkeepingFlag
,
6233 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6234 getIdentifierCString());
6235 result
= kOSKextReturnInUse
;
6239 if (hasOSMetaClassInstances()) {
6241 kOSKextLogErrorLevel
|
6242 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6243 "Can't unload kext %s; classes have instances:",
6244 getIdentifierCString());
6245 reportOSMetaClassInstances(kOSKextLogErrorLevel
|
6246 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
);
6247 result
= kOSKextReturnInUse
;
6252 result
= kOSReturnSuccess
;
6256 if (isKernelComponent()) {
6257 result
= kOSKextReturnInvalidArgument
;
6261 /* Note that the kext is unloading before running any code that
6262 * might be in the kext (request callbacks, module stop function).
6263 * We will deny certain requests made against a kext in the process
6266 flags
.unloading
= 1;
6268 /* Update the string describing the last kext to unload in case we panic.
6270 savePanicString(/* isLoading */ false);
6274 if (result
!= KERN_SUCCESS
) {
6276 kOSKextLogErrorLevel
|
6278 "Kext %s can't unload - module stop returned 0x%x.",
6279 getIdentifierCString(), (unsigned)result
);
6280 result
= kOSKextReturnStartStopError
;
6286 kOSKextLogProgressLevel
|
6288 "Kext %s unloading.",
6289 getIdentifierCString());
6291 /* Even if we don't call the stop function, we want to be sure we
6292 * have no OSMetaClass references before unloading the kext executable
6293 * from memory. OSMetaClasses may have pointers into the kext executable
6294 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6297 metaClasses
->flushCollection();
6300 /* Remove the kext from the list of loaded kexts, patch the gap
6301 * in the kmod_info_t linked list, and reset "kmod" to point to the
6302 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6304 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
6305 if (index
!= (unsigned int)-1) {
6307 sLoadedKexts
->removeObject(index
);
6309 OSKext
* nextKext
= OSDynamicCast(OSKext
,
6310 sLoadedKexts
->getObject(index
));
6314 OSKext
* gapKext
= OSDynamicCast(OSKext
,
6315 sLoadedKexts
->getObject(index
- 1));
6317 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
6319 } else /* index == 0 */ {
6320 nextKext
->kmod_info
->next
= NULL
;
6324 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
6325 if (lastKext
&& !lastKext
->isKernel()) {
6326 kmod
= lastKext
->kmod_info
;
6328 kmod
= NULL
; // clear the global kmod variable
6332 /* Clear out the kmod references that we're keeping for compatibility
6333 * with current panic backtrace code & kgmacros.
6334 * xxx - will want to update those bits sometime and remove this.
6336 num_kmod_refs
= getNumDependencies();
6337 if (num_kmod_refs
&& kmod_info
&& kmod_info
->reference_list
) {
6338 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
6339 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
6340 ref
->info
->reference_count
--;
6342 kfree(kmod_info
->reference_list
,
6343 num_kmod_refs
* sizeof(kmod_reference_t
));
6347 unregisterWithDTrace();
6348 #endif /* CONFIG_DTRACE */
6350 notifyKextUnloadObservers(this);
6352 /* Unwire and free the linked executable.
6354 if (linkedExecutable
) {
6356 if (!isInterface()) {
6357 kernel_segment_command_t
*seg
= NULL
;
6358 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6362 kOSKextLogErrorLevel
|
6364 "Failed to free kext %s; couldn't find the kext map.",
6365 getIdentifierCString());
6366 result
= kOSKextReturnInternalError
;
6371 kOSKextLogProgressLevel
|
6373 "Kext %s unwiring and unmapping linked executable.",
6374 getIdentifierCString());
6376 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6378 if (segmentShouldBeWired(seg
)) {
6379 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6380 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6381 if (result
!= KERN_SUCCESS
) {
6383 kOSKextLogErrorLevel
|
6385 "Failed to unwire kext %s.",
6386 getIdentifierCString());
6387 result
= kOSKextReturnInternalError
;
6392 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6396 OSSafeReleaseNULL(linkedExecutable
);
6399 /* An interface kext has a fake kmod_info that was allocated,
6400 * so we have to free it.
6402 if (isInterface()) {
6403 kfree(kmod_info
, sizeof(kmod_info_t
));
6408 flags
.loaded
= false;
6409 flushDependencies();
6411 /* save a copy of the bundle ID for us to check when deciding to
6412 * rebuild the kernel cache file. If a kext was already in the kernel
6413 * cache and unloaded then later loaded we do not need to rebuild the
6414 * kernel cache. 9055303
6416 if (isPrelinked()) {
6417 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6418 IORecursiveLockLock(sKextLock
);
6419 if (sUnloadedPrelinkedKexts
) {
6420 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6422 IORecursiveLockUnlock(sKextLock
);
6427 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6428 "Kext %s unloaded.", getIdentifierCString());
6430 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6431 OSDynamicCast(OSString
, bundleID
));
6434 OSKext::saveLoadedKextPanicList();
6435 OSKext::updateLoadedKextSummaries();
6437 flags
.unloading
= 0;
6441 /*********************************************************************
6442 * Assumes sKextLock is held.
6443 *********************************************************************/
6446 OSKext::queueKextNotification(
6447 const char * notificationName
,
6448 OSString
* kextIdentifier
)
6450 OSReturn result
= kOSReturnError
;
6451 OSDictionary
* loadRequest
= NULL
; // must release
6453 if (!kextIdentifier
) {
6454 result
= kOSKextReturnInvalidArgument
;
6458 /* Create a new request unless one is already sitting
6459 * in sKernelRequests for this bundle identifier
6461 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6462 if (result
!= kOSReturnSuccess
) {
6465 if (!_OSKextSetRequestArgument(loadRequest
,
6466 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6468 result
= kOSKextReturnNoMemory
;
6471 if (!sKernelRequests
->setObject(loadRequest
)) {
6472 result
= kOSKextReturnNoMemory
;
6476 /* We might want to only queue the notification if kextd is active,
6477 * but that wouldn't work for embedded. Note that we don't care if
6478 * the ping immediately succeeds here so don't do anything with the
6479 * result of this call.
6481 OSKext::pingKextd();
6483 result
= kOSReturnSuccess
;
6486 OSSafeRelease(loadRequest
);
6491 /*********************************************************************
6492 *********************************************************************/
6494 _OSKextConsiderDestroyingLinkContext(
6495 __unused thread_call_param_t p0
,
6496 __unused thread_call_param_t p1
)
6498 /* Take multiple locks in the correct order.
6500 IORecursiveLockLock(sKextLock
);
6501 IORecursiveLockLock(sKextInnerLock
);
6503 /* The first time we destroy the kxldContext is in the first
6504 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6505 * before calling this function. Thereafter any call to this function
6506 * will actually destroy the context.
6508 if (sConsiderUnloadsCalled
&& sKxldContext
) {
6509 kxld_destroy_context(sKxldContext
);
6510 sKxldContext
= NULL
;
6513 /* Free the thread_call that was allocated to execute this function.
6515 if (sDestroyLinkContextThread
) {
6516 if (!thread_call_free(sDestroyLinkContextThread
)) {
6517 OSKextLog(/* kext */ NULL
,
6518 kOSKextLogErrorLevel
|
6519 kOSKextLogGeneralFlag
,
6520 "thread_call_free() failed for kext link context.");
6522 sDestroyLinkContextThread
= 0;
6525 IORecursiveLockUnlock(sKextInnerLock
);
6526 IORecursiveLockUnlock(sKextLock
);
6531 /*********************************************************************
6532 * Destroying the kxldContext requires checking variables under both
6533 * sKextInnerLock and sKextLock, so we do it on a separate thread
6534 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6535 * call relationship.
6537 * This function must be invoked with sKextInnerLock held.
6538 * Do not call any function that takes sKextLock here!
6539 *********************************************************************/
6542 OSKext::considerDestroyingLinkContext(void)
6544 IORecursiveLockLock(sKextInnerLock
);
6546 /* If we have already queued a thread to destroy the link context,
6547 * don't bother resetting; that thread will take care of it.
6549 if (sDestroyLinkContextThread
) {
6553 /* The function to be invoked in the thread will deallocate
6554 * this thread_call, so don't share it around.
6556 sDestroyLinkContextThread
= thread_call_allocate(
6557 &_OSKextConsiderDestroyingLinkContext
, 0);
6558 if (!sDestroyLinkContextThread
) {
6559 OSKextLog(/* kext */ NULL
,
6560 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
| kOSKextLogLinkFlag
,
6561 "Can't create thread to destroy kext link context.");
6565 thread_call_enter(sDestroyLinkContextThread
);
6568 IORecursiveLockUnlock(sKextInnerLock
);
6573 #pragma mark Autounload
6575 /*********************************************************************
6576 * This is a static method because the kext will be deallocated if it
6578 *********************************************************************/
6581 OSKext::autounloadKext(OSKext
* aKext
)
6583 OSReturn result
= kOSKextReturnInUse
;
6585 /* Check for external references to this kext (usu. dependents),
6586 * instances of defined classes (or classes derived from them),
6587 * outstanding requests.
6589 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
6590 !aKext
->flags
.autounloadEnabled
||
6591 aKext
->isKernelComponent()) {
6596 /* Skip a delay-autounload kext, once.
6598 if (aKext
->flags
.delayAutounload
) {
6600 kOSKextLogProgressLevel
|
6601 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6602 "Kext %s has delayed autounload set; skipping and clearing flag.",
6603 aKext
->getIdentifierCString());
6604 aKext
->flags
.delayAutounload
= 0;
6608 if (aKext
->hasOSMetaClassInstances() ||
6609 aKext
->countRequestCallbacks()) {
6613 result
= OSKext::removeKext(aKext
);
6620 /*********************************************************************
6621 *********************************************************************/
6623 _OSKextConsiderUnloads(
6624 __unused thread_call_param_t p0
,
6625 __unused thread_call_param_t p1
)
6627 bool didUnload
= false;
6628 unsigned int count
, i
;
6630 /* Take multiple locks in the correct order
6631 * (note also sKextSummaries lock further down).
6633 IORecursiveLockLock(sKextLock
);
6634 IORecursiveLockLock(sKextInnerLock
);
6636 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6638 IOLockLock(sKextSummariesLock
);
6640 /* If there is an old kext summary, free that now.
6642 if (sPrevLoadedKextSummaries
) {
6643 kmem_free(kernel_map
, (vm_offset_t
)sPrevLoadedKextSummaries
,
6644 sPrevLoadedKextSummariesAllocSize
);
6645 sPrevLoadedKextSummaries
= NULL
;
6646 sPrevLoadedKextSummariesAllocSize
= 0;
6649 IOLockUnlock(sKextSummariesLock
);
6651 /* If the system is powering down, don't try to unload anything.
6657 OSKextLog(/* kext */ NULL
,
6658 kOSKextLogProgressLevel
|
6660 "Checking for unused kexts to autounload.");
6663 * Remove any request callbacks marked as stale,
6664 * and mark as stale any currently in flight.
6666 count
= sRequestCallbackRecords
->getCount();
6670 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
6671 sRequestCallbackRecords
->getObject(i
));
6672 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
6673 callbackRecord
->getObject(kKextRequestStaleKey
));
6675 if (stale
== kOSBooleanTrue
) {
6676 OSKext::invokeRequestCallback(callbackRecord
,
6677 kOSKextReturnTimeout
);
6679 callbackRecord
->setObject(kKextRequestStaleKey
,
6686 * Make multiple passes through the array of loaded kexts until
6687 * we don't unload any. This handles unwinding of dependency
6688 * chains. We have to go *backwards* through the array because
6689 * kexts are removed from it when unloaded, and we cannot make
6690 * a copy or we'll mess up the retain counts we rely on to
6691 * check whether a kext will unload. If only we could have
6692 * nonretaining collections like CF has....
6697 count
= sLoadedKexts
->getCount();
6701 OSKext
* thisKext
= OSDynamicCast(OSKext
,
6702 sLoadedKexts
->getObject(i
));
6703 didUnload
= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
6706 } while (didUnload
);
6709 sConsiderUnloadsPending
= false;
6710 sConsiderUnloadsExecuted
= true;
6712 (void) OSKext::considerRebuildOfPrelinkedKernel();
6714 IORecursiveLockUnlock(sKextInnerLock
);
6715 IORecursiveLockUnlock(sKextLock
);
6720 /*********************************************************************
6721 * Do not call any function that takes sKextLock here!
6722 *********************************************************************/
6723 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
6727 IORecursiveLockLock(sKextInnerLock
);
6729 if (!sUnloadCallout
) {
6730 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, 0);
6733 /* we only reset delay value for unloading if we already have something
6734 * pending. rescheduleOnlyFlag should not start the count down.
6736 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
6740 thread_call_cancel(sUnloadCallout
);
6741 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
6742 clock_interval_to_deadline(sConsiderUnloadDelay
,
6743 1000 * 1000 * 1000, &when
);
6745 OSKextLog(/* kext */ NULL
,
6746 kOSKextLogProgressLevel
|
6748 "%scheduling %sscan for unused kexts in %lu seconds.",
6749 sConsiderUnloadsPending
? "Res" : "S",
6750 sConsiderUnloadsCalled
? "" : "initial ",
6751 (unsigned long)sConsiderUnloadDelay
);
6753 sConsiderUnloadsPending
= true;
6754 thread_call_enter_delayed(sUnloadCallout
, when
);
6758 /* The kxld context should be reused throughout boot. We mark the end of
6759 * period as the first time considerUnloads() is called, and we destroy
6760 * the first kxld context in that function. Afterwards, it will be
6761 * destroyed in flushNonloadedKexts.
6763 if (!sConsiderUnloadsCalled
) {
6764 sConsiderUnloadsCalled
= true;
6765 OSKext::considerDestroyingLinkContext();
6768 IORecursiveLockUnlock(sKextInnerLock
);
6772 /*********************************************************************
6773 * Do not call any function that takes sKextLock here!
6774 *********************************************************************/
6777 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
)
6779 IORecursiveLockLock(sKextInnerLock
);
6781 /* If the system is going to sleep, cancel the reaper thread timer,
6782 * and note that we're in a sleep state in case it just fired but hasn't
6783 * taken the lock yet. If we are coming back from sleep, just
6784 * clear the sleep flag; IOService's normal operation will cause
6785 * unloads to be considered soon enough.
6787 if (messageType
== kIOMessageSystemWillSleep
) {
6788 if (sUnloadCallout
) {
6789 thread_call_cancel(sUnloadCallout
);
6791 sSystemSleep
= true;
6792 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
6793 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
6794 sSystemSleep
= false;
6795 clock_get_uptime(&sLastWakeTime
);
6797 IORecursiveLockUnlock(sKextInnerLock
);
6799 return kIOReturnSuccess
;
6806 #pragma mark Prelinked Kernel
6808 /*********************************************************************
6809 * Do not access sConsiderUnloads... variables other than
6810 * sConsiderUnloadsExecuted in this function. They are guarded by a
6812 *********************************************************************/
6815 OSKext::considerRebuildOfPrelinkedKernel(void)
6817 static bool requestedPrelink
= false;
6818 OSReturn checkResult
= kOSReturnError
;
6819 OSDictionary
* prelinkRequest
= NULL
; // must release
6820 OSCollectionIterator
* kextIterator
= NULL
; // must release
6821 const OSSymbol
* thisID
= NULL
; // do not release
6822 bool doRebuild
= false;
6823 AbsoluteTime my_abstime
;
6827 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
6828 if (requestedPrelink
|| !sPrelinkBoot
) {
6832 /* no direct return from this point */
6833 IORecursiveLockLock(sKextLock
);
6835 /* We need to wait for kextd to get up and running with unloads already done
6836 * and any new startup kexts loaded.
6838 if (!sConsiderUnloadsExecuted
||
6839 !sDeferredLoadSucceeded
) {
6843 /* we really only care about boot / system start up related kexts so bail
6844 * if we're here after REBUILD_MAX_TIME.
6846 if (!_OSKextInPrelinkRebuildWindow()) {
6847 OSKextLog(/* kext */ NULL
,
6848 kOSKextLogArchiveFlag
,
6849 "%s prebuild rebuild has expired",
6851 requestedPrelink
= true;
6855 /* we do not want to trigger a rebuild if we get here too close to waking
6856 * up. (see radar 10233768)
6858 IORecursiveLockLock(sKextInnerLock
);
6860 clock_get_uptime(&my_abstime
);
6861 delta_secs
= MINIMUM_WAKEUP_SECONDS
+ 1;
6862 if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) {
6863 SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
);
6864 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
6865 delta_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
6867 IORecursiveLockUnlock(sKextInnerLock
);
6869 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
6870 /* too close to time of last wake from sleep */
6873 requestedPrelink
= true;
6875 /* Now it's time to see if we have a reason to rebuild. We may have done
6876 * some loads and unloads but the kernel cache didn't actually change.
6877 * We will rebuild if any kext is not marked prelinked AND is not in our
6878 * list of prelinked kexts that got unloaded. (see radar 9055303)
6880 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
6881 if (!kextIterator
) {
6885 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
6886 OSKext
* thisKext
; // do not release
6888 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
6889 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
6893 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
6896 /* kext is loaded and was not in current kernel cache so let's rebuild
6899 OSKextLog(/* kext */ NULL
,
6900 kOSKextLogArchiveFlag
,
6901 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
6902 thisKext
->bundleID
->getCStringNoCopy());
6905 sUnloadedPrelinkedKexts
->flushCollection();
6911 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
6913 if (checkResult
!= kOSReturnSuccess
) {
6917 if (!sKernelRequests
->setObject(prelinkRequest
)) {
6921 OSKext::pingKextd();
6924 IORecursiveLockUnlock(sKextLock
);
6925 OSSafeRelease(prelinkRequest
);
6926 OSSafeRelease(kextIterator
);
6932 #pragma mark Dependencies
6934 /*********************************************************************
6935 *********************************************************************/
6937 OSKext::resolveDependencies(
6938 OSArray
* loopStack
)
6940 bool result
= false;
6941 OSArray
* localLoopStack
= NULL
; // must release
6942 bool addedToLoopStack
= false;
6943 OSDictionary
* libraries
= NULL
; // do not release
6944 OSCollectionIterator
* libraryIterator
= NULL
; // must release
6945 OSString
* libraryID
= NULL
; // do not release
6946 OSString
* infoString
= NULL
; // do not release
6947 OSString
* readableString
= NULL
; // do not release
6948 OSKext
* libraryKext
= NULL
; // do not release
6949 bool hasRawKernelDependency
= false;
6950 bool hasKernelDependency
= false;
6951 bool hasKPIDependency
= false;
6952 bool hasPrivateKPIDependency
= false;
6955 /* A kernel component will automatically have this flag set,
6956 * and a loaded kext should also have it set (as should all its
6957 * loaded dependencies).
6959 if (flags
.hasAllDependencies
) {
6964 /* Check for loops in the dependency graph.
6967 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
6969 kOSKextLogErrorLevel
|
6970 kOSKextLogDependenciesFlag
,
6971 "Kext %s has a dependency loop; can't resolve dependencies.",
6972 getIdentifierCString());
6977 kOSKextLogStepLevel
|
6978 kOSKextLogDependenciesFlag
,
6979 "Kext %s resolving dependencies.",
6980 getIdentifierCString());
6982 loopStack
= OSArray::withCapacity(6); // any small capacity will do
6985 kOSKextLogErrorLevel
|
6986 kOSKextLogDependenciesFlag
,
6987 "Kext %s can't create bookkeeping stack to resolve dependencies.",
6988 getIdentifierCString());
6991 localLoopStack
= loopStack
;
6993 if (!loopStack
->setObject(this)) {
6995 kOSKextLogErrorLevel
|
6996 kOSKextLogDependenciesFlag
,
6997 "Kext %s - internal error resolving dependencies.",
6998 getIdentifierCString());
7001 addedToLoopStack
= true;
7003 /* Purge any existing kexts in the dependency list and start over.
7005 flushDependencies();
7008 kOSKextLogErrorLevel
|
7009 kOSKextLogDependenciesFlag
,
7010 "Kext %s - internal error resolving dependencies.",
7011 getIdentifierCString());
7014 libraries
= OSDynamicCast(OSDictionary
,
7015 getPropertyForHostArch(kOSBundleLibrariesKey
));
7016 if (libraries
== NULL
|| libraries
->getCount() == 0) {
7018 kOSKextLogErrorLevel
|
7019 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7020 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7021 getIdentifierCString(), kOSBundleLibrariesKey
);
7025 /* Make a new array to hold the dependencies (flush freed the old one).
7027 dependencies
= OSArray::withCapacity(libraries
->getCount());
7028 if (!dependencies
) {
7030 kOSKextLogErrorLevel
|
7031 kOSKextLogDependenciesFlag
,
7032 "Kext %s - can't allocate dependencies array.",
7033 getIdentifierCString());
7037 // xxx - compat: We used to add an implicit dependency on kernel 6.0
7038 // xxx - compat: if none were declared.
7040 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
7041 if (!libraryIterator
) {
7043 kOSKextLogErrorLevel
|
7044 kOSKextLogDependenciesFlag
,
7045 "Kext %s - can't allocate dependencies iterator.",
7046 getIdentifierCString());
7050 while ((libraryID
= OSDynamicCast(OSString
,
7051 libraryIterator
->getNextObject()))) {
7053 const char * library_id
= libraryID
->getCStringNoCopy();
7055 OSString
* libraryVersion
= OSDynamicCast(OSString
,
7056 libraries
->getObject(libraryID
));
7057 if (libraryVersion
== NULL
) {
7059 kOSKextLogErrorLevel
|
7060 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7061 "Kext %s - illegal type in OSBundleLibraries.",
7062 getIdentifierCString());
7066 OSKextVersion libraryVers
=
7067 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
7068 if (libraryVers
== -1) {
7070 kOSKextLogErrorLevel
|
7071 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7072 "Kext %s - invalid library version %s.",
7073 getIdentifierCString(),
7074 libraryVersion
->getCStringNoCopy());
7078 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
7079 if (libraryKext
== NULL
) {
7081 kOSKextLogErrorLevel
|
7082 kOSKextLogDependenciesFlag
,
7083 "Kext %s - library kext %s not found.",
7084 getIdentifierCString(), library_id
);
7088 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
7090 kOSKextLogErrorLevel
|
7091 kOSKextLogDependenciesFlag
,
7092 "Kext %s - library kext %s not compatible "
7093 "with requested version %s.",
7094 getIdentifierCString(), library_id
,
7095 libraryVersion
->getCStringNoCopy());
7099 /* If a nonprelinked library somehow got into the mix for a
7100 * prelinked kext, at any point in the chain, we must fail
7101 * because the prelinked relocs for the library will be all wrong.
7103 if (this->isPrelinked() &&
7104 libraryKext
->declaresExecutable() &&
7105 !libraryKext
->isPrelinked()) {
7108 kOSKextLogErrorLevel
|
7109 kOSKextLogDependenciesFlag
,
7110 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7111 getIdentifierCString(), library_id
,
7112 libraryVersion
->getCStringNoCopy());
7116 if (!libraryKext
->resolveDependencies(loopStack
)) {
7120 /* Add the library directly only if it has an executable to link.
7121 * Otherwise it's just used to collect other dependencies, so put
7122 * *its* dependencies on the list for this kext.
7124 // xxx - We are losing info here; would like to make fake entries or
7125 // xxx - keep these in the dependency graph for loaded kexts.
7126 // xxx - I really want to make kernel components not a special case!
7127 if (libraryKext
->declaresExecutable() ||
7128 libraryKext
->isInterface()) {
7130 if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) {
7131 dependencies
->setObject(libraryKext
);
7134 kOSKextLogDetailLevel
|
7135 kOSKextLogDependenciesFlag
,
7136 "Kext %s added dependency %s.",
7137 getIdentifierCString(),
7138 libraryKext
->getIdentifierCString());
7141 int numLibDependencies
= libraryKext
->getNumDependencies();
7142 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
7145 if (numLibDependencies
) {
7146 // xxx - this msg level should be 1 lower than the per-kext one
7148 kOSKextLogDetailLevel
|
7149 kOSKextLogDependenciesFlag
,
7150 "Kext %s pulling %d dependencies from codeless library %s.",
7151 getIdentifierCString(),
7153 libraryKext
->getIdentifierCString());
7155 for (index
= 0; index
< numLibDependencies
; index
++) {
7156 OSKext
* thisLibDependency
= OSDynamicCast(OSKext
,
7157 libraryDependencies
->getObject(index
));
7158 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) {
7159 dependencies
->setObject(thisLibDependency
);
7161 kOSKextLogDetailLevel
|
7162 kOSKextLogDependenciesFlag
,
7163 "Kext %s added dependency %s from codeless library %s.",
7164 getIdentifierCString(),
7165 thisLibDependency
->getIdentifierCString(),
7166 libraryKext
->getIdentifierCString());
7171 if ((strlen(library_id
) == strlen(KERNEL_LIB
)) &&
7172 0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) {
7174 hasRawKernelDependency
= true;
7175 } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) {
7176 hasKernelDependency
= true;
7177 } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) {
7178 hasKPIDependency
= true;
7179 if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) {
7180 hasPrivateKPIDependency
= true;
7185 if (hasRawKernelDependency
) {
7187 kOSKextLogErrorLevel
|
7188 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7189 "Error - kext %s declares a dependency on %s, which is not permitted.",
7190 getIdentifierCString(), KERNEL_LIB
);
7194 if (hasKernelDependency
) {
7196 kOSKextLogErrorLevel
|
7197 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7198 "Error - kext %s declares %s dependencies. "
7199 "Only %s* dependencies are supported for 64-bit kexts.",
7200 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7203 if (!hasKPIDependency
) {
7205 kOSKextLogWarningLevel
|
7206 kOSKextLogDependenciesFlag
,
7207 "Warning - kext %s declares no %s* dependencies. "
7208 "If it uses any KPIs, the link may fail with undefined symbols.",
7209 getIdentifierCString(), KPI_LIB_PREFIX
);
7211 #else /* __LP64__ */
7212 // xxx - will change to flatly disallow "kernel" dependencies at some point
7213 // xxx - is it invalid to do both "com.apple.kernel" and any
7214 // xxx - "com.apple.kernel.*"?
7216 if (hasKernelDependency
&& hasKPIDependency
) {
7218 kOSKextLogWarningLevel
|
7219 kOSKextLogDependenciesFlag
,
7220 "Warning - kext %s has immediate dependencies on both "
7221 "%s* and %s* components; use only one style.",
7222 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7225 if (!hasKernelDependency
&& !hasKPIDependency
) {
7226 // xxx - do we want to use validation flag for these too?
7228 kOSKextLogWarningLevel
|
7229 kOSKextLogDependenciesFlag
,
7230 "Warning - %s declares no kernel dependencies; using %s.",
7231 getIdentifierCString(), KERNEL6_LIB
);
7232 OSKext
* kernelKext
= OSDynamicCast(OSKext
,
7233 sKextsByID
->getObject(KERNEL6_LIB
));
7235 dependencies
->setObject(kernelKext
);
7238 kOSKextLogErrorLevel
|
7239 kOSKextLogDependenciesFlag
,
7240 "Error - Library %s not found for %s.",
7241 KERNEL6_LIB
, getIdentifierCString());
7245 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7246 * its indirect dependencies to simulate old-style linking. XXX - Should
7247 * check for duplicates.
7249 if (!hasKPIDependency
) {
7252 flags
.hasBleedthrough
= true;
7254 count
= getNumDependencies();
7256 /* We add to the dependencies array in this loop, but do not iterate
7257 * past its original count.
7259 for (i
= 0; i
< count
; i
++) {
7260 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
7261 dependencies
->getObject(i
));
7262 dependencyKext
->addBleedthroughDependencies(dependencies
);
7265 #endif /* __LP64__ */
7267 if (hasPrivateKPIDependency
) {
7268 bool hasApplePrefix
= false;
7269 bool infoCopyrightIsValid
= false;
7270 bool readableCopyrightIsValid
= false;
7272 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
7275 infoString
= OSDynamicCast(OSString
,
7276 getPropertyForHostArch("CFBundleGetInfoString"));
7278 infoCopyrightIsValid
=
7279 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
7282 readableString
= OSDynamicCast(OSString
,
7283 getPropertyForHostArch("NSHumanReadableCopyright"));
7284 if (readableString
) {
7285 readableCopyrightIsValid
=
7286 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
7289 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
7291 kOSKextLogErrorLevel
|
7292 kOSKextLogDependenciesFlag
,
7293 "Error - kext %s declares a dependency on %s. "
7294 "Only Apple kexts may declare a dependency on %s.",
7295 getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
);
7301 flags
.hasAllDependencies
= 1;
7305 if (addedToLoopStack
) {
7306 count
= loopStack
->getCount();
7307 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
7308 loopStack
->removeObject(count
- 1);
7311 kOSKextLogErrorLevel
|
7312 kOSKextLogDependenciesFlag
,
7313 "Kext %s - internal error resolving dependencies.",
7314 getIdentifierCString());
7318 if (result
&& localLoopStack
) {
7320 kOSKextLogStepLevel
|
7321 kOSKextLogDependenciesFlag
,
7322 "Kext %s successfully resolved dependencies.",
7323 getIdentifierCString());
7326 OSSafeRelease(localLoopStack
);
7327 OSSafeRelease(libraryIterator
);
7332 /*********************************************************************
7333 *********************************************************************/
7335 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
7337 bool result
= false;
7338 unsigned int dependencyIndex
, dependencyCount
;
7340 dependencyCount
= getNumDependencies();
7342 for (dependencyIndex
= 0;
7343 dependencyIndex
< dependencyCount
;
7344 dependencyIndex
++) {
7346 OSKext
* dependency
= OSDynamicCast(OSKext
,
7347 dependencies
->getObject(dependencyIndex
));
7350 kOSKextLogErrorLevel
|
7351 kOSKextLogDependenciesFlag
,
7352 "Kext %s - internal error propagating compatibility dependencies.",
7353 getIdentifierCString());
7356 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7357 anArray
->setObject(dependency
);
7359 dependency
->addBleedthroughDependencies(anArray
);
7368 /*********************************************************************
7369 *********************************************************************/
7371 OSKext::flushDependencies(bool forceFlag
)
7373 bool result
= false;
7375 /* Only clear the dependencies if the kext isn't loaded;
7376 * we need the info for loaded kexts to track references.
7378 if (!isLoaded() || forceFlag
) {
7380 // xxx - check level
7382 kOSKextLogProgressLevel
|
7383 kOSKextLogDependenciesFlag
,
7384 "Kext %s flushing dependencies.",
7385 getIdentifierCString());
7386 OSSafeReleaseNULL(dependencies
);
7389 if (!isKernelComponent()) {
7390 flags
.hasAllDependencies
= 0;
7398 /*********************************************************************
7399 *********************************************************************/
7401 OSKext::getNumDependencies(void)
7403 if (!dependencies
) {
7406 return dependencies
->getCount();
7409 /*********************************************************************
7410 *********************************************************************/
7412 OSKext::getDependencies(void)
7414 return dependencies
;
7418 #pragma mark OSMetaClass Support
7420 /*********************************************************************
7421 *********************************************************************/
7424 OSMetaClass
* aClass
,
7425 uint32_t numClasses
)
7427 OSReturn result
= kOSMetaClassNoInsKModSet
;
7430 metaClasses
= OSSet::withCapacity(numClasses
);
7436 if (metaClasses
->containsObject(aClass
)) {
7438 kOSKextLogWarningLevel
|
7440 "Notice - kext %s has already registered class %s.",
7441 getIdentifierCString(),
7442 aClass
->getClassName());
7443 result
= kOSReturnSuccess
;
7447 if (!metaClasses
->setObject(aClass
)) {
7451 kOSKextLogDetailLevel
|
7453 "Kext %s registered class %s.",
7454 getIdentifierCString(),
7455 aClass
->getClassName());
7458 if (!flags
.autounloadEnabled
) {
7459 const OSMetaClass
* metaScan
= NULL
; // do not release
7461 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7462 if (metaScan
== OSTypeID(IOService
)) {
7465 kOSKextLogProgressLevel
|
7467 "Kext %s has IOService subclass %s; enabling autounload.",
7468 getIdentifierCString(),
7469 aClass
->getClassName());
7471 flags
.autounloadEnabled
= 1;
7477 notifyAddClassObservers(this, aClass
, flags
);
7479 result
= kOSReturnSuccess
;
7482 if (result
!= kOSReturnSuccess
) {
7484 kOSKextLogErrorLevel
|
7486 "Kext %s failed to register class %s.",
7487 getIdentifierCString(),
7488 aClass
->getClassName());
7494 /*********************************************************************
7495 *********************************************************************/
7497 OSKext::removeClass(
7498 OSMetaClass
* aClass
)
7500 OSReturn result
= kOSMetaClassNoKModSet
;
7506 if (!metaClasses
->containsObject(aClass
)) {
7508 kOSKextLogWarningLevel
|
7510 "Notice - kext %s asked to unregister unknown class %s.",
7511 getIdentifierCString(),
7512 aClass
->getClassName());
7513 result
= kOSReturnSuccess
;
7518 kOSKextLogDetailLevel
|
7520 "Kext %s unregistering class %s.",
7521 getIdentifierCString(),
7522 aClass
->getClassName());
7524 metaClasses
->removeObject(aClass
);
7526 notifyRemoveClassObservers(this, aClass
, flags
);
7528 result
= kOSReturnSuccess
;
7531 if (result
!= kOSReturnSuccess
) {
7533 kOSKextLogErrorLevel
|
7535 "Failed to unregister kext %s class %s.",
7536 getIdentifierCString(),
7537 aClass
->getClassName());
7542 /*********************************************************************
7543 *********************************************************************/
7545 OSKext::getMetaClasses(void)
7550 /*********************************************************************
7551 *********************************************************************/
7553 OSKext::hasOSMetaClassInstances(void)
7555 bool result
= false;
7556 OSCollectionIterator
* classIterator
= NULL
; // must release
7557 OSMetaClass
* checkClass
= NULL
; // do not release
7563 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7564 if (!classIterator
) {
7565 // xxx - log alloc failure?
7568 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7569 if (checkClass
->getInstanceCount()) {
7577 OSSafeRelease(classIterator
);
7581 /*********************************************************************
7582 *********************************************************************/
7585 OSKext::reportOSMetaClassInstances(
7586 const char * kextIdentifier
,
7587 OSKextLogSpec msgLogSpec
)
7589 OSKext
* theKext
= NULL
; // must release
7591 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
7596 theKext
->reportOSMetaClassInstances(msgLogSpec
);
7598 OSSafeRelease(theKext
);
7602 /*********************************************************************
7603 *********************************************************************/
7605 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
7607 OSCollectionIterator
* classIterator
= NULL
; // must release
7608 OSMetaClass
* checkClass
= NULL
; // do not release
7614 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7615 if (!classIterator
) {
7618 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7619 if (checkClass
->getInstanceCount()) {
7622 " Kext %s class %s has %d instance%s.",
7623 getIdentifierCString(),
7624 checkClass
->getClassName(),
7625 checkClass
->getInstanceCount(),
7626 checkClass
->getInstanceCount() == 1 ? "" : "s");
7631 OSSafeRelease(classIterator
);
7636 #pragma mark User-Space Requests
7638 /*********************************************************************
7639 * XXX - this function is a big ugly mess
7640 *********************************************************************/
7643 OSKext::handleRequest(
7644 host_priv_t hostPriv
,
7645 OSKextLogSpec clientLogFilter
,
7646 char * requestBuffer
,
7647 uint32_t requestLength
,
7648 char ** responseOut
,
7649 uint32_t * responseLengthOut
,
7651 uint32_t * logInfoLengthOut
)
7653 OSReturn result
= kOSReturnError
;
7654 kern_return_t kmem_result
= KERN_FAILURE
;
7656 char * response
= NULL
; // returned by reference
7657 uint32_t responseLength
= 0;
7659 OSObject
* parsedXML
= NULL
; // must release
7660 OSDictionary
* requestDict
= NULL
; // do not release
7661 OSString
* errorString
= NULL
; // must release
7663 OSData
* responseData
= NULL
; // must release
7664 OSObject
* responseObject
= NULL
; // must release
7666 OSSerialize
* serializer
= NULL
; // must release
7668 OSArray
* logInfoArray
= NULL
; // must release
7670 OSString
* predicate
= NULL
; // do not release
7671 OSString
* kextIdentifier
= NULL
; // do not release
7672 OSArray
* kextIdentifiers
= NULL
; // do not release
7673 OSKext
* theKext
= NULL
; // do not release
7674 OSBoolean
* boolArg
= NULL
; // do not release
7676 bool hideTheSlide
= false;
7678 IORecursiveLockLock(sKextLock
);
7681 *responseOut
= NULL
;
7682 *responseLengthOut
= 0;
7686 *logInfoLengthOut
= 0;
7689 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
7691 /* XML must be nul-terminated.
7693 if (requestBuffer
[requestLength
- 1] != '\0') {
7694 OSKextLog(/* kext */ NULL
,
7695 kOSKextLogErrorLevel
|
7697 "Invalid request from user space (not nul-terminated).");
7698 result
= kOSKextReturnBadData
;
7701 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
7703 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
7706 const char * errorCString
= "(unknown error)";
7708 if (errorString
&& errorString
->getCStringNoCopy()) {
7709 errorCString
= errorString
->getCStringNoCopy();
7710 } else if (parsedXML
) {
7711 errorCString
= "not a dictionary";
7713 OSKextLog(/* kext */ NULL
,
7714 kOSKextLogErrorLevel
|
7716 "Error unserializing request from user space: %s.",
7718 result
= kOSKextReturnSerialization
;
7722 predicate
= _OSKextGetRequestPredicate(requestDict
);
7724 OSKextLog(/* kext */ NULL
,
7725 kOSKextLogErrorLevel
|
7727 "Recieved kext request from user space with no predicate.");
7728 result
= kOSKextReturnInvalidArgument
;
7732 OSKextLog(/* kext */ NULL
,
7733 kOSKextLogDebugLevel
|
7735 "Received '%s' request from user space.",
7736 predicate
->getCStringNoCopy());
7738 result
= kOSKextReturnNotPrivileged
;
7739 if (hostPriv
== HOST_PRIV_NULL
) {
7741 hideTheSlide
= true;
7742 /* must be root to use these kext requests */
7743 if (predicate
->isEqualTo(kKextRequestPredicateGetKernelLoadAddress
) ||
7744 predicate
->isEqualTo(kKextRequestPredicateUnload
) ||
7745 predicate
->isEqualTo(kKextRequestPredicateStart
) ||
7746 predicate
->isEqualTo(kKextRequestPredicateStop
) ) {
7747 OSKextLog(/* kext */ NULL
,
7748 kOSKextLogErrorLevel
|
7750 "Access Failure - must be root user.");
7756 /* Get common args in anticipation of use.
7758 kextIdentifier
= OSDynamicCast(OSString
, _OSKextGetRequestArgument(
7759 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7760 kextIdentifiers
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument(
7761 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7762 if (kextIdentifier
) {
7763 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
7765 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
7766 requestDict
, kKextRequestArgumentValueKey
));
7768 result
= kOSKextReturnInvalidArgument
;
7770 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
7771 if (!kextIdentifier
) {
7772 OSKextLog(/* kext */ NULL
,
7773 kOSKextLogErrorLevel
|
7775 "Invalid arguments to kext start request.");
7776 } else if (!theKext
) {
7777 OSKextLog(/* kext */ NULL
,
7778 kOSKextLogErrorLevel
|
7780 "Kext %s not found for start request.",
7781 kextIdentifier
->getCStringNoCopy());
7782 result
= kOSKextReturnNotFound
;
7784 result
= theKext
->start();
7787 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
7788 if (!kextIdentifier
) {
7789 OSKextLog(/* kext */ NULL
,
7790 kOSKextLogErrorLevel
|
7792 "Invalid arguments to kext stop request.");
7793 } else if (!theKext
) {
7794 OSKextLog(/* kext */ NULL
,
7795 kOSKextLogErrorLevel
|
7797 "Kext %s not found for stop request.",
7798 kextIdentifier
->getCStringNoCopy());
7799 result
= kOSKextReturnNotFound
;
7801 result
= theKext
->stop();
7804 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
7805 if (!kextIdentifier
) {
7806 OSKextLog(/* kext */ NULL
,
7807 kOSKextLogErrorLevel
|
7809 "Invalid arguments to kext unload request.");
7810 } else if (!theKext
) {
7811 OSKextLog(/* kext */ NULL
,
7812 kOSKextLogErrorLevel
|
7814 "Kext %s not found for unload request.",
7815 kextIdentifier
->getCStringNoCopy());
7816 result
= kOSKextReturnNotFound
;
7818 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
7819 _OSKextGetRequestArgument(requestDict
,
7820 kKextRequestArgumentTerminateIOServicesKey
));
7821 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
7824 } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
7825 result
= OSKext::dispatchResource(requestDict
);
7827 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
7828 OSBoolean
* delayAutounloadBool
= NULL
;
7829 OSObject
* infoKeysRaw
= NULL
;
7830 OSArray
* infoKeys
= NULL
;
7831 uint32_t infoKeysCount
= 0;
7833 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
7834 _OSKextGetRequestArgument(requestDict
,
7835 kKextRequestArgumentDelayAutounloadKey
));
7837 /* If asked to delay autounload, reset the timer if it's currently set.
7838 * (That is, don't schedule an unload if one isn't already pending.
7840 if (delayAutounloadBool
== kOSBooleanTrue
) {
7841 OSKext::considerUnloads(/* rescheduleOnly? */ true);
7844 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
7845 kKextRequestArgumentInfoKeysKey
);
7846 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
7847 if (infoKeysRaw
&& !infoKeys
) {
7848 OSKextLog(/* kext */ NULL
,
7849 kOSKextLogErrorLevel
|
7851 "Invalid arguments to kext info request.");
7856 infoKeysCount
= infoKeys
->getCount();
7857 for (uint32_t i
= 0; i
< infoKeysCount
; i
++) {
7858 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) {
7859 OSKextLog(/* kext */ NULL
,
7860 kOSKextLogErrorLevel
|
7862 "Invalid arguments to kext info request.");
7868 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
7869 if (!responseObject
) {
7870 result
= kOSKextReturnInternalError
;
7872 OSKextLog(/* kext */ NULL
,
7873 kOSKextLogDebugLevel
|
7875 "Returning loaded kext info.");
7876 result
= kOSReturnSuccess
;
7879 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelLoadAddress
)) {
7880 OSNumber
* addressNum
= NULL
; // released as responseObject
7881 unsigned long long unslid_addr
= 0;
7882 kernel_segment_command_t
* textseg
= getsegbyname("__TEXT");
7885 OSKextLog(/* kext */ NULL
,
7886 kOSKextLogErrorLevel
|
7887 kOSKextLogGeneralFlag
| kOSKextLogIPCFlag
,
7888 "Can't find text segment for kernel load address.");
7889 result
= kOSReturnError
;
7893 unslid_addr
= VM_KERNEL_UNSLIDE(textseg
->vmaddr
);
7895 OSKextLog(/* kext */ NULL
,
7896 kOSKextLogDebugLevel
|
7898 "Returning kernel load address 0x%llx.",
7899 (unsigned long long) unslid_addr
);
7901 addressNum
= OSNumber::withNumber((long long unsigned int) unslid_addr
,
7902 8 * sizeof(long long unsigned int));
7903 responseObject
= addressNum
;
7904 result
= kOSReturnSuccess
;
7906 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) {
7908 /* Hand the current sKernelRequests array to the caller
7909 * (who must release it), and make a new one.
7911 responseObject
= sKernelRequests
;
7912 sKernelRequests
= OSArray::withCapacity(0);
7913 sPostedKextLoadIdentifiers
->flushCollection();
7914 OSKextLog(/* kext */ NULL
,
7915 kOSKextLogDebugLevel
|
7917 "Returning kernel requests.");
7918 result
= kOSReturnSuccess
;
7920 } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) {
7922 /* Return the set of all requested bundle identifiers */
7923 responseObject
= sAllKextLoadIdentifiers
;
7924 responseObject
->retain();
7925 OSKextLog(/* kext */ NULL
,
7926 kOSKextLogDebugLevel
|
7928 "Returning load requests.");
7929 result
= kOSReturnSuccess
;
7932 OSKextLog(/* kext */ NULL
,
7933 kOSKextLogDebugLevel
|
7935 "Received '%s' invalid request from user space.",
7936 predicate
->getCStringNoCopy());
7941 * Now we have handle the request, or not. Gather up the response & logging
7942 * info to ship to user space.
7945 /* Note: Nothing in OSKext is supposed to retain requestDict,
7946 * but you never know....
7948 if (requestDict
->getRetainCount() > 1) {
7949 OSKextLog(/* kext */ NULL
,
7950 kOSKextLogWarningLevel
|
7952 "Request from user space still retained by a kext; "
7953 "probable memory leak.");
7956 if (responseData
&& responseObject
) {
7957 OSKextLog(/* kext */ NULL
,
7958 kOSKextLogErrorLevel
|
7960 "Mistakenly generated both data & plist responses to user request "
7961 "(returning only data).");
7964 if (responseData
&& responseData
->getLength() && responseOut
) {
7966 response
= (char *)responseData
->getBytesNoCopy();
7967 responseLength
= responseData
->getLength();
7968 } else if (responseOut
&& responseObject
) {
7969 serializer
= OSSerialize::withCapacity(0);
7971 result
= kOSKextReturnNoMemory
;
7975 if (!responseObject
->serialize(serializer
)) {
7976 OSKextLog(/* kext */ NULL
,
7977 kOSKextLogErrorLevel
|
7979 "Failed to serialize response to request from user space.");
7980 result
= kOSKextReturnSerialization
;
7984 response
= (char *)serializer
->text();
7985 responseLength
= serializer
->getLength();
7988 if (responseOut
&& response
) {
7991 /* This kmem_alloc sets the return value of the function.
7993 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
,
7994 round_page(responseLength
));
7995 if (kmem_result
!= KERN_SUCCESS
) {
7996 OSKextLog(/* kext */ NULL
,
7997 kOSKextLogErrorLevel
|
7999 "Failed to copy response to request from user space.");
8000 result
= kmem_result
;
8003 /* 11981737 - clear uninitialized data in last page */
8004 bzero((void *)(buffer
+ responseLength
),
8005 (round_page(responseLength
) - responseLength
));
8006 memcpy(buffer
, response
, responseLength
);
8007 *responseOut
= buffer
;
8008 *responseLengthOut
= responseLength
;
8014 /* Gather up the collected log messages for user space. Any messages
8015 * messages past this call will not make it up as log messages but
8016 * will be in the system log. Note that we ignore the return of the
8017 * serialize; it has no bearing on the operation at hand even if we
8018 * fail to get the log messages.
8020 logInfoArray
= OSKext::clearUserSpaceLogFilter();
8022 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
8023 (void)OSKext::serializeLogInfo(logInfoArray
,
8024 logInfoOut
, logInfoLengthOut
);
8027 IORecursiveLockUnlock(sKextLock
);
8029 OSSafeRelease(parsedXML
);
8030 OSSafeRelease(errorString
);
8031 OSSafeRelease(responseData
);
8032 OSSafeRelease(responseObject
);
8033 OSSafeRelease(serializer
);
8034 OSSafeRelease(logInfoArray
);
8039 /*********************************************************************
8040 *********************************************************************/
8043 OSKext::copyLoadedKextInfo(
8044 OSArray
* kextIdentifiers
,
8047 OSDictionary
* result
= NULL
;
8048 OSDictionary
* kextInfo
= NULL
; // must release
8050 uint32_t idCount
= 0;
8051 uint32_t idIndex
= 0;
8053 IORecursiveLockLock(sKextLock
);
8055 /* Empty list of bundle ids is equivalent to no list (get all).
8057 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8058 kextIdentifiers
= NULL
;
8059 } else if (kextIdentifiers
) {
8060 idCount
= kextIdentifiers
->getCount();
8065 if (infoKeys
&& !infoKeys
->getCount()) {
8069 count
= sLoadedKexts
->getCount();
8070 result
= OSDictionary::withCapacity(count
);
8074 for (i
= 0; i
< count
; i
++) {
8075 OSKext
* thisKext
= NULL
; // do not release
8076 Boolean includeThis
= true;
8079 kextInfo
->release();
8082 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8087 /* Skip current kext if we have a list of bundle IDs and
8088 * it isn't in the list.
8090 if (kextIdentifiers
) {
8091 const OSString
* thisKextID
= thisKext
->getIdentifier();
8093 includeThis
= false;
8095 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8096 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
8097 kextIdentifiers
->getObject(idIndex
));
8098 if (thisKextID
->isEqualTo(thisRequestID
)) {
8109 kextInfo
= thisKext
->copyInfo(infoKeys
);
8111 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
8116 IORecursiveLockUnlock(sKextLock
);
8118 if (kextInfo
) kextInfo
->release();
8123 /*********************************************************************
8124 * Any info that needs to do allocations must goto finish on alloc
8125 * failure. Info that is just a lookup should just not set the object
8126 * if the info does not exist.
8127 *********************************************************************/
8128 #define _OSKextLoadInfoDictCapacity (12)
8131 OSKext::copyInfo(OSArray
* infoKeys
)
8133 OSDictionary
* result
= NULL
;
8134 bool success
= false;
8135 OSData
* headerData
= NULL
; // must release
8136 OSNumber
* cpuTypeNumber
= NULL
; // must release
8137 OSNumber
* cpuSubtypeNumber
= NULL
; // must release
8138 OSString
* versionString
= NULL
; // do not release
8139 uint32_t executablePathCStringSize
= 0;
8140 char * executablePathCString
= NULL
; // must release
8141 OSString
* executablePathString
= NULL
; // must release
8142 OSData
* uuid
= NULL
; // must release
8143 OSNumber
* scratchNumber
= NULL
; // must release
8144 OSArray
* dependencyLoadTags
= NULL
; // must release
8145 OSCollectionIterator
* metaClassIterator
= NULL
; // must release
8146 OSArray
* metaClassInfo
= NULL
; // must release
8147 OSDictionary
* metaClassDict
= NULL
; // must release
8148 OSMetaClass
* thisMetaClass
= NULL
; // do not release
8149 OSString
* metaClassName
= NULL
; // must release
8150 OSString
* superclassName
= NULL
; // must release
8153 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
8159 /* Empty keys means no keys, but NULL is quicker to check.
8161 if (infoKeys
&& !infoKeys
->getCount()) {
8165 /* Headers, CPU type, and CPU subtype.
8168 _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) ||
8169 _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) ||
8170 _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
))
8173 if (linkedExecutable
&& !isInterface()) {
8175 kernel_mach_header_t
*kext_mach_hdr
= (kernel_mach_header_t
*)
8176 linkedExecutable
->getBytesNoCopy();
8178 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) {
8179 kernel_mach_header_t
* temp_kext_mach_hdr
;
8180 struct load_command
* lcp
;
8182 headerData
= OSData::withBytes(kext_mach_hdr
,
8183 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
8188 // unslide any vmaddrs we return to userspace - 10726716
8189 temp_kext_mach_hdr
= (kernel_mach_header_t
*)
8190 headerData
->getBytesNoCopy();
8191 if (temp_kext_mach_hdr
== NULL
) {
8195 lcp
= (struct load_command
*) (temp_kext_mach_hdr
+ 1);
8196 for (i
= 0; i
< temp_kext_mach_hdr
->ncmds
; i
++) {
8197 if (lcp
->cmd
== LC_SEGMENT_KERNEL
) {
8198 kernel_segment_command_t
* segp
;
8199 kernel_section_t
* secp
;
8201 segp
= (kernel_segment_command_t
*) lcp
;
8202 // 10543468 - if we jettisoned __LINKEDIT clear size info
8203 if (flags
.jettisonLinkeditSeg
) {
8204 if (strncmp(segp
->segname
, SEG_LINKEDIT
, sizeof(segp
->segname
)) == 0) {
8211 OSKextLog(/* kext */ NULL
,
8212 kOSKextLogErrorLevel
|
8213 kOSKextLogGeneralFlag
,
8214 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
8215 __FUNCTION__
, segp
->segname
, segp
->vmaddr
,
8216 VM_KERNEL_UNSLIDE(segp
->vmaddr
),
8217 segp
->vmsize
, segp
->nsects
);
8219 segp
->vmaddr
= VM_KERNEL_UNSLIDE(segp
->vmaddr
);
8221 for (secp
= firstsect(segp
); secp
!= NULL
; secp
= nextsect(segp
, secp
)) {
8222 secp
->addr
= VM_KERNEL_UNSLIDE(secp
->addr
);
8225 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
8227 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
8230 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) {
8231 cpuTypeNumber
= OSNumber::withNumber(
8232 (uint64_t) kext_mach_hdr
->cputype
,
8233 8 * sizeof(kext_mach_hdr
->cputype
));
8234 if (!cpuTypeNumber
) {
8237 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
8240 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
8241 cpuSubtypeNumber
= OSNumber::withNumber(
8242 (uint64_t) kext_mach_hdr
->cpusubtype
,
8243 8 * sizeof(kext_mach_hdr
->cpusubtype
));
8244 if (!cpuSubtypeNumber
) {
8247 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
8252 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
8254 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
8258 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
8259 versionString
= OSDynamicCast(OSString
,
8260 getPropertyForHostArch(kCFBundleVersionKey
));
8261 if (versionString
) {
8262 result
->setObject(kCFBundleVersionKey
, versionString
);
8266 /* OSBundleCompatibleVersion.
8268 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
8269 versionString
= OSDynamicCast(OSString
,
8270 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
8271 if (versionString
) {
8272 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
8278 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
8280 result
->setObject(kOSBundlePathKey
, path
);
8285 /* OSBundleExecutablePath.
8287 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
8288 if (path
&& executableRelPath
) {
8290 uint32_t pathLength
= path
->getLength(); // gets incremented below
8292 // +1 for slash, +1 for \0
8293 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
8295 executablePathCString
= (char *)kalloc((executablePathCStringSize
) *
8296 sizeof(char)); // +1 for \0
8297 if (!executablePathCString
) {
8300 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
8301 executablePathCStringSize
);
8302 executablePathCString
[pathLength
++] = '/';
8303 executablePathCString
[pathLength
++] = '\0';
8304 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
8305 executablePathCStringSize
);
8307 executablePathString
= OSString::withCString(executablePathCString
);
8309 if (!executablePathCString
) {
8313 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
8317 /* UUID, if the kext has one.
8319 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
8322 result
->setObject(kOSBundleUUIDKey
, uuid
);
8327 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
8329 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
8330 result
->setObject(kOSKernelResourceKey
,
8331 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
8334 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
8335 result
->setObject(kOSBundleIsInterfaceKey
,
8336 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
8339 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
8340 result
->setObject(kOSBundlePrelinkedKey
,
8341 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
8344 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
8345 result
->setObject(kOSBundleStartedKey
,
8346 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
8351 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
8352 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
8353 /* numBits */ 8 * sizeof(loadTag
));
8354 if (!scratchNumber
) {
8357 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
8358 OSSafeReleaseNULL(scratchNumber
);
8361 /* LoadAddress, LoadSize.
8364 _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) ||
8365 _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) ||
8366 _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
))
8368 if (isInterface() || linkedExecutable
) {
8369 /* These go to userspace via serialization, so we don't want any doubts
8372 uint64_t loadAddress
= 0;
8373 uint32_t loadSize
= 0;
8374 uint32_t wiredSize
= 0;
8376 /* Interfaces always report 0 load address & size.
8377 * Just the way they roll.
8379 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
8380 * xxx - shouldn't have one!
8382 if (linkedExecutable
/* && !isInterface() */) {
8383 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
8384 loadAddress
= VM_KERNEL_UNSLIDE(loadAddress
);
8385 loadSize
= linkedExecutable
->getLength();
8387 /* If we have a kmod_info struct, calculated the wired size
8388 * from that. Otherwise it's the full load size.
8391 wiredSize
= loadSize
- kmod_info
->hdr_size
;
8393 wiredSize
= loadSize
;
8397 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
8398 scratchNumber
= OSNumber::withNumber(
8399 (unsigned long long)(loadAddress
),
8400 /* numBits */ 8 * sizeof(loadAddress
));
8401 if (!scratchNumber
) {
8404 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
8405 OSSafeReleaseNULL(scratchNumber
);
8407 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
8408 scratchNumber
= OSNumber::withNumber(
8409 (unsigned long long)(loadSize
),
8410 /* numBits */ 8 * sizeof(loadSize
));
8411 if (!scratchNumber
) {
8414 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
8415 OSSafeReleaseNULL(scratchNumber
);
8417 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
8418 scratchNumber
= OSNumber::withNumber(
8419 (unsigned long long)(wiredSize
),
8420 /* numBits */ 8 * sizeof(wiredSize
));
8421 if (!scratchNumber
) {
8424 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
8425 OSSafeReleaseNULL(scratchNumber
);
8430 /* OSBundleDependencies. In descending order for
8431 * easy compatibility with kextstat(8).
8433 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
8434 if ((count
= getNumDependencies())) {
8435 dependencyLoadTags
= OSArray::withCapacity(count
);
8436 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
8440 OSKext
* dependency
= OSDynamicCast(OSKext
,
8441 dependencies
->getObject(i
));
8443 OSSafeReleaseNULL(scratchNumber
);
8448 scratchNumber
= OSNumber::withNumber(
8449 (unsigned long long)dependency
->getLoadTag(),
8450 /* numBits*/ 8 * sizeof(loadTag
));
8451 if (!scratchNumber
) {
8454 dependencyLoadTags
->setObject(scratchNumber
);
8459 OSSafeReleaseNULL(scratchNumber
);
8461 /* OSBundleMetaClasses.
8463 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) {
8464 if (metaClasses
&& metaClasses
->getCount()) {
8465 metaClassIterator
= OSCollectionIterator::withCollection(metaClasses
);
8466 metaClassInfo
= OSArray::withCapacity(metaClasses
->getCount());
8467 if (!metaClassIterator
|| !metaClassInfo
) {
8470 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
8472 while ( (thisMetaClass
= OSDynamicCast(OSMetaClass
,
8473 metaClassIterator
->getNextObject())) ) {
8475 OSSafeReleaseNULL(metaClassDict
);
8476 OSSafeReleaseNULL(scratchNumber
);
8477 OSSafeReleaseNULL(metaClassName
);
8478 OSSafeReleaseNULL(superclassName
);
8480 metaClassDict
= OSDictionary::withCapacity(3);
8481 if (!metaClassDict
) {
8485 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
8486 if (thisMetaClass
->getSuperClass()) {
8487 superclassName
= OSString::withCString(
8488 thisMetaClass
->getSuperClass()->getClassName());
8490 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
8491 8 * sizeof(unsigned int));
8493 /* Bail if any of the essentials is missing. The root class lacks a superclass,
8496 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
8500 metaClassInfo
->setObject(metaClassDict
);
8501 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
8502 if (superclassName
) {
8503 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
8505 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
8510 /* OSBundleRetainCount.
8512 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
8513 OSSafeReleaseNULL(scratchNumber
);
8515 int kextRetainCount
= getRetainCount() - 1;
8519 scratchNumber
= OSNumber::withNumber(
8520 (int)kextRetainCount
,
8521 /* numBits*/ 8 * sizeof(int));
8522 if (scratchNumber
) {
8523 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
8531 OSSafeRelease(headerData
);
8532 OSSafeRelease(cpuTypeNumber
);
8533 OSSafeRelease(cpuSubtypeNumber
);
8534 OSSafeRelease(executablePathString
);
8535 if (executablePathString
) kfree(executablePathCString
, executablePathCStringSize
);
8536 OSSafeRelease(uuid
);
8537 OSSafeRelease(scratchNumber
);
8538 OSSafeRelease(dependencyLoadTags
);
8539 OSSafeRelease(metaClassIterator
);
8540 OSSafeRelease(metaClassInfo
);
8541 OSSafeRelease(metaClassDict
);
8542 OSSafeRelease(metaClassName
);
8543 OSSafeRelease(superclassName
);
8545 OSSafeReleaseNULL(result
);
8550 /*********************************************************************
8551 *********************************************************************/
8554 OSKext::requestResource(
8555 const char * kextIdentifierCString
,
8556 const char * resourceNameCString
,
8557 OSKextRequestResourceCallback callback
,
8559 OSKextRequestTag
* requestTagOut
)
8561 OSReturn result
= kOSReturnError
;
8562 OSKext
* callbackKext
= NULL
; // must release (looked up)
8564 OSKextRequestTag requestTag
= -1;
8565 OSNumber
* requestTagNum
= NULL
; // must release
8567 OSDictionary
* requestDict
= NULL
; // must release
8568 OSString
* kextIdentifier
= NULL
; // must release
8569 OSString
* resourceName
= NULL
; // must release
8571 OSDictionary
* callbackRecord
= NULL
; // must release
8572 OSData
* callbackWrapper
= NULL
; // must release
8574 OSData
* contextWrapper
= NULL
; // must release
8576 IORecursiveLockLock(sKextLock
);
8578 if (requestTagOut
) {
8579 *requestTagOut
= kOSKextRequestTagInvalid
;
8582 /* If requests to user space are disabled, don't go any further */
8583 if (!sKernelRequestsEnabled
) {
8584 OSKextLog(/* kext */ NULL
,
8585 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8586 "Can't request resource %s for %s - requests to user space are disabled.",
8587 resourceNameCString
,
8588 kextIdentifierCString
);
8589 result
= kOSKextReturnDisabled
;
8593 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
8594 result
= kOSKextReturnInvalidArgument
;
8598 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
8599 if (!callbackKext
) {
8600 OSKextLog(/* kext */ NULL
,
8601 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8602 "Resource request has bad callback address.");
8603 result
= kOSKextReturnInvalidArgument
;
8606 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
8607 OSKextLog(/* kext */ NULL
,
8608 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8609 "Resource request callback is in a kext that is not started.");
8610 result
= kOSKextReturnInvalidArgument
;
8614 /* Do not allow any new requests to be made on a kext that is unloading.
8616 if (callbackKext
->flags
.stopping
) {
8617 result
= kOSKextReturnStopping
;
8621 /* If we're wrapped the next available request tag around to the negative
8622 * numbers, we can't service any more requests.
8624 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
8625 OSKextLog(/* kext */ NULL
,
8626 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8627 "No more request tags available; restart required.");
8628 result
= kOSKextReturnNoResources
;
8631 requestTag
= sNextRequestTag
++;
8633 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
8635 if (result
!= kOSReturnSuccess
) {
8639 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
8640 resourceName
= OSString::withCString(resourceNameCString
);
8641 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
8642 8 * sizeof(requestTag
));
8643 if (!kextIdentifier
||
8646 !_OSKextSetRequestArgument(requestDict
,
8647 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
8648 !_OSKextSetRequestArgument(requestDict
,
8649 kKextRequestArgumentNameKey
, resourceName
) ||
8650 !_OSKextSetRequestArgument(requestDict
,
8651 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
8653 result
= kOSKextReturnNoMemory
;
8657 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
8658 if (!callbackRecord
) {
8659 result
= kOSKextReturnNoMemory
;
8662 // we validate callback address at call time
8663 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
8665 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
8667 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
8668 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
8670 result
= kOSKextReturnNoMemory
;
8675 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
8676 kKextRequestArgumentContextKey
, contextWrapper
)) {
8678 result
= kOSKextReturnNoMemory
;
8683 /* Only post the requests after all the other potential failure points
8686 if (!sKernelRequests
->setObject(requestDict
) ||
8687 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
8689 result
= kOSKextReturnNoMemory
;
8693 OSKext::pingKextd();
8695 result
= kOSReturnSuccess
;
8696 if (requestTagOut
) {
8697 *requestTagOut
= requestTag
;
8702 /* If we didn't succeed, yank the request & callback
8703 * from their holding arrays.
8705 if (result
!= kOSReturnSuccess
) {
8708 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
8709 if (index
!= (unsigned int)-1) {
8710 sKernelRequests
->removeObject(index
);
8712 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
8713 if (index
!= (unsigned int)-1) {
8714 sRequestCallbackRecords
->removeObject(index
);
8718 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8720 IORecursiveLockUnlock(sKextLock
);
8722 if (callbackKext
) callbackKext
->release();
8723 if (requestTagNum
) requestTagNum
->release();
8725 if (requestDict
) requestDict
->release();
8726 if (kextIdentifier
) kextIdentifier
->release();
8727 if (resourceName
) resourceName
->release();
8729 if (callbackRecord
) callbackRecord
->release();
8730 if (callbackWrapper
) callbackWrapper
->release();
8731 if (contextWrapper
) contextWrapper
->release();
8736 /*********************************************************************
8737 * Assumes sKextLock is held.
8738 *********************************************************************/
8741 OSKext::dequeueCallbackForRequestTag(
8742 OSKextRequestTag requestTag
,
8743 OSDictionary
** callbackRecordOut
)
8745 OSReturn result
= kOSReturnError
;
8746 OSNumber
* requestTagNum
= NULL
; // must release
8748 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
8749 8 * sizeof(requestTag
));
8750 if (!requestTagNum
) {
8754 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
8758 OSSafeRelease(requestTagNum
);
8763 /*********************************************************************
8764 * Assumes sKextLock is held.
8765 *********************************************************************/
8768 OSKext::dequeueCallbackForRequestTag(
8769 OSNumber
* requestTagNum
,
8770 OSDictionary
** callbackRecordOut
)
8772 OSReturn result
= kOSKextReturnInvalidArgument
;
8773 OSDictionary
* callbackRecord
= NULL
; // retain if matched!
8774 OSNumber
* callbackTagNum
= NULL
; // do not release
8775 unsigned int count
, i
;
8777 result
= kOSReturnError
;
8778 count
= sRequestCallbackRecords
->getCount();
8779 for (i
= 0; i
< count
; i
++) {
8780 callbackRecord
= OSDynamicCast(OSDictionary
,
8781 sRequestCallbackRecords
->getObject(i
));
8782 if (!callbackRecord
) {
8786 /* If we don't find a tag, we basically have a leak here. Maybe
8787 * we should just remove it.
8789 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
8790 callbackRecord
, kKextRequestArgumentRequestTagKey
));
8791 if (!callbackTagNum
) {
8795 /* We could be even more paranoid and check that all the incoming
8796 * args match what's in the callback record.
8798 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
8799 if (callbackRecordOut
) {
8800 *callbackRecordOut
= callbackRecord
;
8801 callbackRecord
->retain();
8803 sRequestCallbackRecords
->removeObject(i
);
8804 result
= kOSReturnSuccess
;
8808 result
= kOSKextReturnNotFound
;
8814 /*********************************************************************
8815 * Assumes sKextLock is held.
8816 *********************************************************************/
8819 OSKext::dispatchResource(OSDictionary
* requestDict
)
8821 OSReturn result
= kOSReturnError
;
8822 OSDictionary
* callbackRecord
= NULL
; // must release
8823 OSNumber
* requestTag
= NULL
; // do not release
8824 OSNumber
* requestResult
= NULL
; // do not release
8825 OSData
* dataObj
= NULL
; // do not release
8826 uint32_t dataLength
= 0;
8827 const void * dataPtr
= NULL
; // do not free
8828 OSData
* callbackWrapper
= NULL
; // do not release
8829 OSKextRequestResourceCallback callback
= NULL
;
8830 OSData
* contextWrapper
= NULL
; // do not release
8831 void * context
= NULL
; // do not free
8832 OSKext
* callbackKext
= NULL
; // must release (looked up)
8834 /* Get the args from the request. Right now we need the tag
8835 * to look up the callback record, and the result for invoking the callback.
8837 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
8838 kKextRequestArgumentRequestTagKey
));
8839 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
8840 kKextRequestArgumentResultKey
));
8841 if (!requestTag
|| !requestResult
) {
8842 result
= kOSKextReturnInvalidArgument
;
8846 /* Look for a callback record matching this request's tag.
8848 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
8849 if (result
!= kOSReturnSuccess
) {
8854 * Get the context pointer of the callback record (if there is one).
8856 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
8857 kKextRequestArgumentContextKey
));
8858 context
= _OSKextExtractPointer(contextWrapper
);
8859 if (contextWrapper
&& !context
) {
8863 callbackWrapper
= OSDynamicCast(OSData
,
8864 _OSKextGetRequestArgument(callbackRecord
,
8865 kKextRequestArgumentCallbackKey
));
8866 callback
= (OSKextRequestResourceCallback
)
8867 _OSKextExtractPointer(callbackWrapper
);
8872 /* Check for a data obj. We might not have one and that's ok, that means
8873 * we didn't find the requested resource, and we still have to tell the
8874 * caller that via the callback.
8876 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
8877 kKextRequestArgumentValueKey
));
8879 dataPtr
= dataObj
->getBytesNoCopy();
8880 dataLength
= dataObj
->getLength();
8883 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
8884 if (!callbackKext
) {
8885 OSKextLog(/* kext */ NULL
,
8886 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8887 "Can't invoke callback for resource request; ");
8890 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
8891 OSKextLog(/* kext */ NULL
,
8892 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8893 "Can't invoke kext resource callback; ");
8897 (void)callback(requestTag
->unsigned32BitValue(),
8898 (OSReturn
)requestResult
->unsigned32BitValue(),
8899 dataPtr
, dataLength
, context
);
8901 result
= kOSReturnSuccess
;
8904 if (callbackKext
) callbackKext
->release();
8905 if (callbackRecord
) callbackRecord
->release();
8910 /*********************************************************************
8911 *********************************************************************/
8914 OSKext::invokeRequestCallback(
8915 OSDictionary
* callbackRecord
,
8916 OSReturn callbackResult
)
8918 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
8919 OSNumber
* resultNum
= NULL
; // must release
8925 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
8926 8 * sizeof(callbackResult
));
8931 /* Insert the result into the callback record and dispatch it as if it
8932 * were the reply coming down from user space.
8934 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
8937 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
8938 /* This removes the pending callback record.
8940 OSKext::dispatchResource(callbackRecord
);
8944 if (resultNum
) resultNum
->release();
8948 /*********************************************************************
8949 * Assumes sKextLock is held.
8950 *********************************************************************/
8953 OSKext::cancelRequest(
8954 OSKextRequestTag requestTag
,
8957 OSReturn result
= kOSKextReturnNoMemory
;
8958 OSDictionary
* callbackRecord
= NULL
; // must release
8959 OSData
* contextWrapper
= NULL
; // do not release
8961 IORecursiveLockLock(sKextLock
);
8962 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
8964 IORecursiveLockUnlock(sKextLock
);
8966 if (result
== kOSReturnSuccess
&& contextOut
) {
8967 contextWrapper
= OSDynamicCast(OSData
,
8968 _OSKextGetRequestArgument(callbackRecord
,
8969 kKextRequestArgumentContextKey
));
8970 *contextOut
= _OSKextExtractPointer(contextWrapper
);
8973 if (callbackRecord
) callbackRecord
->release();
8978 /*********************************************************************
8979 * Assumes sKextLock is held.
8980 *********************************************************************/
8982 OSKext::invokeOrCancelRequestCallbacks(
8983 OSReturn callbackResult
,
8986 unsigned int count
, i
;
8988 count
= sRequestCallbackRecords
->getCount();
8995 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
8996 sRequestCallbackRecords
->getObject(i
));
9001 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9002 _OSKextGetRequestArgument(request
,
9003 kKextRequestArgumentCallbackKey
));
9005 if (!callbackWrapper
) {
9006 sRequestCallbackRecords
->removeObject(i
);
9010 vm_address_t callbackAddress
= (vm_address_t
)
9011 _OSKextExtractPointer(callbackWrapper
);
9013 if ((kmod_info
->address
<= callbackAddress
) &&
9014 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9017 /* This removes the callback record.
9019 invokeRequestCallback(request
, callbackResult
);
9021 sRequestCallbackRecords
->removeObject(i
);
9030 /*********************************************************************
9031 * Assumes sKextLock is held.
9032 *********************************************************************/
9034 OSKext::countRequestCallbacks(void)
9036 uint32_t result
= 0;
9037 unsigned int count
, i
;
9039 count
= sRequestCallbackRecords
->getCount();
9046 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9047 sRequestCallbackRecords
->getObject(i
));
9052 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9053 _OSKextGetRequestArgument(request
,
9054 kKextRequestArgumentCallbackKey
));
9056 if (!callbackWrapper
) {
9060 vm_address_t callbackAddress
= (vm_address_t
)
9061 _OSKextExtractPointer(callbackWrapper
);
9063 if ((kmod_info
->address
<= callbackAddress
) &&
9064 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9074 /*********************************************************************
9075 *********************************************************************/
9076 static OSReturn
_OSKextCreateRequest(
9077 const char * predicate
,
9078 OSDictionary
** requestP
)
9080 OSReturn result
= kOSKextReturnNoMemory
;
9081 OSDictionary
* request
= NULL
; // must release on error
9082 OSDictionary
* args
= NULL
; // must release
9084 request
= OSDictionary::withCapacity(2);
9088 result
= _OSDictionarySetCStringValue(request
,
9089 kKextRequestPredicateKey
, predicate
);
9090 if (result
!= kOSReturnSuccess
) {
9093 result
= kOSReturnSuccess
;
9096 if (result
!= kOSReturnSuccess
) {
9097 if (request
) request
->release();
9099 *requestP
= request
;
9101 if (args
) args
->release();
9106 /*********************************************************************
9107 *********************************************************************/
9108 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
9110 return OSDynamicCast(OSString
,
9111 requestDict
->getObject(kKextRequestPredicateKey
));
9114 /*********************************************************************
9115 *********************************************************************/
9116 static OSObject
* _OSKextGetRequestArgument(
9117 OSDictionary
* requestDict
,
9118 const char * argName
)
9120 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9121 requestDict
->getObject(kKextRequestArgumentsKey
));
9123 return args
->getObject(argName
);
9128 /*********************************************************************
9129 *********************************************************************/
9130 static bool _OSKextSetRequestArgument(
9131 OSDictionary
* requestDict
,
9132 const char * argName
,
9135 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9136 requestDict
->getObject(kKextRequestArgumentsKey
));
9138 args
= OSDictionary::withCapacity(2);
9142 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
9146 return args
->setObject(argName
, value
);
9152 /*********************************************************************
9153 *********************************************************************/
9154 static void * _OSKextExtractPointer(OSData
* wrapper
)
9156 void * result
= NULL
;
9157 const void * resultPtr
= NULL
;
9162 resultPtr
= wrapper
->getBytesNoCopy();
9163 result
= *(void **)resultPtr
;
9168 /*********************************************************************
9169 *********************************************************************/
9170 static OSReturn
_OSDictionarySetCStringValue(
9171 OSDictionary
* dict
,
9173 const char * cValue
)
9175 OSReturn result
= kOSKextReturnNoMemory
;
9176 const OSSymbol
* key
= NULL
; // must release
9177 OSString
* value
= NULL
; // must release
9179 key
= OSSymbol::withCString(cKey
);
9180 value
= OSString::withCString(cValue
);
9181 if (!key
|| !value
) {
9184 if (dict
->setObject(key
, value
)) {
9185 result
= kOSReturnSuccess
;
9189 if (key
) key
->release();
9190 if (value
) value
->release();
9195 /*********************************************************************
9196 *********************************************************************/
9197 static bool _OSArrayContainsCString(
9199 const char * cString
)
9201 bool result
= false;
9202 const OSSymbol
* symbol
= NULL
;
9205 if (!array
|| !cString
) {
9209 symbol
= OSSymbol::withCStringNoCopy(cString
);
9214 count
= array
->getCount();
9215 for (i
= 0; i
< count
; i
++) {
9216 OSObject
* thisObject
= array
->getObject(i
);
9217 if (symbol
->isEqualTo(thisObject
)) {
9224 if (symbol
) symbol
->release();
9228 /*********************************************************************
9229 * We really only care about boot / system start up related kexts.
9230 * We return true if we're less than REBUILD_MAX_TIME since start up,
9231 * otherwise return false.
9232 *********************************************************************/
9233 bool _OSKextInPrelinkRebuildWindow(void)
9235 static bool outside_the_window
= false;
9236 AbsoluteTime my_abstime
;
9240 if (outside_the_window
) {
9243 clock_get_uptime(&my_abstime
);
9244 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
9245 my_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
9246 if (my_secs
> REBUILD_MAX_TIME
) {
9247 outside_the_window
= true;
9253 /*********************************************************************
9254 *********************************************************************/
9255 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
9257 int unLoadedCount
, i
;
9258 bool result
= false;
9260 IORecursiveLockLock(sKextLock
);
9262 if (sUnloadedPrelinkedKexts
== NULL
) {
9265 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
9266 if (unLoadedCount
== 0) {
9270 for (i
= 0; i
< unLoadedCount
; i
++) {
9271 const OSSymbol
* myBundleID
; // do not release
9273 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
9274 if (!myBundleID
) continue;
9275 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
9281 IORecursiveLockUnlock(sKextLock
);
9286 #pragma mark Personalities (IOKit Drivers)
9288 /*********************************************************************
9289 *********************************************************************/
9292 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
9294 OSArray
* result
= NULL
; // returned
9295 OSCollectionIterator
* kextIterator
= NULL
; // must release
9296 OSArray
* personalities
= NULL
; // must release
9297 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
9299 OSString
* kextID
= NULL
; // do not release
9300 OSKext
* theKext
= NULL
; // do not release
9302 IORecursiveLockLock(sKextLock
);
9304 /* Let's conservatively guess that any given kext has around 3
9305 * personalities for now.
9307 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
9312 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
9313 if (!kextIterator
) {
9317 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
9318 if (personalitiesIterator
) {
9319 personalitiesIterator
->release();
9320 personalitiesIterator
= NULL
;
9322 if (personalities
) {
9323 personalities
->release();
9324 personalities
= NULL
;
9327 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
9328 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
9329 personalities
= theKext
->copyPersonalitiesArray();
9330 if (!personalities
) {
9333 result
->merge(personalities
);
9335 // xxx - check for better place to put this log msg
9337 kOSKextLogWarningLevel
|
9339 "Kext %s is not loadable during safe boot; "
9340 "omitting its personalities.",
9341 theKext
->getIdentifierCString());
9347 IORecursiveLockUnlock(sKextLock
);
9349 if (kextIterator
) kextIterator
->release();
9350 if (personalitiesIterator
) personalitiesIterator
->release();
9351 if (personalities
) personalities
->release();
9356 /*********************************************************************
9357 *********************************************************************/
9360 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
9362 int numPersonalities
= 0;
9364 OSKextLog(/* kext */ NULL
,
9365 kOSKextLogStepLevel
|
9367 "Sending all eligible registered kexts' personalities "
9368 "to the IOCatalogue %s.",
9369 startMatching
? "and starting matching" : "but not starting matching");
9371 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
9372 /* filterSafeBootFlag */ true);
9374 if (personalities
) {
9375 gIOCatalogue
->addDrivers(personalities
, startMatching
);
9376 numPersonalities
= personalities
->getCount();
9377 personalities
->release();
9380 OSKextLog(/* kext */ NULL
,
9381 kOSKextLogStepLevel
|
9383 "%d kext personalit%s sent to the IOCatalogue; %s.",
9384 numPersonalities
, numPersonalities
> 0 ? "ies" : "y",
9385 startMatching
? "matching started" : "matching not started");
9389 /*********************************************************************
9390 * Do not make a deep copy, just convert the IOKitPersonalities dict
9391 * to an array for sending to the IOCatalogue.
9392 *********************************************************************/
9394 OSKext::copyPersonalitiesArray(void)
9396 OSArray
* result
= NULL
;
9397 OSDictionary
* personalities
= NULL
; // do not release
9398 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
9400 OSString
* personalityName
= NULL
; // do not release
9401 OSString
* personalityBundleIdentifier
= NULL
; // do not release
9403 personalities
= OSDynamicCast(OSDictionary
,
9404 getPropertyForHostArch(kIOKitPersonalitiesKey
));
9405 if (!personalities
) {
9409 result
= OSArray::withCapacity(personalities
->getCount());
9414 personalitiesIterator
=
9415 OSCollectionIterator::withCollection(personalities
);
9416 if (!personalitiesIterator
) {
9419 while ((personalityName
= OSDynamicCast(OSString
,
9420 personalitiesIterator
->getNextObject()))) {
9422 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
9423 personalities
->getObject(personalityName
));
9426 * If the personality doesn't have a CFBundleIdentifier, or if it
9427 * differs from the kext's, insert the kext's ID so we can find it.
9428 * The publisher ID is used to remove personalities from bundles
9431 personalityBundleIdentifier
= OSDynamicCast(OSString
,
9432 personality
->getObject(kCFBundleIdentifierKey
));
9434 if (!personalityBundleIdentifier
) {
9435 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
9436 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
9437 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
9440 result
->setObject(personality
);
9444 if (personalitiesIterator
) personalitiesIterator
->release();
9449 /*********************************************************************
9450 Might want to change this to a bool return?
9451 *********************************************************************/
9453 OSKext::sendPersonalitiesToCatalog(
9455 OSArray
* personalityNames
)
9457 OSReturn result
= kOSReturnSuccess
;
9458 OSArray
* personalitiesToSend
= NULL
; // must release
9459 OSDictionary
* kextPersonalities
= NULL
; // do not release
9462 if (!sLoadEnabled
) {
9464 kOSKextLogErrorLevel
|
9466 "Kext loading is disabled (attempt to start matching for kext %s).",
9467 getIdentifierCString());
9468 result
= kOSKextReturnDisabled
;
9472 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
9474 kOSKextLogErrorLevel
|
9476 "Kext %s is not loadable during safe boot; "
9477 "not sending personalities to the IOCatalogue.",
9478 getIdentifierCString());
9479 result
= kOSKextReturnNotLoadable
;
9483 if (!personalityNames
|| !personalityNames
->getCount()) {
9484 personalitiesToSend
= copyPersonalitiesArray();
9486 kextPersonalities
= OSDynamicCast(OSDictionary
,
9487 getPropertyForHostArch(kIOKitPersonalitiesKey
));
9488 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
9492 personalitiesToSend
= OSArray::withCapacity(0);
9493 if (!personalitiesToSend
) {
9494 result
= kOSKextReturnNoMemory
;
9497 count
= personalityNames
->getCount();
9498 for (i
= 0; i
< count
; i
++) {
9499 OSString
* name
= OSDynamicCast(OSString
,
9500 personalityNames
->getObject(i
));
9504 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
9505 kextPersonalities
->getObject(name
));
9507 personalitiesToSend
->setObject(personality
);
9511 if (personalitiesToSend
) {
9512 unsigned numPersonalities
= personalitiesToSend
->getCount();
9514 kOSKextLogStepLevel
|
9516 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
9517 getIdentifierCString(),
9519 numPersonalities
> 1 ? "ies" : "y",
9520 startMatching
? " and starting matching" : " but not starting matching");
9521 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
9524 if (personalitiesToSend
) {
9525 personalitiesToSend
->release();
9530 /*********************************************************************
9531 * xxx - We should allow removing the kext's declared personalities,
9532 * xxx - even with other bundle identifiers.
9533 *********************************************************************/
9535 OSKext::removePersonalitiesFromCatalog(void)
9537 OSDictionary
* personality
= NULL
; // do not release
9539 personality
= OSDictionary::withCapacity(1);
9543 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
9546 kOSKextLogStepLevel
|
9548 "Kext %s removing all personalities naming it from the IOCatalogue.",
9549 getIdentifierCString());
9551 /* Have the IOCatalog remove all personalities matching this kext's
9552 * bundle ID and trigger matching anew.
9554 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
9557 if (personality
) personality
->release();
9564 #pragma mark Logging
9566 /*********************************************************************
9567 * Do not call any function that takes sKextLock here!
9568 *********************************************************************/
9571 OSKext::setUserSpaceLogFilter(
9572 OSKextLogSpec newUserLogFilter
,
9575 OSKextLogSpec result
;
9576 bool allocError
= false;
9578 /* Do not call any function that takes sKextLoggingLock during
9579 * this critical block. That means do logging after.
9581 IOLockLock(sKextLoggingLock
);
9583 result
= sUserSpaceKextLogFilter
;
9584 sUserSpaceKextLogFilter
= newUserLogFilter
;
9586 if (newUserLogFilter
&& captureFlag
&&
9587 !sUserSpaceLogSpecArray
&& !sUserSpaceLogMessageArray
) {
9589 // xxx - do some measurements for a good initial capacity?
9590 sUserSpaceLogSpecArray
= OSArray::withCapacity(0);
9591 sUserSpaceLogMessageArray
= OSArray::withCapacity(0);
9593 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
9594 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
9595 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
9600 IOLockUnlock(sKextLoggingLock
);
9602 /* If the config flag itself is changing, log the state change
9603 * going both ways, before setting up the user-space log arrays,
9604 * so that this is only logged in the kernel.
9606 if (result
!= newUserLogFilter
) {
9607 OSKextLog(/* kext */ NULL
,
9608 kOSKextLogDebugLevel
|
9609 kOSKextLogGeneralFlag
,
9610 "User-space log flags changed from 0x%x to 0x%x.",
9611 result
, newUserLogFilter
);
9614 OSKextLog(/* kext */ NULL
,
9615 kOSKextLogErrorLevel
|
9616 kOSKextLogGeneralFlag
,
9617 "Failed to allocate user-space log message arrays.");
9623 /*********************************************************************
9624 * Do not call any function that takes sKextLock here!
9625 *********************************************************************/
9628 OSKext::clearUserSpaceLogFilter(void)
9630 OSArray
* result
= NULL
;
9631 OSKextLogSpec oldLogFilter
;
9632 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
9634 /* Do not call any function that takes sKextLoggingLock during
9635 * this critical block. That means do logging after.
9637 IOLockLock(sKextLoggingLock
);
9639 result
= OSArray::withCapacity(2);
9641 result
->setObject(sUserSpaceLogSpecArray
);
9642 result
->setObject(sUserSpaceLogMessageArray
);
9644 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
9645 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
9647 oldLogFilter
= sUserSpaceKextLogFilter
;
9648 sUserSpaceKextLogFilter
= newLogFilter
;
9650 IOLockUnlock(sKextLoggingLock
);
9652 /* If the config flag itself is changing, log the state change
9653 * going both ways, after tearing down the user-space log
9654 * arrays, so this is only logged within the kernel.
9656 if (oldLogFilter
!= newLogFilter
) {
9657 OSKextLog(/* kext */ NULL
,
9658 kOSKextLogDebugLevel
|
9659 kOSKextLogGeneralFlag
,
9660 "User-space log flags changed from 0x%x to 0x%x.",
9661 oldLogFilter
, newLogFilter
);
9668 /*********************************************************************
9669 * Do not call any function that takes sKextLock here!
9670 *********************************************************************/
9673 OSKext::getUserSpaceLogFilter(void)
9675 OSKextLogSpec result
;
9677 IOLockLock(sKextLoggingLock
);
9678 result
= sUserSpaceKextLogFilter
;
9679 IOLockUnlock(sKextLoggingLock
);
9684 /*********************************************************************
9685 * This function is called by OSMetaClass during kernel C++ setup.
9686 * Be careful what you access here; assume only OSKext::initialize()
9689 * Do not call any function that takes sKextLock here!
9690 *********************************************************************/
9691 #define VTRESET "\033[0m"
9693 #define VTBOLD "\033[1m"
9694 #define VTUNDER "\033[4m"
9696 #define VTRED "\033[31m"
9697 #define VTGREEN "\033[32m"
9698 #define VTYELLOW "\033[33m"
9699 #define VTBLUE "\033[34m"
9700 #define VTMAGENTA "\033[35m"
9701 #define VTCYAN "\033[36m"
9703 inline const char * colorForFlags(OSKextLogSpec flags
)
9705 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
9708 case kOSKextLogErrorLevel
:
9709 return VTRED VTBOLD
;
9711 case kOSKextLogWarningLevel
:
9714 case kOSKextLogBasicLevel
:
9715 return VTYELLOW VTUNDER
;
9717 case kOSKextLogProgressLevel
:
9720 case kOSKextLogStepLevel
:
9723 case kOSKextLogDetailLevel
:
9726 case kOSKextLogDebugLevel
:
9736 inline bool logSpecMatch(
9737 OSKextLogSpec msgLogSpec
,
9738 OSKextLogSpec logFilter
)
9740 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
9741 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
9742 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
9744 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
9745 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
9746 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
9748 /* Explicit messages always get logged.
9750 if (msgLevel
== kOSKextLogExplicitLevel
) {
9754 /* Warnings and errors are logged regardless of the flags.
9756 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
9760 /* A verbose message that isn't for a logging-enabled kext and isn't global
9761 * does *not* get logged.
9763 if (!msgKextGlobal
&& !filterKextGlobal
) {
9767 /* Warnings and errors are logged regardless of the flags.
9768 * All other messages must fit the flags and
9769 * have a level at or below the filter.
9772 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
9783 OSKextLogSpec msgLogSpec
,
9784 const char * format
, ...)
9788 va_start(argList
, format
);
9789 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
9796 OSKextLogSpec msgLogSpec
,
9797 const char * format
,
9800 extern int disableConsoleOutput
;
9802 bool logForKernel
= false;
9803 bool logForUser
= false;
9805 char stackBuffer
[120];
9806 uint32_t length
= 0;
9807 char * allocBuffer
= NULL
; // must kfree
9808 OSNumber
* logSpecNum
= NULL
; // must release
9809 OSString
* logString
= NULL
; // must release
9810 char * buffer
= stackBuffer
; // do not free
9812 IOLockLock(sKextLoggingLock
);
9814 /* Set the kext/global bit in the message spec if we have no
9815 * kext or if the kext requests logging.
9817 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
9818 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
9821 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
9822 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
9823 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
9826 if (! (logForKernel
|| logForUser
) ) {
9830 /* No goto from here until past va_end()!
9832 va_copy(argList
, srcArgList
);
9833 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
9836 if (length
+ 1 >= sizeof(stackBuffer
)) {
9837 allocBuffer
= (char *)kalloc((length
+ 1) * sizeof(char));
9842 /* No goto from here until past va_end()!
9844 va_copy(argList
, srcArgList
);
9845 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
9848 buffer
= allocBuffer
;
9851 /* If user space wants the log message, queue it up.
9853 if (logForUser
&& sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
9854 logSpecNum
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
));
9855 logString
= OSString::withCString(buffer
);
9856 if (logSpecNum
&& logString
) {
9857 sUserSpaceLogSpecArray
->setObject(logSpecNum
);
9858 sUserSpaceLogMessageArray
->setObject(logString
);
9862 /* Always log messages from the kernel according to the kernel's
9867 /* If we are in console mode and have a custom log filter,
9868 * colorize the log message.
9870 if (!disableConsoleOutput
&& sBootArgLogFilterFound
) {
9871 const char * color
= ""; // do not free
9872 color
= colorForFlags(msgLogSpec
);
9873 printf("%s%s%s\n", colorForFlags(msgLogSpec
),
9874 buffer
, color
[0] ? VTRESET
: "");
9876 printf("%s\n", buffer
);
9881 IOLockUnlock(sKextLoggingLock
);
9884 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
9886 OSSafeRelease(logString
);
9887 OSSafeRelease(logSpecNum
);
9891 #if KASLR_IOREG_DEBUG
9893 #define IOLOG_INDENT( the_indention ) \
9896 for ( i = 0; i < (the_indention); i++ ) { \
9901 extern vm_offset_t vm_kernel_stext
;
9902 extern vm_offset_t vm_kernel_etext
;
9903 extern mach_vm_offset_t kext_alloc_base
;
9904 extern mach_vm_offset_t kext_alloc_max
;
9906 bool ScanForAddrInObject(OSObject
* theObject
,
9909 bool ScanForAddrInObject(OSObject
* theObject
,
9912 const OSMetaClass
* myTypeID
;
9913 OSCollectionIterator
* myIter
;
9916 bool myResult
= false;
9918 if ( theObject
== NULL
) {
9919 IOLog("%s: theObject is NULL \n",
9924 myTypeID
= OSTypeIDInst(theObject
);
9926 if ( myTypeID
== OSTypeID(OSDictionary
) ) {
9927 OSDictionary
* myDictionary
;
9929 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
9930 myIter
= OSCollectionIterator::withCollection( myDictionary
);
9931 if ( myIter
== NULL
)
9935 while ( (myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject())) ) {
9938 myValue
= myDictionary
->getObject(myKey
);
9939 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
9941 // if we ever get a true result return true
9943 IOLOG_INDENT(indent
);
9944 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
9949 else if ( myTypeID
== OSTypeID(OSArray
) ) {
9952 myArray
= OSDynamicCast(OSArray
, theObject
);
9953 myIter
= OSCollectionIterator::withCollection(myArray
);
9954 if ( myIter
== NULL
)
9958 while ( (myValue
= myIter
->getNextObject()) ) {
9960 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
9962 // if we ever get a true result return true
9964 IOLOG_INDENT(indent
);
9965 IOLog("OSArray: \n");
9970 else if ( myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
) ) {
9972 // should we look for addresses in strings?
9974 else if ( myTypeID
== OSTypeID(OSData
) ) {
9980 myDataObj
= OSDynamicCast(OSData
, theObject
);
9981 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
9982 myLen
= myDataObj
->getLength();
9984 if (myPtrPtr
&& myLen
&& myLen
> 7) {
9986 int myPtrCount
= (myLen
/ sizeof(void *));
9988 for (i
= 0; i
< myPtrCount
; i
++) {
9989 UInt64 numberValue
= (UInt64
) *(myPtrPtr
);
9991 if ( kext_alloc_max
!= 0 &&
9992 numberValue
>= kext_alloc_base
&&
9993 numberValue
< kext_alloc_max
) {
9995 OSKext
* myKext
= NULL
; // must release (looked up)
9996 // IOLog("found OSData %p in kext map %p to %p \n",
9998 // (void *) kext_alloc_base,
9999 // (void *) kext_alloc_max);
10001 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) *(myPtrPtr
) );
10003 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
10005 myKext
->getIdentifierCString());
10010 if ( vm_kernel_etext
!= 0 &&
10011 numberValue
>= vm_kernel_stext
&&
10012 numberValue
< vm_kernel_etext
) {
10013 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
10015 (void *) vm_kernel_stext
,
10016 (void *) vm_kernel_etext
);
10023 else if ( myTypeID
== OSTypeID(OSBoolean
) ) {
10025 // do nothing here...
10027 else if ( myTypeID
== OSTypeID(OSNumber
) ) {
10029 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
10031 UInt64 numberValue
= number
->unsigned64BitValue();
10033 if ( kext_alloc_max
!= 0 &&
10034 numberValue
>= kext_alloc_base
&&
10035 numberValue
< kext_alloc_max
) {
10037 OSKext
* myKext
= NULL
; // must release (looked up)
10038 IOLog("found OSNumber in kext map %p to %p \n",
10039 (void *) kext_alloc_base
,
10040 (void *) kext_alloc_max
);
10041 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10043 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) numberValue
);
10045 IOLog("found in kext \"%s\" \n",
10046 myKext
->getIdentifierCString());
10052 if ( vm_kernel_etext
!= 0 &&
10053 numberValue
>= vm_kernel_stext
&&
10054 numberValue
< vm_kernel_etext
) {
10055 IOLog("found OSNumber in kernel text segment %p to %p \n",
10056 (void *) vm_kernel_stext
,
10057 (void *) vm_kernel_etext
);
10058 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10064 const OSMetaClass
* myMetaClass
= NULL
;
10066 myMetaClass
= theObject
->getMetaClass();
10067 if ( myMetaClass
) {
10068 IOLog("class %s \n", myMetaClass
->getClassName() );
10071 IOLog("Unknown object \n" );
10078 #endif // KASLR_KEXT_DEBUG
10080 }; /* extern "C" */
10083 #pragma mark Backtrace Dump & kmod_get_info() support
10085 /*********************************************************************
10086 * This function must be safe to call in panic context.
10087 *********************************************************************/
10090 OSKext::printKextsInBacktrace(
10091 vm_offset_t
* addr
,
10093 int (* printf_func
)(const char *fmt
, ...),
10096 addr64_t summary_page
= 0;
10097 addr64_t last_summary_page
= 0;
10098 bool found_kmod
= false;
10102 IOLockLock(sKextSummariesLock
);
10105 if (!gLoadedKextSummaries
) {
10106 (*printf_func
)(" can't perform kext scan: no kext summary");
10110 summary_page
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
);
10111 last_summary_page
= round_page(summary_page
+ sLoadedKextSummariesAllocSize
);
10112 for (; summary_page
< last_summary_page
; summary_page
+= PAGE_SIZE
) {
10113 if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) {
10114 (*printf_func
)(" can't perform kext scan: "
10115 "missing kext summary page %p", summary_page
);
10120 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10121 OSKextLoadedKextSummary
* summary
;
10123 summary
= gLoadedKextSummaries
->summaries
+ i
;
10124 if (!summary
->address
) {
10128 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
10133 (*printf_func
)(" Kernel Extensions in backtrace:\n");
10137 printSummary(summary
, printf_func
);
10142 IOLockUnlock(sKextSummariesLock
);
10148 /*********************************************************************
10149 * This function must be safe to call in panic context.
10150 *********************************************************************/
10153 OSKext::summaryIsInBacktrace(
10154 OSKextLoadedKextSummary
* summary
,
10155 vm_offset_t
* addr
,
10160 for (i
= 0; i
< cnt
; i
++) {
10161 vm_offset_t kscan_addr
= addr
[i
];
10162 if ((kscan_addr
>= summary
->address
) &&
10163 (kscan_addr
< (summary
->address
+ summary
->size
)))
10172 /*********************************************************************
10173 * scan list of loaded kext summaries looking for a load address match and if
10174 * found return the UUID C string. If not found then set empty string.
10175 *********************************************************************/
10176 static void findSummaryUUID(
10178 uuid_string_t uuid
);
10180 static void findSummaryUUID(
10182 uuid_string_t uuid
)
10186 uuid
[0] = 0x00; // default to no UUID
10188 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10189 OSKextLoadedKextSummary
* summary
;
10191 summary
= gLoadedKextSummaries
->summaries
+ i
;
10193 if (summary
->loadTag
== tag_ID
) {
10194 (void) uuid_unparse(summary
->uuid
, uuid
);
10201 /*********************************************************************
10202 * This function must be safe to call in panic context.
10203 *********************************************************************/
10204 void OSKext::printSummary(
10205 OSKextLoadedKextSummary
* summary
,
10206 int (* printf_func
)(const char *fmt
, ...))
10208 kmod_reference_t
* kmod_ref
= NULL
;
10209 uuid_string_t uuid
;
10210 char version
[kOSKextVersionMaxLength
];
10212 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
10213 strlcpy(version
, "unknown version", sizeof(version
));
10215 (void) uuid_unparse(summary
->uuid
, uuid
);
10217 (*printf_func
)(" %s(%s)[%s]@0x%llx->0x%llx\n",
10218 summary
->name
, version
, uuid
,
10219 summary
->address
, summary
->address
+ summary
->size
- 1);
10221 /* print dependency info */
10222 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
10224 kmod_ref
= kmod_ref
->next
) {
10225 kmod_info_t
* rinfo
;
10227 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) {
10228 (*printf_func
)(" kmod dependency scan stopped "
10229 "due to missing dependency page: %p\n", kmod_ref
);
10232 rinfo
= kmod_ref
->info
;
10234 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) {
10235 (*printf_func
)(" kmod dependency scan stopped "
10236 "due to missing kmod page: %p\n", rinfo
);
10240 if (!rinfo
->address
) {
10241 continue; // skip fake entries for built-ins
10244 /* locate UUID in gLoadedKextSummaries */
10245 findSummaryUUID(rinfo
->id
, uuid
);
10247 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
10248 rinfo
->name
, rinfo
->version
, uuid
, rinfo
->address
);
10254 /*******************************************************************************
10255 * substitute() looks at an input string (a pointer within a larger buffer)
10256 * for a match to a substring, and on match it writes the marker & substitution
10257 * character to an output string, updating the scan (from) and
10258 * output (to) indexes as appropriate.
10259 *******************************************************************************/
10260 static int substitute(
10261 const char * scan_string
,
10263 uint32_t * to_index
,
10264 uint32_t * from_index
,
10265 const char * substring
,
10267 char substitution
);
10269 /* string_out must be at least KMOD_MAX_NAME bytes.
10273 const char * scan_string
,
10275 uint32_t * to_index
,
10276 uint32_t * from_index
,
10277 const char * substring
,
10281 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
10283 /* On a substring match, append the marker (if there is one) and then
10284 * the substitution character, updating the output (to) index accordingly.
10285 * Then update the input (from) length by the length of the substring
10286 * that got replaced.
10288 if (!strncmp(scan_string
, substring
, substring_length
)) {
10290 string_out
[(*to_index
)++] = marker
;
10292 string_out
[(*to_index
)++] = substitution
;
10293 (*from_index
) += substring_length
;
10299 /*******************************************************************************
10300 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
10301 * KMOD_MAX_NAME characters and performs various substitutions of common
10302 * prefixes & substrings as defined by tables in kext_panic_report.h.
10303 *******************************************************************************/
10304 static void compactIdentifier(
10305 const char * identifier
,
10306 char * identifier_out
,
10307 char ** identifier_out_end
);
10311 const char * identifier
,
10312 char * identifier_out
,
10313 char ** identifier_out_end
)
10315 uint32_t from_index
, to_index
;
10316 uint32_t scan_from_index
= 0;
10317 uint32_t scan_to_index
= 0;
10318 subs_entry_t
* subs_entry
= NULL
;
10321 from_index
= to_index
= 0;
10322 identifier_out
[0] = '\0';
10324 /* Replace certain identifier prefixes with shorter @+character sequences.
10325 * Check the return value of substitute() so we only replace the prefix.
10327 for (subs_entry
= &kext_identifier_prefix_subs
[0];
10328 subs_entry
->substring
&& !did_sub
;
10331 did_sub
= substitute(identifier
, identifier_out
,
10332 &scan_to_index
, &scan_from_index
,
10333 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
10337 /* Now scan through the identifier looking for the common substrings
10338 * and replacing them with shorter !+character sequences via substitute().
10340 for (/* see above */;
10341 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
10344 const char * scan_string
= &identifier
[scan_from_index
];
10348 if (scan_from_index
) {
10349 for (subs_entry
= &kext_identifier_substring_subs
[0];
10350 subs_entry
->substring
&& !did_sub
;
10353 did_sub
= substitute(scan_string
, identifier_out
,
10354 &scan_to_index
, &scan_from_index
,
10355 subs_entry
->substring
, '!', subs_entry
->substitute
);
10359 /* If we didn't substitute, copy the input character to the output.
10362 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
10366 identifier_out
[scan_to_index
] = '\0';
10367 if (identifier_out_end
) {
10368 *identifier_out_end
= &identifier_out
[scan_to_index
];
10374 /*******************************************************************************
10375 * assemble_identifier_and_version() adds to a string buffer a compacted
10376 * bundle identifier followed by a version string.
10377 *******************************************************************************/
10379 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
10381 static int assemble_identifier_and_version(
10382 kmod_info_t
* kmod_info
,
10383 char * identPlusVers
);
10385 assemble_identifier_and_version(
10386 kmod_info_t
* kmod_info
,
10387 char * identPlusVers
)
10391 compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
);
10392 result
= strnlen(identPlusVers
, KMOD_MAX_NAME
- 1);
10393 identPlusVers
[result
++] = '\t'; // increment for real char
10394 identPlusVers
[result
] = '\0'; // don't increment for nul char
10395 result
= strlcat(identPlusVers
, kmod_info
->version
, KMOD_MAX_NAME
);
10400 /*******************************************************************************
10401 * Assumes sKextLock is held.
10402 *******************************************************************************/
10405 OSKext::saveLoadedKextPanicListTyped(
10406 const char * prefix
,
10410 uint32_t list_size
,
10411 uint32_t * list_length_ptr
)
10413 uint32_t result
= 0;
10415 unsigned int count
, i
;
10417 count
= sLoadedKexts
->getCount();
10424 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
10425 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
10427 char identPlusVers
[2*KMOD_MAX_NAME
];
10428 uint32_t identPlusVersLength
;
10431 printf("OSKext::saveLoadedKextPanicListTyped - "
10432 "NULL kext in loaded kext list; continuing\n");
10437 printf("OSKext::saveLoadedKextPanicListTyped - "
10438 "Kext type cast failed in loaded kext list; continuing\n");
10442 /* Skip all built-in kexts.
10444 if (theKext
->isKernelComponent()) {
10448 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
10450 /* Filter for kmod name (bundle identifier).
10452 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
10453 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
10457 /* Filter for libraries (kexts that have a compatible version).
10459 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
10460 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
10466 !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) {
10468 printf("kext scan stopped due to missing kmod_info page: %p\n",
10474 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
10476 if (!identPlusVersLength
) {
10477 printf("error saving loaded kext info\n");
10481 /* Adding 1 for the newline.
10483 if (*list_length_ptr
+ identPlusVersLength
+ 1 >= list_size
) {
10487 *list_length_ptr
= strlcat(paniclist
, identPlusVers
, list_size
);
10488 *list_length_ptr
= strlcat(paniclist
, "\n", list_size
);
10494 if (*list_length_ptr
+ 1 <= list_size
) {
10495 result
= list_size
- (*list_length_ptr
+ 1);
10502 /*********************************************************************
10503 *********************************************************************/
10506 OSKext::saveLoadedKextPanicList(void)
10508 char * newlist
= NULL
;
10509 uint32_t newlist_size
= 0;
10510 uint32_t newlist_length
= 0;
10512 newlist_length
= 0;
10513 newlist_size
= KEXT_PANICLIST_SIZE
;
10514 newlist
= (char *)kalloc(newlist_size
);
10517 OSKextLog(/* kext */ NULL
,
10518 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
10519 "Couldn't allocate kext panic log buffer.");
10525 // non-"com.apple." kexts
10526 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
10527 /* libs? */ -1, newlist
, newlist_size
, &newlist_length
)) {
10531 // "com.apple." nonlibrary kexts
10532 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10533 /* libs? */ 0, newlist
, newlist_size
, &newlist_length
)) {
10537 // "com.apple." library kexts
10538 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10539 /* libs? */ 1, newlist
, newlist_size
, &newlist_length
)) {
10544 if (loaded_kext_paniclist
) {
10545 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
10547 loaded_kext_paniclist
= newlist
;
10548 loaded_kext_paniclist_size
= newlist_size
;
10549 loaded_kext_paniclist_length
= newlist_length
;
10555 /*********************************************************************
10556 * Assumes sKextLock is held.
10557 *********************************************************************/
10559 OSKext::savePanicString(bool isLoading
)
10564 return; // do not goto finish here b/c of lock
10567 len
= assemble_identifier_and_version(kmod_info
,
10568 (isLoading
) ? last_loaded_str
: last_unloaded_str
);
10570 printf("error saving unloaded kext info\n");
10575 last_loaded_strlen
= len
;
10576 last_loaded_address
= (void *)kmod_info
->address
;
10577 last_loaded_size
= kmod_info
->size
;
10578 clock_get_uptime(&last_loaded_timestamp
);
10580 last_unloaded_strlen
= len
;
10581 last_unloaded_address
= (void *)kmod_info
->address
;
10582 last_unloaded_size
= kmod_info
->size
;
10583 clock_get_uptime(&last_unloaded_timestamp
);
10590 /*********************************************************************
10591 *********************************************************************/
10594 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
10596 if (last_loaded_strlen
) {
10597 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
10598 AbsoluteTime_to_scalar(&last_loaded_timestamp
),
10599 last_loaded_strlen
, last_loaded_str
,
10600 last_loaded_address
, last_loaded_size
);
10603 if (last_unloaded_strlen
) {
10604 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
10605 AbsoluteTime_to_scalar(&last_unloaded_timestamp
),
10606 last_unloaded_strlen
, last_unloaded_str
,
10607 last_unloaded_address
, last_unloaded_size
);
10610 printf_func("loaded kexts:\n");
10611 if (loaded_kext_paniclist
&&
10612 pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) &&
10613 loaded_kext_paniclist
[0]) {
10615 printf_func("%.*s", loaded_kext_paniclist_length
, loaded_kext_paniclist
);
10617 printf_func("(none)\n");
10622 /*********************************************************************
10623 * Assumes sKextLock is held.
10624 *********************************************************************/
10627 OSKext::updateLoadedKextSummaries(void)
10629 kern_return_t result
= KERN_FAILURE
;
10630 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
10631 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
10633 vm_map_offset_t start
, end
;
10634 size_t summarySize
= 0;
10640 IOLockLock(sKextSummariesLock
);
10642 count
= sLoadedKexts
->getCount();
10643 for (i
= 0, numKexts
= 0; i
< count
; ++i
) {
10644 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10645 numKexts
+= (aKext
&& aKext
->isExecutable());
10648 if (!numKexts
) goto finish
;
10650 /* Calculate the size needed for the new summary headers.
10653 size
= sizeof(*gLoadedKextSummaries
);
10654 size
+= numKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
10655 size
= round_page(size
);
10657 /* If the previous summary is large enough, use it (and be sure to make
10658 * it writable). If it's too small, free it and allocate a new buffer.
10661 if (sPrevLoadedKextSummariesAllocSize
< size
) {
10662 if (sPrevLoadedKextSummaries
) {
10663 kmem_free(kernel_map
, (vm_offset_t
)sPrevLoadedKextSummaries
,
10664 sPrevLoadedKextSummariesAllocSize
);
10665 sPrevLoadedKextSummaries
= NULL
;
10666 sPrevLoadedKextSummariesAllocSize
= 0;
10669 result
= kmem_alloc(kernel_map
,
10670 (vm_offset_t
*)&summaryHeaderAlloc
, size
);
10671 if (result
!= KERN_SUCCESS
) goto finish
;
10673 summaryHeader
= summaryHeaderAlloc
;
10674 summarySize
= size
;
10676 summaryHeader
= sPrevLoadedKextSummaries
;
10677 summarySize
= sPrevLoadedKextSummariesAllocSize
;
10679 start
= (vm_map_offset_t
) summaryHeader
;
10680 end
= start
+ summarySize
;
10681 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_DEFAULT
, FALSE
);
10682 if (result
!= KERN_SUCCESS
) goto finish
;
10685 /* Populate the summary header.
10688 bzero(summaryHeader
, summarySize
);
10689 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
10690 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
10691 summaryHeader
->numSummaries
= numKexts
;
10693 /* Populate each kext summary.
10696 count
= sLoadedKexts
->getCount();
10697 for (i
= 0, j
= 0; i
< count
; ++i
) {
10698 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10699 if (!aKext
|| !aKext
->isExecutable()) continue;
10701 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
10704 /* Write protect the buffer and move it into place.
10707 start
= (vm_map_offset_t
) summaryHeader
;
10708 end
= start
+ summarySize
;
10709 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_READ
, FALSE
);
10710 if (result
!= KERN_SUCCESS
) goto finish
;
10712 sPrevLoadedKextSummaries
= gLoadedKextSummaries
;
10713 sPrevLoadedKextSummariesAllocSize
= sLoadedKextSummariesAllocSize
;
10715 gLoadedKextSummaries
= summaryHeader
;
10716 sLoadedKextSummariesAllocSize
= summarySize
;
10718 summaryHeaderAlloc
= NULL
;
10720 /* Call the magic breakpoint function through a static function pointer so
10721 * the compiler can't optimize the function away.
10723 if (sLoadedKextSummariesUpdated
) (*sLoadedKextSummariesUpdated
)();
10726 IOLockUnlock(sKextSummariesLock
);
10728 /* If we had to allocate a new buffer but failed to generate the summaries,
10731 if (summaryHeaderAlloc
) {
10732 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
10738 /*********************************************************************
10739 *********************************************************************/
10741 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
10745 strlcpy(summary
->name
, getIdentifierCString(),
10746 sizeof(summary
->name
));
10750 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
10751 OSSafeRelease(uuid
);
10754 summary
->address
= kmod_info
->address
;
10755 summary
->size
= kmod_info
->size
;
10756 summary
->version
= getVersion();
10757 summary
->loadTag
= kmod_info
->id
;
10758 summary
->flags
= 0;
10759 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
10764 /*********************************************************************
10765 *********************************************************************/
10767 #if CONFIG_KEC_FIPS
10770 #pragma mark Kernel External Components for FIPS compliance
10773 /*********************************************************************
10774 * Kernel External Components for FIPS compliance (KEC_FIPS)
10775 *********************************************************************/
10777 GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
)
10779 AppleTEXTHash_t my_ath
= {1, 0, NULL
};
10780 AppleTEXTHash_t
* my_athp
= NULL
; // do not release
10781 OSDictionary
* textHashDict
= NULL
; // do not release
10782 OSData
* segmentHash
= NULL
; // do not release
10784 if (theKext
== NULL
|| theInfoDict
== NULL
) {
10788 textHashDict
= OSDynamicCast(OSDictionary
, theInfoDict
->getObject(kAppleTextHashesKey
));
10789 if (textHashDict
== NULL
) {
10793 segmentHash
= OSDynamicCast(OSData
,
10794 textHashDict
->getObject(ARCHNAME
));
10795 if (segmentHash
== NULL
) {
10799 // KEC_FIPS type kexts never unload so we don't have to clean up our
10801 if (kmem_alloc(kernel_map
, (vm_offset_t
*) &my_athp
,
10802 sizeof(AppleTEXTHash_t
)) != KERN_SUCCESS
) {
10806 memcpy(my_athp
, &my_ath
, sizeof(my_ath
));
10807 my_athp
->ath_length
= segmentHash
->getLength();
10808 if (my_athp
->ath_length
> 0) {
10809 my_athp
->ath_hash
= (void *)segmentHash
->getBytesNoCopy();
10814 kOSKextLogErrorLevel
|
10815 kOSKextLogGeneralFlag
,
10816 "Kext %s ath_version %d ath_length %d ath_hash %p",
10817 theKext
->getIdentifierCString(),
10818 my_athp
->ath_version
,
10819 my_athp
->ath_length
,
10820 my_athp
->ath_hash
);
10823 return( (void *) my_athp
);
10826 #endif // CONFIG_KEC_FIPS