2 * Copyright (c) 2008-2009 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 <libkern/OSKextLibPrivate.h>
51 #include <libkern/c++/OSKext.h>
52 #include <libkern/c++/OSLib.h>
54 #include <IOKit/IOLib.h>
55 #include <IOKit/IOCatalogue.h>
56 #include <IOKit/IORegistryEntry.h>
57 #include <IOKit/IOService.h>
59 #include <IOKit/IOStatisticsPrivate.h>
62 #pragma mark External & Internal Function Protos
64 /*********************************************************************
65 *********************************************************************/
67 extern int IODTGetLoaderInfo(const char * key
, void ** infoAddr
, int * infoSize
);
68 extern void IODTFreeLoaderInfo(const char * key
, void * infoAddr
, int infoSize
);
69 extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t
* segment
);
70 extern void OSRuntimeUnloadCPP(kmod_info_t
* ki
, void * data
);
72 extern ppnum_t
pmap_find_phys(pmap_t pmap
, addr64_t va
); /* osfmk/machine/pmap.h */
75 static OSReturn
_OSKextCreateRequest(
76 const char * predicate
,
77 OSDictionary
** requestP
);
78 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
);
79 static OSObject
* _OSKextGetRequestArgument(
80 OSDictionary
* requestDict
,
81 const char * argName
);
82 static bool _OSKextSetRequestArgument(
83 OSDictionary
* requestDict
,
86 static void * _OSKextExtractPointer(OSData
* wrapper
);
87 static OSReturn
_OSDictionarySetCStringValue(
91 static bool _OSKextInPrelinkRebuildWindow(void);
92 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol
* theBundleID
);
94 // We really should add containsObject() & containsCString to OSCollection & subclasses.
95 // So few pad slots, though....
96 static bool _OSArrayContainsCString(OSArray
* array
, const char * cString
);
99 static void * GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
);
100 #endif // CONFIG_KEC_FIPS
102 /* Prelinked arm kexts do not have VM entries because the method we use to
103 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
104 * not work on ARM. To get around that, we must free prelinked kext
105 * executables with ml_static_mfree() instead of kext_free().
107 #if __i386__ || __x86_64__
108 #define VM_MAPPED_KEXTS 1
109 #define KASLR_KEXT_DEBUG 0
110 #define KASLR_IOREG_DEBUG 0
112 #error Unsupported architecture
116 #pragma mark Constants & Macros
118 /*********************************************************************
120 *********************************************************************/
122 /* A typical Snow Leopard system has a bit under 120 kexts loaded.
123 * Use this number to create containers.
125 #define kOSKextTypicalLoadCount (120)
127 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
128 * A loaded kext will no dependents or external retains will have 2 retains.
130 #define kOSKextMinRetainCount (1)
131 #define kOSKextMinLoadedRetainCount (2)
134 * Strings and substrings used in dependency resolution.
136 #define APPLE_KEXT_PREFIX "com.apple."
137 #define KERNEL_LIB "com.apple.kernel"
139 #define PRIVATE_KPI "com.apple.kpi.private"
141 /* Version for compatbility pseudokexts (com.apple.kernel.*),
142 * compatible back to v6.0.
144 #define KERNEL6_LIB "com.apple.kernel.6.0"
145 #define KERNEL6_VERSION "7.9.9"
147 #define KERNEL_LIB_PREFIX "com.apple.kernel."
148 #define KPI_LIB_PREFIX "com.apple.kpi."
150 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0)
152 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
153 #define MINIMUM_WAKEUP_SECONDS (30)
155 /*********************************************************************
156 * infoDict keys for internally-stored data. Saves on ivar slots for
157 * objects we don't keep around past boot time or during active load.
158 *********************************************************************/
160 /* A usable, uncompressed file is stored under this key.
162 #define _kOSKextExecutableKey "_OSKextExecutable"
164 /* An indirect reference to the executable file from an mkext
165 * is stored under this key.
167 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference"
169 /* If the file is contained in a larger buffer laid down by the booter or
170 * sent from user space, the OSKext stores that OSData under this key so that
171 * references are properly tracked. This is always an mkext, right now.
173 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
176 #pragma mark Typedefs
178 /*********************************************************************
180 *********************************************************************/
182 /*********************************************************************
183 * MkextEntryRef describes the contents of an OSData object
184 * referencing a file entry from an mkext so that we can uncompress
185 * (if necessary) and extract it on demand.
187 * It contains the mkextVersion in case we ever wind up supporting
188 * multiple mkext formats. Mkext format 1 is officially retired as of
190 *********************************************************************/
191 typedef struct MkextEntryRef
{
192 mkext_basic_header
* mkext
; // beginning of whole mkext file
193 void * fileinfo
; // mkext2_file_entry or equiv; see mkext.h
197 #pragma mark Global and static Module Variables
199 /*********************************************************************
200 * Global & static variables, used to keep track of kexts.
201 *********************************************************************/
203 static bool sPrelinkBoot
= false;
204 static bool sSafeBoot
= false;
205 static bool sKeepSymbols
= false;
207 /*********************************************************************
208 * sKextLock is the principal lock for OSKext, and guards all static
209 * and global variables not owned by other locks (declared further
210 * below). It must be taken by any entry-point method or function,
211 * including internal functions called on scheduled threads.
213 * sKextLock and sKextInnerLock are recursive due to multiple functions
214 * that are called both externally and internally. The other locks are
217 * Which locks are taken depends on what they protect, but if more than
218 * one must be taken, they must always be locked in this order
219 * (and unlocked in reverse order) to prevent deadlocks:
223 * 3. sKextSummariesLock
224 * 4. sKextLoggingLock
226 static IORecursiveLock
* sKextLock
= NULL
;
228 static OSDictionary
* sKextsByID
= NULL
;
229 static OSArray
* sLoadedKexts
= NULL
;
230 static OSArray
* sUnloadedPrelinkedKexts
= NULL
;
232 // Requests to kextd waiting to be picked up.
233 static OSArray
* sKernelRequests
= NULL
;
234 // Identifier of kext load requests in sKernelRequests
235 static OSSet
* sPostedKextLoadIdentifiers
= NULL
;
236 static OSArray
* sRequestCallbackRecords
= NULL
;
238 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
239 static OSSet
* sAllKextLoadIdentifiers
= NULL
;
240 static KXLDContext
* sKxldContext
= NULL
;
241 static uint32_t sNextLoadTag
= 0;
242 static uint32_t sNextRequestTag
= 0;
244 static bool sUserLoadsActive
= false;
245 static bool sKextdActive
= false;
246 static bool sDeferredLoadSucceeded
= false;
247 static bool sConsiderUnloadsExecuted
= false;
250 static bool sKernelRequestsEnabled
= false;
252 static bool sKernelRequestsEnabled
= true;
254 static bool sLoadEnabled
= true;
255 static bool sUnloadEnabled
= true;
257 /*********************************************************************
258 * Stuff for the OSKext representing the kernel itself.
260 static OSKext
* sKernelKext
= NULL
;
262 /* Set up a fake kmod_info struct for the kernel.
263 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
264 * before OSKext is initialized; that call only needs the name
265 * and address to be set correctly.
267 * We don't do much else with the kerne's kmod_info; we never
268 * put it into the kmod list, never adjust the reference count,
269 * and never have kernel components reference it.
270 * For that matter, we don't do much with kmod_info structs
271 * at all anymore! We just keep them filled in for gdb and
272 * binary compability.
274 kmod_info_t g_kernel_kmod_info
= {
276 /* info_version */ KMOD_INFO_VERSION
,
277 /* id */ 0, // loadTag: kernel is always 0
278 /* name */ kOSKextKernelIdentifier
, // bundle identifier
279 /* version */ "0", // filled in in OSKext::initialize()
280 /* reference_count */ -1, // never adjusted; kernel never unloads
281 /* reference_list */ NULL
,
283 /* size */ 0, // filled in in OSKext::initialize()
290 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
291 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
292 // misc_protos.h, db_low_trace.c, kgmacros
293 // 'kmod' is a holdover from the old kmod system, we can't rename it.
294 kmod_info_t
* kmod
= NULL
;
296 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
299 static char * loaded_kext_paniclist
= NULL
;
300 static uint32_t loaded_kext_paniclist_size
= 0;
301 static uint32_t loaded_kext_paniclist_length
= 0;
303 AbsoluteTime last_loaded_timestamp
;
304 static char last_loaded_str
[2*KMOD_MAX_NAME
];
305 static u_long last_loaded_strlen
= 0;
306 static void * last_loaded_address
= NULL
;
307 static u_long last_loaded_size
= 0;
309 AbsoluteTime last_unloaded_timestamp
;
310 static char last_unloaded_str
[2*KMOD_MAX_NAME
];
311 static u_long last_unloaded_strlen
= 0;
312 static void * last_unloaded_address
= NULL
;
313 static u_long last_unloaded_size
= 0;
315 /*********************************************************************
316 * sKextInnerLock protects against cross-calls with IOService and
317 * IOCatalogue, and owns the variables declared immediately below.
319 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
321 * When both sKextLock and sKextInnerLock need to be taken,
322 * always lock sKextLock first and unlock it second. Never take both
323 * locks in an entry point to OSKext; if you need to do so, you must
324 * spawn an independent thread to avoid potential deadlocks for threads
325 * calling into OSKext.
327 static IORecursiveLock
* sKextInnerLock
= NULL
;
329 static bool sAutounloadEnabled
= true;
330 static bool sConsiderUnloadsCalled
= false;
331 static bool sConsiderUnloadsPending
= false;
333 static unsigned int sConsiderUnloadDelay
= 60; // seconds
334 static thread_call_t sUnloadCallout
= 0;
335 static thread_call_t sDestroyLinkContextThread
= 0; // one-shot, one-at-a-time thread
336 static bool sSystemSleep
= false; // true when system going to sleep
337 static AbsoluteTime sLastWakeTime
; // last time we woke up
339 /*********************************************************************
340 * Backtraces can be printed at various times so we need a tight lock
341 * on data used for that. sKextSummariesLock protects the variables
342 * declared immediately below.
344 * gLoadedKextSummaries is accessed by other modules, but only during
345 * a panic so the lock isn't needed then.
347 static IOLock
* sKextSummariesLock
= NULL
;
349 void (*sLoadedKextSummariesUpdated
)(void) = OSKextLoadedKextSummariesUpdated
;
350 OSKextLoadedKextSummaryHeader
* gLoadedKextSummaries
= NULL
;
351 static size_t sLoadedKextSummariesAllocSize
= 0;
352 OSKextLoadedKextSummaryHeader
* sPrevLoadedKextSummaries
= NULL
;
353 static size_t sPrevLoadedKextSummariesAllocSize
= 0;
356 /*********************************************************************
357 * sKextLoggingLock protects the logging variables declared immediately below.
359 static IOLock
* sKextLoggingLock
= NULL
;
361 static const OSKextLogSpec kDefaultKernelLogFilter
= kOSKextLogBasicLevel
|
362 kOSKextLogVerboseFlagsMask
;
363 static OSKextLogSpec sKernelLogFilter
= kDefaultKernelLogFilter
;
364 static bool sBootArgLogFilterFound
= false;
365 SYSCTL_INT(_debug
, OID_AUTO
, kextlog
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &sKernelLogFilter
,
366 sKernelLogFilter
, "kernel kext logging");
368 static OSKextLogSpec sUserSpaceKextLogFilter
= kOSKextLogSilentFilter
;
369 static OSArray
* sUserSpaceLogSpecArray
= NULL
;
370 static OSArray
* sUserSpaceLogMessageArray
= NULL
;
373 * End scope for sKextInnerLock-protected variables.
374 *********************************************************************/
377 #pragma mark OSData callbacks (need to move to OSData)
379 /*********************************************************************
380 * C functions used for callbacks.
381 *********************************************************************/
383 void osdata_kmem_free(void * ptr
, unsigned int length
) {
384 kmem_free(kernel_map
, (vm_address_t
)ptr
, length
);
388 void osdata_phys_free(void * ptr
, unsigned int length
) {
389 ml_static_mfree((vm_offset_t
)ptr
, length
);
393 void osdata_vm_deallocate(void * ptr
, unsigned int length
)
395 (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
);
399 void osdata_kext_free(void * ptr
, unsigned int length
)
401 (void)kext_free((vm_offset_t
)ptr
, length
);
407 #pragma mark KXLD Allocation Callback
409 /*********************************************************************
410 * KXLD Allocation Callback
411 *********************************************************************/
415 KXLDAllocateFlags
* flags
,
418 vm_address_t result
= 0; // returned
419 kern_return_t mach_result
= KERN_FAILURE
;
420 bool success
= false;
421 OSKext
* theKext
= (OSKext
*)user_data
;
422 u_long roundSize
= round_page(size
);
423 OSData
* linkBuffer
= NULL
; // must release
425 mach_result
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
);
426 if (mach_result
!= KERN_SUCCESS
) {
428 kOSKextLogErrorLevel
|
429 kOSKextLogGeneralFlag
,
430 "Can't allocate kernel memory to link %s.",
431 theKext
->getIdentifierCString());
435 /* Create an OSData wrapper for the allocated buffer.
437 linkBuffer
= OSData::withBytesNoCopy((void *)result
, roundSize
);
440 kOSKextLogErrorLevel
|
441 kOSKextLogGeneralFlag
,
442 "Can't allocate linked executable wrapper for %s.",
443 theKext
->getIdentifierCString());
446 linkBuffer
->setDeallocFunction(osdata_kext_free
);
449 kOSKextLogProgressLevel
|
450 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
451 "Allocated link buffer for kext %s at %p (%lu bytes).",
452 theKext
->getIdentifierCString(),
453 (void *)result
, (unsigned long)roundSize
);
455 theKext
->setLinkedExecutable(linkBuffer
);
457 *flags
= kKxldAllocateWritable
;
461 if (!success
&& result
) {
462 kext_free(result
, roundSize
);
466 OSSafeRelease(linkBuffer
);
468 return (kxld_addr_t
)result
;
471 /*********************************************************************
472 *********************************************************************/
475 KXLDLogSubsystem subsystem
,
481 OSKext
*theKext
= (OSKext
*) user_data
;
482 OSKextLogSpec logSpec
= 0;
485 case kKxldLogLinking
:
486 logSpec
|= kOSKextLogLinkFlag
;
488 case kKxldLogPatching
:
489 logSpec
|= kOSKextLogPatchFlag
;
494 case kKxldLogExplicit
:
495 logSpec
|= kOSKextLogExplicitLevel
;
498 logSpec
|= kOSKextLogErrorLevel
;
501 logSpec
|= kOSKextLogWarningLevel
;
504 logSpec
|= kOSKextLogProgressLevel
;
507 logSpec
|= kOSKextLogDetailLevel
;
510 logSpec
|= kOSKextLogDebugLevel
;
514 OSKextVLog(theKext
, logSpec
, format
, argList
);
518 #pragma mark IOStatistics defines
523 #define notifyKextLoadObservers(kext, kmod_info) \
525 IOStatistics::onKextLoad(kext, kmod_info); \
528 #define notifyKextUnloadObservers(kext) \
530 IOStatistics::onKextUnload(kext); \
533 #define notifyAddClassObservers(kext, addedClass, flags) \
535 IOStatistics::onClassAdded(kext, addedClass); \
538 #define notifyRemoveClassObservers(kext, removedClass, flags) \
540 IOStatistics::onClassRemoved(kext, removedClass); \
545 #define notifyKextLoadObservers(kext, kmod_info)
546 #define notifyKextUnloadObservers(kext)
547 #define notifyAddClassObservers(kext, addedClass, flags)
548 #define notifyRemoveClassObservers(kext, removedClass, flags)
550 #endif /* IOKITSTATS */
553 #pragma mark Module Config (Startup & Shutdown)
555 /*********************************************************************
556 * Module Config (Class Definition & Class Methods)
557 *********************************************************************/
558 #define super OSObject
559 OSDefineMetaClassAndStructors(OSKext
, OSObject
)
561 /*********************************************************************
562 *********************************************************************/
565 OSKext::initialize(void)
567 OSData
* kernelExecutable
= NULL
; // do not release
568 u_char
* kernelStart
= NULL
; // do not free
569 size_t kernelLength
= 0;
570 OSString
* scratchString
= NULL
; // must release
571 IORegistryEntry
* registryRoot
= NULL
; // do not release
572 OSNumber
* kernelCPUType
= NULL
; // must release
573 OSNumber
* kernelCPUSubtype
= NULL
; // must release
574 OSKextLogSpec bootLogFilter
= kOSKextLogSilentFilter
;
575 bool setResult
= false;
576 uint64_t * timestamp
= 0;
577 char bootArgBuffer
[16]; // for PE_parse_boot_argn w/strings
579 /* This must be the first thing allocated. Everything else grabs this lock.
581 sKextLock
= IORecursiveLockAlloc();
582 sKextInnerLock
= IORecursiveLockAlloc();
583 sKextSummariesLock
= IOLockAlloc();
584 sKextLoggingLock
= IOLockAlloc();
586 assert(sKextInnerLock
);
587 assert(sKextSummariesLock
);
588 assert(sKextLoggingLock
);
590 sKextsByID
= OSDictionary::withCapacity(kOSKextTypicalLoadCount
);
591 sLoadedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
);
592 sUnloadedPrelinkedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
/ 10);
593 sKernelRequests
= OSArray::withCapacity(0);
594 sPostedKextLoadIdentifiers
= OSSet::withCapacity(0);
595 sAllKextLoadIdentifiers
= OSSet::withCapacity(kOSKextTypicalLoadCount
);
596 sRequestCallbackRecords
= OSArray::withCapacity(0);
597 assert(sKextsByID
&& sLoadedKexts
&& sKernelRequests
&&
598 sPostedKextLoadIdentifiers
&& sAllKextLoadIdentifiers
&&
599 sRequestCallbackRecords
&& sUnloadedPrelinkedKexts
);
601 /* Read the log flag boot-args and set the log flags.
603 if (PE_parse_boot_argn("kextlog", &bootLogFilter
, sizeof(bootLogFilter
))) {
604 sBootArgLogFilterFound
= true;
605 sKernelLogFilter
= bootLogFilter
;
606 // log this if any flags are set
607 OSKextLog(/* kext */ NULL
,
608 kOSKextLogBasicLevel
|
610 "Kernel kext log filter 0x%x per kextlog boot arg.",
611 (unsigned)sKernelLogFilter
);
614 sSafeBoot
= PE_parse_boot_argn("-x", bootArgBuffer
,
615 sizeof(bootArgBuffer
)) ? true : false;
618 OSKextLog(/* kext */ NULL
,
619 kOSKextLogWarningLevel
|
620 kOSKextLogGeneralFlag
,
621 "SAFE BOOT DETECTED - "
622 "only valid OSBundleRequired kexts will be loaded.");
625 PE_parse_boot_argn("keepsyms", &sKeepSymbols
, sizeof(sKeepSymbols
));
627 /* Set up an OSKext instance to represent the kernel itself.
629 sKernelKext
= new OSKext
;
632 kernelStart
= (u_char
*)&_mh_execute_header
;
633 kernelLength
= getlastaddr() - (vm_offset_t
)kernelStart
;
634 kernelExecutable
= OSData::withBytesNoCopy(
635 kernelStart
, kernelLength
);
636 assert(kernelExecutable
);
639 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu \n",
640 (unsigned long)kernelStart
,
641 (unsigned long)getlastaddr(),
645 sKernelKext
->loadTag
= sNextLoadTag
++; // the kernel is load tag 0
646 sKernelKext
->bundleID
= OSSymbol::withCString(kOSKextKernelIdentifier
);
648 sKernelKext
->version
= OSKextParseVersionString(osrelease
);
649 sKernelKext
->compatibleVersion
= sKernelKext
->version
;
650 sKernelKext
->linkedExecutable
= kernelExecutable
;
652 sKernelKext
->flags
.hasAllDependencies
= 1;
653 sKernelKext
->flags
.kernelComponent
= 1;
654 sKernelKext
->flags
.prelinked
= 0;
655 sKernelKext
->flags
.loaded
= 1;
656 sKernelKext
->flags
.started
= 1;
657 sKernelKext
->flags
.CPPInitialized
= 0;
658 sKernelKext
->flags
.jettisonLinkeditSeg
= 0;
660 sKernelKext
->kmod_info
= &g_kernel_kmod_info
;
661 strlcpy(g_kernel_kmod_info
.version
, osrelease
,
662 sizeof(g_kernel_kmod_info
.version
));
663 g_kernel_kmod_info
.size
= kernelLength
;
664 g_kernel_kmod_info
.id
= sKernelKext
->loadTag
;
666 /* Cons up an info dict, so we don't have to have special-case
669 sKernelKext
->infoDict
= OSDictionary::withCapacity(5);
670 assert(sKernelKext
->infoDict
);
671 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
,
672 sKernelKext
->bundleID
);
674 setResult
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
,
678 scratchString
= OSString::withCStringNoCopy(osrelease
);
679 assert(scratchString
);
680 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
,
683 OSSafeReleaseNULL(scratchString
);
685 scratchString
= OSString::withCStringNoCopy("mach_kernel");
686 assert(scratchString
);
687 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
,
690 OSSafeReleaseNULL(scratchString
);
692 /* Add the kernel kext to the bookkeeping dictionaries. Note that
693 * the kernel kext doesn't have a kmod_info struct. copyInfo()
694 * gathers info from other places anyhow.
696 setResult
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
);
698 setResult
= sLoadedKexts
->setObject(sKernelKext
);
700 sKernelKext
->release();
702 registryRoot
= IORegistryEntry::getRegistryRoot();
703 kernelCPUType
= OSNumber::withNumber(
704 (long long unsigned int)_mh_execute_header
.cputype
,
705 8 * sizeof(_mh_execute_header
.cputype
));
706 kernelCPUSubtype
= OSNumber::withNumber(
707 (long long unsigned int)_mh_execute_header
.cpusubtype
,
708 8 * sizeof(_mh_execute_header
.cpusubtype
));
709 assert(registryRoot
&& kernelCPUSubtype
&& kernelCPUType
);
711 registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
);
712 registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
);
714 OSSafeRelease(kernelCPUType
);
715 OSSafeRelease(kernelCPUSubtype
);
717 timestamp
= __OSAbsoluteTimePtr(&last_loaded_timestamp
);
719 timestamp
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
);
721 timestamp
= __OSAbsoluteTimePtr(&sLastWakeTime
);
724 OSKextLog(/* kext */ NULL
,
725 kOSKextLogProgressLevel
|
726 kOSKextLogGeneralFlag
,
727 "Kext system initialized.");
729 notifyKextLoadObservers(sKernelKext
, sKernelKext
->kmod_info
);
734 /*********************************************************************
735 * This could be in OSKextLib.cpp but we need to hold a lock
736 * while removing all the segments and sKextLock will do.
737 *********************************************************************/
740 OSKext::removeKextBootstrap(void)
742 OSReturn result
= kOSReturnError
;
744 static bool alreadyDone
= false;
746 const char * dt_kernel_header_name
= "Kernel-__HEADER";
747 const char * dt_kernel_symtab_name
= "Kernel-__SYMTAB";
748 kernel_mach_header_t
* dt_mach_header
= NULL
;
749 int dt_mach_header_size
= 0;
750 struct symtab_command
* dt_symtab
= NULL
;
751 int dt_symtab_size
= 0;
754 kernel_segment_command_t
* seg_to_remove
= NULL
;
757 /* This must be the very first thing done by this function.
759 IORecursiveLockLock(sKextLock
);
761 /* If we already did this, it's a success.
764 result
= kOSReturnSuccess
;
768 OSKextLog(/* kext */ NULL
,
769 kOSKextLogProgressLevel
|
770 kOSKextLogGeneralFlag
,
771 "Jettisoning kext bootstrap segments.");
774 * Dispose of unnecessary stuff that the booter didn't need to load.
776 dt_result
= IODTGetLoaderInfo(dt_kernel_header_name
,
777 (void **)&dt_mach_header
, &dt_mach_header_size
);
778 if (dt_result
== 0 && dt_mach_header
) {
779 IODTFreeLoaderInfo(dt_kernel_header_name
, (void *)dt_mach_header
,
780 round_page_32(dt_mach_header_size
));
782 dt_result
= IODTGetLoaderInfo(dt_kernel_symtab_name
,
783 (void **)&dt_symtab
, &dt_symtab_size
);
784 if (dt_result
== 0 && dt_symtab
) {
785 IODTFreeLoaderInfo(dt_kernel_symtab_name
, (void *)dt_symtab
,
786 round_page_32(dt_symtab_size
));
790 * KLD bootstrap segment.
792 // xxx - should rename KLD segment
793 seg_to_remove
= getsegbyname("__KLD");
795 OSRuntimeUnloadCPPForSegment(seg_to_remove
);
798 #if __i386__ || __x86_64__
799 /* On x86, use the mapping data from the segment load command to
800 * unload KLD directly.
801 * This may invalidate any assumptions about "avail_start"
802 * defining the lower bound for valid physical addresses.
804 if (seg_to_remove
&& seg_to_remove
->vmaddr
&& seg_to_remove
->vmsize
) {
805 // 04/18/11 - gab: <rdar://problem/9236163>
806 // overwrite memory occupied by KLD segment with random data before
808 read_random((void *) seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
809 ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
815 seg_to_remove
= NULL
;
818 * Prelinked kernel's symtab (if there is one).
820 kernel_section_t
* sect
;
821 sect
= getsectbyname("__PRELINK", "__symtab");
822 if (sect
&& sect
->addr
&& sect
->size
) {
823 ml_static_mfree(sect
->addr
, sect
->size
);
826 seg_to_remove
= (kernel_segment_command_t
*)getsegbyname("__LINKEDIT");
828 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
829 * pageable, unless keepsyms is set. To do that, we have to copy it from
830 * its booter-allocated memory, free the booter memory, reallocate proper
831 * managed memory, then copy the segment back in.
835 kern_return_t mem_result
;
836 void *seg_copy
= NULL
;
837 void *seg_data
= NULL
;
838 vm_map_offset_t seg_offset
= 0;
839 vm_map_offset_t seg_copy_offset
= 0;
840 vm_map_size_t seg_length
= 0;
842 seg_data
= (void *) seg_to_remove
->vmaddr
;
843 seg_offset
= (vm_map_offset_t
) seg_to_remove
->vmaddr
;
844 seg_length
= (vm_map_size_t
) seg_to_remove
->vmsize
;
846 /* Allocate space for the LINKEDIT copy.
848 mem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*) &seg_copy
,
850 if (mem_result
!= KERN_SUCCESS
) {
851 OSKextLog(/* kext */ NULL
,
852 kOSKextLogErrorLevel
|
853 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
854 "Can't copy __LINKEDIT segment for VM reassign.");
857 seg_copy_offset
= (vm_map_offset_t
) seg_copy
;
861 memcpy(seg_copy
, seg_data
, seg_length
);
863 /* Dump the booter memory.
865 ml_static_mfree(seg_offset
, seg_length
);
867 /* Set up the VM region.
869 mem_result
= vm_map_enter_mem_object(
872 seg_length
, /* mask */ 0,
873 VM_FLAGS_FIXED
| VM_FLAGS_OVERWRITE
,
875 (vm_object_offset_t
) 0,
877 /* cur_protection */ VM_PROT_READ
| VM_PROT_WRITE
,
878 /* max_protection */ VM_PROT_ALL
,
879 /* inheritance */ VM_INHERIT_DEFAULT
);
880 if ((mem_result
!= KERN_SUCCESS
) ||
881 (seg_offset
!= (vm_map_offset_t
) seg_data
))
883 OSKextLog(/* kext */ NULL
,
884 kOSKextLogErrorLevel
|
885 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
886 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
887 seg_data
, seg_length
, mem_result
);
893 memcpy(seg_data
, seg_copy
, seg_length
);
897 kmem_free(kernel_map
, seg_copy_offset
, seg_length
);
899 #else /* we are not CONFIG_KXLD */
900 #error CONFIG_KXLD is expected for this arch
903 * Dump the LINKEDIT segment, unless keepsyms is set.
906 const char *dt_segment_name
= "Kernel-__LINKEDIT";
907 if (0 == IODTGetLoaderInfo(dt_segment_name
,
908 &segment_paddress
, &segment_size
)) {
910 vm_offset_t vmaddr
= ml_static_ptovirt((vm_offset_t
)segment_paddress
);
911 bzero((void*)vmaddr
, segment_size
);
913 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
917 OSKextLog(/* kext */ NULL
,
918 kOSKextLogBasicLevel
|
919 kOSKextLogGeneralFlag
,
920 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
922 #endif /* CONFIG_KXLD */
924 seg_to_remove
= NULL
;
927 result
= kOSReturnSuccess
;
931 /* This must be the very last thing done before returning.
933 IORecursiveLockUnlock(sKextLock
);
938 /*********************************************************************
939 *********************************************************************/
941 OSKext::flushNonloadedKexts(
942 Boolean flushPrelinkedKexts
)
944 OSSet
* prelinkedKexts
= NULL
; // must release
945 OSCollectionIterator
* kextIterator
= NULL
; // must release
946 OSCollectionIterator
* prelinkIterator
= NULL
; // must release
947 const OSSymbol
* thisID
= NULL
; // do not release
948 OSKext
* thisKext
= NULL
; // do not release
951 IORecursiveLockLock(sKextLock
);
953 OSKextLog(/* kext */ NULL
,
954 kOSKextLogProgressLevel
|
955 kOSKextLogKextBookkeepingFlag
,
956 "Flushing nonloaded kexts and other unused data.");
958 OSKext::considerDestroyingLinkContext();
960 /* If we aren't flushing unused prelinked kexts, we have to put them
961 * aside while we flush everything else so make a container for them.
963 if (!flushPrelinkedKexts
) {
964 prelinkedKexts
= OSSet::withCapacity(0);
965 if (!prelinkedKexts
) {
970 /* Set aside prelinked kexts (in-use or not) and break
971 * any lingering inter-kext references for nonloaded kexts
972 * so they have min. retain counts.
974 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
979 while ((thisID
= OSDynamicCast(OSSymbol
,
980 kextIterator
->getNextObject()))) {
982 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
985 if (prelinkedKexts
&& thisKext
->isPrelinked()) {
986 prelinkedKexts
->setObject(thisKext
);
988 thisKext
->flushDependencies(/* forceIfLoaded */ false);
992 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
994 sKextsByID
->flushCollection();
996 /* Now put the loaded kexts back into the ID dictionary.
998 count
= sLoadedKexts
->getCount();
999 for (i
= 0; i
< count
; i
++) {
1000 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
1001 sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
);
1004 /* Finally, put back the prelinked kexts if we saved any.
1006 if (prelinkedKexts
) {
1007 prelinkIterator
= OSCollectionIterator::withCollection(prelinkedKexts
);
1008 if (!prelinkIterator
) {
1012 while ((thisKext
= OSDynamicCast(OSKext
,
1013 prelinkIterator
->getNextObject()))) {
1015 sKextsByID
->setObject(thisKext
->getIdentifierCString(),
1021 IORecursiveLockUnlock(sKextLock
);
1023 OSSafeRelease(prelinkedKexts
);
1024 OSSafeRelease(kextIterator
);
1025 OSSafeRelease(prelinkIterator
);
1030 /*********************************************************************
1031 *********************************************************************/
1034 OSKext::setKextdActive(Boolean active
)
1036 IORecursiveLockLock(sKextLock
);
1037 sKextdActive
= active
;
1038 if (sKernelRequests
->getCount()) {
1039 OSKext::pingKextd();
1041 IORecursiveLockUnlock(sKextLock
);
1046 /*********************************************************************
1047 * OSKextLib.cpp might need access to this someday but for now it's
1049 *********************************************************************/
1051 extern void ipc_port_release_send(ipc_port_t
);
1056 OSKext::pingKextd(void)
1058 OSReturn result
= kOSReturnError
;
1060 mach_port_t kextd_port
= IPC_PORT_NULL
;
1062 if (!sKextdActive
) {
1063 result
= kOSKextReturnDisabled
; // basically unavailable
1067 result
= host_get_kextd_port(host_priv_self(), &kextd_port
);
1068 if (result
!= KERN_SUCCESS
|| !IPC_PORT_VALID(kextd_port
)) {
1069 OSKextLog(/* kext */ NULL
,
1070 kOSKextLogErrorLevel
|
1072 "Can't get kextd port.");
1076 result
= kextd_ping(kextd_port
);
1077 if (result
!= KERN_SUCCESS
) {
1078 OSKextLog(/* kext */ NULL
,
1079 kOSKextLogErrorLevel
|
1081 "kextd ping failed (0x%x).", (int)result
);
1086 if (IPC_PORT_VALID(kextd_port
)) {
1087 ipc_port_release_send(kextd_port
);
1094 /*********************************************************************
1095 *********************************************************************/
1098 OSKext::setDeferredLoadSucceeded(Boolean succeeded
)
1100 IORecursiveLockLock(sKextLock
);
1101 sDeferredLoadSucceeded
= succeeded
;
1102 IORecursiveLockUnlock(sKextLock
);
1107 /*********************************************************************
1108 * Called from IOSystemShutdownNotification.
1109 *********************************************************************/
1112 OSKext::willShutdown(void)
1115 OSReturn checkResult
= kOSReturnError
;
1117 OSDictionary
* exitRequest
= NULL
; // must release
1119 IORecursiveLockLock(sKextLock
);
1121 OSKext::setLoadEnabled(false);
1122 OSKext::setUnloadEnabled(false);
1123 OSKext::setAutounloadsEnabled(false);
1124 OSKext::setKernelRequestsEnabled(false);
1127 OSKextLog(/* kext */ NULL
,
1128 kOSKextLogProgressLevel
|
1129 kOSKextLogGeneralFlag
,
1130 "System shutdown; requesting immediate kextd exit.");
1132 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
,
1134 if (checkResult
!= kOSReturnSuccess
) {
1137 if (!sKernelRequests
->setObject(exitRequest
)) {
1141 OSKext::pingKextd();
1146 IORecursiveLockUnlock(sKextLock
);
1148 OSSafeRelease(exitRequest
);
1152 /*********************************************************************
1153 *********************************************************************/
1156 OSKext::getLoadEnabled(void)
1160 IORecursiveLockLock(sKextLock
);
1161 result
= sLoadEnabled
;
1162 IORecursiveLockUnlock(sKextLock
);
1166 /*********************************************************************
1167 *********************************************************************/
1170 OSKext::setLoadEnabled(bool flag
)
1174 IORecursiveLockLock(sKextLock
);
1175 result
= sLoadEnabled
;
1176 sLoadEnabled
= (flag
? true : false);
1178 if (sLoadEnabled
!= result
) {
1179 OSKextLog(/* kext */ NULL
,
1180 kOSKextLogBasicLevel
|
1182 "Kext loading now %sabled.", sLoadEnabled
? "en" : "dis");
1185 IORecursiveLockUnlock(sKextLock
);
1190 /*********************************************************************
1191 *********************************************************************/
1194 OSKext::getUnloadEnabled(void)
1198 IORecursiveLockLock(sKextLock
);
1199 result
= sUnloadEnabled
;
1200 IORecursiveLockUnlock(sKextLock
);
1204 /*********************************************************************
1205 *********************************************************************/
1208 OSKext::setUnloadEnabled(bool flag
)
1212 IORecursiveLockLock(sKextLock
);
1213 result
= sUnloadEnabled
;
1214 sUnloadEnabled
= (flag
? true : false);
1215 IORecursiveLockUnlock(sKextLock
);
1217 if (sUnloadEnabled
!= result
) {
1218 OSKextLog(/* kext */ NULL
,
1219 kOSKextLogBasicLevel
|
1220 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1221 "Kext unloading now %sabled.", sUnloadEnabled
? "en" : "dis");
1227 /*********************************************************************
1228 * Do not call any function that takes sKextLock here!
1229 *********************************************************************/
1232 OSKext::getAutounloadEnabled(void)
1236 IORecursiveLockLock(sKextInnerLock
);
1237 result
= sAutounloadEnabled
? true : false;
1238 IORecursiveLockUnlock(sKextInnerLock
);
1242 /*********************************************************************
1243 * Do not call any function that takes sKextLock here!
1244 *********************************************************************/
1247 OSKext::setAutounloadsEnabled(bool flag
)
1251 IORecursiveLockLock(sKextInnerLock
);
1253 result
= sAutounloadEnabled
;
1254 sAutounloadEnabled
= (flag
? true : false);
1255 if (!sAutounloadEnabled
&& sUnloadCallout
) {
1256 thread_call_cancel(sUnloadCallout
);
1259 if (sAutounloadEnabled
!= result
) {
1260 OSKextLog(/* kext */ NULL
,
1261 kOSKextLogBasicLevel
|
1262 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1263 "Kext autounloading now %sabled.",
1264 sAutounloadEnabled
? "en" : "dis");
1267 IORecursiveLockUnlock(sKextInnerLock
);
1272 /*********************************************************************
1273 *********************************************************************/
1274 /* instance method operating on OSKext field */
1276 OSKext::setAutounloadEnabled(bool flag
)
1278 bool result
= flags
.autounloadEnabled
? true : false;
1279 flags
.autounloadEnabled
= flag
? 1 : 0;
1281 if (result
!= (flag
? true : false)) {
1283 kOSKextLogProgressLevel
|
1284 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
1285 "Autounloading for kext %s now %sabled.",
1286 getIdentifierCString(),
1287 flags
.autounloadEnabled
? "en" : "dis");
1292 /*********************************************************************
1293 *********************************************************************/
1296 OSKext::setKernelRequestsEnabled(bool flag
)
1300 IORecursiveLockLock(sKextLock
);
1301 result
= sKernelRequestsEnabled
;
1302 sKernelRequestsEnabled
= flag
? true : false;
1304 if (sKernelRequestsEnabled
!= result
) {
1305 OSKextLog(/* kext */ NULL
,
1306 kOSKextLogBasicLevel
|
1307 kOSKextLogGeneralFlag
,
1308 "Kernel requests now %sabled.",
1309 sKernelRequestsEnabled
? "en" : "dis");
1311 IORecursiveLockUnlock(sKextLock
);
1315 /*********************************************************************
1316 *********************************************************************/
1319 OSKext::getKernelRequestsEnabled(void)
1323 IORecursiveLockLock(sKextLock
);
1324 result
= sKernelRequestsEnabled
;
1325 IORecursiveLockUnlock(sKextLock
);
1330 #pragma mark Kext Life Cycle
1332 /*********************************************************************
1333 *********************************************************************/
1335 OSKext::withPrelinkedInfoDict(
1336 OSDictionary
* anInfoDict
)
1338 OSKext
* newKext
= new OSKext
;
1340 if (newKext
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
)) {
1348 /*********************************************************************
1349 *********************************************************************/
1351 OSKext::initWithPrelinkedInfoDict(
1352 OSDictionary
* anInfoDict
)
1354 bool result
= false;
1355 OSString
* kextPath
= NULL
; // do not release
1356 OSNumber
* addressNum
= NULL
; // reused; do not release
1357 OSNumber
* lengthNum
= NULL
; // reused; do not release
1358 void * data
= NULL
; // do not free
1359 void * srcData
= NULL
; // do not free
1360 OSData
* prelinkedExecutable
= NULL
; // must release
1361 uint32_t length
= 0; // reused
1363 if (!super::init()) {
1367 /* Get the path. Don't look for an arch-specific path property.
1369 kextPath
= OSDynamicCast(OSString
,
1370 anInfoDict
->getObject(kPrelinkBundlePathKey
));
1372 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
1375 #if KASLR_KEXT_DEBUG
1376 IOLog("kaslr: kext %s \n", getIdentifierCString());
1379 /* Also get the executable's bundle-relative path if present.
1380 * Don't look for an arch-specific path property.
1382 executableRelPath
= OSDynamicCast(OSString
,
1383 anInfoDict
->getObject(kPrelinkExecutableRelativePathKey
));
1384 if (executableRelPath
) {
1385 executableRelPath
->retain();
1388 /* Don't need the paths to be in the info dictionary any more.
1390 anInfoDict
->removeObject(kPrelinkBundlePathKey
);
1391 anInfoDict
->removeObject(kPrelinkExecutableRelativePathKey
);
1393 /* Create an OSData wrapper around the linked executable.
1395 addressNum
= OSDynamicCast(OSNumber
,
1396 anInfoDict
->getObject(kPrelinkExecutableLoadKey
));
1398 lengthNum
= OSDynamicCast(OSNumber
,
1399 anInfoDict
->getObject(kPrelinkExecutableSizeKey
));
1402 kOSKextLogErrorLevel
|
1403 kOSKextLogArchiveFlag
,
1404 "Kext %s can't find prelinked kext executable size.",
1405 getIdentifierCString());
1409 data
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1410 length
= (uint32_t) (lengthNum
->unsigned32BitValue());
1412 #if KASLR_KEXT_DEBUG
1413 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1414 (unsigned long)VM_KERNEL_UNSLIDE(data
),
1415 (unsigned long)data
,
1419 anInfoDict
->removeObject(kPrelinkExecutableLoadKey
);
1420 anInfoDict
->removeObject(kPrelinkExecutableSizeKey
);
1422 /* If the kext's load address differs from its source address, allocate
1423 * space in the kext map at the load address and copy the kext over.
1425 addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
));
1427 srcData
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1429 #if KASLR_KEXT_DEBUG
1430 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1431 (unsigned long)VM_KERNEL_UNSLIDE(srcData
),
1432 (unsigned long)srcData
);
1435 if (data
!= srcData
) {
1437 kern_return_t alloc_result
;
1439 alloc_result
= kext_alloc((vm_offset_t
*)&data
, length
, /* fixed */ TRUE
);
1440 if (alloc_result
!= KERN_SUCCESS
) {
1442 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1443 "Failed to allocate space for prelinked kext %s.",
1444 getIdentifierCString());
1447 memcpy(data
, srcData
, length
);
1450 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1451 "Error: prelinked kext %s - source and load addresses "
1452 "differ on ILP32 architecture.",
1453 getIdentifierCString());
1455 #endif /* __LP64__ */
1458 anInfoDict
->removeObject(kPrelinkExecutableSourceKey
);
1461 prelinkedExecutable
= OSData::withBytesNoCopy(data
, length
);
1462 if (!prelinkedExecutable
) {
1464 kOSKextLogErrorLevel
|
1465 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
1466 "Kext %s failed to create executable wrapper.",
1467 getIdentifierCString());
1472 prelinkedExecutable
->setDeallocFunction(osdata_kext_free
);
1474 prelinkedExecutable
->setDeallocFunction(osdata_phys_free
);
1476 setLinkedExecutable(prelinkedExecutable
);
1478 addressNum
= OSDynamicCast(OSNumber
,
1479 anInfoDict
->getObject(kPrelinkKmodInfoKey
));
1482 kOSKextLogErrorLevel
|
1483 kOSKextLogArchiveFlag
,
1484 "Kext %s can't find prelinked kext kmod_info address.",
1485 getIdentifierCString());
1489 if (addressNum
->unsigned64BitValue() != 0) {
1490 kmod_info
= (kmod_info_t
*) (intptr_t) (addressNum
->unsigned64BitValue() + vm_kernel_slide
);
1491 kmod_info
->address
+= vm_kernel_slide
;
1492 #if KASLR_KEXT_DEBUG
1493 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1494 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
),
1495 (unsigned long)kmod_info
);
1496 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1497 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
1498 (unsigned long)kmod_info
->address
);
1502 anInfoDict
->removeObject(kPrelinkKmodInfoKey
);
1505 /* If the plist has a UUID for an interface, save that off.
1507 if (isInterface()) {
1508 interfaceUUID
= OSDynamicCast(OSData
,
1509 anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
));
1510 if (interfaceUUID
) {
1511 interfaceUUID
->retain();
1512 anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
);
1516 flags
.prelinked
= true;
1518 /* If we created a kext from prelink info,
1519 * we must be booting from a prelinked kernel.
1521 sPrelinkBoot
= true;
1523 result
= registerIdentifier();
1526 OSSafeRelease(prelinkedExecutable
);
1531 /*********************************************************************
1532 *********************************************************************/
1534 OSKext::withBooterData(
1535 OSString
* deviceTreeName
,
1536 OSData
* booterData
)
1538 OSKext
* newKext
= new OSKext
;
1540 if (newKext
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) {
1548 /*********************************************************************
1549 *********************************************************************/
1550 typedef struct _BooterKextFileInfo
{
1551 uint32_t infoDictPhysAddr
;
1552 uint32_t infoDictLength
;
1553 uint32_t executablePhysAddr
;
1554 uint32_t executableLength
;
1555 uint32_t bundlePathPhysAddr
;
1556 uint32_t bundlePathLength
;
1557 } _BooterKextFileInfo
;
1560 OSKext::initWithBooterData(
1561 OSString
* deviceTreeName
,
1562 OSData
* booterData
)
1564 bool result
= false;
1565 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not free
1566 char * infoDictAddr
= NULL
; // do not free
1567 void * executableAddr
= NULL
; // do not free
1568 char * bundlePathAddr
= NULL
; // do not free
1570 OSObject
* parsedXML
= NULL
; // must release
1571 OSDictionary
* theInfoDict
= NULL
; // do not release
1572 OSString
* kextPath
= NULL
; // must release
1573 OSString
* errorString
= NULL
; // must release
1574 OSData
* executable
= NULL
; // must release
1576 if (!super::init()) {
1580 kextFileInfo
= (_BooterKextFileInfo
*)booterData
->getBytesNoCopy();
1581 if (!kextFileInfo
) {
1583 kOSKextLogErrorLevel
|
1584 kOSKextLogGeneralFlag
,
1585 "No booter-provided data for kext device tree entry %s.",
1586 deviceTreeName
->getCStringNoCopy());
1590 /* The info plist must exist or we can't read the kext.
1592 if (!kextFileInfo
->infoDictPhysAddr
|| !kextFileInfo
->infoDictLength
) {
1594 kOSKextLogErrorLevel
|
1595 kOSKextLogGeneralFlag
,
1596 "No kext info dictionary for booter device tree entry %s.",
1597 deviceTreeName
->getCStringNoCopy());
1601 infoDictAddr
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
1602 if (!infoDictAddr
) {
1604 kOSKextLogErrorLevel
|
1605 kOSKextLogGeneralFlag
,
1606 "Can't translate physical address 0x%x of kext info dictionary "
1607 "for device tree entry %s.",
1608 (int)kextFileInfo
->infoDictPhysAddr
,
1609 deviceTreeName
->getCStringNoCopy());
1613 parsedXML
= OSUnserializeXML(infoDictAddr
, &errorString
);
1615 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
1618 const char * errorCString
= "(unknown error)";
1620 if (errorString
&& errorString
->getCStringNoCopy()) {
1621 errorCString
= errorString
->getCStringNoCopy();
1622 } else if (parsedXML
) {
1623 errorCString
= "not a dictionary";
1626 kOSKextLogErrorLevel
|
1627 kOSKextLogGeneralFlag
,
1628 "Error unserializing info dictionary for device tree entry %s: %s.",
1629 deviceTreeName
->getCStringNoCopy(), errorCString
);
1633 /* A bundle path is not mandatory.
1635 if (kextFileInfo
->bundlePathPhysAddr
&& kextFileInfo
->bundlePathLength
) {
1636 bundlePathAddr
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
);
1637 if (!bundlePathAddr
) {
1639 kOSKextLogErrorLevel
|
1640 kOSKextLogGeneralFlag
,
1641 "Can't translate physical address 0x%x of kext bundle path "
1642 "for device tree entry %s.",
1643 (int)kextFileInfo
->bundlePathPhysAddr
,
1644 deviceTreeName
->getCStringNoCopy());
1647 bundlePathAddr
[kextFileInfo
->bundlePathLength
-1] = '\0'; // just in case!
1649 kextPath
= OSString::withCString(bundlePathAddr
);
1652 kOSKextLogErrorLevel
|
1653 kOSKextLogGeneralFlag
,
1654 "Failed to create wrapper for device tree entry %s kext path %s.",
1655 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
);
1660 if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) {
1664 /* An executable is not mandatory.
1666 if (kextFileInfo
->executablePhysAddr
&& kextFileInfo
->executableLength
) {
1667 executableAddr
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
);
1668 if (!executableAddr
) {
1670 kOSKextLogErrorLevel
|
1671 kOSKextLogGeneralFlag
,
1672 "Can't translate physical address 0x%x of kext executable "
1673 "for device tree entry %s.",
1674 (int)kextFileInfo
->executablePhysAddr
,
1675 deviceTreeName
->getCStringNoCopy());
1679 executable
= OSData::withBytesNoCopy(executableAddr
,
1680 kextFileInfo
->executableLength
);
1683 kOSKextLogErrorLevel
|
1684 kOSKextLogGeneralFlag
,
1685 "Failed to create executable wrapper for device tree entry %s.",
1686 deviceTreeName
->getCStringNoCopy());
1690 /* A kext with an executable needs to retain the whole booterData
1691 * object to keep the executable in memory.
1693 if (!setExecutable(executable
, booterData
)) {
1695 kOSKextLogErrorLevel
|
1696 kOSKextLogGeneralFlag
,
1697 "Failed to set kext executable for device tree entry %s.",
1698 deviceTreeName
->getCStringNoCopy());
1703 result
= registerIdentifier();
1706 OSSafeRelease(parsedXML
);
1707 OSSafeRelease(kextPath
);
1708 OSSafeRelease(errorString
);
1709 OSSafeRelease(executable
);
1714 /*********************************************************************
1715 *********************************************************************/
1717 OSKext::registerIdentifier(void)
1719 bool result
= false;
1720 OSKext
* existingKext
= NULL
; // do not release
1721 bool existingIsLoaded
= false;
1722 bool existingIsPrelinked
= false;
1723 OSKextVersion newVersion
= -1;
1724 OSKextVersion existingVersion
= -1;
1725 char newVersionCString
[kOSKextVersionMaxLength
];
1726 char existingVersionCString
[kOSKextVersionMaxLength
];
1727 OSData
* newUUID
= NULL
; // must release
1728 OSData
* existingUUID
= NULL
; // must release
1730 IORecursiveLockLock(sKextLock
);
1732 /* Get the new kext's version for checks & log messages.
1734 newVersion
= getVersion();
1735 OSKextVersionGetString(newVersion
, newVersionCString
,
1736 kOSKextVersionMaxLength
);
1738 /* If we don't have an existing kext with this identifier,
1739 * just record the new kext and we're done!
1741 existingKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
));
1742 if (!existingKext
) {
1743 sKextsByID
->setObject(bundleID
, this);
1748 /* Get the existing kext's version for checks & log messages.
1750 existingVersion
= existingKext
->getVersion();
1751 OSKextVersionGetString(existingVersion
,
1752 existingVersionCString
, kOSKextVersionMaxLength
);
1754 existingIsLoaded
= existingKext
->isLoaded();
1755 existingIsPrelinked
= existingKext
->isPrelinked();
1757 /* If we have a kext with this identifier that's already loaded/prelinked,
1758 * we can't use the new one, but let's be really thorough and check how
1759 * the two are related for a precise diagnostic log message.
1761 * Note that user space can't find out about nonloaded prelinked kexts,
1762 * so in this case we log a message when new & existing are equivalent
1763 * at the step rather than warning level, because we are always going
1764 * be getting a copy of the kext in the user load request mkext.
1766 if (existingIsLoaded
|| existingIsPrelinked
) {
1767 bool sameVersion
= (newVersion
== existingVersion
);
1768 bool sameExecutable
= true; // assume true unless we have UUIDs
1770 /* Only get the UUID if the existing kext is loaded. Doing so
1771 * might have to uncompress an mkext executable and we shouldn't
1772 * take that hit when neither kext is loaded.
1774 newUUID
= copyUUID();
1775 existingUUID
= existingKext
->copyUUID();
1777 /* I'm entirely too paranoid about checking equivalence of executables,
1778 * but I remember nasty problems with it in the past.
1780 * - If we have UUIDs for both kexts, compare them.
1781 * - If only one kext has a UUID, they're definitely different.
1783 if (newUUID
&& existingUUID
) {
1784 sameExecutable
= newUUID
->isEqualTo(existingUUID
);
1785 } else if (newUUID
|| existingUUID
) {
1786 sameExecutable
= false;
1789 if (!newUUID
&& !existingUUID
) {
1791 /* If there are no UUIDs, we can't really tell that the executables
1792 * are *different* without a lot of work; the loaded kext's
1793 * unrelocated executable is no longer around (and we never had it
1794 * in-kernel for a prelinked kext). We certainly don't want to do
1795 * a whole fake link for the new kext just to compare, either.
1798 OSKextVersionGetString(version
, newVersionCString
,
1799 sizeof(newVersionCString
));
1801 kOSKextLogWarningLevel
|
1802 kOSKextLogKextBookkeepingFlag
,
1803 "Notice - new kext %s, v%s matches %s kext "
1804 "but can't determine if executables are the same (no UUIDs).",
1805 getIdentifierCString(),
1807 (existingIsLoaded
? "loaded" : "prelinked"));
1810 if (sameVersion
&& sameExecutable
) {
1812 (existingIsLoaded
? kOSKextLogWarningLevel
: kOSKextLogStepLevel
) |
1813 kOSKextLogKextBookkeepingFlag
,
1814 "Refusing new kext %s, v%s: a %s copy is already present "
1815 "(same version and executable).",
1816 getIdentifierCString(), newVersionCString
,
1817 (existingIsLoaded
? "loaded" : "prelinked"));
1820 /* This condition is significant so log it under warnings.
1823 kOSKextLogWarningLevel
|
1824 kOSKextLogKextBookkeepingFlag
,
1825 "Refusing new kext %s, v%s: already have %s v%s.",
1826 getIdentifierCString(),
1828 (existingIsLoaded
? "loaded" : "prelinked"),
1829 existingVersionCString
);
1831 /* This condition is significant so log it under warnings.
1834 kOSKextLogWarningLevel
| kOSKextLogKextBookkeepingFlag
,
1835 "Refusing new kext %s, v%s: a %s copy with a different "
1836 "executable UUID is already present.",
1837 getIdentifierCString(), newVersionCString
,
1838 (existingIsLoaded
? "loaded" : "prelinked"));
1842 } /* if (existingIsLoaded || existingIsPrelinked) */
1844 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
1845 * user loads are happening or if we're still in early boot. User agents are
1846 * supposed to resolve dependencies topside and include only the exact
1847 * kexts needed; so we always accept the new kext (in fact we should never
1848 * see an older unloaded copy hanging around).
1850 if (sUserLoadsActive
) {
1851 sKextsByID
->setObject(bundleID
, this);
1855 kOSKextLogStepLevel
|
1856 kOSKextLogKextBookkeepingFlag
,
1857 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
1858 getIdentifierCString(),
1859 existingVersionCString
,
1865 /* During early boot, the kext with the highest version always wins out.
1866 * Prelinked kernels will never hit this, but mkexts and booter-read
1867 * kexts might have duplicates.
1869 if (newVersion
> existingVersion
) {
1870 sKextsByID
->setObject(bundleID
, this);
1874 kOSKextLogStepLevel
|
1875 kOSKextLogKextBookkeepingFlag
,
1876 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
1877 existingVersionCString
,
1878 getIdentifierCString(),
1883 kOSKextLogStepLevel
|
1884 kOSKextLogKextBookkeepingFlag
,
1885 "Kext %s is already registered with a higher/same version (v%s); "
1886 "dropping newly-added (v%s).",
1887 getIdentifierCString(),
1888 existingVersionCString
,
1892 /* result has been set appropriately by now. */
1896 IORecursiveLockUnlock(sKextLock
);
1900 kOSKextLogStepLevel
|
1901 kOSKextLogKextBookkeepingFlag
,
1902 "Kext %s, v%s registered and available for loading.",
1903 getIdentifierCString(), newVersionCString
);
1906 OSSafeRelease(newUUID
);
1907 OSSafeRelease(existingUUID
);
1912 /*********************************************************************
1913 * Does the bare minimum validation to look up a kext.
1914 * All other validation is done on the spot as needed.
1915 **********************************************************************/
1917 OSKext::setInfoDictionaryAndPath(
1918 OSDictionary
* aDictionary
,
1921 bool result
= false;
1922 OSString
* bundleIDString
= NULL
; // do not release
1923 OSString
* versionString
= NULL
; // do not release
1924 OSString
* compatibleVersionString
= NULL
; // do not release
1925 const char * versionCString
= NULL
; // do not free
1926 const char * compatibleVersionCString
= NULL
; // do not free
1927 OSBoolean
* scratchBool
= NULL
; // do not release
1928 OSDictionary
* scratchDict
= NULL
; // do not release
1931 panic("Attempt to set info dictionary on a kext "
1932 "that already has one (%s).",
1933 getIdentifierCString());
1936 if (!aDictionary
|| !OSDynamicCast(OSDictionary
, aDictionary
)) {
1940 infoDict
= aDictionary
;
1943 /* Check right away if the info dictionary has any log flags.
1945 scratchBool
= OSDynamicCast(OSBoolean
,
1946 getPropertyForHostArch(kOSBundleEnableKextLoggingKey
));
1947 if (scratchBool
== kOSBooleanTrue
) {
1948 flags
.loggingEnabled
= 1;
1951 /* The very next thing to get is the bundle identifier. Unlike
1952 * in user space, a kext with no bundle identifier gets axed
1955 bundleIDString
= OSDynamicCast(OSString
,
1956 getPropertyForHostArch(kCFBundleIdentifierKey
));
1957 if (!bundleIDString
) {
1959 kOSKextLogErrorLevel
|
1960 kOSKextLogValidationFlag
,
1961 "CFBundleIdentifier missing/invalid type in kext %s.",
1962 aPath
? aPath
->getCStringNoCopy() : "(unknown)");
1965 bundleID
= OSSymbol::withString(bundleIDString
);
1968 kOSKextLogErrorLevel
|
1969 kOSKextLogValidationFlag
,
1970 "Can't copy bundle identifier as symbol for kext %s.",
1971 bundleIDString
->getCStringNoCopy());
1975 /* Save the path if we got one (it should always be available but it's
1976 * just something nice to have for bookkeeping).
1984 * Minimal validation to initialize. We'll do other validation on the spot.
1986 if (bundleID
->getLength() >= KMOD_MAX_NAME
) {
1988 kOSKextLogErrorLevel
|
1989 kOSKextLogValidationFlag
,
1990 "Kext %s error - CFBundleIdentifier over max length %d.",
1991 getIdentifierCString(), KMOD_MAX_NAME
- 1);
1995 version
= compatibleVersion
= -1;
1997 versionString
= OSDynamicCast(OSString
,
1998 getPropertyForHostArch(kCFBundleVersionKey
));
1999 if (!versionString
) {
2001 kOSKextLogErrorLevel
|
2002 kOSKextLogValidationFlag
,
2003 "Kext %s error - CFBundleVersion missing/invalid type.",
2004 getIdentifierCString());
2007 versionCString
= versionString
->getCStringNoCopy();
2008 version
= OSKextParseVersionString(versionCString
);
2011 kOSKextLogErrorLevel
|
2012 kOSKextLogValidationFlag
,
2013 "Kext %s error - CFBundleVersion bad value '%s'.",
2014 getIdentifierCString(), versionCString
);
2018 compatibleVersion
= -1; // set to illegal value for kexts that don't have
2020 compatibleVersionString
= OSDynamicCast(OSString
,
2021 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
2022 if (compatibleVersionString
) {
2023 compatibleVersionCString
= compatibleVersionString
->getCStringNoCopy();
2024 compatibleVersion
= OSKextParseVersionString(compatibleVersionCString
);
2025 if (compatibleVersion
< 0) {
2027 kOSKextLogErrorLevel
|
2028 kOSKextLogValidationFlag
,
2029 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2030 getIdentifierCString(), compatibleVersionCString
);
2034 if (compatibleVersion
> version
) {
2036 kOSKextLogErrorLevel
|
2037 kOSKextLogValidationFlag
,
2038 "Kext %s error - %s %s > %s %s (must be <=).",
2039 getIdentifierCString(),
2040 kOSBundleCompatibleVersionKey
, compatibleVersionCString
,
2041 kCFBundleVersionKey
, versionCString
);
2046 /* Set flags for later use if the infoDict gets flushed. We only
2047 * check for true values, not false ones(!)
2049 scratchBool
= OSDynamicCast(OSBoolean
,
2050 getPropertyForHostArch(kOSBundleIsInterfaceKey
));
2051 if (scratchBool
== kOSBooleanTrue
) {
2052 flags
.interface
= 1;
2055 scratchBool
= OSDynamicCast(OSBoolean
,
2056 getPropertyForHostArch(kOSKernelResourceKey
));
2057 if (scratchBool
== kOSBooleanTrue
) {
2058 flags
.kernelComponent
= 1;
2059 flags
.interface
= 1; // xxx - hm. the kernel itself isn't an interface...
2062 /* A kernel component has one implicit dependency on the kernel.
2064 flags
.hasAllDependencies
= 1;
2067 /* Make sure common string values in personalities are uniqued to OSSymbols.
2069 scratchDict
= OSDynamicCast(OSDictionary
,
2070 getPropertyForHostArch(kIOKitPersonalitiesKey
));
2072 uniquePersonalityProperties(scratchDict
);
2082 /*********************************************************************
2083 * Not used for prelinked kernel boot as there is no unrelocated
2085 *********************************************************************/
2087 OSKext::setExecutable(
2088 OSData
* anExecutable
,
2089 OSData
* externalData
,
2090 bool externalDataIsMkext
)
2092 bool result
= false;
2093 const char * executableKey
= NULL
; // do not free
2095 if (!anExecutable
) {
2096 infoDict
->removeObject(_kOSKextExecutableKey
);
2097 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
2098 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
2103 if (infoDict
->getObject(_kOSKextExecutableKey
) ||
2104 infoDict
->getObject(_kOSKextMkextExecutableReferenceKey
)) {
2106 panic("Attempt to set an executable on a kext "
2107 "that already has one (%s).",
2108 getIdentifierCString());
2112 if (externalDataIsMkext
) {
2113 executableKey
= _kOSKextMkextExecutableReferenceKey
;
2115 executableKey
= _kOSKextExecutableKey
;
2119 infoDict
->setObject(executableKey
, anExecutable
);
2121 infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
);
2131 /*********************************************************************
2132 *********************************************************************/
2134 uniqueStringPlistProperty(OSDictionary
* dict
, const char * key
)
2136 OSString
* stringValue
= NULL
; // do not release
2137 const OSSymbol
* symbolValue
= NULL
; // must release
2139 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2144 symbolValue
= OSSymbol::withString(stringValue
);
2149 dict
->setObject(key
, symbolValue
);
2152 if (symbolValue
) symbolValue
->release();
2157 /*********************************************************************
2158 *********************************************************************/
2160 uniqueStringPlistProperty(OSDictionary
* dict
, const OSString
* key
)
2162 OSString
* stringValue
= NULL
; // do not release
2163 const OSSymbol
* symbolValue
= NULL
; // must release
2165 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2170 symbolValue
= OSSymbol::withString(stringValue
);
2175 dict
->setObject(key
, symbolValue
);
2178 if (symbolValue
) symbolValue
->release();
2183 /*********************************************************************
2184 * Replace common personality property values with uniqued instances
2185 * to save on wired memory.
2186 *********************************************************************/
2189 OSKext::uniquePersonalityProperties(OSDictionary
* personalityDict
)
2191 /* Properties every personality has.
2193 uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKey
);
2194 uniqueStringPlistProperty(personalityDict
, kIOProviderClassKey
);
2195 uniqueStringPlistProperty(personalityDict
, gIOClassKey
);
2197 /* Other commonly used properties.
2199 uniqueStringPlistProperty(personalityDict
, gIOMatchCategoryKey
);
2200 uniqueStringPlistProperty(personalityDict
, gIOResourceMatchKey
);
2201 uniqueStringPlistProperty(personalityDict
, gIOUserClientClassKey
);
2203 uniqueStringPlistProperty(personalityDict
, "HIDDefaultBehavior");
2204 uniqueStringPlistProperty(personalityDict
, "HIDPointerAccelerationType");
2205 uniqueStringPlistProperty(personalityDict
, "HIDRemoteControlType");
2206 uniqueStringPlistProperty(personalityDict
, "HIDScrollAccelerationType");
2207 uniqueStringPlistProperty(personalityDict
, "IOPersonalityPublisher");
2208 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect");
2209 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect Location");
2210 uniqueStringPlistProperty(personalityDict
, "Vendor");
2211 uniqueStringPlistProperty(personalityDict
, "Vendor Identification");
2212 uniqueStringPlistProperty(personalityDict
, "Vendor Name");
2213 uniqueStringPlistProperty(personalityDict
, "bConfigurationValue");
2214 uniqueStringPlistProperty(personalityDict
, "bInterfaceNumber");
2215 uniqueStringPlistProperty(personalityDict
, "idProduct");
2220 /*********************************************************************
2221 *********************************************************************/
2226 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2229 OSSafeRelease(infoDict
);
2230 OSSafeRelease(bundleID
);
2231 OSSafeRelease(path
);
2232 OSSafeRelease(executableRelPath
);
2233 OSSafeRelease(dependencies
);
2234 OSSafeRelease(linkedExecutable
);
2235 OSSafeRelease(metaClasses
);
2236 OSSafeRelease(interfaceUUID
);
2238 if (isInterface() && kmod_info
) {
2239 kfree(kmod_info
, sizeof(kmod_info_t
));
2247 #pragma mark Mkext files
2249 /*********************************************************************
2250 *********************************************************************/
2252 OSKext::readMkextArchive(OSData
* mkextData
,
2253 uint32_t * checksumPtr
)
2255 OSReturn result
= kOSKextReturnBadData
;
2256 uint32_t mkextLength
= 0;
2257 mkext_header
* mkextHeader
= 0; // do not free
2258 uint32_t mkextVersion
= 0;
2260 /* Note default return of kOSKextReturnBadData above.
2262 mkextLength
= mkextData
->getLength();
2263 if (mkextLength
< sizeof(mkext_basic_header
)) {
2264 OSKextLog(/* kext */ NULL
,
2265 kOSKextLogErrorLevel
|
2266 kOSKextLogArchiveFlag
,
2267 "Mkext archive too small to be valid.");
2271 mkextHeader
= (mkext_header
*)mkextData
->getBytesNoCopy();
2273 if (MKEXT_GET_MAGIC(mkextHeader
) != MKEXT_MAGIC
||
2274 MKEXT_GET_SIGNATURE(mkextHeader
) != MKEXT_SIGN
) {
2275 OSKextLog(/* kext */ NULL
,
2276 kOSKextLogErrorLevel
|
2277 kOSKextLogArchiveFlag
,
2278 "Mkext archive has invalid magic or signature.");
2282 if (MKEXT_GET_LENGTH(mkextHeader
) != mkextLength
) {
2283 OSKextLog(/* kext */ NULL
,
2284 kOSKextLogErrorLevel
|
2285 kOSKextLogArchiveFlag
,
2286 "Mkext archive recorded length doesn't match actual file length.");
2290 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2292 if (mkextVersion
== MKEXT_VERS_2
) {
2293 result
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
);
2294 } else if (mkextVersion
== MKEXT_VERS_1
) {
2295 result
= OSKext::readMkext1Archive(mkextData
, checksumPtr
);
2297 OSKextLog(/* kext */ NULL
,
2298 kOSKextLogErrorLevel
|
2299 kOSKextLogArchiveFlag
,
2300 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
);
2301 result
= kOSKextReturnUnsupported
;
2308 /*********************************************************************
2309 * Assumes magic, signature, version, length have been checked.
2311 * Doesn't do as much bounds-checking as it should, but we're dropping
2312 * mkext1 support from the kernel for SnowLeopard soon.
2314 * Should keep track of all kexts created so far, and if we hit a
2315 * fatal error halfway through, remove those kexts. If we've dropped
2316 * an older version that had already been read, whoops! Might want to
2317 * add a level of buffering?
2318 *********************************************************************/
2321 OSKext::readMkext1Archive(
2323 uint32_t * checksumPtr
)
2325 OSReturn result
= kOSReturnError
;
2326 uint32_t mkextLength
;
2327 mkext1_header
* mkextHeader
= 0; // do not free
2328 void * mkextEnd
= 0; // do not free
2329 uint32_t mkextVersion
;
2330 uint8_t * crc_address
= 0;
2332 uint32_t numKexts
= 0;
2334 OSData
* infoDictDataObject
= NULL
; // must release
2335 OSObject
* parsedXML
= NULL
; // must release
2336 OSDictionary
* infoDict
= NULL
; // do not release
2337 OSString
* errorString
= NULL
; // must release
2338 OSData
* mkextExecutableInfo
= NULL
; // must release
2339 OSKext
* theKext
= NULL
; // must release
2341 mkextLength
= mkextData
->getLength();
2342 mkextHeader
= (mkext1_header
*)mkextData
->getBytesNoCopy();
2343 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2344 mkextVersion
= OSSwapBigToHostInt32(mkextHeader
->version
);
2346 crc_address
= (u_int8_t
*)&mkextHeader
->version
;
2347 checksum
= mkext_adler32(crc_address
,
2348 (uintptr_t)mkextHeader
+
2349 OSSwapBigToHostInt32(mkextHeader
->length
) - (uintptr_t)crc_address
);
2351 if (OSSwapBigToHostInt32(mkextHeader
->adler32
) != checksum
) {
2352 OSKextLog(/* kext */ NULL
,
2353 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2354 "Kext archive has a bad checksum.");
2355 result
= kOSKextReturnBadData
;
2360 *checksumPtr
= checksum
;
2363 /* Check that the CPU type & subtype match that of the running kernel. */
2364 if (OSSwapBigToHostInt32(mkextHeader
->cputype
) != (UInt32
)CPU_TYPE_ANY
) {
2365 if ((UInt32
)_mh_execute_header
.cputype
!=
2366 OSSwapBigToHostInt32(mkextHeader
->cputype
)) {
2368 OSKextLog(/* kext */ NULL
,
2369 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2370 "Kext archive doesn't contain software "
2371 "for this computer's CPU type.");
2372 result
= kOSKextReturnArchNotFound
;
2377 numKexts
= OSSwapBigToHostInt32(mkextHeader
->numkexts
);
2379 for (uint32_t i
= 0; i
< numKexts
; i
++) {
2381 OSSafeReleaseNULL(infoDictDataObject
);
2382 OSSafeReleaseNULL(infoDict
);
2383 OSSafeReleaseNULL(mkextExecutableInfo
);
2384 OSSafeReleaseNULL(errorString
);
2385 OSSafeReleaseNULL(theKext
);
2387 mkext_kext
* kextEntry
= &mkextHeader
->kext
[i
];
2388 mkext_file
* infoDictPtr
= &kextEntry
->plist
;
2389 mkext_file
* executablePtr
= &kextEntry
->module;
2390 if (kextEntry
>= mkextEnd
) {
2391 OSKextLog(/* kext */ NULL
,
2392 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2393 "Mkext file overrun.");
2394 result
= kOSKextReturnBadData
;
2398 /* Note that we're pretty tolerant of errors in individual entries.
2399 * As long as we can keep processing, we do.
2401 infoDictDataObject
= OSKext::extractMkext1Entry(
2402 mkextHeader
, infoDictPtr
);
2403 if (!infoDictDataObject
) {
2404 OSKextLog(/* kext */ NULL
,
2405 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2406 "Can't uncompress info dictionary "
2407 "from mkext archive entry %d.", i
);
2411 parsedXML
= OSUnserializeXML(
2412 (const char *)infoDictDataObject
->getBytesNoCopy(),
2415 infoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
2418 const char * errorCString
= "(unknown error)";
2420 if (errorString
&& errorString
->getCStringNoCopy()) {
2421 errorCString
= errorString
->getCStringNoCopy();
2422 } else if (parsedXML
) {
2423 errorCString
= "not a dictionary";
2425 OSKextLog(/* kext */ NULL
,
2426 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2427 "Error: Can't read XML property list "
2428 "for mkext archive entry %d: %s.", i
, errorCString
);
2432 theKext
= new OSKext
;
2434 OSKextLog(/* kext */ NULL
,
2435 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2436 "Kext allocation failure.");
2441 * Prepare an entry to hold the mkext entry info for the
2442 * compressed binary module, if there is one. If all four fields
2443 * of the module entry are zero, there isn't one.
2445 if ((OSSwapBigToHostInt32(executablePtr
->offset
) ||
2446 OSSwapBigToHostInt32(executablePtr
->compsize
) ||
2447 OSSwapBigToHostInt32(executablePtr
->realsize
) ||
2448 OSSwapBigToHostInt32(executablePtr
->modifiedsecs
))) {
2450 MkextEntryRef entryRef
;
2452 mkextExecutableInfo
= OSData::withCapacity(sizeof(entryRef
));
2453 if (!mkextExecutableInfo
) {
2454 panic("Error: Couldn't allocate data object "
2455 "for mkext archive entry %d.\n", i
);
2458 entryRef
.mkext
= (mkext_basic_header
*)mkextHeader
;
2459 entryRef
.fileinfo
= (uint8_t *)executablePtr
;
2460 if (!mkextExecutableInfo
->appendBytes(&entryRef
,
2461 sizeof(entryRef
))) {
2463 OSKextLog(/* kext */ NULL
,
2464 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2465 "Couldn't record executable info "
2466 "for mkext archive entry %d.", i
);
2467 // we might hit a load error later but oh well
2468 // xxx - should probably remove theKext
2474 /* Init can fail because of a data/runtime error, or because the
2475 * kext is a dup. Either way, we don't care here.
2477 if (!theKext
->initWithMkext1Info(infoDict
, mkextExecutableInfo
,
2480 // theKext is released at the top of the loop or in the finish block
2484 /* If we got even one kext out of the mkext archive,
2485 * we have successfully read the archive, in that we
2486 * have data references into its mapped memory.
2488 result
= kOSReturnSuccess
;
2493 OSSafeRelease(infoDictDataObject
);
2494 OSSafeRelease(parsedXML
);
2495 OSSafeRelease(errorString
);
2496 OSSafeRelease(mkextExecutableInfo
);
2497 OSSafeRelease(theKext
);
2502 /*********************************************************************
2503 *********************************************************************/
2505 OSKext::initWithMkext1Info(
2506 OSDictionary
* anInfoDict
,
2507 OSData
* executableWrapper
,
2510 bool result
= false;
2512 // mkext1 doesn't allow for path (might stuff in info dict)
2513 if (!setInfoDictionaryAndPath(anInfoDict
, /* path */ NULL
)) {
2517 if (!registerIdentifier()) {
2521 if (!setExecutable(executableWrapper
, mkextData
, true)) {
2529 /* If we can't init, remove the kext from the lookup dictionary.
2530 * This is safe to call in init because there's an implicit retain.
2533 OSKext::removeKext(this, /* removePersonalities? */ false);
2539 /*********************************************************************
2540 * xxx - this should take the input data length
2541 *********************************************************************/
2544 OSKext::extractMkext1Entry(
2545 const void * mkextFileBase
,
2548 OSData
* result
= NULL
;
2549 OSData
* uncompressedData
= NULL
; // release on error
2550 const char * errmsg
= NULL
;
2552 mkext_file
* fileinfo
;
2553 uint8_t * uncompressedDataBuffer
= 0; // do not free (panic on alloc. fail)
2554 size_t uncompressed_size
= 0;
2555 kern_return_t kern_result
;
2557 fileinfo
= (mkext_file
*)entry
;
2559 size_t offset
= OSSwapBigToHostInt32(fileinfo
->offset
);
2560 size_t compressed_size
= OSSwapBigToHostInt32(fileinfo
->compsize
);
2561 size_t expected_size
= OSSwapBigToHostInt32(fileinfo
->realsize
);
2563 // Add 1 for '\0' to terminate XML string (for plists)
2564 // (we really should have the archive format include that).
2565 size_t alloc_size
= expected_size
+ 1;
2566 time_t modifiedsecs
= OSSwapBigToHostInt32(fileinfo
->modifiedsecs
);
2568 /* If these four fields are zero there's no file, but it's up to
2569 * the calling context to decide if that's an error.
2571 if (offset
== 0 && compressed_size
== 0 &&
2572 expected_size
== 0 && modifiedsecs
== 0) {
2576 kern_result
= kmem_alloc(kernel_map
,
2577 (vm_offset_t
*)&uncompressedDataBuffer
,
2579 if (kern_result
!= KERN_SUCCESS
) {
2584 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
,
2586 if (uncompressedData
== NULL
) {
2587 /* No need to free uncompressedDataBuffer here, either. */
2591 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
2593 /* Do the decompression if necessary. Note that even if the file isn't
2594 * compressed, we want to make a copy so that we don't have the tie to
2595 * the larger mkext file buffer any more.
2596 * xxx - need to detect decompression overflow too
2598 if (compressed_size
!= 0) {
2599 errmsg
= "OSKext::uncompressMkext - "
2600 "uncompressed file shorter than expected";
2601 uncompressed_size
= decompress_lzss(uncompressedDataBuffer
,
2603 ((uint8_t *)mkextFileBase
) + offset
,
2605 if (uncompressed_size
!= expected_size
) {
2609 memcpy(uncompressedDataBuffer
,
2610 ((uint8_t *)mkextFileBase
) + offset
,
2614 // Add a terminating nul character in case the data is XML.
2615 // (we really should have the archive format include that).
2616 uncompressedDataBuffer
[expected_size
] = '\0';
2618 result
= uncompressedData
;
2623 OSKextLog(/* kext */ NULL
,
2624 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
2627 if (uncompressedData
) {
2628 uncompressedData
->release();
2634 /*********************************************************************
2635 * Assumes magic, signature, version, length have been checked.
2636 * xxx - need to add further bounds checking for each file entry
2638 * Should keep track of all kexts created so far, and if we hit a
2639 * fatal error halfway through, remove those kexts. If we've dropped
2640 * an older version that had already been read, whoops! Might want to
2641 * add a level of buffering?
2642 *********************************************************************/
2645 OSKext::readMkext2Archive(
2647 OSDictionary
** mkextPlistOut
,
2648 uint32_t * checksumPtr
)
2650 OSReturn result
= kOSReturnError
;
2651 uint32_t mkextLength
;
2652 mkext2_header
* mkextHeader
= NULL
; // do not free
2653 void * mkextEnd
= NULL
; // do not free
2654 uint32_t mkextVersion
;
2655 uint8_t * crc_address
= NULL
;
2657 uint32_t mkextPlistOffset
;
2658 uint32_t mkextPlistCompressedSize
;
2659 char * mkextPlistEnd
= NULL
; // do not free
2660 uint32_t mkextPlistFullSize
;
2661 OSString
* errorString
= NULL
; // must release
2662 OSData
* mkextPlistUncompressedData
= NULL
; // must release
2663 const char * mkextPlistDataBuffer
= NULL
; // do not free
2664 OSObject
* parsedXML
= NULL
; // must release
2665 OSDictionary
* mkextPlist
= NULL
; // do not release
2666 OSArray
* mkextInfoDictArray
= NULL
; // do not release
2669 mkextLength
= mkextData
->getLength();
2670 mkextHeader
= (mkext2_header
*)mkextData
->getBytesNoCopy();
2671 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2672 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2674 crc_address
= (u_int8_t
*)&mkextHeader
->version
;
2675 checksum
= mkext_adler32(crc_address
,
2676 (uintptr_t)mkextHeader
+
2677 MKEXT_GET_LENGTH(mkextHeader
) - (uintptr_t)crc_address
);
2679 if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) {
2680 OSKextLog(/* kext */ NULL
,
2681 kOSKextLogErrorLevel
|
2682 kOSKextLogArchiveFlag
,
2683 "Mkext archive has bad checksum.");
2684 result
= kOSKextReturnBadData
;
2689 *checksumPtr
= checksum
;
2692 /* Check that the CPU type & subtype match that of the running kernel. */
2693 if (MKEXT_GET_CPUTYPE(mkextHeader
) == (UInt32
)CPU_TYPE_ANY
) {
2694 OSKextLog(/* kext */ NULL
,
2695 kOSKextLogErrorLevel
|
2696 kOSKextLogArchiveFlag
,
2697 "Mkext archive must have a specific CPU type.");
2698 result
= kOSKextReturnBadData
;
2701 if ((UInt32
)_mh_execute_header
.cputype
!=
2702 MKEXT_GET_CPUTYPE(mkextHeader
)) {
2704 OSKextLog(/* kext */ NULL
,
2705 kOSKextLogErrorLevel
|
2706 kOSKextLogArchiveFlag
,
2707 "Mkext archive does not match the running kernel's CPU type.");
2708 result
= kOSKextReturnArchNotFound
;
2713 mkextPlistOffset
= MKEXT2_GET_PLIST(mkextHeader
);
2714 mkextPlistCompressedSize
= MKEXT2_GET_PLIST_COMPSIZE(mkextHeader
);
2715 mkextPlistEnd
= (char *)mkextHeader
+ mkextPlistOffset
+
2716 mkextPlistCompressedSize
;
2717 if (mkextPlistEnd
> mkextEnd
) {
2718 OSKextLog(/* kext */ NULL
,
2719 kOSKextLogErrorLevel
|
2720 kOSKextLogArchiveFlag
,
2721 "Mkext archive file overrun.");
2722 result
= kOSKextReturnBadData
;
2725 mkextPlistFullSize
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
);
2726 if (mkextPlistCompressedSize
) {
2727 mkextPlistUncompressedData
= sKernelKext
->extractMkext2FileData(
2728 (UInt8
*)mkextHeader
+ mkextPlistOffset
,
2730 mkextPlistCompressedSize
, mkextPlistFullSize
);
2731 if (!mkextPlistUncompressedData
) {
2734 mkextPlistDataBuffer
= (const char *)
2735 mkextPlistUncompressedData
->getBytesNoCopy();
2737 mkextPlistDataBuffer
= (const char *)mkextHeader
+ mkextPlistOffset
;
2740 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2742 parsedXML
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
);
2744 mkextPlist
= OSDynamicCast(OSDictionary
, parsedXML
);
2747 const char * errorCString
= "(unknown error)";
2749 if (errorString
&& errorString
->getCStringNoCopy()) {
2750 errorCString
= errorString
->getCStringNoCopy();
2751 } else if (parsedXML
) {
2752 errorCString
= "not a dictionary";
2754 OSKextLog(/* kext */ NULL
,
2755 kOSKextLogErrorLevel
|
2756 kOSKextLogArchiveFlag
,
2757 "Error unserializing mkext plist: %s.", errorCString
);
2761 /* If the caller needs the plist, hand it back and retain it.
2762 * (This function releases it at the end.)
2764 if (mkextPlistOut
) {
2765 *mkextPlistOut
= mkextPlist
;
2766 (*mkextPlistOut
)->retain();
2769 mkextInfoDictArray
= OSDynamicCast(OSArray
,
2770 mkextPlist
->getObject(kMKEXTInfoDictionariesKey
));
2771 if (!mkextInfoDictArray
) {
2772 OSKextLog(/* kext */ NULL
,
2773 kOSKextLogErrorLevel
|
2774 kOSKextLogArchiveFlag
,
2775 "Mkext archive contains no kext info dictionaries.");
2779 count
= mkextInfoDictArray
->getCount();
2780 for (i
= 0; i
< count
; i
++) {
2781 OSDictionary
* infoDict
;
2784 infoDict
= OSDynamicCast(OSDictionary
,
2785 mkextInfoDictArray
->getObject(i
));
2787 /* Create the kext for the entry, then release it, because the
2788 * kext system keeps them around until explicitly removed.
2789 * Any creation/registration failures are already logged for us.
2791 OSKext
* newKext
= OSKext::withMkext2Info(infoDict
, mkextData
);
2792 OSSafeRelease(newKext
);
2795 /* Even if we didn't keep any kexts from the mkext, we may have a load
2796 * request to process, so we are successful (no errors occurred).
2798 result
= kOSReturnSuccess
;
2802 OSSafeRelease(parsedXML
);
2803 OSSafeRelease(mkextPlistUncompressedData
);
2804 OSSafeRelease(errorString
);
2809 /*********************************************************************
2810 *********************************************************************/
2813 OSKext::withMkext2Info(
2814 OSDictionary
* anInfoDict
,
2817 OSKext
* newKext
= new OSKext
;
2819 if (newKext
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) {
2827 /*********************************************************************
2828 *********************************************************************/
2830 OSKext::initWithMkext2Info(
2831 OSDictionary
* anInfoDict
,
2834 bool result
= false;
2835 OSString
* kextPath
= NULL
; // do not release
2836 OSNumber
* executableOffsetNum
= NULL
; // do not release
2837 OSCollectionIterator
* iterator
= NULL
; // must release
2838 OSData
* executable
= NULL
; // must release
2840 if (!super::init()) {
2844 /* Get the path. Don't look for an arch-specific path property.
2846 kextPath
= OSDynamicCast(OSString
,
2847 anInfoDict
->getObject(kMKEXTBundlePathKey
));
2849 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
2853 /* If we have a path to the executable, save it.
2855 executableRelPath
= OSDynamicCast(OSString
,
2856 anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
));
2857 if (executableRelPath
) {
2858 executableRelPath
->retain();
2861 /* Don't need the paths to be in the info dictionary any more.
2863 anInfoDict
->removeObject(kMKEXTBundlePathKey
);
2864 anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
);
2866 executableOffsetNum
= OSDynamicCast(OSNumber
,
2867 infoDict
->getObject(kMKEXTExecutableKey
));
2868 if (executableOffsetNum
) {
2869 executable
= createMkext2FileEntry(mkextData
,
2870 executableOffsetNum
, "executable");
2871 infoDict
->removeObject(kMKEXTExecutableKey
);
2875 if (!setExecutable(executable
, mkextData
, true)) {
2880 result
= registerIdentifier();
2884 OSSafeRelease(executable
);
2885 OSSafeRelease(iterator
);
2889 /*********************************************************************
2890 *********************************************************************/
2892 OSKext::createMkext2FileEntry(
2894 OSNumber
* offsetNum
,
2897 OSData
* result
= NULL
;
2898 MkextEntryRef entryRef
;
2899 uint8_t * mkextBuffer
= (uint8_t *)mkextData
->getBytesNoCopy();
2900 uint32_t entryOffset
= offsetNum
->unsigned32BitValue();
2902 result
= OSData::withCapacity(sizeof(entryRef
));
2907 entryRef
.mkext
= (mkext_basic_header
*)mkextBuffer
;
2908 entryRef
.fileinfo
= mkextBuffer
+ entryOffset
;
2909 if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) {
2910 OSSafeReleaseNULL(result
);
2917 kOSKextLogErrorLevel
|
2918 kOSKextLogArchiveFlag
,
2919 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2920 name
, getIdentifierCString());
2925 /*********************************************************************
2926 *********************************************************************/
2928 static void * z_alloc(void *, u_int items
, u_int size
);
2929 static void z_free(void *, void *ptr
);
2931 typedef struct z_mem
{
2932 uint32_t alloc_size
;
2937 * Space allocation and freeing routines for use by zlib routines.
2940 z_alloc(void * notused __unused
, u_int num_items
, u_int size
)
2942 void * result
= NULL
;
2943 z_mem
* zmem
= NULL
;
2944 uint32_t total
= num_items
* size
;
2945 uint32_t allocSize
= total
+ sizeof(zmem
);
2947 zmem
= (z_mem
*)kalloc(allocSize
);
2951 zmem
->alloc_size
= allocSize
;
2952 result
= (void *)&(zmem
->data
);
2958 z_free(void * notused __unused
, void * ptr
)
2960 uint32_t * skipper
= (uint32_t *)ptr
- 1;
2961 z_mem
* zmem
= (z_mem
*)skipper
;
2962 kfree((void *)zmem
, zmem
->alloc_size
);
2968 OSKext::extractMkext2FileData(
2971 uint32_t compressedSize
,
2974 OSData
* result
= NULL
;
2976 OSData
* uncompressedData
= NULL
; // release on error
2978 uint8_t * uncompressedDataBuffer
= 0; // do not free
2979 unsigned long uncompressedSize
;
2981 bool zstream_inited
= false;
2984 /* If the file isn't compressed, we want to make a copy
2985 * so that we don't have the tie to the larger mkext file buffer any more.
2987 if (!compressedSize
) {
2988 uncompressedData
= OSData::withBytes(data
, fullSize
);
2989 // xxx - no check for failure?
2990 result
= uncompressedData
;
2994 if (KERN_SUCCESS
!= kmem_alloc(kernel_map
,
2995 (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
)) {
2997 /* How's this for cheesy? The kernel is only asked to extract
2998 * kext plists so we tailor the log messages.
3002 kOSKextLogErrorLevel
|
3003 kOSKextLogArchiveFlag
,
3004 "Allocation failure extracting %s from mkext.", name
);
3007 kOSKextLogErrorLevel
|
3008 kOSKextLogArchiveFlag
,
3009 "Allocation failure extracting %s from mkext for kext %s.",
3010 name
, getIdentifierCString());
3015 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
);
3016 if (!uncompressedData
) {
3019 kOSKextLogErrorLevel
|
3020 kOSKextLogArchiveFlag
,
3021 "Allocation failure extracting %s from mkext.", name
);
3024 kOSKextLogErrorLevel
|
3025 kOSKextLogArchiveFlag
,
3026 "Allocation failure extracting %s from mkext for kext %s.",
3027 name
, getIdentifierCString());
3031 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
3035 kOSKextLogDetailLevel
|
3036 kOSKextLogArchiveFlag
,
3037 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3038 name
, compressedSize
, fullSize
);
3041 kOSKextLogDetailLevel
|
3042 kOSKextLogArchiveFlag
,
3043 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3044 getIdentifierCString(), name
, compressedSize
, fullSize
);
3047 bzero(&zstream
, sizeof(zstream
));
3048 zstream
.next_in
= (UInt8
*)data
;
3049 zstream
.avail_in
= compressedSize
;
3051 zstream
.next_out
= uncompressedDataBuffer
;
3052 zstream
.avail_out
= fullSize
;
3054 zstream
.zalloc
= z_alloc
;
3055 zstream
.zfree
= z_free
;
3057 zlib_result
= inflateInit(&zstream
);
3058 if (Z_OK
!= zlib_result
) {
3061 kOSKextLogErrorLevel
|
3062 kOSKextLogArchiveFlag
,
3063 "Mkext error; zlib inflateInit failed (%d) for %s.",
3067 kOSKextLogErrorLevel
|
3068 kOSKextLogArchiveFlag
,
3069 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3070 getIdentifierCString(), zlib_result
, name
);
3074 zstream_inited
= true;
3077 zlib_result
= inflate(&zstream
, Z_FINISH
);
3079 if (zlib_result
== Z_STREAM_END
|| zlib_result
== Z_OK
) {
3080 uncompressedSize
= zstream
.total_out
;
3084 kOSKextLogErrorLevel
|
3085 kOSKextLogArchiveFlag
,
3086 "Mkext error; zlib inflate failed (%d) for %s.",
3090 kOSKextLogErrorLevel
|
3091 kOSKextLogArchiveFlag
,
3092 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3093 getIdentifierCString(), zlib_result
, name
);
3097 kOSKextLogErrorLevel
|
3098 kOSKextLogArchiveFlag
,
3099 "zlib error: %s.", zstream
.msg
);
3104 if (uncompressedSize
!= fullSize
) {
3107 kOSKextLogErrorLevel
|
3108 kOSKextLogArchiveFlag
,
3109 "Mkext error; zlib inflate discrepancy for %s, "
3110 "uncompressed size != original size.", name
);
3113 kOSKextLogErrorLevel
|
3114 kOSKextLogArchiveFlag
,
3115 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3116 "uncompressed size != original size.",
3117 getIdentifierCString(), name
);
3122 result
= uncompressedData
;
3125 /* Don't bother checking return, nothing we can do on fail.
3127 if (zstream_inited
) inflateEnd(&zstream
);
3130 OSSafeRelease(uncompressedData
);
3136 /*********************************************************************
3137 *********************************************************************/
3140 OSKext::loadFromMkext(
3141 OSKextLogSpec clientLogFilter
,
3143 uint32_t mkextBufferLength
,
3145 uint32_t * logInfoLengthOut
)
3147 OSReturn result
= kOSReturnError
;
3148 OSReturn tempResult
= kOSReturnError
;
3150 OSData
* mkextData
= NULL
; // must release
3151 OSDictionary
* mkextPlist
= NULL
; // must release
3153 OSArray
* logInfoArray
= NULL
; // must release
3154 OSSerialize
* serializer
= NULL
; // must release
3156 OSString
* predicate
= NULL
; // do not release
3157 OSDictionary
* requestArgs
= NULL
; // do not release
3159 OSString
* kextIdentifier
= NULL
; // do not release
3160 OSNumber
* startKextExcludeNum
= NULL
; // do not release
3161 OSNumber
* startMatchingExcludeNum
= NULL
; // do not release
3162 OSBoolean
* delayAutounloadBool
= NULL
; // do not release
3163 OSArray
* personalityNames
= NULL
; // do not release
3165 /* Default values for these two options: regular autounload behavior,
3166 * load all kexts, send no personalities.
3168 Boolean delayAutounload
= false;
3169 OSKextExcludeLevel startKextExcludeLevel
= kOSKextExcludeNone
;
3170 OSKextExcludeLevel startMatchingExcludeLevel
= kOSKextExcludeAll
;
3172 IORecursiveLockLock(sKextLock
);
3176 *logInfoLengthOut
= 0;
3179 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
3181 OSKextLog(/* kext */ NULL
,
3182 kOSKextLogDebugLevel
|
3184 "Received kext load request from user space.");
3186 /* Regardless of processing, the fact that we have gotten here means some
3187 * user-space program is up and talking to us, so we'll switch our kext
3188 * registration to reflect that.
3190 if (!sUserLoadsActive
) {
3191 OSKextLog(/* kext */ NULL
,
3192 kOSKextLogProgressLevel
|
3193 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
3194 "Switching to late startup (user-space) kext loading policy.");
3196 sUserLoadsActive
= true;
3199 if (!sLoadEnabled
) {
3200 OSKextLog(/* kext */ NULL
,
3201 kOSKextLogErrorLevel
|
3203 "Kext loading is disabled.");
3204 result
= kOSKextReturnDisabled
;
3208 /* Note that we do not set a dealloc function on this OSData
3209 * object! No references to it can remain after the loadFromMkext()
3210 * call since we are in a MIG function, and will vm_deallocate()
3213 mkextData
= OSData::withBytesNoCopy(mkextBuffer
,
3216 OSKextLog(/* kext */ NULL
,
3217 kOSKextLogErrorLevel
|
3218 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3219 "Failed to create wrapper for kext load request.");
3220 result
= kOSKextReturnNoMemory
;
3224 result
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
);
3225 if (result
!= kOSReturnSuccess
) {
3226 OSKextLog(/* kext */ NULL
,
3227 kOSKextLogErrorLevel
|
3229 "Failed to read kext load request.");
3233 predicate
= _OSKextGetRequestPredicate(mkextPlist
);
3234 if (!predicate
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) {
3235 OSKextLog(/* kext */ NULL
,
3236 kOSKextLogErrorLevel
|
3238 "Received kext load request with no predicate; skipping.");
3239 result
= kOSKextReturnInvalidArgument
;
3243 requestArgs
= OSDynamicCast(OSDictionary
,
3244 mkextPlist
->getObject(kKextRequestArgumentsKey
));
3245 if (!requestArgs
|| !requestArgs
->getCount()) {
3246 OSKextLog(/* kext */ NULL
,
3247 kOSKextLogErrorLevel
|
3249 "Received kext load request with no arguments.");
3250 result
= kOSKextReturnInvalidArgument
;
3254 kextIdentifier
= OSDynamicCast(OSString
,
3255 requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
));
3256 if (!kextIdentifier
) {
3257 OSKextLog(/* kext */ NULL
,
3258 kOSKextLogErrorLevel
|
3260 "Received kext load request with no kext identifier.");
3261 result
= kOSKextReturnInvalidArgument
;
3265 startKextExcludeNum
= OSDynamicCast(OSNumber
,
3266 requestArgs
->getObject(kKextRequestArgumentStartExcludeKey
));
3267 startMatchingExcludeNum
= OSDynamicCast(OSNumber
,
3268 requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
));
3269 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
3270 requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
));
3271 personalityNames
= OSDynamicCast(OSArray
,
3272 requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
));
3274 if (delayAutounloadBool
) {
3275 delayAutounload
= delayAutounloadBool
->getValue();
3277 if (startKextExcludeNum
) {
3278 startKextExcludeLevel
= startKextExcludeNum
->unsigned8BitValue();
3280 if (startMatchingExcludeNum
) {
3281 startMatchingExcludeLevel
= startMatchingExcludeNum
->unsigned8BitValue();
3284 OSKextLog(/* kext */ NULL
,
3285 kOSKextLogProgressLevel
|
3287 "Received request from user space to load kext %s.",
3288 kextIdentifier
->getCStringNoCopy());
3290 /* Load the kext, with no deferral, since this is a load from outside
3292 * xxx - Would like a better way to handle the default values for the
3293 * xxx - start/match opt args.
3295 result
= OSKext::loadKextWithIdentifier(
3297 /* allowDefer */ false,
3299 startKextExcludeLevel
,
3300 startMatchingExcludeLevel
,
3302 if (result
!= kOSReturnSuccess
) {
3305 /* If the load came down from kextd, it will shortly inform IOCatalogue
3306 * for matching via a separate IOKit calldown.
3311 /* Gather up the collected log messages for user space. Any
3312 * error messages past this call will not make it up as log messages
3313 * but will be in the system log.
3315 logInfoArray
= OSKext::clearUserSpaceLogFilter();
3317 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
3318 tempResult
= OSKext::serializeLogInfo(logInfoArray
,
3319 logInfoOut
, logInfoLengthOut
);
3320 if (tempResult
!= kOSReturnSuccess
) {
3321 result
= tempResult
;
3325 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3327 /* Note: mkextDataObject will have been retained by every kext w/an
3328 * executable in it. That should all have been flushed out at the
3329 * and of the load operation, but you never know....
3331 if (mkextData
&& mkextData
->getRetainCount() > 1) {
3332 OSKextLog(/* kext */ NULL
,
3333 kOSKextLogErrorLevel
|
3334 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3335 "Kext load request buffer from user space still retained by a kext; "
3336 "probable memory leak.");
3339 IORecursiveLockUnlock(sKextLock
);
3341 OSSafeRelease(mkextData
);
3342 OSSafeRelease(mkextPlist
);
3343 OSSafeRelease(serializer
);
3344 OSSafeRelease(logInfoArray
);
3349 /*********************************************************************
3350 *********************************************************************/
3353 OSKext::serializeLogInfo(
3354 OSArray
* logInfoArray
,
3356 uint32_t * logInfoLengthOut
)
3358 OSReturn result
= kOSReturnError
;
3359 char * buffer
= NULL
;
3360 kern_return_t kmem_result
= KERN_FAILURE
;
3361 OSSerialize
* serializer
= NULL
; // must release; reused
3362 char * logInfo
= NULL
; // returned by reference
3363 uint32_t logInfoLength
= 0;
3365 if (!logInfoArray
|| !logInfoOut
|| !logInfoLengthOut
) {
3366 OSKextLog(/* kext */ NULL
,
3367 kOSKextLogErrorLevel
|
3369 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3370 /* Bad programmer. */
3371 result
= kOSKextReturnInvalidArgument
;
3375 serializer
= OSSerialize::withCapacity(0);
3377 OSKextLog(/* kext */ NULL
,
3378 kOSKextLogErrorLevel
|
3380 "Failed to create serializer on log info for request from user space.");
3381 /* Incidental error; we're going to (try to) allow the request
3382 * itself to succeed. */
3385 if (!logInfoArray
->serialize(serializer
)) {
3386 OSKextLog(/* kext */ NULL
,
3387 kOSKextLogErrorLevel
|
3389 "Failed to serialize log info for request from user space.");
3390 /* Incidental error; we're going to (try to) allow the request
3391 * itself to succeed. */
3393 logInfo
= serializer
->text();
3394 logInfoLength
= serializer
->getLength();
3396 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
, logInfoLength
);
3397 if (kmem_result
!= KERN_SUCCESS
) {
3398 OSKextLog(/* kext */ NULL
,
3399 kOSKextLogErrorLevel
|
3401 "Failed to copy log info for request from user space.");
3402 /* Incidental error; we're going to (try to) allow the request
3405 memcpy(buffer
, logInfo
, logInfoLength
);
3406 *logInfoOut
= buffer
;
3407 *logInfoLengthOut
= logInfoLength
;
3411 result
= kOSReturnSuccess
;
3413 OSSafeRelease(serializer
);
3418 #pragma mark Instance Management Methods
3420 /*********************************************************************
3421 *********************************************************************/
3423 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
)
3425 OSKext
* foundKext
= NULL
;
3427 IORecursiveLockLock(sKextLock
);
3428 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3430 foundKext
->retain();
3432 IORecursiveLockUnlock(sKextLock
);
3437 /*********************************************************************
3438 *********************************************************************/
3440 OSKext::lookupKextWithIdentifier(OSString
* kextIdentifier
)
3442 return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy());
3445 /*********************************************************************
3446 *********************************************************************/
3448 OSKext::lookupKextWithLoadTag(uint32_t aTag
)
3450 OSKext
* foundKext
= NULL
; // returned
3453 IORecursiveLockLock(sKextLock
);
3455 count
= sLoadedKexts
->getCount();
3456 for (i
= 0; i
< count
; i
++) {
3457 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3458 if (thisKext
->getLoadTag() == aTag
) {
3459 foundKext
= thisKext
;
3460 foundKext
->retain();
3466 IORecursiveLockUnlock(sKextLock
);
3471 /*********************************************************************
3472 *********************************************************************/
3474 OSKext::lookupKextWithAddress(vm_address_t address
)
3476 OSKext
* foundKext
= NULL
; // returned
3479 IORecursiveLockLock(sKextLock
);
3481 count
= sLoadedKexts
->getCount();
3482 for (i
= 0; i
< count
; i
++) {
3483 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3484 if (thisKext
->linkedExecutable
) {
3485 vm_address_t kext_start
=
3486 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy();
3487 vm_address_t kext_end
= kext_start
+
3488 thisKext
->linkedExecutable
->getLength();
3490 if ((kext_start
<= address
) && (address
< kext_end
)) {
3491 foundKext
= thisKext
;
3492 foundKext
->retain();
3499 IORecursiveLockUnlock(sKextLock
);
3504 /*********************************************************************
3505 *********************************************************************/
3507 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
)
3509 bool result
= false;
3510 OSKext
* foundKext
= NULL
; // returned
3512 IORecursiveLockLock(sKextLock
);
3514 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3515 if (foundKext
&& foundKext
->isLoaded()) {
3519 IORecursiveLockUnlock(sKextLock
);
3524 /*********************************************************************
3525 * xxx - should spawn a separate thread so a kext can safely have
3526 * xxx - itself unloaded.
3527 *********************************************************************/
3532 bool terminateServicesAndRemovePersonalitiesFlag
)
3534 OSReturn result
= kOSKextReturnInUse
;
3535 OSKext
* checkKext
= NULL
; // do not release
3537 IORecursiveLockLock(sKextLock
);
3539 /* If the kext has no identifier, it failed to init
3540 * so isn't in sKextsByID and it isn't loaded.
3542 if (!aKext
->getIdentifier()) {
3543 result
= kOSReturnSuccess
;
3547 checkKext
= OSDynamicCast(OSKext
,
3548 sKextsByID
->getObject(aKext
->getIdentifier()));
3549 if (checkKext
!= aKext
) {
3550 result
= kOSKextReturnNotFound
;
3554 if (aKext
->isLoaded()) {
3556 /* If we are terminating, send the request to the IOCatalogue
3557 * (which will actually call us right back but that's ok we have
3558 * a recursive lock don't you know) but do not ask the IOCatalogue
3559 * to call back with an unload, we'll do that right here.
3561 if (terminateServicesAndRemovePersonalitiesFlag
) {
3562 result
= gIOCatalogue
->terminateDriversForModule(
3563 aKext
->getIdentifierCString(), /* unload */ false);
3564 if (result
!= kOSReturnSuccess
) {
3566 kOSKextLogErrorLevel
|
3567 kOSKextLogKextBookkeepingFlag
,
3568 "Can't remove kext %s; services failed to terminate - 0x%x.",
3569 aKext
->getIdentifierCString(), result
);
3574 result
= aKext
->unload();
3575 if (result
!= kOSReturnSuccess
) {
3580 /* Remove personalities as requested. This is a bit redundant for a loaded
3581 * kext as IOCatalogue::terminateDriversForModule() removes driver
3582 * personalities, but it doesn't restart matching, which we always want
3583 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3586 if (terminateServicesAndRemovePersonalitiesFlag
) {
3587 aKext
->removePersonalitiesFromCatalog();
3591 kOSKextLogProgressLevel
|
3592 kOSKextLogKextBookkeepingFlag
,
3593 "Removing kext %s.",
3594 aKext
->getIdentifierCString());
3596 sKextsByID
->removeObject(aKext
->getIdentifier());
3597 result
= kOSReturnSuccess
;
3600 IORecursiveLockUnlock(sKextLock
);
3604 /*********************************************************************
3605 *********************************************************************/
3608 OSKext::removeKextWithIdentifier(
3609 const char * kextIdentifier
,
3610 bool terminateServicesAndRemovePersonalitiesFlag
)
3612 OSReturn result
= kOSReturnError
;
3614 IORecursiveLockLock(sKextLock
);
3616 OSKext
* aKext
= OSDynamicCast(OSKext
,
3617 sKextsByID
->getObject(kextIdentifier
));
3619 result
= kOSKextReturnNotFound
;
3620 OSKextLog(/* kext */ NULL
,
3621 kOSKextLogErrorLevel
|
3622 kOSKextLogKextBookkeepingFlag
,
3623 "Can't remove kext %s - not found.",
3628 result
= OSKext::removeKext(aKext
,
3629 terminateServicesAndRemovePersonalitiesFlag
);
3632 IORecursiveLockUnlock(sKextLock
);
3637 /*********************************************************************
3638 *********************************************************************/
3641 OSKext::removeKextWithLoadTag(
3642 OSKextLoadTag loadTag
,
3643 bool terminateServicesAndRemovePersonalitiesFlag
)
3645 OSReturn result
= kOSReturnError
;
3646 OSKext
* foundKext
= NULL
;
3649 IORecursiveLockLock(sKextLock
);
3651 count
= sLoadedKexts
->getCount();
3652 for (i
= 0; i
< count
; i
++) {
3653 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3654 if (thisKext
->loadTag
== loadTag
) {
3655 foundKext
= thisKext
;
3661 result
= kOSKextReturnNotFound
;
3662 OSKextLog(/* kext */ NULL
,
3663 kOSKextLogErrorLevel
|
3664 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
3665 "Can't remove kext with load tag %d - not found.",
3670 result
= OSKext::removeKext(foundKext
,
3671 terminateServicesAndRemovePersonalitiesFlag
);
3674 IORecursiveLockUnlock(sKextLock
);
3679 /*********************************************************************
3680 *********************************************************************/
3682 OSKext::copyKexts(void)
3684 OSDictionary
* result
;
3686 IORecursiveLockLock(sKextLock
);
3687 result
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection());
3688 IORecursiveLockUnlock(sKextLock
);
3694 #pragma mark Accessors
3696 /*********************************************************************
3697 *********************************************************************/
3699 OSKext::getIdentifier(void)
3704 /*********************************************************************
3705 * A kext must have a bundle identifier to even survive initialization;
3706 * this is guaranteed to exist past then.
3707 *********************************************************************/
3709 OSKext::getIdentifierCString(void)
3711 return bundleID
->getCStringNoCopy();
3714 /*********************************************************************
3715 *********************************************************************/
3717 OSKext::getVersion(void)
3722 /*********************************************************************
3723 *********************************************************************/
3725 OSKext::getCompatibleVersion(void)
3727 return compatibleVersion
;
3730 /*********************************************************************
3731 *********************************************************************/
3733 OSKext::isLibrary(void)
3735 return (getCompatibleVersion() > 0);
3738 /*********************************************************************
3739 *********************************************************************/
3741 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
)
3743 if ((compatibleVersion
> -1 && version
> -1) &&
3744 (compatibleVersion
<= version
&& aVersion
<= version
)) {
3750 /*********************************************************************
3751 *********************************************************************/
3753 OSKext::declaresExecutable(void)
3755 return (getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
);
3758 /*********************************************************************
3759 *********************************************************************/
3761 OSKext::getExecutable(void)
3763 OSData
* result
= NULL
;
3764 OSData
* extractedExecutable
= NULL
; // must release
3765 OSData
* mkextExecutableRef
= NULL
; // do not release
3767 result
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
));
3772 mkextExecutableRef
= OSDynamicCast(OSData
,
3773 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
));
3775 if (mkextExecutableRef
) {
3777 MkextEntryRef
* mkextEntryRef
= (MkextEntryRef
*)
3778 mkextExecutableRef
->getBytesNoCopy();
3779 uint32_t mkextVersion
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
);
3780 if (mkextVersion
== MKEXT_VERS_2
) {
3781 mkext2_file_entry
* fileinfo
=
3782 (mkext2_file_entry
*)mkextEntryRef
->fileinfo
;
3783 uint32_t compressedSize
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
);
3784 uint32_t fullSize
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
);
3785 extractedExecutable
= extractMkext2FileData(
3786 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable",
3787 compressedSize
, fullSize
);
3788 } else if (mkextVersion
== MKEXT_VERS_1
) {
3789 extractedExecutable
= extractMkext1Entry(
3790 mkextEntryRef
->mkext
, mkextEntryRef
->fileinfo
);
3792 OSKextLog(this, kOSKextLogErrorLevel
|
3793 kOSKextLogArchiveFlag
,
3794 "Kext %s - unknown mkext version 0x%x for executable.",
3795 getIdentifierCString(), mkextVersion
);
3798 /* Regardless of success, remove the mkext executable,
3799 * and drop one reference on the mkext. (setExecutable() does not
3800 * replace, it removes, or panics if asked to replace.)
3802 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
3803 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
3805 if (extractedExecutable
&& extractedExecutable
->getLength()) {
3806 if (!setExecutable(extractedExecutable
)) {
3809 result
= extractedExecutable
;
3817 OSSafeRelease(extractedExecutable
);
3822 /*********************************************************************
3823 *********************************************************************/
3825 OSKext::isInterface(void)
3827 return flags
.interface
;
3830 /*********************************************************************
3831 *********************************************************************/
3833 OSKext::isKernel(void)
3835 return (this == sKernelKext
);
3838 /*********************************************************************
3839 *********************************************************************/
3841 OSKext::isKernelComponent(void)
3843 return flags
.kernelComponent
? true : false;
3846 /*********************************************************************
3847 *********************************************************************/
3849 OSKext::isExecutable(void)
3851 return (!isKernel() && !isInterface() && declaresExecutable());
3854 /*********************************************************************
3855 * We might want to check this recursively for all dependencies,
3856 * since a subtree of dependencies could get loaded before we hit
3857 * a dependency that isn't safe-boot-loadable.
3859 * xxx - Might want to return false if OSBundleEnableKextLogging or
3860 * OSBundleDebugLevel
3861 * or IOKitDebug is nonzero too (we used to do that, but I don't see
3862 * the point except it's usually development drivers, which might
3863 * cause panics on startup, that have those properties). Heh; could
3864 * use a "kx" boot-arg!
3865 *********************************************************************/
3867 OSKext::isLoadableInSafeBoot(void)
3869 bool result
= false;
3870 OSString
* required
= NULL
; // do not release
3877 required
= OSDynamicCast(OSString
,
3878 getPropertyForHostArch(kOSBundleRequiredKey
));
3882 if (required
->isEqualTo(kOSBundleRequiredRoot
) ||
3883 required
->isEqualTo(kOSBundleRequiredLocalRoot
) ||
3884 required
->isEqualTo(kOSBundleRequiredNetworkRoot
) ||
3885 required
->isEqualTo(kOSBundleRequiredSafeBoot
) ||
3886 required
->isEqualTo(kOSBundleRequiredConsole
)) {
3895 /*********************************************************************
3896 *********************************************************************/
3898 OSKext::isPrelinked(void)
3900 return flags
.prelinked
? true : false;
3903 /*********************************************************************
3904 *********************************************************************/
3905 bool OSKext::isLoaded(void)
3907 return flags
.loaded
? true : false;
3910 /*********************************************************************
3911 *********************************************************************/
3913 OSKext::isStarted(void)
3915 return flags
.started
? true : false;
3918 /*********************************************************************
3919 *********************************************************************/
3921 OSKext::isCPPInitialized(void)
3923 return flags
.CPPInitialized
;
3926 /*********************************************************************
3927 *********************************************************************/
3929 OSKext::setCPPInitialized(bool initialized
)
3931 flags
.CPPInitialized
= initialized
;
3934 /*********************************************************************
3935 *********************************************************************/
3937 OSKext::getLoadTag(void)
3942 /*********************************************************************
3943 *********************************************************************/
3944 void OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
)
3946 if (linkedExecutable
) {
3947 *loadSize
= linkedExecutable
->getLength();
3949 /* If we have a kmod_info struct, calculated the wired size
3950 * from that. Otherwise it's the full load size.
3953 *wiredSize
= *loadSize
- kmod_info
->hdr_size
;
3955 *wiredSize
= *loadSize
;
3964 /*********************************************************************
3965 *********************************************************************/
3967 OSKext::copyUUID(void)
3969 OSData
* result
= NULL
;
3970 OSData
* theExecutable
= NULL
; // do not release
3971 const kernel_mach_header_t
* header
= NULL
;
3972 const struct load_command
* load_cmd
= NULL
;
3973 const struct uuid_command
* uuid_cmd
= NULL
;
3976 /* An interface kext doesn't have a linked executable with an LC_UUID,
3977 * we create one when it's linked.
3979 if (interfaceUUID
) {
3980 result
= interfaceUUID
;
3985 /* For real kexts, try to get the UUID from the linked executable,
3986 * or if is hasn't been linked yet, the unrelocated executable.
3988 theExecutable
= linkedExecutable
;
3989 if (!theExecutable
) {
3990 theExecutable
= getExecutable();
3992 if (!theExecutable
) {
3996 header
= (const kernel_mach_header_t
*)theExecutable
->getBytesNoCopy();
3997 load_cmd
= (const struct load_command
*)&header
[1];
3999 for (i
= 0; i
< header
->ncmds
; i
++) {
4000 if (load_cmd
->cmd
== LC_UUID
) {
4001 uuid_cmd
= (struct uuid_command
*)load_cmd
;
4002 result
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
));
4005 load_cmd
= (struct load_command
*)((caddr_t
)load_cmd
+ load_cmd
->cmdsize
);
4012 /*********************************************************************
4013 *********************************************************************/
4015 #if defined (__i386__)
4016 #define ARCHNAME "i386"
4017 #elif defined (__x86_64__)
4018 #define ARCHNAME "x86_64"
4020 #error architecture not supported
4023 #define ARCH_SEPARATOR_CHAR '_'
4025 static char * makeHostArchKey(const char * key
, uint32_t * keySizeOut
)
4027 char * result
= NULL
;
4028 uint32_t keyLength
= strlen(key
);
4031 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4033 keySize
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
);
4034 result
= (char *)kalloc(keySize
);
4038 strlcpy(result
, key
, keySize
);
4039 result
[keyLength
++] = ARCH_SEPARATOR_CHAR
;
4040 result
[keyLength
] = '\0';
4041 strlcat(result
, ARCHNAME
, keySize
);
4042 *keySizeOut
= keySize
;
4048 /*********************************************************************
4049 *********************************************************************/
4051 OSKext::getPropertyForHostArch(const char * key
)
4053 OSObject
* result
= NULL
; // do not release
4054 uint32_t hostArchKeySize
= 0;
4055 char * hostArchKey
= NULL
; // must kfree
4057 if (!key
|| !infoDict
) {
4061 /* Some properties are not allowed to be arch-variant:
4062 * - Any CFBundle... property.
4063 * - OSBundleIsInterface.
4064 * - OSKernelResource.
4066 if (STRING_HAS_PREFIX(key
, "OS") ||
4067 STRING_HAS_PREFIX(key
, "IO")) {
4069 hostArchKey
= makeHostArchKey(key
, &hostArchKeySize
);
4071 OSKextLog(/* kext (this isn't about a kext) */ NULL
,
4072 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4073 "Allocation failure.");
4076 result
= infoDict
->getObject(hostArchKey
);
4080 result
= infoDict
->getObject(key
);
4084 if (hostArchKey
) kfree(hostArchKey
, hostArchKeySize
);
4089 #pragma mark Load/Start/Stop/Unload
4091 /*********************************************************************
4092 *********************************************************************/
4095 OSKext::loadKextWithIdentifier(
4096 const char * kextIdentifierCString
,
4097 Boolean allowDeferFlag
,
4098 Boolean delayAutounloadFlag
,
4099 OSKextExcludeLevel startOpt
,
4100 OSKextExcludeLevel startMatchingOpt
,
4101 OSArray
* personalityNames
)
4103 OSReturn result
= kOSReturnError
;
4104 OSString
* kextIdentifier
= NULL
; // must release
4106 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
4107 if (!kextIdentifier
) {
4108 result
= kOSKextReturnNoMemory
;
4111 result
= OSKext::loadKextWithIdentifier(kextIdentifier
,
4112 allowDeferFlag
, delayAutounloadFlag
,
4113 startOpt
, startMatchingOpt
, personalityNames
);
4116 OSSafeRelease(kextIdentifier
);
4120 /*********************************************************************
4121 *********************************************************************/
4123 OSKext::loadKextWithIdentifier(
4124 OSString
* kextIdentifier
,
4125 Boolean allowDeferFlag
,
4126 Boolean delayAutounloadFlag
,
4127 OSKextExcludeLevel startOpt
,
4128 OSKextExcludeLevel startMatchingOpt
,
4129 OSArray
* personalityNames
)
4131 OSReturn result
= kOSReturnError
;
4132 OSReturn pingResult
= kOSReturnError
;
4133 OSKext
* theKext
= NULL
; // do not release
4134 OSDictionary
* loadRequest
= NULL
; // must release
4135 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4137 IORecursiveLockLock(sKextLock
);
4139 if (!kextIdentifier
) {
4140 result
= kOSKextReturnInvalidArgument
;
4144 OSKext::recordIdentifierRequest(kextIdentifier
);
4146 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
4148 if (!allowDeferFlag
) {
4149 OSKextLog(/* kext */ NULL
,
4150 kOSKextLogErrorLevel
|
4152 "Can't load kext %s - not found.",
4153 kextIdentifier
->getCStringNoCopy());
4157 if (!sKernelRequestsEnabled
) {
4159 kOSKextLogErrorLevel
|
4161 "Can't load kext %s - requests to user space are disabled.",
4162 kextIdentifier
->getCStringNoCopy());
4163 result
= kOSKextReturnDisabled
;
4167 /* Create a new request unless one is already sitting
4168 * in sKernelRequests for this bundle identifier
4170 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4171 if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4172 result
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
,
4174 if (result
!= kOSReturnSuccess
) {
4177 if (!_OSKextSetRequestArgument(loadRequest
,
4178 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
4180 result
= kOSKextReturnNoMemory
;
4183 if (!sKernelRequests
->setObject(loadRequest
)) {
4184 result
= kOSKextReturnNoMemory
;
4188 if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4189 result
= kOSKextReturnNoMemory
;
4194 kOSKextLogDebugLevel
|
4196 "Kext %s not found; queued load request to user space.",
4197 kextIdentifier
->getCStringNoCopy());
4200 pingResult
= OSKext::pingKextd();
4201 if (pingResult
== kOSKextReturnDisabled
) {
4202 OSKextLog(/* kext */ NULL
,
4203 ((sPrelinkBoot
) ? kOSKextLogDebugLevel
: kOSKextLogErrorLevel
) |
4205 "Kext %s might not load - kextd is currently unavailable.",
4206 kextIdentifier
->getCStringNoCopy());
4209 result
= kOSKextReturnDeferred
;
4213 result
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
);
4215 if (result
!= kOSReturnSuccess
) {
4217 kOSKextLogErrorLevel
|
4219 "Failed to load kext %s (error 0x%x).",
4220 kextIdentifier
->getCStringNoCopy(), (int)result
);
4222 OSKext::removeKext(theKext
,
4223 /* terminateService/removePersonalities */ true);
4227 if (delayAutounloadFlag
) {
4229 kOSKextLogProgressLevel
|
4230 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4231 "Setting delayed autounload for %s.",
4232 kextIdentifier
->getCStringNoCopy());
4233 theKext
->flags
.delayAutounload
= 1;
4237 OSSafeRelease(loadRequest
);
4238 OSSafeRelease(kextIdentifierSymbol
);
4240 IORecursiveLockUnlock(sKextLock
);
4245 /*********************************************************************
4246 *********************************************************************/
4249 OSKext::recordIdentifierRequest(
4250 OSString
* kextIdentifier
)
4252 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4255 if (!sAllKextLoadIdentifiers
|| !kextIdentifier
) {
4259 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4260 if (!kextIdentifierSymbol
) {
4261 // xxx - this is really a basic alloc failure
4266 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4267 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4270 // xxx - need to find a way to associate this whole func w/the kext
4271 OSKextLog(/* kext */ NULL
,
4272 // xxx - check level
4273 kOSKextLogStepLevel
|
4274 kOSKextLogArchiveFlag
,
4275 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4276 kextIdentifier
->getCStringNoCopy());
4282 OSKextLog(/* kext */ NULL
,
4283 kOSKextLogErrorLevel
|
4284 kOSKextLogArchiveFlag
,
4285 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4286 kextIdentifier
->getCStringNoCopy());
4288 OSSafeRelease(kextIdentifierSymbol
);
4292 /*********************************************************************
4293 *********************************************************************/
4296 OSKextExcludeLevel startOpt
,
4297 OSKextExcludeLevel startMatchingOpt
,
4298 OSArray
* personalityNames
)
4300 OSReturn result
= kOSReturnError
;
4301 kern_return_t kxldResult
;
4302 OSKextExcludeLevel dependenciesStartOpt
= startOpt
;
4303 OSKextExcludeLevel dependenciesStartMatchingOpt
= startMatchingOpt
;
4304 unsigned int i
, count
;
4305 Boolean alreadyLoaded
= false;
4306 OSKext
* lastLoadedKext
= NULL
;
4309 alreadyLoaded
= true;
4310 result
= kOSReturnSuccess
;
4313 kOSKextLogDebugLevel
|
4314 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4315 "Kext %s is already loaded.",
4316 getIdentifierCString());
4320 if (!sLoadEnabled
) {
4322 kOSKextLogErrorLevel
|
4324 "Kext loading is disabled (attempt to load kext %s).",
4325 getIdentifierCString());
4326 result
= kOSKextReturnDisabled
;
4330 /* If we've pushed the next available load tag to the invalid value,
4331 * we can't load any more kexts.
4333 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4335 kOSKextLogErrorLevel
|
4337 "Can't load kext %s - no more load tags to assign.",
4338 getIdentifierCString());
4339 result
= kOSKextReturnNoResources
;
4343 /* This is a bit of a hack, because we shouldn't be handling
4344 * personalities within the load function.
4346 if (!declaresExecutable()) {
4347 result
= kOSReturnSuccess
;
4351 /* Are we in safe boot?
4353 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4355 kOSKextLogErrorLevel
|
4357 "Can't load kext %s - not loadable during safe boot.",
4358 getIdentifierCString());
4359 result
= kOSKextReturnBootLevel
;
4364 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4366 getIdentifierCString());
4369 if (!sKxldContext
) {
4370 kxldResult
= kxld_create_context(&sKxldContext
, &kern_allocate
,
4371 &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,
4372 /* cputype */ 0, /* cpusubtype */ 0);
4375 kOSKextLogErrorLevel
|
4376 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4377 "Can't load kext %s - failed to create link context.",
4378 getIdentifierCString());
4379 result
= kOSKextReturnNoMemory
;
4384 /* We only need to resolve dependencies once for the whole graph, but
4385 * resolveDependencies will just return if there's no work to do, so it's
4386 * safe to call it more than once.
4388 if (!resolveDependencies()) {
4389 // xxx - check resolveDependencies() for log msg
4391 kOSKextLogErrorLevel
|
4392 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4393 "Can't load kext %s - failed to resolve library dependencies.",
4394 getIdentifierCString());
4395 result
= kOSKextReturnDependencies
;
4399 /* If we are excluding just the kext being loaded now (and not its
4400 * dependencies), drop the exclusion level to none so dependencies
4401 * start and/or add their personalities.
4403 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4404 dependenciesStartOpt
= kOSKextExcludeNone
;
4407 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4408 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4411 /* Load the dependencies, recursively.
4413 count
= getNumDependencies();
4414 for (i
= 0; i
< count
; i
++) {
4415 OSKext
* dependency
= OSDynamicCast(OSKext
,
4416 dependencies
->getObject(i
));
4417 if (dependency
== NULL
) {
4419 kOSKextLogErrorLevel
|
4420 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4421 "Internal error loading kext %s; dependency disappeared.",
4422 getIdentifierCString());
4423 result
= kOSKextReturnInternalError
;
4427 /* Dependencies must be started accorting to the opt,
4428 * but not given the personality names of the main kext.
4430 result
= dependency
->load(dependenciesStartOpt
,
4431 dependenciesStartMatchingOpt
,
4432 /* personalityNames */ NULL
);
4433 if (result
!= KERN_SUCCESS
) {
4435 kOSKextLogErrorLevel
|
4436 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4437 "Dependency %s of kext %s failed to load.",
4438 dependency
->getIdentifierCString(),
4439 getIdentifierCString());
4441 OSKext::removeKext(dependency
,
4442 /* terminateService/removePersonalities */ true);
4443 result
= kOSKextReturnDependencyLoadError
;
4449 result
= loadExecutable();
4450 if (result
!= KERN_SUCCESS
) {
4454 flags
.loaded
= true;
4456 /* Add the kext to the list of loaded kexts and update the kmod_info
4457 * struct to point to that of the last loaded kext (which is the way
4458 * it's always been done, though I'd rather do them in order now).
4460 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
4461 sLoadedKexts
->setObject(this);
4463 /* Keep the kernel itself out of the kmod list.
4465 if (lastLoadedKext
->isKernel()) {
4466 lastLoadedKext
= NULL
;
4469 if (lastLoadedKext
) {
4470 kmod_info
->next
= lastLoadedKext
->kmod_info
;
4473 notifyKextLoadObservers(this, kmod_info
);
4475 /* Make the global kmod list point at the just-loaded kext. Note that the
4476 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4477 * although we do report it in kextstat these days by using the newer
4478 * OSArray of loaded kexts, which does contain it.
4480 * (The OSKext object representing the kernel doesn't even have a kmod_info
4481 * struct, though I suppose we could stick a pointer to it from the
4482 * static struct in OSRuntime.cpp.)
4486 /* Save the list of loaded kexts in case we panic.
4488 OSKext::saveLoadedKextPanicList();
4490 if (isExecutable()) {
4491 OSKext::updateLoadedKextSummaries();
4492 savePanicString(/* isLoading */ true);
4495 registerWithDTrace();
4497 jettisonLinkeditSegment();
4498 #endif /* CONFIG_DTRACE */
4502 if (isExecutable() && !flags
.started
) {
4503 if (startOpt
== kOSKextExcludeNone
) {
4505 if (result
!= kOSReturnSuccess
) {
4507 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4508 "Kext %s start failed (result 0x%x).",
4509 getIdentifierCString(), result
);
4510 result
= kOSKextReturnStartStopError
;
4515 /* If not excluding matching, send the personalities to the kernel.
4516 * This never affects the result of the load operation.
4517 * This is a bit of a hack, because we shouldn't be handling
4518 * personalities within the load function.
4520 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
4521 result
= sendPersonalitiesToCatalog(true, personalityNames
);
4526 /* More hack! If the kext doesn't declare an executable, even if we
4527 * "loaded" it, we have to remove any personalities naming it, or we'll
4528 * never see the registry go quiet. Errors here do not count for the
4529 * load operation itself.
4531 * Note that in every other regard it's perfectly ok for a kext to
4532 * not declare an executable and serve only as a package for personalities
4533 * naming another kext, so we do have to allow such kexts to be "loaded"
4534 * so that those other personalities get added & matched.
4536 if (!declaresExecutable()) {
4538 kOSKextLogStepLevel
| kOSKextLogLoadFlag
,
4539 "Kext %s has no executable; removing any personalities naming it.",
4540 getIdentifierCString());
4541 removePersonalitiesFromCatalog();
4544 if (result
!= kOSReturnSuccess
) {
4546 kOSKextLogErrorLevel
|
4548 "Kext %s failed to load (0x%x).",
4549 getIdentifierCString(), (int)result
);
4550 } else if (!alreadyLoaded
) {
4552 kOSKextLogProgressLevel
|
4555 getIdentifierCString());
4557 queueKextNotification(kKextRequestPredicateLoadNotification
,
4558 OSDynamicCast(OSString
, bundleID
));
4563 /*********************************************************************
4565 *********************************************************************/
4566 static char * strdup(const char * string
)
4568 char * result
= NULL
;
4575 size
= 1 + strlen(string
);
4576 result
= (char *)kalloc(size
);
4581 memcpy(result
, string
, size
);
4587 /*********************************************************************
4589 *********************************************************************/
4591 OSKext::slidePrelinkedExecutable()
4593 OSReturn result
= kOSKextReturnBadData
;
4594 kernel_mach_header_t
* mh
= NULL
;
4595 kernel_segment_command_t
* seg
= NULL
;
4596 kernel_segment_command_t
* linkeditSeg
= NULL
;
4597 kernel_section_t
* sec
= NULL
;
4598 char * linkeditBase
= NULL
;
4599 bool haveLinkeditBase
= false;
4600 char * relocBase
= NULL
;
4601 bool haveRelocBase
= false;
4602 struct dysymtab_command
* dysymtab
= NULL
;
4603 struct symtab_command
* symtab
= NULL
;
4604 kernel_nlist_t
* sym
= NULL
;
4605 struct relocation_info
* reloc
= NULL
;
4608 vm_offset_t new_kextsize
;
4610 if (linkedExecutable
== NULL
|| vm_kernel_slide
== 0) {
4611 result
= kOSReturnSuccess
;
4615 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4617 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4618 seg
->vmaddr
+= vm_kernel_slide
;
4620 #if KASLR_KEXT_DEBUG
4621 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
4623 (unsigned long)VM_KERNEL_UNSLIDE(seg
->vmaddr
),
4624 (unsigned long)seg
->vmaddr
);
4627 if (!haveRelocBase
) {
4628 relocBase
= (char *) seg
->vmaddr
;
4629 haveRelocBase
= true;
4631 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
4632 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
4633 haveLinkeditBase
= true;
4636 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4637 sec
->addr
+= vm_kernel_slide
;
4639 #if KASLR_KEXT_DEBUG
4640 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
4642 (unsigned long)VM_KERNEL_UNSLIDE(sec
->addr
),
4643 (unsigned long)sec
->addr
);
4648 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
4650 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
4652 if (symtab
!= NULL
) {
4653 /* Some pseudo-kexts have symbol tables without segments.
4655 if (symtab
->nsyms
> 0 && haveLinkeditBase
) {
4656 sym
= (kernel_nlist_t
*) (linkeditBase
+ symtab
->symoff
);
4657 for (i
= 0; i
< symtab
->nsyms
; i
++) {
4658 if (sym
[i
].n_type
& N_STAB
) {
4661 sym
[i
].n_value
+= vm_kernel_slide
;
4663 #if KASLR_KEXT_DEBUG
4664 #define MAX_SYMS_TO_LOG 5
4665 if ( i
< MAX_SYMS_TO_LOG
) {
4666 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
4667 (unsigned long)VM_KERNEL_UNSLIDE(sym
[i
].n_value
),
4668 (unsigned long)sym
[i
].n_value
);
4675 if (dysymtab
!= NULL
) {
4676 if (dysymtab
->nextrel
> 0) {
4678 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4680 "Sliding kext %s: External relocations found.",
4681 getIdentifierCString());
4685 if (dysymtab
->nlocrel
> 0) {
4686 if (!haveLinkeditBase
) {
4688 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4690 "Sliding kext %s: No linkedit segment.",
4691 getIdentifierCString());
4695 if (!haveRelocBase
) {
4697 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4700 "Sliding kext %s: No writable segments.",
4702 "Sliding kext %s: No segments.",
4704 getIdentifierCString());
4708 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
4709 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
4711 for (i
= 0; i
< dysymtab
->nlocrel
; i
++) {
4712 if ( reloc
[i
].r_extern
!= 0
4713 || reloc
[i
].r_type
!= 0
4714 || reloc
[i
].r_length
!= (sizeof(void *) == 8 ? 3 : 2)
4716 || (reloc
[i
].r_address
& R_SCATTERED
)
4720 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4722 "Sliding kext %s: Unexpected relocation found.",
4723 getIdentifierCString());
4726 if (reloc
[i
].r_pcrel
!= 0) {
4729 *((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)) += vm_kernel_slide
;
4731 #if KASLR_KEXT_DEBUG
4732 #define MAX_DYSYMS_TO_LOG 5
4733 if ( i
< MAX_DYSYMS_TO_LOG
) {
4734 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
4735 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
))),
4736 (unsigned long)*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)));
4741 /* We should free these relocations, not just delete the reference to them.
4742 * <rdar://problem/10535549> Free relocations from PIE kexts.
4744 new_kextsize
= round_page(kmod_info
->size
- reloc_size
);
4746 if ((kmod_info
->size
- new_kextsize
) > PAGE_SIZE
) {
4747 vm_offset_t endofkext
= kmod_info
->address
+ kmod_info
->size
;
4748 vm_offset_t new_endofkext
= kmod_info
->address
+ new_kextsize
;
4749 vm_offset_t endofrelocInfo
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
);
4750 int bytes_remaining
= endofkext
- endofrelocInfo
;
4751 OSData
* new_osdata
= NULL
;
4753 /* fix up symbol offsets if they are after the dsymtab local relocs */
4755 if (dysymtab
->locreloff
< symtab
->symoff
){
4756 symtab
->symoff
-= reloc_size
;
4758 if (dysymtab
->locreloff
< symtab
->stroff
) {
4759 symtab
->stroff
-= reloc_size
;
4762 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
4763 dysymtab
->extreloff
-= reloc_size
;
4766 /* move data behind reloc info down to new offset */
4767 if (endofrelocInfo
< endofkext
) {
4768 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
4771 /* Create a new OSData for the smaller kext object and reflect
4772 * new linkedit segment size.
4774 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
4775 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
4777 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
4779 /* Fix up kmod info and linkedExecutable.
4781 kmod_info
->size
= new_kextsize
;
4782 linkedExecutable
->setDeallocFunction(NULL
);
4783 linkedExecutable
->release();
4784 linkedExecutable
= new_osdata
;
4787 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
4789 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
4793 dysymtab
->nlocrel
= 0;
4794 dysymtab
->locreloff
= 0;
4798 result
= kOSReturnSuccess
;
4803 /*********************************************************************
4804 * called only by load()
4805 *********************************************************************/
4807 OSKext::loadExecutable()
4809 OSReturn result
= kOSReturnError
;
4810 kern_return_t kxldResult
;
4811 KXLDDependency
* kxlddeps
= NULL
; // must kfree
4812 uint32_t num_kxlddeps
= 0;
4813 OSArray
* linkDependencies
= NULL
; // must release
4814 uint32_t numDirectDependencies
= 0;
4815 uint32_t num_kmod_refs
= 0;
4816 struct mach_header
** kxldHeaderPtr
= NULL
; // do not free
4817 struct mach_header
* kxld_header
= NULL
; // xxx - need to free here?
4818 OSData
* theExecutable
= NULL
; // do not release
4819 OSString
* versString
= NULL
; // do not release
4820 const char * versCString
= NULL
; // do not free
4821 const char * string
= NULL
; // do not free
4824 /* We need the version string for a variety of bits below.
4826 versString
= OSDynamicCast(OSString
,
4827 getPropertyForHostArch(kCFBundleVersionKey
));
4831 versCString
= versString
->getCStringNoCopy();
4833 if (isKernelComponent()) {
4834 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
4836 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
4838 kOSKextLogErrorLevel
|
4840 "Kernel component %s has incorrect version %s; "
4842 getIdentifierCString(),
4843 versCString
, KERNEL6_VERSION
);
4844 result
= kOSKextReturnInternalError
;
4846 } else if (strcmp(versCString
, osrelease
)) {
4848 kOSKextLogErrorLevel
|
4850 "Kernel component %s has incorrect version %s; "
4852 getIdentifierCString(),
4853 versCString
, osrelease
);
4854 result
= kOSKextReturnInternalError
;
4860 if (isPrelinked()) {
4861 result
= slidePrelinkedExecutable();
4862 if (result
!= kOSReturnSuccess
) {
4868 theExecutable
= getExecutable();
4869 if (!theExecutable
) {
4870 if (declaresExecutable()) {
4872 kOSKextLogErrorLevel
|
4874 "Can't load kext %s - executable is missing.",
4875 getIdentifierCString());
4876 result
= kOSKextReturnValidation
;
4882 if (isInterface()) {
4883 OSData
*executableCopy
= OSData::withData(theExecutable
);
4884 setLinkedExecutable(executableCopy
);
4885 executableCopy
->release();
4889 numDirectDependencies
= getNumDependencies();
4891 if (flags
.hasBleedthrough
) {
4892 linkDependencies
= dependencies
;
4893 linkDependencies
->retain();
4895 linkDependencies
= OSArray::withArray(dependencies
);
4896 if (!linkDependencies
) {
4898 kOSKextLogErrorLevel
|
4899 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4900 "Can't allocate link dependencies to load kext %s.",
4901 getIdentifierCString());
4905 for (i
= 0; i
< numDirectDependencies
; ++i
) {
4906 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
4907 dependencies
->getObject(i
));
4908 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
4912 num_kxlddeps
= linkDependencies
->getCount();
4913 if (!num_kxlddeps
) {
4915 kOSKextLogErrorLevel
|
4916 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4917 "Can't load kext %s - it has no library dependencies.",
4918 getIdentifierCString());
4922 kxlddeps
= (KXLDDependency
*)kalloc(num_kxlddeps
* sizeof(*kxlddeps
));
4925 kOSKextLogErrorLevel
|
4926 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4927 "Can't allocate link context to load kext %s.",
4928 getIdentifierCString());
4931 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
4933 for (i
= 0; i
< num_kxlddeps
; ++i
) {
4934 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
4936 if (dependency
->isInterface()) {
4937 OSKext
*interfaceTargetKext
= NULL
;
4938 OSData
* interfaceTarget
= NULL
;
4940 if (dependency
->isKernelComponent()) {
4941 interfaceTargetKext
= sKernelKext
;
4942 interfaceTarget
= sKernelKext
->linkedExecutable
;
4944 interfaceTargetKext
= OSDynamicCast(OSKext
,
4945 dependency
->dependencies
->getObject(0));
4947 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
4950 if (!interfaceTarget
) {
4955 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
4956 * it will be useful to have them in the debugger.
4957 * strdup() failing isn't critical right here so we don't check that.
4959 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
4960 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
4961 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
4963 kxlddeps
[i
].interface
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
4964 kxlddeps
[i
].interface_size
= dependency
->linkedExecutable
->getLength();
4965 kxlddeps
[i
].interface_name
= strdup(dependency
->getIdentifierCString());
4967 kxlddeps
[i
].kext
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
4968 kxlddeps
[i
].kext_size
= dependency
->linkedExecutable
->getLength();
4969 kxlddeps
[i
].kext_name
= strdup(dependency
->getIdentifierCString());
4972 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
4975 kxldHeaderPtr
= &kxld_header
;
4979 kOSKextLogExplicitLevel
|
4980 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4981 "Kext %s - calling kxld_link_file:\n"
4982 " kxld_context: %p\n"
4983 " executable: %p executable_length: %d\n"
4985 " kxld_dependencies: %p num_dependencies: %d\n"
4986 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
4987 getIdentifierCString(), sKxldContext
,
4988 theExecutable
->getBytesNoCopy(), theExecutable
->getLength(),
4989 this, kxlddeps
, num_kxlddeps
,
4990 kxldHeaderPtr
, &kmod_info
);
4993 /* After this call, the linkedExecutable instance variable
4996 kxldResult
= kxld_link_file(sKxldContext
,
4997 (u_char
*)theExecutable
->getBytesNoCopy(),
4998 theExecutable
->getLength(),
4999 getIdentifierCString(), this, kxlddeps
, num_kxlddeps
,
5000 (u_char
**)kxldHeaderPtr
, (kxld_addr_t
*)&kmod_info
);
5002 if (kxldResult
!= KERN_SUCCESS
) {
5003 // xxx - add kxldResult here?
5005 kOSKextLogErrorLevel
|
5007 "Can't load kext %s - link failed.",
5008 getIdentifierCString());
5009 result
= kOSKextReturnLinkError
;
5013 /* We've written data & instructions into kernel memory, so flush the data
5014 * cache and invalidate the instruction cache.
5015 * I/D caches are coherent on x86
5017 #if !defined(__i386__) && !defined(__x86_64__)
5018 flush_dcache(kmod_info
->address
, kmod_info
->size
, false);
5019 invalidate_icache(kmod_info
->address
, kmod_info
->size
, false);
5023 if (isInterface()) {
5025 /* Whip up a fake kmod_info entry for the interface kext.
5027 kmod_info
= (kmod_info_t
*)kalloc(sizeof(kmod_info_t
));
5029 result
= KERN_MEMORY_ERROR
;
5033 /* A pseudokext has almost nothing in its kmod_info struct.
5035 bzero(kmod_info
, sizeof(kmod_info_t
));
5037 kmod_info
->info_version
= KMOD_INFO_VERSION
;
5039 /* An interface kext doesn't have a linkedExecutable, so save a
5040 * copy of the UUID out of the original executable via copyUUID()
5041 * while we still have the original executable.
5043 interfaceUUID
= copyUUID();
5046 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5047 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5049 /* Stamp the bundle ID and version from the OSKext over anything
5050 * resident inside the kmod_info.
5052 string
= getIdentifierCString();
5053 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5055 string
= versCString
;
5056 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5058 /* Add the dependencies' kmod_info structs as kmod_references.
5060 num_kmod_refs
= getNumDependencies();
5061 if (num_kmod_refs
) {
5062 kmod_info
->reference_list
= (kmod_reference_t
*)kalloc(
5063 num_kmod_refs
* sizeof(kmod_reference_t
));
5064 if (!kmod_info
->reference_list
) {
5065 result
= KERN_MEMORY_ERROR
;
5068 bzero(kmod_info
->reference_list
,
5069 num_kmod_refs
* sizeof(kmod_reference_t
));
5070 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5071 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5072 OSKext
* refKext
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
));
5073 ref
->info
= refKext
->kmod_info
;
5074 ref
->info
->reference_count
++;
5076 if (refIndex
+ 1 < num_kmod_refs
) {
5077 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5082 if (!isInterface() && linkedExecutable
) {
5084 kOSKextLogProgressLevel
|
5086 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5088 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5089 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5090 (unsigned)kmod_info
->id
);
5093 result
= setVMProtections();
5094 if (result
!= KERN_SUCCESS
) {
5098 result
= kOSReturnSuccess
;
5101 OSSafeRelease(linkDependencies
);
5103 /* Clear up locally allocated dependency info.
5105 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5108 if (kxlddeps
[i
].kext_name
) {
5109 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5110 kfree(kxlddeps
[i
].kext_name
, size
);
5112 if (kxlddeps
[i
].interface_name
) {
5113 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5114 kfree(kxlddeps
[i
].interface_name
, size
);
5117 if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5119 /* We no longer need the unrelocated executable (which the linker
5120 * has altered anyhow).
5122 setExecutable(NULL
);
5124 if (result
!= kOSReturnSuccess
) {
5126 kOSKextLogErrorLevel
|
5128 "Failed to load executable for kext %s.",
5129 getIdentifierCString());
5131 if (kmod_info
&& kmod_info
->reference_list
) {
5132 kfree(kmod_info
->reference_list
,
5133 num_kmod_refs
* sizeof(kmod_reference_t
));
5135 if (isInterface()) {
5136 kfree(kmod_info
, sizeof(kmod_info_t
));
5139 if (linkedExecutable
) {
5140 linkedExecutable
->release();
5141 linkedExecutable
= NULL
;
5148 /*********************************************************************
5149 * The linkedit segment is used by the kext linker for dependency
5150 * resolution, and by dtrace for probe initialization. We can free it
5151 * for non-library kexts, since no kexts depend on non-library kexts
5152 * by definition, once dtrace has been initialized.
5153 *********************************************************************/
5155 OSKext::jettisonLinkeditSegment(void)
5157 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5158 kernel_segment_command_t
* linkedit
= NULL
;
5160 vm_size_t linkeditsize
, kextsize
;
5161 OSData
* data
= NULL
;
5164 /* We can free symbol tables for all embedded kexts because we don't
5165 * support runtime kext linking.
5167 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5169 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5174 /* Find the linkedit segment. If it's not the last segment, then freeing
5175 * it will fragment the kext into multiple VM regions, which OSKext is not
5176 * designed to handle, so we'll have to skip it.
5178 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5183 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5184 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
))
5189 /* Create a new OSData for the smaller kext object.
5191 linkeditsize
= round_page(linkedit
->vmsize
);
5192 kextsize
= kmod_info
->size
- linkeditsize
;
5193 start
= linkedit
->vmaddr
;
5195 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5200 /* Fix the kmod info and linkedExecutable.
5202 kmod_info
->size
= kextsize
;
5203 linkedExecutable
->setDeallocFunction(NULL
);
5204 linkedExecutable
->release();
5205 linkedExecutable
= data
;
5206 flags
.jettisonLinkeditSeg
= 1;
5208 /* Free the linkedit segment.
5211 kext_free(start
, linkeditsize
);
5213 ml_static_mfree(start
, linkeditsize
);
5220 /*********************************************************************
5221 *********************************************************************/
5223 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5225 if (linkedExecutable
) {
5226 panic("Attempt to set linked executable on kext "
5227 "that already has one (%s).\n",
5228 getIdentifierCString());
5230 linkedExecutable
= anExecutable
;
5231 linkedExecutable
->retain();
5236 /*********************************************************************
5237 * Go through all loaded kexts and tell them to register with dtrace.
5238 * The instance method only registers if necessary.
5239 *********************************************************************/
5242 OSKext::registerKextsWithDTrace(void)
5244 uint32_t count
= sLoadedKexts
->getCount();
5247 IORecursiveLockLock(sKextLock
);
5249 for (i
= 0; i
< count
; i
++) {
5250 OSKext
* thisKext
= NULL
; // do not release
5252 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5253 if (!thisKext
|| !thisKext
->isExecutable()) {
5257 thisKext
->registerWithDTrace();
5260 IORecursiveLockUnlock(sKextLock
);
5266 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5267 extern int (*dtrace_modunload
)(struct kmod_info
*);
5270 /*********************************************************************
5271 *********************************************************************/
5273 OSKext::registerWithDTrace(void)
5275 /* Register kext with dtrace. A dtrace_modload failure should not
5276 * prevent a kext from loading, so we ignore the return code.
5278 if (!flags
.dtraceInitialized
&& (dtrace_modload
!= NULL
)) {
5279 uint32_t modflag
= 0;
5280 OSObject
* forceInit
= getPropertyForHostArch("OSBundleForceDTraceInit");
5281 if (forceInit
== kOSBooleanTrue
) {
5282 modflag
|= KMOD_DTRACE_FORCE_INIT
;
5285 (void)(*dtrace_modload
)(kmod_info
, modflag
);
5286 flags
.dtraceInitialized
= true;
5287 jettisonLinkeditSegment();
5291 /*********************************************************************
5292 *********************************************************************/
5294 OSKext::unregisterWithDTrace(void)
5296 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5297 * prevent a kext from loading, so we ignore the return code.
5299 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
5300 (void)(*dtrace_modunload
)(kmod_info
);
5301 flags
.dtraceInitialized
= false;
5305 #endif /* CONFIG_DTRACE */
5308 /*********************************************************************
5309 * called only by loadExecutable()
5310 *********************************************************************/
5311 #if !VM_MAPPED_KEXTS
5312 #error Unrecognized architecture
5314 static inline kern_return_t
5317 vm_map_offset_t start
,
5318 vm_map_offset_t end
,
5322 if (start
== end
) { // 10538581
5323 return(KERN_SUCCESS
);
5325 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
5328 static inline kern_return_t
5331 vm_map_offset_t start
,
5332 vm_map_offset_t end
,
5333 vm_prot_t access_type
,
5334 boolean_t user_wire
)
5336 return vm_map_wire(map
, start
, end
, access_type
, user_wire
);
5341 OSKext::setVMProtections(void)
5343 vm_map_t kext_map
= NULL
;
5344 kernel_segment_command_t
* seg
= NULL
;
5345 vm_map_offset_t start
= 0;
5346 vm_map_offset_t end
= 0;
5347 OSReturn result
= kOSReturnError
;
5349 if (!kmod_info
->address
&& !kmod_info
->size
) {
5350 result
= kOSReturnSuccess
;
5354 /* Get the kext's vm map */
5355 kext_map
= kext_get_vm_map(kmod_info
);
5357 result
= KERN_MEMORY_ERROR
;
5361 /* Protect the headers as read-only; they do not need to be wired */
5362 result
= OSKext_protect(kext_map
, kmod_info
->address
,
5363 kmod_info
->address
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
);
5364 if (result
!= KERN_SUCCESS
) {
5368 /* Set the VM protections and wire down each of the segments */
5369 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5371 start
= round_page(seg
->vmaddr
);
5372 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
5374 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
5375 if (result
!= KERN_SUCCESS
) {
5377 kOSKextLogErrorLevel
|
5379 "Kext %s failed to set maximum VM protections "
5380 "for segment %s - 0x%x.",
5381 getIdentifierCString(), seg
->segname
, (int)result
);
5385 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5386 if (result
!= KERN_SUCCESS
) {
5388 kOSKextLogErrorLevel
|
5390 "Kext %s failed to set initial VM protections "
5391 "for segment %s - 0x%x.",
5392 getIdentifierCString(), seg
->segname
, (int)result
);
5396 if (segmentShouldBeWired(seg
)) {
5397 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5398 if (result
!= KERN_SUCCESS
) {
5403 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5410 /*********************************************************************
5411 *********************************************************************/
5413 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
5415 return (sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
)));
5418 /*********************************************************************
5419 *********************************************************************/
5421 OSKext::validateKextMapping(bool startFlag
)
5423 OSReturn result
= kOSReturnError
;
5424 const char * whichOp
= startFlag
? "start" : "stop";
5425 kern_return_t kern_result
= 0;
5426 vm_map_t kext_map
= NULL
;
5427 kernel_segment_command_t
* seg
= NULL
;
5428 mach_vm_address_t address
= 0;
5429 mach_vm_size_t size
= 0;
5431 mach_msg_type_number_t count
;
5432 vm_region_submap_short_info_data_64_t info
;
5434 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
5435 bzero(&info
, sizeof(info
));
5437 // xxx - do we need a distinct OSReturn value for these or is "bad data"
5438 // xxx - sufficient?
5440 /* Verify that the kmod_info and start/stop pointers are non-NULL.
5444 kOSKextLogErrorLevel
|
5446 "Kext %s - NULL kmod_info pointer.",
5447 getIdentifierCString());
5448 result
= kOSKextReturnBadData
;
5453 address
= (mach_vm_address_t
)kmod_info
->start
;
5455 address
= (mach_vm_address_t
)kmod_info
->stop
;
5460 kOSKextLogErrorLevel
|
5462 "Kext %s - NULL module %s pointer.",
5463 getIdentifierCString(), whichOp
);
5464 result
= kOSKextReturnBadData
;
5468 kext_map
= kext_get_vm_map(kmod_info
);
5469 depth
= (kernel_map
== kext_map
) ? 1 : 2;
5471 /* Verify that the start/stop function lies within the kext's address range.
5473 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
5474 kmod_info
->address
+ kmod_info
->size
<= address
)
5477 kOSKextLogErrorLevel
|
5479 "Kext %s module %s pointer is outside of kext range "
5480 "(%s %p - kext at %p-%p)..",
5481 getIdentifierCString(),
5484 (void *)VM_KERNEL_UNSLIDE(address
),
5485 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5486 (void *)(VM_KERNEL_UNSLIDE(kmod_info
->address
) + kmod_info
->size
));
5487 result
= kOSKextReturnBadData
;
5491 /* Only do these checks before calling the start function;
5492 * If anything goes wrong with the mapping while the kext is running,
5493 * we'll likely have panicked well before any attempt to stop the kext.
5497 /* Verify that the start/stop function is executable.
5499 kern_result
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
,
5500 (vm_region_recurse_info_t
)&info
, &count
);
5501 if (kern_result
!= KERN_SUCCESS
) {
5503 kOSKextLogErrorLevel
|
5505 "Kext %s - bad %s pointer %p.",
5506 getIdentifierCString(),
5507 whichOp
, (void *)VM_KERNEL_UNSLIDE(address
));
5508 result
= kOSKextReturnBadData
;
5513 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
5515 kOSKextLogErrorLevel
|
5517 "Kext %s - memory region containing module %s function "
5518 "is not executable.",
5519 getIdentifierCString(), whichOp
);
5520 result
= kOSKextReturnBadData
;
5525 /* Verify that the kext's segments are backed by physical memory.
5527 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5529 if (!verifySegmentMapping(seg
)) {
5530 result
= kOSKextReturnBadData
;
5534 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5539 result
= kOSReturnSuccess
;
5544 /*********************************************************************
5545 *********************************************************************/
5547 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
5549 mach_vm_address_t address
= 0;
5551 if (!segmentShouldBeWired(seg
)) return true;
5553 for (address
= seg
->vmaddr
;
5554 address
< round_page(seg
->vmaddr
+ seg
->vmsize
);
5555 address
+= PAGE_SIZE
)
5557 if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) {
5559 kOSKextLogErrorLevel
|
5561 "Kext %s - page %p is not backed by physical memory.",
5562 getIdentifierCString(),
5571 /*********************************************************************
5572 *********************************************************************/
5574 OSKext::start(bool startDependenciesFlag
)
5576 OSReturn result
= kOSReturnError
;
5577 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
5578 unsigned int i
, count
;
5579 void * kmodStartData
= NULL
;
5581 if (isStarted() || isInterface() || isKernelComponent()) {
5582 result
= kOSReturnSuccess
;
5588 kOSKextLogErrorLevel
|
5590 "Attempt to start nonloaded kext %s.",
5591 getIdentifierCString());
5592 result
= kOSKextReturnInvalidArgument
;
5596 if (!sLoadEnabled
) {
5598 kOSKextLogErrorLevel
|
5600 "Kext loading is disabled (attempt to start kext %s).",
5601 getIdentifierCString());
5602 result
= kOSKextReturnDisabled
;
5606 result
= validateKextMapping(/* start? */ true);
5607 if (result
!= kOSReturnSuccess
) {
5611 startfunc
= kmod_info
->start
;
5613 count
= getNumDependencies();
5614 for (i
= 0; i
< count
; i
++) {
5615 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
5616 if (dependency
== NULL
) {
5618 kOSKextLogErrorLevel
|
5620 "Kext %s start - internal error, dependency disappeared.",
5621 getIdentifierCString());
5624 if (!dependency
->isStarted()) {
5625 if (startDependenciesFlag
) {
5626 OSReturn dependencyResult
=
5627 dependency
->start(startDependenciesFlag
);
5628 if (dependencyResult
!= KERN_SUCCESS
) {
5630 kOSKextLogErrorLevel
|
5632 "Kext %s start - dependency %s failed to start (error 0x%x).",
5633 getIdentifierCString(),
5634 dependency
->getIdentifierCString(),
5640 kOSKextLogErrorLevel
|
5642 "Not starting %s - dependency %s not started yet.",
5643 getIdentifierCString(),
5644 dependency
->getIdentifierCString());
5645 result
= kOSKextReturnStartStopError
; // xxx - make new return?
5652 kOSKextLogDetailLevel
|
5654 "Kext %s calling module start function.",
5655 getIdentifierCString());
5659 #if !CONFIG_STATIC_CPPINIT
5660 result
= OSRuntimeInitializeCPP(kmod_info
, NULL
);
5661 if (result
== KERN_SUCCESS
) {
5665 kmodStartData
= GetAppleTEXTHashForKext(this, this->infoDict
);
5668 if (kmodStartData
) {
5670 kOSKextLogErrorLevel
|
5671 kOSKextLogGeneralFlag
,
5672 "Kext %s calling module start function. kmodStartData %p. arch %s",
5673 getIdentifierCString(), kmodStartData
, ARCHNAME
);
5676 #endif // CONFIG_KEC_FIPS
5678 result
= startfunc(kmod_info
, kmodStartData
);
5680 #if !CONFIG_STATIC_CPPINIT
5681 if (result
!= KERN_SUCCESS
) {
5682 (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
);
5689 /* On success overlap the setting of started/starting. On failure just
5692 if (result
== KERN_SUCCESS
) {
5695 // xxx - log start error from kernel?
5697 kOSKextLogProgressLevel
|
5699 "Kext %s is now started.",
5700 getIdentifierCString());
5702 invokeOrCancelRequestCallbacks(
5703 /* result not actually used */ kOSKextReturnStartStopError
,
5704 /* invokeFlag */ false);
5706 kOSKextLogProgressLevel
|
5708 "Kext %s did not start (return code 0x%x).",
5709 getIdentifierCString(), result
);
5716 /*********************************************************************
5717 *********************************************************************/
5719 bool OSKext::canUnloadKextWithIdentifier(
5720 OSString
* kextIdentifier
,
5721 bool checkClassesFlag
)
5723 bool result
= false;
5724 OSKext
* aKext
= NULL
; // do not release
5726 IORecursiveLockLock(sKextLock
);
5728 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
5731 goto finish
; // can't unload what's not loaded
5734 if (aKext
->isLoaded()) {
5735 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
5738 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
5746 IORecursiveLockUnlock(sKextLock
);
5750 /*********************************************************************
5751 *********************************************************************/
5755 OSReturn result
= kOSReturnError
;
5756 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
5758 if (!isStarted() || isInterface()) {
5759 result
= kOSReturnSuccess
;
5765 kOSKextLogErrorLevel
|
5767 "Attempt to stop nonloaded kext %s.",
5768 getIdentifierCString());
5769 result
= kOSKextReturnInvalidArgument
;
5773 /* Refuse to stop if we have clients or instances. It is up to
5774 * the caller to make sure those aren't true.
5776 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
5778 kOSKextLogErrorLevel
|
5780 "Kext %s - C++ instances; can't stop.",
5781 getIdentifierCString());
5782 result
= kOSKextReturnInUse
;
5786 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
5789 kOSKextLogErrorLevel
|
5791 "Kext %s - has references (linkage or tracking object); "
5793 getIdentifierCString());
5794 result
= kOSKextReturnInUse
;
5798 /* Note: If validateKextMapping fails on the stop & unload path,
5799 * we are in serious trouble and a kernel panic is likely whether
5800 * we stop & unload the kext or not.
5802 result
= validateKextMapping(/* start? */ false);
5803 if (result
!= kOSReturnSuccess
) {
5807 stopfunc
= kmod_info
->stop
;
5810 kOSKextLogDetailLevel
|
5812 "Kext %s calling module stop function.",
5813 getIdentifierCString());
5817 result
= stopfunc(kmod_info
, /* userData */ NULL
);
5818 #if !CONFIG_STATIC_CPPINIT
5819 if (result
== KERN_SUCCESS
) {
5820 result
= OSRuntimeFinalizeCPP(kmod_info
, NULL
);
5826 if (result
== KERN_SUCCESS
) {
5830 kOSKextLogDetailLevel
|
5832 "Kext %s is now stopped and ready to unload.",
5833 getIdentifierCString());
5836 kOSKextLogErrorLevel
|
5838 "Kext %s did not stop (return code 0x%x).",
5839 getIdentifierCString(), result
);
5840 result
= kOSKextReturnStartStopError
;
5848 /*********************************************************************
5849 *********************************************************************/
5851 OSKext::unload(void)
5853 OSReturn result
= kOSReturnError
;
5855 uint32_t num_kmod_refs
= 0;
5857 if (!sUnloadEnabled
) {
5859 kOSKextLogErrorLevel
|
5861 "Kext unloading is disabled (%s).",
5862 this->getIdentifierCString());
5864 result
= kOSKextReturnDisabled
;
5868 /* Refuse to unload if we have clients or instances. It is up to
5869 * the caller to make sure those aren't true.
5871 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
5872 // xxx - Don't log under errors? this is more of an info thing
5874 kOSKextLogErrorLevel
|
5875 kOSKextLogKextBookkeepingFlag
,
5876 "Can't unload kext %s; outstanding references (linkage or tracking object).",
5877 getIdentifierCString());
5878 result
= kOSKextReturnInUse
;
5882 if (hasOSMetaClassInstances()) {
5884 kOSKextLogErrorLevel
|
5885 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
5886 "Can't unload kext %s; classes have instances:",
5887 getIdentifierCString());
5888 reportOSMetaClassInstances(kOSKextLogErrorLevel
|
5889 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
);
5890 result
= kOSKextReturnInUse
;
5895 result
= kOSReturnSuccess
;
5899 if (isKernelComponent()) {
5900 result
= kOSKextReturnInvalidArgument
;
5904 /* Note that the kext is unloading before running any code that
5905 * might be in the kext (request callbacks, module stop function).
5906 * We will deny certain requests made against a kext in the process
5909 flags
.unloading
= 1;
5911 /* Update the string describing the last kext to unload in case we panic.
5913 savePanicString(/* isLoading */ false);
5917 if (result
!= KERN_SUCCESS
) {
5919 kOSKextLogErrorLevel
|
5921 "Kext %s can't unload - module stop returned 0x%x.",
5922 getIdentifierCString(), (unsigned)result
);
5923 result
= kOSKextReturnStartStopError
;
5929 kOSKextLogProgressLevel
|
5931 "Kext %s unloading.",
5932 getIdentifierCString());
5934 /* Even if we don't call the stop function, we want to be sure we
5935 * have no OSMetaClass references before unloading the kext executable
5936 * from memory. OSMetaClasses may have pointers into the kext executable
5937 * and that would cause a panic on OSKext::free() when metaClasses is freed.
5940 metaClasses
->flushCollection();
5943 /* Remove the kext from the list of loaded kexts, patch the gap
5944 * in the kmod_info_t linked list, and reset "kmod" to point to the
5945 * last loaded kext that isn't the fake kernel kext (sKernelKext).
5947 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
5948 if (index
!= (unsigned int)-1) {
5950 sLoadedKexts
->removeObject(index
);
5952 OSKext
* nextKext
= OSDynamicCast(OSKext
,
5953 sLoadedKexts
->getObject(index
));
5957 OSKext
* gapKext
= OSDynamicCast(OSKext
,
5958 sLoadedKexts
->getObject(index
- 1));
5960 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
5962 } else /* index == 0 */ {
5963 nextKext
->kmod_info
->next
= NULL
;
5967 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
5968 if (lastKext
&& !lastKext
->isKernel()) {
5969 kmod
= lastKext
->kmod_info
;
5971 kmod
= NULL
; // clear the global kmod variable
5975 /* Clear out the kmod references that we're keeping for compatibility
5976 * with current panic backtrace code & kgmacros.
5977 * xxx - will want to update those bits sometime and remove this.
5979 num_kmod_refs
= getNumDependencies();
5980 if (num_kmod_refs
&& kmod_info
&& kmod_info
->reference_list
) {
5981 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5982 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5983 ref
->info
->reference_count
--;
5985 kfree(kmod_info
->reference_list
,
5986 num_kmod_refs
* sizeof(kmod_reference_t
));
5990 unregisterWithDTrace();
5991 #endif /* CONFIG_DTRACE */
5993 notifyKextUnloadObservers(this);
5995 /* Unwire and free the linked executable.
5997 if (linkedExecutable
) {
5999 if (!isInterface()) {
6000 kernel_segment_command_t
*seg
= NULL
;
6001 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6005 kOSKextLogErrorLevel
|
6007 "Failed to free kext %s; couldn't find the kext map.",
6008 getIdentifierCString());
6009 result
= kOSKextReturnInternalError
;
6014 kOSKextLogProgressLevel
|
6016 "Kext %s unwiring and unmapping linked executable.",
6017 getIdentifierCString());
6019 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6021 if (segmentShouldBeWired(seg
)) {
6022 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6023 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6024 if (result
!= KERN_SUCCESS
) {
6026 kOSKextLogErrorLevel
|
6028 "Failed to unwire kext %s.",
6029 getIdentifierCString());
6030 result
= kOSKextReturnInternalError
;
6035 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6039 OSSafeReleaseNULL(linkedExecutable
);
6042 /* An interface kext has a fake kmod_info that was allocated,
6043 * so we have to free it.
6045 if (isInterface()) {
6046 kfree(kmod_info
, sizeof(kmod_info_t
));
6051 flags
.loaded
= false;
6052 flushDependencies();
6054 /* save a copy of the bundle ID for us to check when deciding to
6055 * rebuild the kernel cache file. If a kext was already in the kernel
6056 * cache and unloaded then later loaded we do not need to rebuild the
6057 * kernel cache. 9055303
6059 if (isPrelinked()) {
6060 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6061 IORecursiveLockLock(sKextLock
);
6062 if (sUnloadedPrelinkedKexts
) {
6063 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6065 IORecursiveLockUnlock(sKextLock
);
6070 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6071 "Kext %s unloaded.", getIdentifierCString());
6073 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6074 OSDynamicCast(OSString
, bundleID
));
6077 OSKext::saveLoadedKextPanicList();
6078 OSKext::updateLoadedKextSummaries();
6080 flags
.unloading
= 0;
6084 /*********************************************************************
6085 * Assumes sKextLock is held.
6086 *********************************************************************/
6089 OSKext::queueKextNotification(
6090 const char * notificationName
,
6091 OSString
* kextIdentifier
)
6093 OSReturn result
= kOSReturnError
;
6094 OSDictionary
* loadRequest
= NULL
; // must release
6096 if (!kextIdentifier
) {
6097 result
= kOSKextReturnInvalidArgument
;
6101 /* Create a new request unless one is already sitting
6102 * in sKernelRequests for this bundle identifier
6104 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6105 if (result
!= kOSReturnSuccess
) {
6108 if (!_OSKextSetRequestArgument(loadRequest
,
6109 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6111 result
= kOSKextReturnNoMemory
;
6114 if (!sKernelRequests
->setObject(loadRequest
)) {
6115 result
= kOSKextReturnNoMemory
;
6119 /* We might want to only queue the notification if kextd is active,
6120 * but that wouldn't work for embedded. Note that we don't care if
6121 * the ping immediately succeeds here so don't do anything with the
6122 * result of this call.
6124 OSKext::pingKextd();
6126 result
= kOSReturnSuccess
;
6129 OSSafeRelease(loadRequest
);
6134 /*********************************************************************
6135 *********************************************************************/
6137 _OSKextConsiderDestroyingLinkContext(
6138 __unused thread_call_param_t p0
,
6139 __unused thread_call_param_t p1
)
6141 /* Take multiple locks in the correct order.
6143 IORecursiveLockLock(sKextLock
);
6144 IORecursiveLockLock(sKextInnerLock
);
6146 /* The first time we destroy the kxldContext is in the first
6147 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6148 * before calling this function. Thereafter any call to this function
6149 * will actually destroy the context.
6151 if (sConsiderUnloadsCalled
&& sKxldContext
) {
6152 kxld_destroy_context(sKxldContext
);
6153 sKxldContext
= NULL
;
6156 /* Free the thread_call that was allocated to execute this function.
6158 if (sDestroyLinkContextThread
) {
6159 if (!thread_call_free(sDestroyLinkContextThread
)) {
6160 OSKextLog(/* kext */ NULL
,
6161 kOSKextLogErrorLevel
|
6162 kOSKextLogGeneralFlag
,
6163 "thread_call_free() failed for kext link context.");
6165 sDestroyLinkContextThread
= 0;
6168 IORecursiveLockUnlock(sKextInnerLock
);
6169 IORecursiveLockUnlock(sKextLock
);
6174 /*********************************************************************
6175 * Destroying the kxldContext requires checking variables under both
6176 * sKextInnerLock and sKextLock, so we do it on a separate thread
6177 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6178 * call relationship.
6180 * This function must be invoked with sKextInnerLock held.
6181 * Do not call any function that takes sKextLock here!
6182 *********************************************************************/
6185 OSKext::considerDestroyingLinkContext(void)
6187 IORecursiveLockLock(sKextInnerLock
);
6189 /* If we have already queued a thread to destroy the link context,
6190 * don't bother resetting; that thread will take care of it.
6192 if (sDestroyLinkContextThread
) {
6196 /* The function to be invoked in the thread will deallocate
6197 * this thread_call, so don't share it around.
6199 sDestroyLinkContextThread
= thread_call_allocate(
6200 &_OSKextConsiderDestroyingLinkContext
, 0);
6201 if (!sDestroyLinkContextThread
) {
6202 OSKextLog(/* kext */ NULL
,
6203 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
| kOSKextLogLinkFlag
,
6204 "Can't create thread to destroy kext link context.");
6208 thread_call_enter(sDestroyLinkContextThread
);
6211 IORecursiveLockUnlock(sKextInnerLock
);
6216 #pragma mark Autounload
6218 /*********************************************************************
6219 * This is a static method because the kext will be deallocated if it
6221 *********************************************************************/
6224 OSKext::autounloadKext(OSKext
* aKext
)
6226 OSReturn result
= kOSKextReturnInUse
;
6228 /* Check for external references to this kext (usu. dependents),
6229 * instances of defined classes (or classes derived from them),
6230 * outstanding requests.
6232 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
6233 !aKext
->flags
.autounloadEnabled
||
6234 aKext
->isKernelComponent()) {
6239 /* Skip a delay-autounload kext, once.
6241 if (aKext
->flags
.delayAutounload
) {
6243 kOSKextLogProgressLevel
|
6244 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6245 "Kext %s has delayed autounload set; skipping and clearing flag.",
6246 aKext
->getIdentifierCString());
6247 aKext
->flags
.delayAutounload
= 0;
6251 if (aKext
->hasOSMetaClassInstances() ||
6252 aKext
->countRequestCallbacks()) {
6256 result
= OSKext::removeKext(aKext
);
6263 /*********************************************************************
6264 *********************************************************************/
6266 _OSKextConsiderUnloads(
6267 __unused thread_call_param_t p0
,
6268 __unused thread_call_param_t p1
)
6270 bool didUnload
= false;
6271 unsigned int count
, i
;
6273 /* Take multiple locks in the correct order
6274 * (note also sKextSummaries lock further down).
6276 IORecursiveLockLock(sKextLock
);
6277 IORecursiveLockLock(sKextInnerLock
);
6279 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6281 IOLockLock(sKextSummariesLock
);
6283 /* If there is an old kext summary, free that now.
6285 if (sPrevLoadedKextSummaries
) {
6286 kmem_free(kernel_map
, (vm_offset_t
)sPrevLoadedKextSummaries
,
6287 sPrevLoadedKextSummariesAllocSize
);
6288 sPrevLoadedKextSummaries
= NULL
;
6289 sPrevLoadedKextSummariesAllocSize
= 0;
6292 IOLockUnlock(sKextSummariesLock
);
6294 /* If the system is powering down, don't try to unload anything.
6300 OSKextLog(/* kext */ NULL
,
6301 kOSKextLogProgressLevel
|
6303 "Checking for unused kexts to autounload.");
6306 * Remove any request callbacks marked as stale,
6307 * and mark as stale any currently in flight.
6309 count
= sRequestCallbackRecords
->getCount();
6313 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
6314 sRequestCallbackRecords
->getObject(i
));
6315 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
6316 callbackRecord
->getObject(kKextRequestStaleKey
));
6318 if (stale
== kOSBooleanTrue
) {
6319 OSKext::invokeRequestCallback(callbackRecord
,
6320 kOSKextReturnTimeout
);
6322 callbackRecord
->setObject(kKextRequestStaleKey
,
6329 * Make multiple passes through the array of loaded kexts until
6330 * we don't unload any. This handles unwinding of dependency
6331 * chains. We have to go *backwards* through the array because
6332 * kexts are removed from it when unloaded, and we cannot make
6333 * a copy or we'll mess up the retain counts we rely on to
6334 * check whether a kext will unload. If only we could have
6335 * nonretaining collections like CF has....
6340 count
= sLoadedKexts
->getCount();
6344 OSKext
* thisKext
= OSDynamicCast(OSKext
,
6345 sLoadedKexts
->getObject(i
));
6346 didUnload
= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
6349 } while (didUnload
);
6352 sConsiderUnloadsPending
= false;
6353 sConsiderUnloadsExecuted
= true;
6355 (void) OSKext::considerRebuildOfPrelinkedKernel();
6357 IORecursiveLockUnlock(sKextInnerLock
);
6358 IORecursiveLockUnlock(sKextLock
);
6363 /*********************************************************************
6364 * Do not call any function that takes sKextLock here!
6365 *********************************************************************/
6366 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
6370 IORecursiveLockLock(sKextInnerLock
);
6372 if (!sUnloadCallout
) {
6373 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, 0);
6376 /* we only reset delay value for unloading if we already have something
6377 * pending. rescheduleOnlyFlag should not start the count down.
6379 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
6383 thread_call_cancel(sUnloadCallout
);
6384 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
6385 clock_interval_to_deadline(sConsiderUnloadDelay
,
6386 1000 * 1000 * 1000, &when
);
6388 OSKextLog(/* kext */ NULL
,
6389 kOSKextLogProgressLevel
|
6391 "%scheduling %sscan for unused kexts in %lu seconds.",
6392 sConsiderUnloadsPending
? "Res" : "S",
6393 sConsiderUnloadsCalled
? "" : "initial ",
6394 (unsigned long)sConsiderUnloadDelay
);
6396 sConsiderUnloadsPending
= true;
6397 thread_call_enter_delayed(sUnloadCallout
, when
);
6401 /* The kxld context should be reused throughout boot. We mark the end of
6402 * period as the first time considerUnloads() is called, and we destroy
6403 * the first kxld context in that function. Afterwards, it will be
6404 * destroyed in flushNonloadedKexts.
6406 if (!sConsiderUnloadsCalled
) {
6407 sConsiderUnloadsCalled
= true;
6408 OSKext::considerDestroyingLinkContext();
6411 IORecursiveLockUnlock(sKextInnerLock
);
6415 /*********************************************************************
6416 * Do not call any function that takes sKextLock here!
6417 *********************************************************************/
6420 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
)
6422 IORecursiveLockLock(sKextInnerLock
);
6424 /* If the system is going to sleep, cancel the reaper thread timer,
6425 * and note that we're in a sleep state in case it just fired but hasn't
6426 * taken the lock yet. If we are coming back from sleep, just
6427 * clear the sleep flag; IOService's normal operation will cause
6428 * unloads to be considered soon enough.
6430 if (messageType
== kIOMessageSystemWillSleep
) {
6431 if (sUnloadCallout
) {
6432 thread_call_cancel(sUnloadCallout
);
6434 sSystemSleep
= true;
6435 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
6436 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
6437 sSystemSleep
= false;
6438 clock_get_uptime(&sLastWakeTime
);
6440 IORecursiveLockUnlock(sKextInnerLock
);
6442 return kIOReturnSuccess
;
6449 #pragma mark Prelinked Kernel
6451 /*********************************************************************
6452 * Do not access sConsiderUnloads... variables other than
6453 * sConsiderUnloadsExecuted in this function. They are guarded by a
6455 *********************************************************************/
6458 OSKext::considerRebuildOfPrelinkedKernel(void)
6460 static bool requestedPrelink
= false;
6461 OSReturn checkResult
= kOSReturnError
;
6462 OSDictionary
* prelinkRequest
= NULL
; // must release
6463 OSCollectionIterator
* kextIterator
= NULL
; // must release
6464 const OSSymbol
* thisID
= NULL
; // do not release
6465 bool doRebuild
= false;
6466 AbsoluteTime my_abstime
;
6470 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
6471 if (requestedPrelink
|| !sPrelinkBoot
) {
6475 /* no direct return from this point */
6476 IORecursiveLockLock(sKextLock
);
6478 /* We need to wait for kextd to get up and running with unloads already done
6479 * and any new startup kexts loaded.
6481 if (!sConsiderUnloadsExecuted
||
6482 !sDeferredLoadSucceeded
) {
6486 /* we really only care about boot / system start up related kexts so bail
6487 * if we're here after REBUILD_MAX_TIME.
6489 if (!_OSKextInPrelinkRebuildWindow()) {
6490 OSKextLog(/* kext */ NULL
,
6491 kOSKextLogArchiveFlag
,
6492 "%s prebuild rebuild has expired",
6494 requestedPrelink
= true;
6498 /* we do not want to trigger a rebuild if we get here too close to waking
6499 * up. (see radar 10233768)
6501 IORecursiveLockLock(sKextInnerLock
);
6503 clock_get_uptime(&my_abstime
);
6504 delta_secs
= MINIMUM_WAKEUP_SECONDS
+ 1;
6505 if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) {
6506 SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
);
6507 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
6508 delta_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
6510 IORecursiveLockUnlock(sKextInnerLock
);
6512 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
6513 /* too close to time of last wake from sleep */
6516 requestedPrelink
= true;
6518 /* Now it's time to see if we have a reason to rebuild. We may have done
6519 * some loads and unloads but the kernel cache didn't actually change.
6520 * We will rebuild if any kext is not marked prelinked AND is not in our
6521 * list of prelinked kexts that got unloaded. (see radar 9055303)
6523 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
6524 if (!kextIterator
) {
6528 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
6529 OSKext
* thisKext
; // do not release
6531 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
6532 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
6536 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
6539 /* kext is loaded and was not in current kernel cache so let's rebuild
6542 OSKextLog(/* kext */ NULL
,
6543 kOSKextLogArchiveFlag
,
6544 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
6545 thisKext
->bundleID
->getCStringNoCopy());
6548 sUnloadedPrelinkedKexts
->flushCollection();
6554 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
6556 if (checkResult
!= kOSReturnSuccess
) {
6560 if (!sKernelRequests
->setObject(prelinkRequest
)) {
6564 OSKext::pingKextd();
6567 IORecursiveLockUnlock(sKextLock
);
6568 OSSafeRelease(prelinkRequest
);
6569 OSSafeRelease(kextIterator
);
6575 #pragma mark Dependencies
6577 /*********************************************************************
6578 *********************************************************************/
6580 OSKext::resolveDependencies(
6581 OSArray
* loopStack
)
6583 bool result
= false;
6584 OSArray
* localLoopStack
= NULL
; // must release
6585 bool addedToLoopStack
= false;
6586 OSDictionary
* libraries
= NULL
; // do not release
6587 OSCollectionIterator
* libraryIterator
= NULL
; // must release
6588 OSString
* libraryID
= NULL
; // do not release
6589 OSString
* infoString
= NULL
; // do not release
6590 OSString
* readableString
= NULL
; // do not release
6591 OSKext
* libraryKext
= NULL
; // do not release
6592 bool hasRawKernelDependency
= false;
6593 bool hasKernelDependency
= false;
6594 bool hasKPIDependency
= false;
6595 bool hasPrivateKPIDependency
= false;
6598 /* A kernel component will automatically have this flag set,
6599 * and a loaded kext should also have it set (as should all its
6600 * loaded dependencies).
6602 if (flags
.hasAllDependencies
) {
6607 /* Check for loops in the dependency graph.
6610 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
6612 kOSKextLogErrorLevel
|
6613 kOSKextLogDependenciesFlag
,
6614 "Kext %s has a dependency loop; can't resolve dependencies.",
6615 getIdentifierCString());
6620 kOSKextLogStepLevel
|
6621 kOSKextLogDependenciesFlag
,
6622 "Kext %s resolving dependencies.",
6623 getIdentifierCString());
6625 loopStack
= OSArray::withCapacity(6); // any small capacity will do
6628 kOSKextLogErrorLevel
|
6629 kOSKextLogDependenciesFlag
,
6630 "Kext %s can't create bookkeeping stack to resolve dependencies.",
6631 getIdentifierCString());
6634 localLoopStack
= loopStack
;
6636 if (!loopStack
->setObject(this)) {
6638 kOSKextLogErrorLevel
|
6639 kOSKextLogDependenciesFlag
,
6640 "Kext %s - internal error resolving dependencies.",
6641 getIdentifierCString());
6644 addedToLoopStack
= true;
6646 /* Purge any existing kexts in the dependency list and start over.
6648 flushDependencies();
6651 kOSKextLogErrorLevel
|
6652 kOSKextLogDependenciesFlag
,
6653 "Kext %s - internal error resolving dependencies.",
6654 getIdentifierCString());
6657 libraries
= OSDynamicCast(OSDictionary
,
6658 getPropertyForHostArch(kOSBundleLibrariesKey
));
6659 if (libraries
== NULL
|| libraries
->getCount() == 0) {
6661 kOSKextLogErrorLevel
|
6662 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6663 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
6664 getIdentifierCString(), kOSBundleLibrariesKey
);
6668 /* Make a new array to hold the dependencies (flush freed the old one).
6670 dependencies
= OSArray::withCapacity(libraries
->getCount());
6671 if (!dependencies
) {
6673 kOSKextLogErrorLevel
|
6674 kOSKextLogDependenciesFlag
,
6675 "Kext %s - can't allocate dependencies array.",
6676 getIdentifierCString());
6680 // xxx - compat: We used to add an implicit dependency on kernel 6.0
6681 // xxx - compat: if none were declared.
6683 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
6684 if (!libraryIterator
) {
6686 kOSKextLogErrorLevel
|
6687 kOSKextLogDependenciesFlag
,
6688 "Kext %s - can't allocate dependencies iterator.",
6689 getIdentifierCString());
6693 while ((libraryID
= OSDynamicCast(OSString
,
6694 libraryIterator
->getNextObject()))) {
6696 const char * library_id
= libraryID
->getCStringNoCopy();
6698 OSString
* libraryVersion
= OSDynamicCast(OSString
,
6699 libraries
->getObject(libraryID
));
6700 if (libraryVersion
== NULL
) {
6702 kOSKextLogErrorLevel
|
6703 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6704 "Kext %s - illegal type in OSBundleLibraries.",
6705 getIdentifierCString());
6709 OSKextVersion libraryVers
=
6710 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
6711 if (libraryVers
== -1) {
6713 kOSKextLogErrorLevel
|
6714 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6715 "Kext %s - invalid library version %s.",
6716 getIdentifierCString(),
6717 libraryVersion
->getCStringNoCopy());
6721 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
6722 if (libraryKext
== NULL
) {
6724 kOSKextLogErrorLevel
|
6725 kOSKextLogDependenciesFlag
,
6726 "Kext %s - library kext %s not found.",
6727 getIdentifierCString(), library_id
);
6731 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
6733 kOSKextLogErrorLevel
|
6734 kOSKextLogDependenciesFlag
,
6735 "Kext %s - library kext %s not compatible "
6736 "with requested version %s.",
6737 getIdentifierCString(), library_id
,
6738 libraryVersion
->getCStringNoCopy());
6742 /* If a nonprelinked library somehow got into the mix for a
6743 * prelinked kext, at any point in the chain, we must fail
6744 * because the prelinked relocs for the library will be all wrong.
6746 if (this->isPrelinked() &&
6747 libraryKext
->declaresExecutable() &&
6748 !libraryKext
->isPrelinked()) {
6751 kOSKextLogErrorLevel
|
6752 kOSKextLogDependenciesFlag
,
6753 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
6754 getIdentifierCString(), library_id
,
6755 libraryVersion
->getCStringNoCopy());
6759 if (!libraryKext
->resolveDependencies(loopStack
)) {
6763 /* Add the library directly only if it has an executable to link.
6764 * Otherwise it's just used to collect other dependencies, so put
6765 * *its* dependencies on the list for this kext.
6767 // xxx - We are losing info here; would like to make fake entries or
6768 // xxx - keep these in the dependency graph for loaded kexts.
6769 // xxx - I really want to make kernel components not a special case!
6770 if (libraryKext
->declaresExecutable() ||
6771 libraryKext
->isInterface()) {
6773 if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) {
6774 dependencies
->setObject(libraryKext
);
6777 kOSKextLogDetailLevel
|
6778 kOSKextLogDependenciesFlag
,
6779 "Kext %s added dependency %s.",
6780 getIdentifierCString(),
6781 libraryKext
->getIdentifierCString());
6784 int numLibDependencies
= libraryKext
->getNumDependencies();
6785 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
6788 if (numLibDependencies
) {
6789 // xxx - this msg level should be 1 lower than the per-kext one
6791 kOSKextLogDetailLevel
|
6792 kOSKextLogDependenciesFlag
,
6793 "Kext %s pulling %d dependencies from codeless library %s.",
6794 getIdentifierCString(),
6796 libraryKext
->getIdentifierCString());
6798 for (index
= 0; index
< numLibDependencies
; index
++) {
6799 OSKext
* thisLibDependency
= OSDynamicCast(OSKext
,
6800 libraryDependencies
->getObject(index
));
6801 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) {
6802 dependencies
->setObject(thisLibDependency
);
6804 kOSKextLogDetailLevel
|
6805 kOSKextLogDependenciesFlag
,
6806 "Kext %s added dependency %s from codeless library %s.",
6807 getIdentifierCString(),
6808 thisLibDependency
->getIdentifierCString(),
6809 libraryKext
->getIdentifierCString());
6814 if ((strlen(library_id
) == strlen(KERNEL_LIB
)) &&
6815 0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) {
6817 hasRawKernelDependency
= true;
6818 } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) {
6819 hasKernelDependency
= true;
6820 } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) {
6821 hasKPIDependency
= true;
6822 if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) {
6823 hasPrivateKPIDependency
= true;
6828 if (hasRawKernelDependency
) {
6830 kOSKextLogErrorLevel
|
6831 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6832 "Error - kext %s declares a dependency on %s, which is not permitted.",
6833 getIdentifierCString(), KERNEL_LIB
);
6837 if (hasKernelDependency
) {
6839 kOSKextLogErrorLevel
|
6840 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6841 "Error - kext %s declares %s dependencies. "
6842 "Only %s* dependencies are supported for 64-bit kexts.",
6843 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
6846 if (!hasKPIDependency
) {
6848 kOSKextLogWarningLevel
|
6849 kOSKextLogDependenciesFlag
,
6850 "Warning - kext %s declares no %s* dependencies. "
6851 "If it uses any KPIs, the link may fail with undefined symbols.",
6852 getIdentifierCString(), KPI_LIB_PREFIX
);
6854 #else /* __LP64__ */
6855 // xxx - will change to flatly disallow "kernel" dependencies at some point
6856 // xxx - is it invalid to do both "com.apple.kernel" and any
6857 // xxx - "com.apple.kernel.*"?
6859 if (hasKernelDependency
&& hasKPIDependency
) {
6861 kOSKextLogWarningLevel
|
6862 kOSKextLogDependenciesFlag
,
6863 "Warning - kext %s has immediate dependencies on both "
6864 "%s* and %s* components; use only one style.",
6865 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
6868 if (!hasKernelDependency
&& !hasKPIDependency
) {
6869 // xxx - do we want to use validation flag for these too?
6871 kOSKextLogWarningLevel
|
6872 kOSKextLogDependenciesFlag
,
6873 "Warning - %s declares no kernel dependencies; using %s.",
6874 getIdentifierCString(), KERNEL6_LIB
);
6875 OSKext
* kernelKext
= OSDynamicCast(OSKext
,
6876 sKextsByID
->getObject(KERNEL6_LIB
));
6878 dependencies
->setObject(kernelKext
);
6881 kOSKextLogErrorLevel
|
6882 kOSKextLogDependenciesFlag
,
6883 "Error - Library %s not found for %s.",
6884 KERNEL6_LIB
, getIdentifierCString());
6888 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
6889 * its indirect dependencies to simulate old-style linking. XXX - Should
6890 * check for duplicates.
6892 if (!hasKPIDependency
) {
6895 flags
.hasBleedthrough
= true;
6897 count
= getNumDependencies();
6899 /* We add to the dependencies array in this loop, but do not iterate
6900 * past its original count.
6902 for (i
= 0; i
< count
; i
++) {
6903 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
6904 dependencies
->getObject(i
));
6905 dependencyKext
->addBleedthroughDependencies(dependencies
);
6908 #endif /* __LP64__ */
6910 if (hasPrivateKPIDependency
) {
6911 bool hasApplePrefix
= false;
6912 bool infoCopyrightIsValid
= false;
6913 bool readableCopyrightIsValid
= false;
6915 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
6918 infoString
= OSDynamicCast(OSString
,
6919 getPropertyForHostArch("CFBundleGetInfoString"));
6921 infoCopyrightIsValid
=
6922 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
6925 readableString
= OSDynamicCast(OSString
,
6926 getPropertyForHostArch("NSHumanReadableCopyright"));
6927 if (readableString
) {
6928 readableCopyrightIsValid
=
6929 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
6932 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
6934 kOSKextLogErrorLevel
|
6935 kOSKextLogDependenciesFlag
,
6936 "Error - kext %s declares a dependency on %s. "
6937 "Only Apple kexts may declare a dependency on %s.",
6938 getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
);
6944 flags
.hasAllDependencies
= 1;
6948 if (addedToLoopStack
) {
6949 count
= loopStack
->getCount();
6950 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
6951 loopStack
->removeObject(count
- 1);
6954 kOSKextLogErrorLevel
|
6955 kOSKextLogDependenciesFlag
,
6956 "Kext %s - internal error resolving dependencies.",
6957 getIdentifierCString());
6961 if (result
&& localLoopStack
) {
6963 kOSKextLogStepLevel
|
6964 kOSKextLogDependenciesFlag
,
6965 "Kext %s successfully resolved dependencies.",
6966 getIdentifierCString());
6969 OSSafeRelease(localLoopStack
);
6970 OSSafeRelease(libraryIterator
);
6975 /*********************************************************************
6976 *********************************************************************/
6978 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
6980 bool result
= false;
6981 unsigned int dependencyIndex
, dependencyCount
;
6983 dependencyCount
= getNumDependencies();
6985 for (dependencyIndex
= 0;
6986 dependencyIndex
< dependencyCount
;
6987 dependencyIndex
++) {
6989 OSKext
* dependency
= OSDynamicCast(OSKext
,
6990 dependencies
->getObject(dependencyIndex
));
6993 kOSKextLogErrorLevel
|
6994 kOSKextLogDependenciesFlag
,
6995 "Kext %s - internal error propagating compatibility dependencies.",
6996 getIdentifierCString());
6999 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7000 anArray
->setObject(dependency
);
7002 dependency
->addBleedthroughDependencies(anArray
);
7011 /*********************************************************************
7012 *********************************************************************/
7014 OSKext::flushDependencies(bool forceFlag
)
7016 bool result
= false;
7018 /* Only clear the dependencies if the kext isn't loaded;
7019 * we need the info for loaded kexts to track references.
7021 if (!isLoaded() || forceFlag
) {
7023 // xxx - check level
7025 kOSKextLogProgressLevel
|
7026 kOSKextLogDependenciesFlag
,
7027 "Kext %s flushing dependencies.",
7028 getIdentifierCString());
7029 OSSafeReleaseNULL(dependencies
);
7032 if (!isKernelComponent()) {
7033 flags
.hasAllDependencies
= 0;
7041 /*********************************************************************
7042 *********************************************************************/
7044 OSKext::getNumDependencies(void)
7046 if (!dependencies
) {
7049 return dependencies
->getCount();
7052 /*********************************************************************
7053 *********************************************************************/
7055 OSKext::getDependencies(void)
7057 return dependencies
;
7061 #pragma mark OSMetaClass Support
7063 /*********************************************************************
7064 *********************************************************************/
7067 OSMetaClass
* aClass
,
7068 uint32_t numClasses
)
7070 OSReturn result
= kOSMetaClassNoInsKModSet
;
7073 metaClasses
= OSSet::withCapacity(numClasses
);
7079 if (metaClasses
->containsObject(aClass
)) {
7081 kOSKextLogWarningLevel
|
7083 "Notice - kext %s has already registered class %s.",
7084 getIdentifierCString(),
7085 aClass
->getClassName());
7086 result
= kOSReturnSuccess
;
7090 if (!metaClasses
->setObject(aClass
)) {
7094 kOSKextLogDetailLevel
|
7096 "Kext %s registered class %s.",
7097 getIdentifierCString(),
7098 aClass
->getClassName());
7101 if (!flags
.autounloadEnabled
) {
7102 const OSMetaClass
* metaScan
= NULL
; // do not release
7104 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7105 if (metaScan
== OSTypeID(IOService
)) {
7108 kOSKextLogProgressLevel
|
7110 "Kext %s has IOService subclass %s; enabling autounload.",
7111 getIdentifierCString(),
7112 aClass
->getClassName());
7114 flags
.autounloadEnabled
= 1;
7120 notifyAddClassObservers(this, aClass
, flags
);
7122 result
= kOSReturnSuccess
;
7125 if (result
!= kOSReturnSuccess
) {
7127 kOSKextLogErrorLevel
|
7129 "Kext %s failed to register class %s.",
7130 getIdentifierCString(),
7131 aClass
->getClassName());
7137 /*********************************************************************
7138 *********************************************************************/
7140 OSKext::removeClass(
7141 OSMetaClass
* aClass
)
7143 OSReturn result
= kOSMetaClassNoKModSet
;
7149 if (!metaClasses
->containsObject(aClass
)) {
7151 kOSKextLogWarningLevel
|
7153 "Notice - kext %s asked to unregister unknown class %s.",
7154 getIdentifierCString(),
7155 aClass
->getClassName());
7156 result
= kOSReturnSuccess
;
7161 kOSKextLogDetailLevel
|
7163 "Kext %s unregistering class %s.",
7164 getIdentifierCString(),
7165 aClass
->getClassName());
7167 metaClasses
->removeObject(aClass
);
7169 notifyRemoveClassObservers(this, aClass
, flags
);
7171 result
= kOSReturnSuccess
;
7174 if (result
!= kOSReturnSuccess
) {
7176 kOSKextLogErrorLevel
|
7178 "Failed to unregister kext %s class %s.",
7179 getIdentifierCString(),
7180 aClass
->getClassName());
7185 /*********************************************************************
7186 *********************************************************************/
7188 OSKext::getMetaClasses(void)
7193 /*********************************************************************
7194 *********************************************************************/
7196 OSKext::hasOSMetaClassInstances(void)
7198 bool result
= false;
7199 OSCollectionIterator
* classIterator
= NULL
; // must release
7200 OSMetaClass
* checkClass
= NULL
; // do not release
7206 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7207 if (!classIterator
) {
7208 // xxx - log alloc failure?
7211 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7212 if (checkClass
->getInstanceCount()) {
7220 OSSafeRelease(classIterator
);
7224 /*********************************************************************
7225 *********************************************************************/
7228 OSKext::reportOSMetaClassInstances(
7229 const char * kextIdentifier
,
7230 OSKextLogSpec msgLogSpec
)
7232 OSKext
* theKext
= NULL
; // must release
7234 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
7239 theKext
->reportOSMetaClassInstances(msgLogSpec
);
7241 OSSafeRelease(theKext
);
7245 /*********************************************************************
7246 *********************************************************************/
7248 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
7250 OSCollectionIterator
* classIterator
= NULL
; // must release
7251 OSMetaClass
* checkClass
= NULL
; // do not release
7257 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7258 if (!classIterator
) {
7261 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7262 if (checkClass
->getInstanceCount()) {
7265 " Kext %s class %s has %d instance%s.",
7266 getIdentifierCString(),
7267 checkClass
->getClassName(),
7268 checkClass
->getInstanceCount(),
7269 checkClass
->getInstanceCount() == 1 ? "" : "s");
7274 OSSafeRelease(classIterator
);
7279 #pragma mark User-Space Requests
7281 /*********************************************************************
7282 * XXX - this function is a big ugly mess
7283 *********************************************************************/
7286 OSKext::handleRequest(
7287 host_priv_t hostPriv
,
7288 OSKextLogSpec clientLogFilter
,
7289 char * requestBuffer
,
7290 uint32_t requestLength
,
7291 char ** responseOut
,
7292 uint32_t * responseLengthOut
,
7294 uint32_t * logInfoLengthOut
)
7296 OSReturn result
= kOSReturnError
;
7297 kern_return_t kmem_result
= KERN_FAILURE
;
7299 char * response
= NULL
; // returned by reference
7300 uint32_t responseLength
= 0;
7302 OSObject
* parsedXML
= NULL
; // must release
7303 OSDictionary
* requestDict
= NULL
; // do not release
7304 OSString
* errorString
= NULL
; // must release
7306 OSData
* responseData
= NULL
; // must release
7307 OSObject
* responseObject
= NULL
; // must release
7309 OSSerialize
* serializer
= NULL
; // must release
7311 OSArray
* logInfoArray
= NULL
; // must release
7313 OSString
* predicate
= NULL
; // do not release
7314 OSString
* kextIdentifier
= NULL
; // do not release
7315 OSArray
* kextIdentifiers
= NULL
; // do not release
7316 OSKext
* theKext
= NULL
; // do not release
7317 OSBoolean
* boolArg
= NULL
; // do not release
7319 bool hideTheSlide
= false;
7321 IORecursiveLockLock(sKextLock
);
7324 *responseOut
= NULL
;
7325 *responseLengthOut
= 0;
7329 *logInfoLengthOut
= 0;
7332 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
7334 /* XML must be nul-terminated.
7336 if (requestBuffer
[requestLength
- 1] != '\0') {
7337 OSKextLog(/* kext */ NULL
,
7338 kOSKextLogErrorLevel
|
7340 "Invalid request from user space (not nul-terminated).");
7341 result
= kOSKextReturnBadData
;
7344 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
7346 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
7349 const char * errorCString
= "(unknown error)";
7351 if (errorString
&& errorString
->getCStringNoCopy()) {
7352 errorCString
= errorString
->getCStringNoCopy();
7353 } else if (parsedXML
) {
7354 errorCString
= "not a dictionary";
7356 OSKextLog(/* kext */ NULL
,
7357 kOSKextLogErrorLevel
|
7359 "Error unserializing request from user space: %s.",
7361 result
= kOSKextReturnSerialization
;
7365 predicate
= _OSKextGetRequestPredicate(requestDict
);
7367 OSKextLog(/* kext */ NULL
,
7368 kOSKextLogErrorLevel
|
7370 "Recieved kext request from user space with no predicate.");
7371 result
= kOSKextReturnInvalidArgument
;
7375 OSKextLog(/* kext */ NULL
,
7376 kOSKextLogDebugLevel
|
7378 "Received '%s' request from user space.",
7379 predicate
->getCStringNoCopy());
7381 result
= kOSKextReturnNotPrivileged
;
7382 if (hostPriv
== HOST_PRIV_NULL
) {
7384 hideTheSlide
= true;
7386 /* must be root to use these kext requests */
7387 if (predicate
->isEqualTo(kKextRequestPredicateGetKernelLoadAddress
) ) {
7388 OSKextLog(/* kext */ NULL
,
7389 kOSKextLogErrorLevel
|
7391 "Access Failure - must be root user.");
7397 /* Get common args in anticipation of use.
7399 kextIdentifier
= OSDynamicCast(OSString
, _OSKextGetRequestArgument(
7400 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7401 kextIdentifiers
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument(
7402 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7403 if (kextIdentifier
) {
7404 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
7406 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
7407 requestDict
, kKextRequestArgumentValueKey
));
7409 result
= kOSKextReturnInvalidArgument
;
7411 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
7412 if (!kextIdentifier
) {
7413 OSKextLog(/* kext */ NULL
,
7414 kOSKextLogErrorLevel
|
7416 "Invalid arguments to kext start request.");
7417 } else if (!theKext
) {
7418 OSKextLog(/* kext */ NULL
,
7419 kOSKextLogErrorLevel
|
7421 "Kext %s not found for start request.",
7422 kextIdentifier
->getCStringNoCopy());
7423 result
= kOSKextReturnNotFound
;
7425 result
= theKext
->start();
7428 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
7429 if (!kextIdentifier
) {
7430 OSKextLog(/* kext */ NULL
,
7431 kOSKextLogErrorLevel
|
7433 "Invalid arguments to kext stop request.");
7434 } else if (!theKext
) {
7435 OSKextLog(/* kext */ NULL
,
7436 kOSKextLogErrorLevel
|
7438 "Kext %s not found for stop request.",
7439 kextIdentifier
->getCStringNoCopy());
7440 result
= kOSKextReturnNotFound
;
7442 result
= theKext
->stop();
7445 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
7446 if (!kextIdentifier
) {
7447 OSKextLog(/* kext */ NULL
,
7448 kOSKextLogErrorLevel
|
7450 "Invalid arguments to kext unload request.");
7451 } else if (!theKext
) {
7452 OSKextLog(/* kext */ NULL
,
7453 kOSKextLogErrorLevel
|
7455 "Kext %s not found for unload request.",
7456 kextIdentifier
->getCStringNoCopy());
7457 result
= kOSKextReturnNotFound
;
7459 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
7460 _OSKextGetRequestArgument(requestDict
,
7461 kKextRequestArgumentTerminateIOServicesKey
));
7462 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
7465 } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
7466 result
= OSKext::dispatchResource(requestDict
);
7468 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
7469 OSBoolean
* delayAutounloadBool
= NULL
;
7470 OSObject
* infoKeysRaw
= NULL
;
7471 OSArray
* infoKeys
= NULL
;
7472 uint32_t infoKeysCount
= 0;
7474 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
7475 _OSKextGetRequestArgument(requestDict
,
7476 kKextRequestArgumentDelayAutounloadKey
));
7478 /* If asked to delay autounload, reset the timer if it's currently set.
7479 * (That is, don't schedule an unload if one isn't already pending.
7481 if (delayAutounloadBool
== kOSBooleanTrue
) {
7482 OSKext::considerUnloads(/* rescheduleOnly? */ true);
7485 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
7486 kKextRequestArgumentInfoKeysKey
);
7487 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
7488 if (infoKeysRaw
&& !infoKeys
) {
7489 OSKextLog(/* kext */ NULL
,
7490 kOSKextLogErrorLevel
|
7492 "Invalid arguments to kext info request.");
7497 infoKeysCount
= infoKeys
->getCount();
7498 for (uint32_t i
= 0; i
< infoKeysCount
; i
++) {
7499 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) {
7500 OSKextLog(/* kext */ NULL
,
7501 kOSKextLogErrorLevel
|
7503 "Invalid arguments to kext info request.");
7509 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
7510 if (!responseObject
) {
7511 result
= kOSKextReturnInternalError
;
7513 OSKextLog(/* kext */ NULL
,
7514 kOSKextLogDebugLevel
|
7516 "Returning loaded kext info.");
7517 result
= kOSReturnSuccess
;
7520 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelLoadAddress
)) {
7521 OSNumber
* addressNum
= NULL
; // released as responseObject
7522 kernel_segment_command_t
* textseg
= getsegbyname("__TEXT");
7525 OSKextLog(/* kext */ NULL
,
7526 kOSKextLogErrorLevel
|
7527 kOSKextLogGeneralFlag
| kOSKextLogIPCFlag
,
7528 "Can't find text segment for kernel load address.");
7529 result
= kOSReturnError
;
7533 OSKextLog(/* kext */ NULL
,
7534 kOSKextLogDebugLevel
|
7536 "Returning kernel load address 0x%llx.",
7537 (unsigned long long) textseg
->vmaddr
);
7539 addressNum
= OSNumber::withNumber((long long unsigned int)textseg
->vmaddr
,
7540 8 * sizeof(long long unsigned int));
7541 responseObject
= addressNum
;
7542 result
= kOSReturnSuccess
;
7544 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) {
7546 /* Hand the current sKernelRequests array to the caller
7547 * (who must release it), and make a new one.
7549 responseObject
= sKernelRequests
;
7550 sKernelRequests
= OSArray::withCapacity(0);
7551 sPostedKextLoadIdentifiers
->flushCollection();
7552 OSKextLog(/* kext */ NULL
,
7553 kOSKextLogDebugLevel
|
7555 "Returning kernel requests.");
7556 result
= kOSReturnSuccess
;
7558 } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) {
7560 /* Return the set of all requested bundle identifiers */
7561 responseObject
= sAllKextLoadIdentifiers
;
7562 responseObject
->retain();
7563 OSKextLog(/* kext */ NULL
,
7564 kOSKextLogDebugLevel
|
7566 "Returning load requests.");
7567 result
= kOSReturnSuccess
;
7571 * Now we have handle the request, or not. Gather up the response & logging
7572 * info to ship to user space.
7575 /* Note: Nothing in OSKext is supposed to retain requestDict,
7576 * but you never know....
7578 if (requestDict
->getRetainCount() > 1) {
7579 OSKextLog(/* kext */ NULL
,
7580 kOSKextLogWarningLevel
|
7582 "Request from user space still retained by a kext; "
7583 "probable memory leak.");
7586 if (responseData
&& responseObject
) {
7587 OSKextLog(/* kext */ NULL
,
7588 kOSKextLogErrorLevel
|
7590 "Mistakenly generated both data & plist responses to user request "
7591 "(returning only data).");
7594 if (responseData
&& responseData
->getLength() && responseOut
) {
7596 response
= (char *)responseData
->getBytesNoCopy();
7597 responseLength
= responseData
->getLength();
7598 } else if (responseOut
&& responseObject
) {
7599 serializer
= OSSerialize::withCapacity(0);
7601 result
= kOSKextReturnNoMemory
;
7605 if (!responseObject
->serialize(serializer
)) {
7606 OSKextLog(/* kext */ NULL
,
7607 kOSKextLogErrorLevel
|
7609 "Failed to serialize response to request from user space.");
7610 result
= kOSKextReturnSerialization
;
7614 response
= (char *)serializer
->text();
7615 responseLength
= serializer
->getLength();
7618 if (responseOut
&& response
) {
7621 /* This kmem_alloc sets the return value of the function.
7623 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
,
7625 if (kmem_result
!= KERN_SUCCESS
) {
7626 OSKextLog(/* kext */ NULL
,
7627 kOSKextLogErrorLevel
|
7629 "Failed to copy response to request from user space.");
7630 result
= kmem_result
;
7633 memcpy(buffer
, response
, responseLength
);
7634 *responseOut
= buffer
;
7635 *responseLengthOut
= responseLength
;
7641 /* Gather up the collected log messages for user space. Any messages
7642 * messages past this call will not make it up as log messages but
7643 * will be in the system log. Note that we ignore the return of the
7644 * serialize; it has no bearing on the operation at hand even if we
7645 * fail to get the log messages.
7647 logInfoArray
= OSKext::clearUserSpaceLogFilter();
7649 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
7650 (void)OSKext::serializeLogInfo(logInfoArray
,
7651 logInfoOut
, logInfoLengthOut
);
7654 IORecursiveLockUnlock(sKextLock
);
7656 OSSafeRelease(parsedXML
);
7657 OSSafeRelease(errorString
);
7658 OSSafeRelease(responseData
);
7659 OSSafeRelease(responseObject
);
7660 OSSafeRelease(serializer
);
7661 OSSafeRelease(logInfoArray
);
7666 /*********************************************************************
7667 *********************************************************************/
7670 OSKext::copyLoadedKextInfo(
7671 OSArray
* kextIdentifiers
,
7674 OSDictionary
* result
= NULL
;
7675 OSDictionary
* kextInfo
= NULL
; // must release
7677 uint32_t idCount
= 0;
7678 uint32_t idIndex
= 0;
7680 IORecursiveLockLock(sKextLock
);
7682 /* Empty list of bundle ids is equivalent to no list (get all).
7684 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
7685 kextIdentifiers
= NULL
;
7686 } else if (kextIdentifiers
) {
7687 idCount
= kextIdentifiers
->getCount();
7692 if (infoKeys
&& !infoKeys
->getCount()) {
7696 count
= sLoadedKexts
->getCount();
7697 result
= OSDictionary::withCapacity(count
);
7701 for (i
= 0; i
< count
; i
++) {
7702 OSKext
* thisKext
= NULL
; // do not release
7703 Boolean includeThis
= true;
7706 kextInfo
->release();
7709 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
7714 /* Skip current kext if we have a list of bundle IDs and
7715 * it isn't in the list.
7717 if (kextIdentifiers
) {
7718 const OSString
* thisKextID
= thisKext
->getIdentifier();
7720 includeThis
= false;
7722 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
7723 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
7724 kextIdentifiers
->getObject(idIndex
));
7725 if (thisKextID
->isEqualTo(thisRequestID
)) {
7736 kextInfo
= thisKext
->copyInfo(infoKeys
);
7738 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
7743 IORecursiveLockUnlock(sKextLock
);
7745 if (kextInfo
) kextInfo
->release();
7750 /*********************************************************************
7751 * Any info that needs to do allocations must goto finish on alloc
7752 * failure. Info that is just a lookup should just not set the object
7753 * if the info does not exist.
7754 *********************************************************************/
7755 #define _OSKextLoadInfoDictCapacity (12)
7758 OSKext::copyInfo(OSArray
* infoKeys
)
7760 OSDictionary
* result
= NULL
;
7761 bool success
= false;
7762 OSData
* headerData
= NULL
; // must release
7763 OSNumber
* cpuTypeNumber
= NULL
; // must release
7764 OSNumber
* cpuSubtypeNumber
= NULL
; // must release
7765 OSString
* versionString
= NULL
; // do not release
7766 uint32_t executablePathCStringSize
= 0;
7767 char * executablePathCString
= NULL
; // must release
7768 OSString
* executablePathString
= NULL
; // must release
7769 OSData
* uuid
= NULL
; // must release
7770 OSNumber
* scratchNumber
= NULL
; // must release
7771 OSArray
* dependencyLoadTags
= NULL
; // must release
7772 OSCollectionIterator
* metaClassIterator
= NULL
; // must release
7773 OSArray
* metaClassInfo
= NULL
; // must release
7774 OSDictionary
* metaClassDict
= NULL
; // must release
7775 OSMetaClass
* thisMetaClass
= NULL
; // do not release
7776 OSString
* metaClassName
= NULL
; // must release
7777 OSString
* superclassName
= NULL
; // must release
7780 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
7786 /* Empty keys means no keys, but NULL is quicker to check.
7788 if (infoKeys
&& !infoKeys
->getCount()) {
7792 /* Headers, CPU type, and CPU subtype.
7795 _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) ||
7796 _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) ||
7797 _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
))
7800 if (linkedExecutable
&& !isInterface()) {
7802 kernel_mach_header_t
*kext_mach_hdr
= (kernel_mach_header_t
*)
7803 linkedExecutable
->getBytesNoCopy();
7805 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) {
7806 kernel_mach_header_t
* temp_kext_mach_hdr
;
7807 struct load_command
* lcp
;
7809 headerData
= OSData::withBytes(kext_mach_hdr
,
7810 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
7815 // unslide any vmaddrs we return to userspace - 10726716
7816 temp_kext_mach_hdr
= (kernel_mach_header_t
*)
7817 headerData
->getBytesNoCopy();
7818 if (temp_kext_mach_hdr
== NULL
) {
7822 lcp
= (struct load_command
*) (temp_kext_mach_hdr
+ 1);
7823 for (i
= 0; i
< temp_kext_mach_hdr
->ncmds
; i
++) {
7824 if (lcp
->cmd
== LC_SEGMENT_KERNEL
) {
7825 kernel_segment_command_t
* scp
;
7827 scp
= (kernel_segment_command_t
*) lcp
;
7828 // 10543468 - if we jettisoned __LINKEDIT clear size info
7829 if (flags
.jettisonLinkeditSeg
) {
7830 if (strncmp(scp
->segname
, SEG_LINKEDIT
, sizeof(scp
->segname
)) == 0) {
7837 OSKextLog(/* kext */ NULL
,
7838 kOSKextLogErrorLevel
|
7839 kOSKextLogGeneralFlag
,
7840 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
7841 __FUNCTION__
, scp
->segname
, scp
->vmaddr
,
7842 VM_KERNEL_UNSLIDE(scp
->vmaddr
),
7843 scp
->vmsize
, scp
->nsects
);
7845 scp
->vmaddr
= VM_KERNEL_UNSLIDE(scp
->vmaddr
);
7847 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
7849 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
7852 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) {
7853 cpuTypeNumber
= OSNumber::withNumber(
7854 (uint64_t) kext_mach_hdr
->cputype
,
7855 8 * sizeof(kext_mach_hdr
->cputype
));
7856 if (!cpuTypeNumber
) {
7859 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
7862 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
7863 cpuSubtypeNumber
= OSNumber::withNumber(
7864 (uint64_t) kext_mach_hdr
->cpusubtype
,
7865 8 * sizeof(kext_mach_hdr
->cpusubtype
));
7866 if (!cpuSubtypeNumber
) {
7869 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
7874 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
7876 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
7880 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
7881 versionString
= OSDynamicCast(OSString
,
7882 getPropertyForHostArch(kCFBundleVersionKey
));
7883 if (versionString
) {
7884 result
->setObject(kCFBundleVersionKey
, versionString
);
7888 /* OSBundleCompatibleVersion.
7890 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
7891 versionString
= OSDynamicCast(OSString
,
7892 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
7893 if (versionString
) {
7894 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
7900 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
7902 result
->setObject(kOSBundlePathKey
, path
);
7907 /* OSBundleExecutablePath.
7909 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
7910 if (path
&& executableRelPath
) {
7912 uint32_t pathLength
= path
->getLength(); // gets incremented below
7914 // +1 for slash, +1 for \0
7915 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
7917 executablePathCString
= (char *)kalloc((executablePathCStringSize
) *
7918 sizeof(char)); // +1 for \0
7919 if (!executablePathCString
) {
7922 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
7923 executablePathCStringSize
);
7924 executablePathCString
[pathLength
++] = '/';
7925 executablePathCString
[pathLength
++] = '\0';
7926 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
7927 executablePathCStringSize
);
7929 executablePathString
= OSString::withCString(executablePathCString
);
7931 if (!executablePathCString
) {
7935 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
7939 /* UUID, if the kext has one.
7941 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
7944 result
->setObject(kOSBundleUUIDKey
, uuid
);
7949 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
7951 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
7952 result
->setObject(kOSKernelResourceKey
,
7953 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
7956 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
7957 result
->setObject(kOSBundleIsInterfaceKey
,
7958 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
7961 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
7962 result
->setObject(kOSBundlePrelinkedKey
,
7963 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
7966 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
7967 result
->setObject(kOSBundleStartedKey
,
7968 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
7973 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
7974 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
7975 /* numBits */ 8 * sizeof(loadTag
));
7976 if (!scratchNumber
) {
7979 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
7980 OSSafeReleaseNULL(scratchNumber
);
7983 /* LoadAddress, LoadSize.
7986 _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) ||
7987 _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) ||
7988 _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
))
7990 if (isInterface() || linkedExecutable
) {
7991 /* These go to userspace via serialization, so we don't want any doubts
7994 uint64_t loadAddress
= 0;
7995 uint32_t loadSize
= 0;
7996 uint32_t wiredSize
= 0;
7998 /* Interfaces always report 0 load address & size.
7999 * Just the way they roll.
8001 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
8002 * xxx - shouldn't have one!
8004 if (linkedExecutable
/* && !isInterface() */) {
8005 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
8006 loadAddress
= VM_KERNEL_UNSLIDE(loadAddress
);
8007 loadSize
= linkedExecutable
->getLength();
8009 /* If we have a kmod_info struct, calculated the wired size
8010 * from that. Otherwise it's the full load size.
8013 wiredSize
= loadSize
- kmod_info
->hdr_size
;
8015 wiredSize
= loadSize
;
8019 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
8020 scratchNumber
= OSNumber::withNumber(
8021 (unsigned long long)(loadAddress
),
8022 /* numBits */ 8 * sizeof(loadAddress
));
8023 if (!scratchNumber
) {
8026 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
8027 OSSafeReleaseNULL(scratchNumber
);
8029 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
8030 scratchNumber
= OSNumber::withNumber(
8031 (unsigned long long)(loadSize
),
8032 /* numBits */ 8 * sizeof(loadSize
));
8033 if (!scratchNumber
) {
8036 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
8037 OSSafeReleaseNULL(scratchNumber
);
8039 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
8040 scratchNumber
= OSNumber::withNumber(
8041 (unsigned long long)(wiredSize
),
8042 /* numBits */ 8 * sizeof(wiredSize
));
8043 if (!scratchNumber
) {
8046 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
8047 OSSafeReleaseNULL(scratchNumber
);
8052 /* OSBundleDependencies. In descending order for
8053 * easy compatibility with kextstat(8).
8055 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
8056 if ((count
= getNumDependencies())) {
8057 dependencyLoadTags
= OSArray::withCapacity(count
);
8058 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
8062 OSKext
* dependency
= OSDynamicCast(OSKext
,
8063 dependencies
->getObject(i
));
8065 OSSafeReleaseNULL(scratchNumber
);
8070 scratchNumber
= OSNumber::withNumber(
8071 (unsigned long long)dependency
->getLoadTag(),
8072 /* numBits*/ 8 * sizeof(loadTag
));
8073 if (!scratchNumber
) {
8076 dependencyLoadTags
->setObject(scratchNumber
);
8081 OSSafeReleaseNULL(scratchNumber
);
8083 /* OSBundleMetaClasses.
8085 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) {
8086 if (metaClasses
&& metaClasses
->getCount()) {
8087 metaClassIterator
= OSCollectionIterator::withCollection(metaClasses
);
8088 metaClassInfo
= OSArray::withCapacity(metaClasses
->getCount());
8089 if (!metaClassIterator
|| !metaClassInfo
) {
8092 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
8094 while ( (thisMetaClass
= OSDynamicCast(OSMetaClass
,
8095 metaClassIterator
->getNextObject())) ) {
8097 OSSafeReleaseNULL(metaClassDict
);
8098 OSSafeReleaseNULL(scratchNumber
);
8099 OSSafeReleaseNULL(metaClassName
);
8100 OSSafeReleaseNULL(superclassName
);
8102 metaClassDict
= OSDictionary::withCapacity(3);
8103 if (!metaClassDict
) {
8107 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
8108 if (thisMetaClass
->getSuperClass()) {
8109 superclassName
= OSString::withCString(
8110 thisMetaClass
->getSuperClass()->getClassName());
8112 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
8113 8 * sizeof(unsigned int));
8115 /* Bail if any of the essentials is missing. The root class lacks a superclass,
8118 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
8122 metaClassInfo
->setObject(metaClassDict
);
8123 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
8124 if (superclassName
) {
8125 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
8127 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
8132 /* OSBundleRetainCount.
8134 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
8135 OSSafeReleaseNULL(scratchNumber
);
8137 int kextRetainCount
= getRetainCount() - 1;
8141 scratchNumber
= OSNumber::withNumber(
8142 (int)kextRetainCount
,
8143 /* numBits*/ 8 * sizeof(int));
8144 if (scratchNumber
) {
8145 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
8153 OSSafeRelease(headerData
);
8154 OSSafeRelease(cpuTypeNumber
);
8155 OSSafeRelease(cpuSubtypeNumber
);
8156 OSSafeRelease(executablePathString
);
8157 if (executablePathString
) kfree(executablePathCString
, executablePathCStringSize
);
8158 OSSafeRelease(uuid
);
8159 OSSafeRelease(scratchNumber
);
8160 OSSafeRelease(dependencyLoadTags
);
8161 OSSafeRelease(metaClassIterator
);
8162 OSSafeRelease(metaClassInfo
);
8163 OSSafeRelease(metaClassDict
);
8164 OSSafeRelease(metaClassName
);
8165 OSSafeRelease(superclassName
);
8167 OSSafeReleaseNULL(result
);
8172 /*********************************************************************
8173 *********************************************************************/
8176 OSKext::requestResource(
8177 const char * kextIdentifierCString
,
8178 const char * resourceNameCString
,
8179 OSKextRequestResourceCallback callback
,
8181 OSKextRequestTag
* requestTagOut
)
8183 OSReturn result
= kOSReturnError
;
8184 OSKext
* callbackKext
= NULL
; // must release (looked up)
8186 OSKextRequestTag requestTag
= -1;
8187 OSNumber
* requestTagNum
= NULL
; // must release
8189 OSDictionary
* requestDict
= NULL
; // must release
8190 OSString
* kextIdentifier
= NULL
; // must release
8191 OSString
* resourceName
= NULL
; // must release
8193 OSDictionary
* callbackRecord
= NULL
; // must release
8194 OSData
* callbackWrapper
= NULL
; // must release
8196 OSData
* contextWrapper
= NULL
; // must release
8198 IORecursiveLockLock(sKextLock
);
8200 if (requestTagOut
) {
8201 *requestTagOut
= kOSKextRequestTagInvalid
;
8204 /* If requests to user space are disabled, don't go any further */
8205 if (!sKernelRequestsEnabled
) {
8206 OSKextLog(/* kext */ NULL
,
8207 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8208 "Can't request resource %s for %s - requests to user space are disabled.",
8209 resourceNameCString
,
8210 kextIdentifierCString
);
8211 result
= kOSKextReturnDisabled
;
8215 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
8216 result
= kOSKextReturnInvalidArgument
;
8220 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
8221 if (!callbackKext
) {
8222 OSKextLog(/* kext */ NULL
,
8223 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8224 "Resource request has bad callback address.");
8225 result
= kOSKextReturnInvalidArgument
;
8228 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
8229 OSKextLog(/* kext */ NULL
,
8230 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8231 "Resource request callback is in a kext that is not started.");
8232 result
= kOSKextReturnInvalidArgument
;
8236 /* Do not allow any new requests to be made on a kext that is unloading.
8238 if (callbackKext
->flags
.stopping
) {
8239 result
= kOSKextReturnStopping
;
8243 /* If we're wrapped the next available request tag around to the negative
8244 * numbers, we can't service any more requests.
8246 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
8247 OSKextLog(/* kext */ NULL
,
8248 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8249 "No more request tags available; restart required.");
8250 result
= kOSKextReturnNoResources
;
8253 requestTag
= sNextRequestTag
++;
8255 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
8257 if (result
!= kOSReturnSuccess
) {
8261 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
8262 resourceName
= OSString::withCString(resourceNameCString
);
8263 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
8264 8 * sizeof(requestTag
));
8265 if (!kextIdentifier
||
8268 !_OSKextSetRequestArgument(requestDict
,
8269 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
8270 !_OSKextSetRequestArgument(requestDict
,
8271 kKextRequestArgumentNameKey
, resourceName
) ||
8272 !_OSKextSetRequestArgument(requestDict
,
8273 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
8275 result
= kOSKextReturnNoMemory
;
8279 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
8280 if (!callbackRecord
) {
8281 result
= kOSKextReturnNoMemory
;
8284 // we validate callback address at call time
8285 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
8287 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
8289 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
8290 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
8292 result
= kOSKextReturnNoMemory
;
8297 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
8298 kKextRequestArgumentContextKey
, contextWrapper
)) {
8300 result
= kOSKextReturnNoMemory
;
8305 /* Only post the requests after all the other potential failure points
8308 if (!sKernelRequests
->setObject(requestDict
) ||
8309 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
8311 result
= kOSKextReturnNoMemory
;
8315 OSKext::pingKextd();
8317 result
= kOSReturnSuccess
;
8318 if (requestTagOut
) {
8319 *requestTagOut
= requestTag
;
8324 /* If we didn't succeed, yank the request & callback
8325 * from their holding arrays.
8327 if (result
!= kOSReturnSuccess
) {
8330 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
8331 if (index
!= (unsigned int)-1) {
8332 sKernelRequests
->removeObject(index
);
8334 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
8335 if (index
!= (unsigned int)-1) {
8336 sRequestCallbackRecords
->removeObject(index
);
8340 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8342 IORecursiveLockUnlock(sKextLock
);
8344 if (callbackKext
) callbackKext
->release();
8345 if (requestTagNum
) requestTagNum
->release();
8347 if (requestDict
) requestDict
->release();
8348 if (kextIdentifier
) kextIdentifier
->release();
8349 if (resourceName
) resourceName
->release();
8351 if (callbackRecord
) callbackRecord
->release();
8352 if (callbackWrapper
) callbackWrapper
->release();
8353 if (contextWrapper
) contextWrapper
->release();
8358 /*********************************************************************
8359 * Assumes sKextLock is held.
8360 *********************************************************************/
8363 OSKext::dequeueCallbackForRequestTag(
8364 OSKextRequestTag requestTag
,
8365 OSDictionary
** callbackRecordOut
)
8367 OSReturn result
= kOSReturnError
;
8368 OSNumber
* requestTagNum
= NULL
; // must release
8370 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
8371 8 * sizeof(requestTag
));
8372 if (!requestTagNum
) {
8376 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
8380 OSSafeRelease(requestTagNum
);
8385 /*********************************************************************
8386 * Assumes sKextLock is held.
8387 *********************************************************************/
8390 OSKext::dequeueCallbackForRequestTag(
8391 OSNumber
* requestTagNum
,
8392 OSDictionary
** callbackRecordOut
)
8394 OSReturn result
= kOSKextReturnInvalidArgument
;
8395 OSDictionary
* callbackRecord
= NULL
; // retain if matched!
8396 OSNumber
* callbackTagNum
= NULL
; // do not release
8397 unsigned int count
, i
;
8399 result
= kOSReturnError
;
8400 count
= sRequestCallbackRecords
->getCount();
8401 for (i
= 0; i
< count
; i
++) {
8402 callbackRecord
= OSDynamicCast(OSDictionary
,
8403 sRequestCallbackRecords
->getObject(i
));
8404 if (!callbackRecord
) {
8408 /* If we don't find a tag, we basically have a leak here. Maybe
8409 * we should just remove it.
8411 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
8412 callbackRecord
, kKextRequestArgumentRequestTagKey
));
8413 if (!callbackTagNum
) {
8417 /* We could be even more paranoid and check that all the incoming
8418 * args match what's in the callback record.
8420 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
8421 if (callbackRecordOut
) {
8422 *callbackRecordOut
= callbackRecord
;
8423 callbackRecord
->retain();
8425 sRequestCallbackRecords
->removeObject(i
);
8426 result
= kOSReturnSuccess
;
8430 result
= kOSKextReturnNotFound
;
8436 /*********************************************************************
8437 * Assumes sKextLock is held.
8438 *********************************************************************/
8441 OSKext::dispatchResource(OSDictionary
* requestDict
)
8443 OSReturn result
= kOSReturnError
;
8444 OSDictionary
* callbackRecord
= NULL
; // must release
8445 OSNumber
* requestTag
= NULL
; // do not release
8446 OSNumber
* requestResult
= NULL
; // do not release
8447 OSData
* dataObj
= NULL
; // do not release
8448 uint32_t dataLength
= 0;
8449 const void * dataPtr
= NULL
; // do not free
8450 OSData
* callbackWrapper
= NULL
; // do not release
8451 OSKextRequestResourceCallback callback
= NULL
;
8452 OSData
* contextWrapper
= NULL
; // do not release
8453 void * context
= NULL
; // do not free
8454 OSKext
* callbackKext
= NULL
; // must release (looked up)
8456 /* Get the args from the request. Right now we need the tag
8457 * to look up the callback record, and the result for invoking the callback.
8459 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
8460 kKextRequestArgumentRequestTagKey
));
8461 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
8462 kKextRequestArgumentResultKey
));
8463 if (!requestTag
|| !requestResult
) {
8464 result
= kOSKextReturnInvalidArgument
;
8468 /* Look for a callback record matching this request's tag.
8470 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
8471 if (result
!= kOSReturnSuccess
) {
8476 * Get the context pointer of the callback record (if there is one).
8478 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
8479 kKextRequestArgumentContextKey
));
8480 context
= _OSKextExtractPointer(contextWrapper
);
8481 if (contextWrapper
&& !context
) {
8485 callbackWrapper
= OSDynamicCast(OSData
,
8486 _OSKextGetRequestArgument(callbackRecord
,
8487 kKextRequestArgumentCallbackKey
));
8488 callback
= (OSKextRequestResourceCallback
)
8489 _OSKextExtractPointer(callbackWrapper
);
8494 /* Check for a data obj. We might not have one and that's ok, that means
8495 * we didn't find the requested resource, and we still have to tell the
8496 * caller that via the callback.
8498 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
8499 kKextRequestArgumentValueKey
));
8501 dataPtr
= dataObj
->getBytesNoCopy();
8502 dataLength
= dataObj
->getLength();
8505 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
8506 if (!callbackKext
) {
8507 OSKextLog(/* kext */ NULL
,
8508 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8509 "Can't invoke callback for resource request; ");
8512 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
8513 OSKextLog(/* kext */ NULL
,
8514 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8515 "Can't invoke kext resource callback; ");
8519 (void)callback(requestTag
->unsigned32BitValue(),
8520 (OSReturn
)requestResult
->unsigned32BitValue(),
8521 dataPtr
, dataLength
, context
);
8523 result
= kOSReturnSuccess
;
8526 if (callbackKext
) callbackKext
->release();
8527 if (callbackRecord
) callbackRecord
->release();
8532 /*********************************************************************
8533 *********************************************************************/
8536 OSKext::invokeRequestCallback(
8537 OSDictionary
* callbackRecord
,
8538 OSReturn callbackResult
)
8540 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
8541 OSNumber
* resultNum
= NULL
; // must release
8547 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
8548 8 * sizeof(callbackResult
));
8553 /* Insert the result into the callback record and dispatch it as if it
8554 * were the reply coming down from user space.
8556 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
8559 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
8560 /* This removes the pending callback record.
8562 OSKext::dispatchResource(callbackRecord
);
8566 if (resultNum
) resultNum
->release();
8570 /*********************************************************************
8571 * Assumes sKextLock is held.
8572 *********************************************************************/
8575 OSKext::cancelRequest(
8576 OSKextRequestTag requestTag
,
8579 OSReturn result
= kOSKextReturnNoMemory
;
8580 OSDictionary
* callbackRecord
= NULL
; // must release
8581 OSData
* contextWrapper
= NULL
; // do not release
8583 IORecursiveLockLock(sKextLock
);
8584 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
8586 IORecursiveLockUnlock(sKextLock
);
8588 if (result
== kOSReturnSuccess
&& contextOut
) {
8589 contextWrapper
= OSDynamicCast(OSData
,
8590 _OSKextGetRequestArgument(callbackRecord
,
8591 kKextRequestArgumentContextKey
));
8592 *contextOut
= _OSKextExtractPointer(contextWrapper
);
8595 if (callbackRecord
) callbackRecord
->release();
8600 /*********************************************************************
8601 * Assumes sKextLock is held.
8602 *********************************************************************/
8604 OSKext::invokeOrCancelRequestCallbacks(
8605 OSReturn callbackResult
,
8608 unsigned int count
, i
;
8610 count
= sRequestCallbackRecords
->getCount();
8617 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
8618 sRequestCallbackRecords
->getObject(i
));
8623 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
8624 _OSKextGetRequestArgument(request
,
8625 kKextRequestArgumentCallbackKey
));
8627 if (!callbackWrapper
) {
8628 sRequestCallbackRecords
->removeObject(i
);
8632 vm_address_t callbackAddress
= (vm_address_t
)
8633 _OSKextExtractPointer(callbackWrapper
);
8635 if ((kmod_info
->address
<= callbackAddress
) &&
8636 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
8639 /* This removes the callback record.
8641 invokeRequestCallback(request
, callbackResult
);
8643 sRequestCallbackRecords
->removeObject(i
);
8652 /*********************************************************************
8653 * Assumes sKextLock is held.
8654 *********************************************************************/
8656 OSKext::countRequestCallbacks(void)
8658 uint32_t result
= 0;
8659 unsigned int count
, i
;
8661 count
= sRequestCallbackRecords
->getCount();
8668 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
8669 sRequestCallbackRecords
->getObject(i
));
8674 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
8675 _OSKextGetRequestArgument(request
,
8676 kKextRequestArgumentCallbackKey
));
8678 if (!callbackWrapper
) {
8682 vm_address_t callbackAddress
= (vm_address_t
)
8683 _OSKextExtractPointer(callbackWrapper
);
8685 if ((kmod_info
->address
<= callbackAddress
) &&
8686 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
8696 /*********************************************************************
8697 *********************************************************************/
8698 static OSReturn
_OSKextCreateRequest(
8699 const char * predicate
,
8700 OSDictionary
** requestP
)
8702 OSReturn result
= kOSKextReturnNoMemory
;
8703 OSDictionary
* request
= NULL
; // must release on error
8704 OSDictionary
* args
= NULL
; // must release
8706 request
= OSDictionary::withCapacity(2);
8710 result
= _OSDictionarySetCStringValue(request
,
8711 kKextRequestPredicateKey
, predicate
);
8712 if (result
!= kOSReturnSuccess
) {
8715 result
= kOSReturnSuccess
;
8718 if (result
!= kOSReturnSuccess
) {
8719 if (request
) request
->release();
8721 *requestP
= request
;
8723 if (args
) args
->release();
8728 /*********************************************************************
8729 *********************************************************************/
8730 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
8732 return OSDynamicCast(OSString
,
8733 requestDict
->getObject(kKextRequestPredicateKey
));
8736 /*********************************************************************
8737 *********************************************************************/
8738 static OSObject
* _OSKextGetRequestArgument(
8739 OSDictionary
* requestDict
,
8740 const char * argName
)
8742 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
8743 requestDict
->getObject(kKextRequestArgumentsKey
));
8745 return args
->getObject(argName
);
8750 /*********************************************************************
8751 *********************************************************************/
8752 static bool _OSKextSetRequestArgument(
8753 OSDictionary
* requestDict
,
8754 const char * argName
,
8757 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
8758 requestDict
->getObject(kKextRequestArgumentsKey
));
8760 args
= OSDictionary::withCapacity(2);
8764 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
8768 return args
->setObject(argName
, value
);
8774 /*********************************************************************
8775 *********************************************************************/
8776 static void * _OSKextExtractPointer(OSData
* wrapper
)
8778 void * result
= NULL
;
8779 const void * resultPtr
= NULL
;
8784 resultPtr
= wrapper
->getBytesNoCopy();
8785 result
= *(void **)resultPtr
;
8790 /*********************************************************************
8791 *********************************************************************/
8792 static OSReturn
_OSDictionarySetCStringValue(
8793 OSDictionary
* dict
,
8795 const char * cValue
)
8797 OSReturn result
= kOSKextReturnNoMemory
;
8798 const OSSymbol
* key
= NULL
; // must release
8799 OSString
* value
= NULL
; // must release
8801 key
= OSSymbol::withCString(cKey
);
8802 value
= OSString::withCString(cValue
);
8803 if (!key
|| !value
) {
8806 if (dict
->setObject(key
, value
)) {
8807 result
= kOSReturnSuccess
;
8811 if (key
) key
->release();
8812 if (value
) value
->release();
8817 /*********************************************************************
8818 *********************************************************************/
8819 static bool _OSArrayContainsCString(
8821 const char * cString
)
8823 bool result
= false;
8824 const OSSymbol
* symbol
= NULL
;
8827 if (!array
|| !cString
) {
8831 symbol
= OSSymbol::withCStringNoCopy(cString
);
8836 count
= array
->getCount();
8837 for (i
= 0; i
< count
; i
++) {
8838 OSObject
* thisObject
= array
->getObject(i
);
8839 if (symbol
->isEqualTo(thisObject
)) {
8846 if (symbol
) symbol
->release();
8850 /*********************************************************************
8851 * We really only care about boot / system start up related kexts.
8852 * We return true if we're less than REBUILD_MAX_TIME since start up,
8853 * otherwise return false.
8854 *********************************************************************/
8855 bool _OSKextInPrelinkRebuildWindow(void)
8857 static bool outside_the_window
= false;
8858 AbsoluteTime my_abstime
;
8862 if (outside_the_window
) {
8865 clock_get_uptime(&my_abstime
);
8866 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
8867 my_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
8868 if (my_secs
> REBUILD_MAX_TIME
) {
8869 outside_the_window
= true;
8875 /*********************************************************************
8876 *********************************************************************/
8877 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
8879 int unLoadedCount
, i
;
8880 bool result
= false;
8882 IORecursiveLockLock(sKextLock
);
8884 if (sUnloadedPrelinkedKexts
== NULL
) {
8887 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
8888 if (unLoadedCount
== 0) {
8892 for (i
= 0; i
< unLoadedCount
; i
++) {
8893 const OSSymbol
* myBundleID
; // do not release
8895 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
8896 if (!myBundleID
) continue;
8897 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
8903 IORecursiveLockUnlock(sKextLock
);
8908 #pragma mark Personalities (IOKit Drivers)
8910 /*********************************************************************
8911 *********************************************************************/
8914 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
8916 OSArray
* result
= NULL
; // returned
8917 OSCollectionIterator
* kextIterator
= NULL
; // must release
8918 OSArray
* personalities
= NULL
; // must release
8919 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
8921 OSString
* kextID
= NULL
; // do not release
8922 OSKext
* theKext
= NULL
; // do not release
8924 IORecursiveLockLock(sKextLock
);
8926 /* Let's conservatively guess that any given kext has around 3
8927 * personalities for now.
8929 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
8934 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
8935 if (!kextIterator
) {
8939 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
8940 if (personalitiesIterator
) {
8941 personalitiesIterator
->release();
8942 personalitiesIterator
= NULL
;
8944 if (personalities
) {
8945 personalities
->release();
8946 personalities
= NULL
;
8949 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
8950 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
8951 personalities
= theKext
->copyPersonalitiesArray();
8952 if (!personalities
) {
8955 result
->merge(personalities
);
8957 // xxx - check for better place to put this log msg
8959 kOSKextLogWarningLevel
|
8961 "Kext %s is not loadable during safe boot; "
8962 "omitting its personalities.",
8963 theKext
->getIdentifierCString());
8969 IORecursiveLockUnlock(sKextLock
);
8971 if (kextIterator
) kextIterator
->release();
8972 if (personalitiesIterator
) personalitiesIterator
->release();
8973 if (personalities
) personalities
->release();
8978 /*********************************************************************
8979 *********************************************************************/
8982 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
8984 int numPersonalities
= 0;
8986 OSKextLog(/* kext */ NULL
,
8987 kOSKextLogStepLevel
|
8989 "Sending all eligible registered kexts' personalities "
8990 "to the IOCatalogue %s.",
8991 startMatching
? "and starting matching" : "but not starting matching");
8993 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
8994 /* filterSafeBootFlag */ true);
8996 if (personalities
) {
8997 gIOCatalogue
->addDrivers(personalities
, startMatching
);
8998 numPersonalities
= personalities
->getCount();
8999 personalities
->release();
9002 OSKextLog(/* kext */ NULL
,
9003 kOSKextLogStepLevel
|
9005 "%d kext personalit%s sent to the IOCatalogue; %s.",
9006 numPersonalities
, numPersonalities
> 0 ? "ies" : "y",
9007 startMatching
? "matching started" : "matching not started");
9011 /*********************************************************************
9012 * Do not make a deep copy, just convert the IOKitPersonalities dict
9013 * to an array for sending to the IOCatalogue.
9014 *********************************************************************/
9016 OSKext::copyPersonalitiesArray(void)
9018 OSArray
* result
= NULL
;
9019 OSDictionary
* personalities
= NULL
; // do not release
9020 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
9022 OSString
* personalityName
= NULL
; // do not release
9023 OSString
* personalityBundleIdentifier
= NULL
; // do not release
9025 personalities
= OSDynamicCast(OSDictionary
,
9026 getPropertyForHostArch(kIOKitPersonalitiesKey
));
9027 if (!personalities
) {
9031 result
= OSArray::withCapacity(personalities
->getCount());
9036 personalitiesIterator
=
9037 OSCollectionIterator::withCollection(personalities
);
9038 if (!personalitiesIterator
) {
9041 while ((personalityName
= OSDynamicCast(OSString
,
9042 personalitiesIterator
->getNextObject()))) {
9044 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
9045 personalities
->getObject(personalityName
));
9048 * If the personality doesn't have a CFBundleIdentifier, or if it
9049 * differs from the kext's, insert the kext's ID so we can find it.
9050 * The publisher ID is used to remove personalities from bundles
9053 personalityBundleIdentifier
= OSDynamicCast(OSString
,
9054 personality
->getObject(kCFBundleIdentifierKey
));
9056 if (!personalityBundleIdentifier
) {
9057 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
9058 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
9059 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
9062 result
->setObject(personality
);
9066 if (personalitiesIterator
) personalitiesIterator
->release();
9071 /*********************************************************************
9072 Might want to change this to a bool return?
9073 *********************************************************************/
9075 OSKext::sendPersonalitiesToCatalog(
9077 OSArray
* personalityNames
)
9079 OSReturn result
= kOSReturnSuccess
;
9080 OSArray
* personalitiesToSend
= NULL
; // must release
9081 OSDictionary
* kextPersonalities
= NULL
; // do not release
9084 if (!sLoadEnabled
) {
9086 kOSKextLogErrorLevel
|
9088 "Kext loading is disabled (attempt to start matching for kext %s).",
9089 getIdentifierCString());
9090 result
= kOSKextReturnDisabled
;
9094 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
9096 kOSKextLogErrorLevel
|
9098 "Kext %s is not loadable during safe boot; "
9099 "not sending personalities to the IOCatalogue.",
9100 getIdentifierCString());
9101 result
= kOSKextReturnNotLoadable
;
9105 if (!personalityNames
|| !personalityNames
->getCount()) {
9106 personalitiesToSend
= copyPersonalitiesArray();
9108 kextPersonalities
= OSDynamicCast(OSDictionary
,
9109 getPropertyForHostArch(kIOKitPersonalitiesKey
));
9110 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
9114 personalitiesToSend
= OSArray::withCapacity(0);
9115 if (!personalitiesToSend
) {
9116 result
= kOSKextReturnNoMemory
;
9119 count
= personalityNames
->getCount();
9120 for (i
= 0; i
< count
; i
++) {
9121 OSString
* name
= OSDynamicCast(OSString
,
9122 personalityNames
->getObject(i
));
9126 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
9127 kextPersonalities
->getObject(name
));
9129 personalitiesToSend
->setObject(personality
);
9133 if (personalitiesToSend
) {
9134 unsigned numPersonalities
= personalitiesToSend
->getCount();
9136 kOSKextLogStepLevel
|
9138 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
9139 getIdentifierCString(),
9141 numPersonalities
> 1 ? "ies" : "y",
9142 startMatching
? " and starting matching" : " but not starting matching");
9143 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
9146 if (personalitiesToSend
) {
9147 personalitiesToSend
->release();
9152 /*********************************************************************
9153 * xxx - We should allow removing the kext's declared personalities,
9154 * xxx - even with other bundle identifiers.
9155 *********************************************************************/
9157 OSKext::removePersonalitiesFromCatalog(void)
9159 OSDictionary
* personality
= NULL
; // do not release
9161 personality
= OSDictionary::withCapacity(1);
9165 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
9168 kOSKextLogStepLevel
|
9170 "Kext %s removing all personalities naming it from the IOCatalogue.",
9171 getIdentifierCString());
9173 /* Have the IOCatalog remove all personalities matching this kext's
9174 * bundle ID and trigger matching anew.
9176 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
9179 if (personality
) personality
->release();
9186 #pragma mark Logging
9188 /*********************************************************************
9189 * Do not call any function that takes sKextLock here!
9190 *********************************************************************/
9193 OSKext::setUserSpaceLogFilter(
9194 OSKextLogSpec newUserLogFilter
,
9197 OSKextLogSpec result
;
9198 bool allocError
= false;
9200 /* Do not call any function that takes sKextLoggingLock during
9201 * this critical block. That means do logging after.
9203 IOLockLock(sKextLoggingLock
);
9205 result
= sUserSpaceKextLogFilter
;
9206 sUserSpaceKextLogFilter
= newUserLogFilter
;
9208 if (newUserLogFilter
&& captureFlag
&&
9209 !sUserSpaceLogSpecArray
&& !sUserSpaceLogMessageArray
) {
9211 // xxx - do some measurements for a good initial capacity?
9212 sUserSpaceLogSpecArray
= OSArray::withCapacity(0);
9213 sUserSpaceLogMessageArray
= OSArray::withCapacity(0);
9215 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
9216 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
9217 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
9222 IOLockUnlock(sKextLoggingLock
);
9224 /* If the config flag itself is changing, log the state change
9225 * going both ways, before setting up the user-space log arrays,
9226 * so that this is only logged in the kernel.
9228 if (result
!= newUserLogFilter
) {
9229 OSKextLog(/* kext */ NULL
,
9230 kOSKextLogDebugLevel
|
9231 kOSKextLogGeneralFlag
,
9232 "User-space log flags changed from 0x%x to 0x%x.",
9233 result
, newUserLogFilter
);
9236 OSKextLog(/* kext */ NULL
,
9237 kOSKextLogErrorLevel
|
9238 kOSKextLogGeneralFlag
,
9239 "Failed to allocate user-space log message arrays.");
9245 /*********************************************************************
9246 * Do not call any function that takes sKextLock here!
9247 *********************************************************************/
9250 OSKext::clearUserSpaceLogFilter(void)
9252 OSArray
* result
= NULL
;
9253 OSKextLogSpec oldLogFilter
;
9254 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
9256 /* Do not call any function that takes sKextLoggingLock during
9257 * this critical block. That means do logging after.
9259 IOLockLock(sKextLoggingLock
);
9261 result
= OSArray::withCapacity(2);
9263 result
->setObject(sUserSpaceLogSpecArray
);
9264 result
->setObject(sUserSpaceLogMessageArray
);
9266 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
9267 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
9269 oldLogFilter
= sUserSpaceKextLogFilter
;
9270 sUserSpaceKextLogFilter
= newLogFilter
;
9272 IOLockUnlock(sKextLoggingLock
);
9274 /* If the config flag itself is changing, log the state change
9275 * going both ways, after tearing down the user-space log
9276 * arrays, so this is only logged within the kernel.
9278 if (oldLogFilter
!= newLogFilter
) {
9279 OSKextLog(/* kext */ NULL
,
9280 kOSKextLogDebugLevel
|
9281 kOSKextLogGeneralFlag
,
9282 "User-space log flags changed from 0x%x to 0x%x.",
9283 oldLogFilter
, newLogFilter
);
9290 /*********************************************************************
9291 * Do not call any function that takes sKextLock here!
9292 *********************************************************************/
9295 OSKext::getUserSpaceLogFilter(void)
9297 OSKextLogSpec result
;
9299 IOLockLock(sKextLoggingLock
);
9300 result
= sUserSpaceKextLogFilter
;
9301 IOLockUnlock(sKextLoggingLock
);
9306 /*********************************************************************
9307 * This function is called by OSMetaClass during kernel C++ setup.
9308 * Be careful what you access here; assume only OSKext::initialize()
9311 * Do not call any function that takes sKextLock here!
9312 *********************************************************************/
9313 #define VTRESET "\033[0m"
9315 #define VTBOLD "\033[1m"
9316 #define VTUNDER "\033[4m"
9318 #define VTRED "\033[31m"
9319 #define VTGREEN "\033[32m"
9320 #define VTYELLOW "\033[33m"
9321 #define VTBLUE "\033[34m"
9322 #define VTMAGENTA "\033[35m"
9323 #define VTCYAN "\033[36m"
9325 inline const char * colorForFlags(OSKextLogSpec flags
)
9327 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
9330 case kOSKextLogErrorLevel
:
9331 return VTRED VTBOLD
;
9333 case kOSKextLogWarningLevel
:
9336 case kOSKextLogBasicLevel
:
9337 return VTYELLOW VTUNDER
;
9339 case kOSKextLogProgressLevel
:
9342 case kOSKextLogStepLevel
:
9345 case kOSKextLogDetailLevel
:
9348 case kOSKextLogDebugLevel
:
9358 inline bool logSpecMatch(
9359 OSKextLogSpec msgLogSpec
,
9360 OSKextLogSpec logFilter
)
9362 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
9363 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
9364 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
9366 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
9367 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
9368 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
9370 /* Explicit messages always get logged.
9372 if (msgLevel
== kOSKextLogExplicitLevel
) {
9376 /* Warnings and errors are logged regardless of the flags.
9378 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
9382 /* A verbose message that isn't for a logging-enabled kext and isn't global
9383 * does *not* get logged.
9385 if (!msgKextGlobal
&& !filterKextGlobal
) {
9389 /* Warnings and errors are logged regardless of the flags.
9390 * All other messages must fit the flags and
9391 * have a level at or below the filter.
9394 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
9405 OSKextLogSpec msgLogSpec
,
9406 const char * format
, ...)
9410 va_start(argList
, format
);
9411 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
9418 OSKextLogSpec msgLogSpec
,
9419 const char * format
,
9422 extern int disableConsoleOutput
;
9424 bool logForKernel
= false;
9425 bool logForUser
= false;
9427 char stackBuffer
[120];
9428 uint32_t length
= 0;
9429 char * allocBuffer
= NULL
; // must kfree
9430 OSNumber
* logSpecNum
= NULL
; // must release
9431 OSString
* logString
= NULL
; // must release
9432 char * buffer
= stackBuffer
; // do not free
9434 IOLockLock(sKextLoggingLock
);
9436 /* Set the kext/global bit in the message spec if we have no
9437 * kext or if the kext requests logging.
9439 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
9440 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
9443 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
9444 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
9445 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
9448 if (! (logForKernel
|| logForUser
) ) {
9452 /* No goto from here until past va_end()!
9454 va_copy(argList
, srcArgList
);
9455 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
9458 if (length
+ 1 >= sizeof(stackBuffer
)) {
9459 allocBuffer
= (char *)kalloc((length
+ 1) * sizeof(char));
9464 /* No goto from here until past va_end()!
9466 va_copy(argList
, srcArgList
);
9467 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
9470 buffer
= allocBuffer
;
9473 /* If user space wants the log message, queue it up.
9475 if (logForUser
&& sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
9476 logSpecNum
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
));
9477 logString
= OSString::withCString(buffer
);
9478 if (logSpecNum
&& logString
) {
9479 sUserSpaceLogSpecArray
->setObject(logSpecNum
);
9480 sUserSpaceLogMessageArray
->setObject(logString
);
9484 /* Always log messages from the kernel according to the kernel's
9489 /* If we are in console mode and have a custom log filter,
9490 * colorize the log message.
9492 if (!disableConsoleOutput
&& sBootArgLogFilterFound
) {
9493 const char * color
= ""; // do not free
9494 color
= colorForFlags(msgLogSpec
);
9495 printf("%s%s%s\n", colorForFlags(msgLogSpec
),
9496 buffer
, color
[0] ? VTRESET
: "");
9498 printf("%s\n", buffer
);
9503 IOLockUnlock(sKextLoggingLock
);
9506 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
9508 OSSafeRelease(logString
);
9509 OSSafeRelease(logSpecNum
);
9513 #if KASLR_IOREG_DEBUG
9515 #define IOLOG_INDENT( the_indention ) \
9518 for ( i = 0; i < (the_indention); i++ ) { \
9523 extern vm_offset_t vm_kernel_stext
;
9524 extern vm_offset_t vm_kernel_etext
;
9525 extern mach_vm_offset_t kext_alloc_base
;
9526 extern mach_vm_offset_t kext_alloc_max
;
9528 bool ScanForAddrInObject(OSObject
* theObject
,
9531 bool ScanForAddrInObject(OSObject
* theObject
,
9534 const OSMetaClass
* myTypeID
;
9535 OSCollectionIterator
* myIter
;
9538 bool myResult
= false;
9540 if ( theObject
== NULL
) {
9541 IOLog("%s: theObject is NULL \n",
9546 myTypeID
= OSTypeIDInst(theObject
);
9548 if ( myTypeID
== OSTypeID(OSDictionary
) ) {
9549 OSDictionary
* myDictionary
;
9551 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
9552 myIter
= OSCollectionIterator::withCollection( myDictionary
);
9553 if ( myIter
== NULL
)
9557 while ( (myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject())) ) {
9560 myValue
= myDictionary
->getObject(myKey
);
9561 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
9563 // if we ever get a true result return true
9565 IOLOG_INDENT(indent
);
9566 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
9571 else if ( myTypeID
== OSTypeID(OSArray
) ) {
9574 myArray
= OSDynamicCast(OSArray
, theObject
);
9575 myIter
= OSCollectionIterator::withCollection(myArray
);
9576 if ( myIter
== NULL
)
9580 while ( (myValue
= myIter
->getNextObject()) ) {
9582 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
9584 // if we ever get a true result return true
9586 IOLOG_INDENT(indent
);
9587 IOLog("OSArray: \n");
9592 else if ( myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
) ) {
9594 // should we look for addresses in strings?
9596 else if ( myTypeID
== OSTypeID(OSData
) ) {
9602 myDataObj
= OSDynamicCast(OSData
, theObject
);
9603 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
9604 myLen
= myDataObj
->getLength();
9606 if (myPtrPtr
&& myLen
&& myLen
> 7) {
9608 int myPtrCount
= (myLen
/ sizeof(void *));
9610 for (i
= 0; i
< myPtrCount
; i
++) {
9611 UInt64 numberValue
= (UInt64
) *(myPtrPtr
);
9613 if ( kext_alloc_max
!= 0 &&
9614 numberValue
>= kext_alloc_base
&&
9615 numberValue
< kext_alloc_max
) {
9617 OSKext
* myKext
= NULL
; // must release (looked up)
9618 // IOLog("found OSData %p in kext map %p to %p \n",
9620 // (void *) kext_alloc_base,
9621 // (void *) kext_alloc_max);
9623 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) *(myPtrPtr
) );
9625 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
9627 myKext
->getIdentifierCString());
9632 if ( vm_kernel_etext
!= 0 &&
9633 numberValue
>= vm_kernel_stext
&&
9634 numberValue
< vm_kernel_etext
) {
9635 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
9637 (void *) vm_kernel_stext
,
9638 (void *) vm_kernel_etext
);
9645 else if ( myTypeID
== OSTypeID(OSBoolean
) ) {
9647 // do nothing here...
9649 else if ( myTypeID
== OSTypeID(OSNumber
) ) {
9651 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
9653 UInt64 numberValue
= number
->unsigned64BitValue();
9655 if ( kext_alloc_max
!= 0 &&
9656 numberValue
>= kext_alloc_base
&&
9657 numberValue
< kext_alloc_max
) {
9659 OSKext
* myKext
= NULL
; // must release (looked up)
9660 IOLog("found OSNumber in kext map %p to %p \n",
9661 (void *) kext_alloc_base
,
9662 (void *) kext_alloc_max
);
9663 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
9665 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) numberValue
);
9667 IOLog("found in kext \"%s\" \n",
9668 myKext
->getIdentifierCString());
9674 if ( vm_kernel_etext
!= 0 &&
9675 numberValue
>= vm_kernel_stext
&&
9676 numberValue
< vm_kernel_etext
) {
9677 IOLog("found OSNumber in kernel text segment %p to %p \n",
9678 (void *) vm_kernel_stext
,
9679 (void *) vm_kernel_etext
);
9680 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
9686 const OSMetaClass
* myMetaClass
= NULL
;
9688 myMetaClass
= theObject
->getMetaClass();
9689 if ( myMetaClass
) {
9690 IOLog("class %s \n", myMetaClass
->getClassName() );
9693 IOLog("Unknown object \n" );
9700 #endif // KASLR_KEXT_DEBUG
9705 #pragma mark Backtrace Dump & kmod_get_info() support
9707 /*********************************************************************
9708 * This function must be safe to call in panic context.
9709 *********************************************************************/
9712 OSKext::printKextsInBacktrace(
9715 int (* printf_func
)(const char *fmt
, ...),
9718 addr64_t summary_page
= 0;
9719 addr64_t last_summary_page
= 0;
9720 bool found_kmod
= false;
9724 IOLockLock(sKextSummariesLock
);
9727 if (!gLoadedKextSummaries
) {
9728 (*printf_func
)(" can't perform kext scan: no kext summary");
9732 summary_page
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
);
9733 last_summary_page
= round_page(summary_page
+ sLoadedKextSummariesAllocSize
);
9734 for (; summary_page
< last_summary_page
; summary_page
+= PAGE_SIZE
) {
9735 if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) {
9736 (*printf_func
)(" can't perform kext scan: "
9737 "missing kext summary page %p", summary_page
);
9742 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
9743 OSKextLoadedKextSummary
* summary
;
9745 summary
= gLoadedKextSummaries
->summaries
+ i
;
9746 if (!summary
->address
) {
9750 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
9755 (*printf_func
)(" Kernel Extensions in backtrace:\n");
9759 printSummary(summary
, printf_func
);
9764 IOLockUnlock(sKextSummariesLock
);
9770 /*********************************************************************
9771 * This function must be safe to call in panic context.
9772 *********************************************************************/
9775 OSKext::summaryIsInBacktrace(
9776 OSKextLoadedKextSummary
* summary
,
9782 for (i
= 0; i
< cnt
; i
++) {
9783 vm_offset_t kscan_addr
= addr
[i
];
9784 if ((kscan_addr
>= summary
->address
) &&
9785 (kscan_addr
< (summary
->address
+ summary
->size
)))
9794 /*********************************************************************
9795 * scan list of loaded kext summaries looking for a load address match and if
9796 * found return the UUID C string. If not found then set empty string.
9797 *********************************************************************/
9798 static void findSummaryUUID(
9800 uuid_string_t uuid
);
9802 static void findSummaryUUID(
9808 uuid
[0] = 0x00; // default to no UUID
9810 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
9811 OSKextLoadedKextSummary
* summary
;
9813 summary
= gLoadedKextSummaries
->summaries
+ i
;
9815 if (summary
->loadTag
== tag_ID
) {
9816 (void) uuid_unparse(summary
->uuid
, uuid
);
9823 /*********************************************************************
9824 * This function must be safe to call in panic context.
9825 *********************************************************************/
9826 void OSKext::printSummary(
9827 OSKextLoadedKextSummary
* summary
,
9828 int (* printf_func
)(const char *fmt
, ...))
9830 kmod_reference_t
* kmod_ref
= NULL
;
9832 char version
[kOSKextVersionMaxLength
];
9834 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
9835 strlcpy(version
, "unknown version", sizeof(version
));
9837 (void) uuid_unparse(summary
->uuid
, uuid
);
9839 (*printf_func
)(" %s(%s)[%s]@0x%llx->0x%llx\n",
9840 summary
->name
, version
, uuid
,
9841 summary
->address
, summary
->address
+ summary
->size
- 1);
9843 /* print dependency info */
9844 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
9846 kmod_ref
= kmod_ref
->next
) {
9847 kmod_info_t
* rinfo
;
9849 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) {
9850 (*printf_func
)(" kmod dependency scan stopped "
9851 "due to missing dependency page: %p\n", kmod_ref
);
9854 rinfo
= kmod_ref
->info
;
9856 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) {
9857 (*printf_func
)(" kmod dependency scan stopped "
9858 "due to missing kmod page: %p\n", rinfo
);
9862 if (!rinfo
->address
) {
9863 continue; // skip fake entries for built-ins
9866 /* locate UUID in gLoadedKextSummaries */
9867 findSummaryUUID(rinfo
->id
, uuid
);
9869 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
9870 rinfo
->name
, rinfo
->version
, uuid
, rinfo
->address
);
9876 /*******************************************************************************
9877 * substitute() looks at an input string (a pointer within a larger buffer)
9878 * for a match to a substring, and on match it writes the marker & substitution
9879 * character to an output string, updating the scan (from) and
9880 * output (to) indexes as appropriate.
9881 *******************************************************************************/
9882 static int substitute(
9883 const char * scan_string
,
9885 uint32_t * to_index
,
9886 uint32_t * from_index
,
9887 const char * substring
,
9891 /* string_out must be at least KMOD_MAX_NAME bytes.
9895 const char * scan_string
,
9897 uint32_t * to_index
,
9898 uint32_t * from_index
,
9899 const char * substring
,
9903 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
9905 /* On a substring match, append the marker (if there is one) and then
9906 * the substitution character, updating the output (to) index accordingly.
9907 * Then update the input (from) length by the length of the substring
9908 * that got replaced.
9910 if (!strncmp(scan_string
, substring
, substring_length
)) {
9912 string_out
[(*to_index
)++] = marker
;
9914 string_out
[(*to_index
)++] = substitution
;
9915 (*from_index
) += substring_length
;
9921 /*******************************************************************************
9922 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
9923 * KMOD_MAX_NAME characters and performs various substitutions of common
9924 * prefixes & substrings as defined by tables in kext_panic_report.h.
9925 *******************************************************************************/
9926 static void compactIdentifier(
9927 const char * identifier
,
9928 char * identifier_out
,
9929 char ** identifier_out_end
);
9933 const char * identifier
,
9934 char * identifier_out
,
9935 char ** identifier_out_end
)
9937 uint32_t from_index
, to_index
;
9938 uint32_t scan_from_index
= 0;
9939 uint32_t scan_to_index
= 0;
9940 subs_entry_t
* subs_entry
= NULL
;
9943 from_index
= to_index
= 0;
9944 identifier_out
[0] = '\0';
9946 /* Replace certain identifier prefixes with shorter @+character sequences.
9947 * Check the return value of substitute() so we only replace the prefix.
9949 for (subs_entry
= &kext_identifier_prefix_subs
[0];
9950 subs_entry
->substring
&& !did_sub
;
9953 did_sub
= substitute(identifier
, identifier_out
,
9954 &scan_to_index
, &scan_from_index
,
9955 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
9959 /* Now scan through the identifier looking for the common substrings
9960 * and replacing them with shorter !+character sequences via substitute().
9962 for (/* see above */;
9963 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
9966 const char * scan_string
= &identifier
[scan_from_index
];
9970 if (scan_from_index
) {
9971 for (subs_entry
= &kext_identifier_substring_subs
[0];
9972 subs_entry
->substring
&& !did_sub
;
9975 did_sub
= substitute(scan_string
, identifier_out
,
9976 &scan_to_index
, &scan_from_index
,
9977 subs_entry
->substring
, '!', subs_entry
->substitute
);
9981 /* If we didn't substitute, copy the input character to the output.
9984 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
9988 identifier_out
[scan_to_index
] = '\0';
9989 if (identifier_out_end
) {
9990 *identifier_out_end
= &identifier_out
[scan_to_index
];
9996 /*******************************************************************************
9997 * assemble_identifier_and_version() adds to a string buffer a compacted
9998 * bundle identifier followed by a version string.
9999 *******************************************************************************/
10001 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
10003 static int assemble_identifier_and_version(
10004 kmod_info_t
* kmod_info
,
10005 char * identPlusVers
);
10007 assemble_identifier_and_version(
10008 kmod_info_t
* kmod_info
,
10009 char * identPlusVers
)
10013 compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
);
10014 result
= strnlen(identPlusVers
, KMOD_MAX_NAME
- 1);
10015 identPlusVers
[result
++] = '\t'; // increment for real char
10016 identPlusVers
[result
] = '\0'; // don't increment for nul char
10017 result
= strlcat(identPlusVers
, kmod_info
->version
, KMOD_MAX_NAME
);
10022 /*******************************************************************************
10023 * Assumes sKextLock is held.
10024 *******************************************************************************/
10027 OSKext::saveLoadedKextPanicListTyped(
10028 const char * prefix
,
10032 uint32_t list_size
,
10033 uint32_t * list_length_ptr
)
10035 uint32_t result
= 0;
10037 unsigned int count
, i
;
10039 count
= sLoadedKexts
->getCount();
10046 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
10047 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
10049 char identPlusVers
[2*KMOD_MAX_NAME
];
10050 uint32_t identPlusVersLength
;
10053 printf("OSKext::saveLoadedKextPanicListTyped - "
10054 "NULL kext in loaded kext list; continuing\n");
10059 printf("OSKext::saveLoadedKextPanicListTyped - "
10060 "Kext type cast failed in loaded kext list; continuing\n");
10064 /* Skip all built-in kexts.
10066 if (theKext
->isKernelComponent()) {
10070 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
10072 /* Filter for kmod name (bundle identifier).
10074 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
10075 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
10079 /* Filter for libraries (kexts that have a compatible version).
10081 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
10082 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
10088 !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) {
10090 printf("kext scan stopped due to missing kmod_info page: %p\n",
10096 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
10098 if (!identPlusVersLength
) {
10099 printf("error saving loaded kext info\n");
10103 /* Adding 1 for the newline.
10105 if (*list_length_ptr
+ identPlusVersLength
+ 1 >= list_size
) {
10109 *list_length_ptr
= strlcat(paniclist
, identPlusVers
, list_size
);
10110 *list_length_ptr
= strlcat(paniclist
, "\n", list_size
);
10116 if (*list_length_ptr
+ 1 <= list_size
) {
10117 result
= list_size
- (*list_length_ptr
+ 1);
10124 /*********************************************************************
10125 *********************************************************************/
10128 OSKext::saveLoadedKextPanicList(void)
10130 char * newlist
= NULL
;
10131 uint32_t newlist_size
= 0;
10132 uint32_t newlist_length
= 0;
10134 newlist_length
= 0;
10135 newlist_size
= KEXT_PANICLIST_SIZE
;
10136 newlist
= (char *)kalloc(newlist_size
);
10139 OSKextLog(/* kext */ NULL
,
10140 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
10141 "Couldn't allocate kext panic log buffer.");
10147 // non-"com.apple." kexts
10148 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
10149 /* libs? */ -1, newlist
, newlist_size
, &newlist_length
)) {
10153 // "com.apple." nonlibrary kexts
10154 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10155 /* libs? */ 0, newlist
, newlist_size
, &newlist_length
)) {
10159 // "com.apple." library kexts
10160 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10161 /* libs? */ 1, newlist
, newlist_size
, &newlist_length
)) {
10166 if (loaded_kext_paniclist
) {
10167 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
10169 loaded_kext_paniclist
= newlist
;
10170 loaded_kext_paniclist_size
= newlist_size
;
10171 loaded_kext_paniclist_length
= newlist_length
;
10177 /*********************************************************************
10178 * Assumes sKextLock is held.
10179 *********************************************************************/
10181 OSKext::savePanicString(bool isLoading
)
10186 return; // do not goto finish here b/c of lock
10189 len
= assemble_identifier_and_version(kmod_info
,
10190 (isLoading
) ? last_loaded_str
: last_unloaded_str
);
10192 printf("error saving unloaded kext info\n");
10197 last_loaded_strlen
= len
;
10198 last_loaded_address
= (void *)kmod_info
->address
;
10199 last_loaded_size
= kmod_info
->size
;
10200 clock_get_uptime(&last_loaded_timestamp
);
10202 last_unloaded_strlen
= len
;
10203 last_unloaded_address
= (void *)kmod_info
->address
;
10204 last_unloaded_size
= kmod_info
->size
;
10205 clock_get_uptime(&last_unloaded_timestamp
);
10212 /*********************************************************************
10213 *********************************************************************/
10216 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
10218 if (last_loaded_strlen
) {
10219 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
10220 AbsoluteTime_to_scalar(&last_loaded_timestamp
),
10221 last_loaded_strlen
, last_loaded_str
,
10222 last_loaded_address
, last_loaded_size
);
10225 if (last_unloaded_strlen
) {
10226 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
10227 AbsoluteTime_to_scalar(&last_unloaded_timestamp
),
10228 last_unloaded_strlen
, last_unloaded_str
,
10229 last_unloaded_address
, last_unloaded_size
);
10232 printf_func("loaded kexts:\n");
10233 if (loaded_kext_paniclist
&&
10234 pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) &&
10235 loaded_kext_paniclist
[0]) {
10237 printf_func("%.*s", loaded_kext_paniclist_length
, loaded_kext_paniclist
);
10239 printf_func("(none)\n");
10244 /*********************************************************************
10245 * Assumes sKextLock is held.
10246 *********************************************************************/
10249 OSKext::updateLoadedKextSummaries(void)
10251 kern_return_t result
= KERN_FAILURE
;
10252 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
10253 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
10255 vm_map_offset_t start
, end
;
10256 size_t summarySize
= 0;
10262 IOLockLock(sKextSummariesLock
);
10264 count
= sLoadedKexts
->getCount();
10265 for (i
= 0, numKexts
= 0; i
< count
; ++i
) {
10266 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10267 numKexts
+= (aKext
&& aKext
->isExecutable());
10270 if (!numKexts
) goto finish
;
10272 /* Calculate the size needed for the new summary headers.
10275 size
= sizeof(*gLoadedKextSummaries
);
10276 size
+= numKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
10277 size
= round_page(size
);
10279 /* If the previous summary is large enough, use it (and be sure to make
10280 * it writable). If it's too small, free it and allocate a new buffer.
10283 if (sPrevLoadedKextSummariesAllocSize
< size
) {
10284 if (sPrevLoadedKextSummaries
) {
10285 kmem_free(kernel_map
, (vm_offset_t
)sPrevLoadedKextSummaries
,
10286 sPrevLoadedKextSummariesAllocSize
);
10287 sPrevLoadedKextSummaries
= NULL
;
10288 sPrevLoadedKextSummariesAllocSize
= 0;
10291 result
= kmem_alloc(kernel_map
,
10292 (vm_offset_t
*)&summaryHeaderAlloc
, size
);
10293 if (result
!= KERN_SUCCESS
) goto finish
;
10295 summaryHeader
= summaryHeaderAlloc
;
10296 summarySize
= size
;
10298 summaryHeader
= sPrevLoadedKextSummaries
;
10299 summarySize
= sPrevLoadedKextSummariesAllocSize
;
10301 start
= (vm_map_offset_t
) summaryHeader
;
10302 end
= start
+ summarySize
;
10305 /* Populate the summary header.
10308 bzero(summaryHeader
, summarySize
);
10309 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
10310 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
10311 summaryHeader
->numSummaries
= numKexts
;
10313 /* Populate each kext summary.
10316 count
= sLoadedKexts
->getCount();
10317 for (i
= 0, j
= 0; i
< count
; ++i
) {
10318 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10319 if (!aKext
|| !aKext
->isExecutable()) continue;
10321 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
10324 /* Write protect the buffer and move it into place.
10327 start
= (vm_map_offset_t
) summaryHeader
;
10328 end
= start
+ summarySize
;
10330 sPrevLoadedKextSummaries
= gLoadedKextSummaries
;
10331 sPrevLoadedKextSummariesAllocSize
= sLoadedKextSummariesAllocSize
;
10333 gLoadedKextSummaries
= summaryHeader
;
10334 sLoadedKextSummariesAllocSize
= summarySize
;
10336 summaryHeaderAlloc
= NULL
;
10338 /* Call the magic breakpoint function through a static function pointer so
10339 * the compiler can't optimize the function away.
10341 if (sLoadedKextSummariesUpdated
) (*sLoadedKextSummariesUpdated
)();
10344 IOLockUnlock(sKextSummariesLock
);
10346 /* If we had to allocate a new buffer but failed to generate the summaries,
10349 if (summaryHeaderAlloc
) {
10350 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
10356 /*********************************************************************
10357 *********************************************************************/
10359 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
10363 strlcpy(summary
->name
, getIdentifierCString(),
10364 sizeof(summary
->name
));
10368 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
10369 OSSafeRelease(uuid
);
10372 summary
->address
= kmod_info
->address
;
10373 summary
->size
= kmod_info
->size
;
10374 summary
->version
= getVersion();
10375 summary
->loadTag
= kmod_info
->id
;
10376 summary
->flags
= 0;
10377 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
10382 /*********************************************************************
10383 *********************************************************************/
10387 OSKext::getKmodInfo(
10388 kmod_info_array_t
* kmodList
,
10389 mach_msg_type_number_t
* kmodCount
)
10391 kern_return_t result
= KERN_FAILURE
;
10392 vm_offset_t data
= 0;
10393 kmod_info_t
* k
, * kmod_info_scan_ptr
;
10394 kmod_reference_t
* r
, * ref_scan_ptr
;
10398 *kmodList
= (kmod_info_t
*)0;
10401 IORecursiveLockLock(sKextLock
);
10405 size
+= sizeof(kmod_info_t
);
10406 r
= k
->reference_list
;
10408 size
+=sizeof(kmod_reference_t
);
10414 result
= KERN_SUCCESS
;
10418 result
= kmem_alloc(kernel_map
, &data
, size
);
10419 if (result
!= KERN_SUCCESS
) {
10423 /* Copy each kmod_info struct sequentially into the data buffer.
10424 * Set each struct's nonzero 'next' pointer back to itself as a sentinel;
10425 * the kernel space address is used to match refs, and a zero 'next' flags
10426 * the end of kmod_infos in the data buffer and the beginning of references.
10429 kmod_info_scan_ptr
= (kmod_info_t
*)data
;
10431 *kmod_info_scan_ptr
= *k
;
10433 kmod_info_scan_ptr
->next
= k
;
10435 kmod_info_scan_ptr
++;
10439 /* Now add references after the kmod_info structs in the same buffer.
10440 * Update each kmod_info with the ref_count so we can associate
10441 * references with kmod_info structs.
10444 ref_scan_ptr
= (kmod_reference_t
*)kmod_info_scan_ptr
;
10445 kmod_info_scan_ptr
= (kmod_info_t
*)data
;
10447 r
= k
->reference_list
;
10450 /* Note the last kmod_info in the data buffer has its next == 0.
10451 * Since there can only be one like that,
10452 * this case is handled by the caller.
10454 *ref_scan_ptr
= *r
;
10459 /* Stuff the # of refs into the 'reference_list' field of the kmod_info
10460 * struct for the client to interpret.
10462 kmod_info_scan_ptr
->reference_list
= (kmod_reference_t
*)(long)ref_count
;
10463 kmod_info_scan_ptr
++;
10467 result
= vm_map_copyin(kernel_map
, data
, size
, TRUE
, (vm_map_copy_t
*)kmodList
);
10468 if (result
!= KERN_SUCCESS
) {
10473 result
= KERN_SUCCESS
;
10476 IORecursiveLockUnlock(sKextLock
);
10478 if (result
!= KERN_SUCCESS
&& data
) {
10479 kmem_free(kernel_map
, data
, size
);
10480 *kmodList
= (kmod_info_t
*)0;
10485 #endif /* __i386__ */
10487 #if CONFIG_KEC_FIPS
10490 #pragma mark Kernel External Components for FIPS compliance
10493 /*********************************************************************
10494 * Kernel External Components for FIPS compliance (KEC_FIPS)
10495 *********************************************************************/
10497 GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
)
10499 AppleTEXTHash_t my_ath
= {1, 0, NULL
};
10500 AppleTEXTHash_t
* my_athp
= NULL
; // do not release
10501 OSDictionary
* textHashDict
= NULL
; // do not release
10502 OSData
* segmentHash
= NULL
; // do not release
10504 if (theKext
== NULL
|| theInfoDict
== NULL
) {
10508 textHashDict
= OSDynamicCast(OSDictionary
, theInfoDict
->getObject(kAppleTextHashesKey
));
10509 if (textHashDict
== NULL
) {
10513 segmentHash
= OSDynamicCast(OSData
,
10514 textHashDict
->getObject(ARCHNAME
));
10515 if (segmentHash
== NULL
) {
10519 // KEC_FIPS type kexts never unload so we don't have to clean up our
10521 if (kmem_alloc(kernel_map
, (vm_offset_t
*) &my_athp
,
10522 sizeof(AppleTEXTHash_t
)) != KERN_SUCCESS
) {
10526 memcpy(my_athp
, &my_ath
, sizeof(my_ath
));
10527 my_athp
->ath_length
= segmentHash
->getLength();
10528 if (my_athp
->ath_length
> 0) {
10529 my_athp
->ath_hash
= (void *)segmentHash
->getBytesNoCopy();
10534 kOSKextLogErrorLevel
|
10535 kOSKextLogGeneralFlag
,
10536 "Kext %s ath_version %d ath_length %d ath_hash %p",
10537 theKext
->getIdentifierCString(),
10538 my_athp
->ath_version
,
10539 my_athp
->ath_length
,
10540 my_athp
->ath_hash
);
10543 return( (void *) my_athp
);
10546 #endif // CONFIG_KEC_FIPS