2 * Copyright (c) 2008-2012 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 #include <kern/clock.h>
31 #include <kern/host.h>
32 #include <kern/kext_alloc.h>
33 #include <vm/vm_kern.h>
34 #include <kextd/kextd_mach.h>
35 #include <libkern/kernel_mach_header.h>
36 #include <libkern/kext_panic_report.h>
37 #include <libkern/kext_request_keys.h>
38 #include <libkern/mkext.h>
39 #include <libkern/prelink.h>
40 #include <libkern/version.h>
41 #include <libkern/zlib.h>
42 #include <mach/host_special_ports.h>
43 #include <mach/mach_vm.h>
44 #include <mach/mach_time.h>
45 #include <sys/sysctl.h>
46 #include <uuid/uuid.h>
47 // 04/18/11 - gab: <rdar://problem/9236163>
48 #include <sys/random.h>
53 #include <sys/kauth.h>
54 #include <security/mac_framework.h>
58 #include <libkern/OSKextLibPrivate.h>
59 #include <libkern/c++/OSKext.h>
60 #include <libkern/c++/OSLib.h>
62 #include <IOKit/IOLib.h>
63 #include <IOKit/IOCatalogue.h>
64 #include <IOKit/IORegistryEntry.h>
65 #include <IOKit/IOService.h>
67 #include <IOKit/IOStatisticsPrivate.h>
68 #include <IOKit/IOBSD.h>
71 #pragma mark External & Internal Function Protos
73 /*********************************************************************
74 *********************************************************************/
76 extern int IODTGetLoaderInfo(const char * key
, void ** infoAddr
, int * infoSize
);
77 extern void IODTFreeLoaderInfo(const char * key
, void * infoAddr
, int infoSize
);
78 extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t
* segment
);
79 extern void OSRuntimeUnloadCPP(kmod_info_t
* ki
, void * data
);
81 extern ppnum_t
pmap_find_phys(pmap_t pmap
, addr64_t va
); /* osfmk/machine/pmap.h */
84 static OSReturn
_OSKextCreateRequest(
85 const char * predicate
,
86 OSDictionary
** requestP
);
87 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
);
88 static OSObject
* _OSKextGetRequestArgument(
89 OSDictionary
* requestDict
,
90 const char * argName
);
91 static bool _OSKextSetRequestArgument(
92 OSDictionary
* requestDict
,
95 static void * _OSKextExtractPointer(OSData
* wrapper
);
96 static OSReturn
_OSDictionarySetCStringValue(
100 static bool _OSKextInPrelinkRebuildWindow(void);
101 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol
* theBundleID
);
103 // We really should add containsObject() & containsCString to OSCollection & subclasses.
104 // So few pad slots, though....
105 static bool _OSArrayContainsCString(OSArray
* array
, const char * cString
);
108 static void * GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
);
109 #endif // CONFIG_KEC_FIPS
111 /* Prelinked arm kexts do not have VM entries because the method we use to
112 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
113 * not work on ARM. To get around that, we must free prelinked kext
114 * executables with ml_static_mfree() instead of kext_free().
116 #if __i386__ || __x86_64__
117 #define VM_MAPPED_KEXTS 1
118 #define KASLR_KEXT_DEBUG 0
119 #define KASLR_IOREG_DEBUG 0
121 #error Unsupported architecture
125 #pragma mark Constants & Macros
127 /*********************************************************************
129 *********************************************************************/
131 /* Use this number to create containers.
133 #define kOSKextTypicalLoadCount (150)
135 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
136 * A loaded kext will no dependents or external retains will have 2 retains.
138 #define kOSKextMinRetainCount (1)
139 #define kOSKextMinLoadedRetainCount (2)
142 * Strings and substrings used in dependency resolution.
144 #define APPLE_KEXT_PREFIX "com.apple."
145 #define KERNEL_LIB "com.apple.kernel"
147 #define PRIVATE_KPI "com.apple.kpi.private"
149 /* Version for compatbility pseudokexts (com.apple.kernel.*),
150 * compatible back to v6.0.
152 #define KERNEL6_LIB "com.apple.kernel.6.0"
153 #define KERNEL6_VERSION "7.9.9"
155 #define KERNEL_LIB_PREFIX "com.apple.kernel."
156 #define KPI_LIB_PREFIX "com.apple.kpi."
158 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0)
160 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
161 #define MINIMUM_WAKEUP_SECONDS (30)
163 /*********************************************************************
164 * infoDict keys for internally-stored data. Saves on ivar slots for
165 * objects we don't keep around past boot time or during active load.
166 *********************************************************************/
168 /* A usable, uncompressed file is stored under this key.
170 #define _kOSKextExecutableKey "_OSKextExecutable"
172 /* An indirect reference to the executable file from an mkext
173 * is stored under this key.
175 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference"
177 /* If the file is contained in a larger buffer laid down by the booter or
178 * sent from user space, the OSKext stores that OSData under this key so that
179 * references are properly tracked. This is always an mkext, right now.
181 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
184 #pragma mark Typedefs
186 /*********************************************************************
188 *********************************************************************/
190 /*********************************************************************
191 * MkextEntryRef describes the contents of an OSData object
192 * referencing a file entry from an mkext so that we can uncompress
193 * (if necessary) and extract it on demand.
195 * It contains the mkextVersion in case we ever wind up supporting
196 * multiple mkext formats. Mkext format 1 is officially retired as of
198 *********************************************************************/
199 typedef struct MkextEntryRef
{
200 mkext_basic_header
* mkext
; // beginning of whole mkext file
201 void * fileinfo
; // mkext2_file_entry or equiv; see mkext.h
205 #pragma mark Global and static Module Variables
207 /*********************************************************************
208 * Global & static variables, used to keep track of kexts.
209 *********************************************************************/
211 static bool sPrelinkBoot
= false;
212 static bool sSafeBoot
= false;
213 static bool sKeepSymbols
= false;
215 /*********************************************************************
216 * sKextLock is the principal lock for OSKext, and guards all static
217 * and global variables not owned by other locks (declared further
218 * below). It must be taken by any entry-point method or function,
219 * including internal functions called on scheduled threads.
221 * sKextLock and sKextInnerLock are recursive due to multiple functions
222 * that are called both externally and internally. The other locks are
225 * Which locks are taken depends on what they protect, but if more than
226 * one must be taken, they must always be locked in this order
227 * (and unlocked in reverse order) to prevent deadlocks:
231 * 3. sKextSummariesLock
232 * 4. sKextLoggingLock
234 static IORecursiveLock
* sKextLock
= NULL
;
236 static OSDictionary
* sKextsByID
= NULL
;
237 static OSDictionary
* sExcludeListByID
= NULL
;
238 static OSArray
* sLoadedKexts
= NULL
;
239 static OSArray
* sUnloadedPrelinkedKexts
= NULL
;
241 // Requests to kextd waiting to be picked up.
242 static OSArray
* sKernelRequests
= NULL
;
243 // Identifier of kext load requests in sKernelRequests
244 static OSSet
* sPostedKextLoadIdentifiers
= NULL
;
245 static OSArray
* sRequestCallbackRecords
= NULL
;
247 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
248 static OSSet
* sAllKextLoadIdentifiers
= NULL
;
249 static KXLDContext
* sKxldContext
= NULL
;
250 static uint32_t sNextLoadTag
= 0;
251 static uint32_t sNextRequestTag
= 0;
253 static bool sUserLoadsActive
= false;
254 static bool sKextdActive
= false;
255 static bool sDeferredLoadSucceeded
= false;
256 static bool sConsiderUnloadsExecuted
= false;
259 static bool sKernelRequestsEnabled
= false;
261 static bool sKernelRequestsEnabled
= true;
263 static bool sLoadEnabled
= true;
264 static bool sUnloadEnabled
= true;
266 /*********************************************************************
267 * Stuff for the OSKext representing the kernel itself.
269 static OSKext
* sKernelKext
= NULL
;
271 /* Set up a fake kmod_info struct for the kernel.
272 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
273 * before OSKext is initialized; that call only needs the name
274 * and address to be set correctly.
276 * We don't do much else with the kerne's kmod_info; we never
277 * put it into the kmod list, never adjust the reference count,
278 * and never have kernel components reference it.
279 * For that matter, we don't do much with kmod_info structs
280 * at all anymore! We just keep them filled in for gdb and
281 * binary compability.
283 kmod_info_t g_kernel_kmod_info
= {
285 /* info_version */ KMOD_INFO_VERSION
,
286 /* id */ 0, // loadTag: kernel is always 0
287 /* name */ kOSKextKernelIdentifier
, // bundle identifier
288 /* version */ "0", // filled in in OSKext::initialize()
289 /* reference_count */ -1, // never adjusted; kernel never unloads
290 /* reference_list */ NULL
,
292 /* size */ 0, // filled in in OSKext::initialize()
299 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
300 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
301 // misc_protos.h, db_low_trace.c, kgmacros
302 // 'kmod' is a holdover from the old kmod system, we can't rename it.
303 kmod_info_t
* kmod
= NULL
;
305 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
308 static char * loaded_kext_paniclist
= NULL
;
309 static uint32_t loaded_kext_paniclist_size
= 0;
311 AbsoluteTime last_loaded_timestamp
;
312 static char last_loaded_str_buf
[2*KMOD_MAX_NAME
];
313 static u_long last_loaded_strlen
= 0;
314 static void * last_loaded_address
= NULL
;
315 static u_long last_loaded_size
= 0;
317 AbsoluteTime last_unloaded_timestamp
;
318 static char last_unloaded_str_buf
[2*KMOD_MAX_NAME
];
319 static u_long last_unloaded_strlen
= 0;
320 static void * last_unloaded_address
= NULL
;
321 static u_long last_unloaded_size
= 0;
323 /*********************************************************************
324 * sKextInnerLock protects against cross-calls with IOService and
325 * IOCatalogue, and owns the variables declared immediately below.
327 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
329 * When both sKextLock and sKextInnerLock need to be taken,
330 * always lock sKextLock first and unlock it second. Never take both
331 * locks in an entry point to OSKext; if you need to do so, you must
332 * spawn an independent thread to avoid potential deadlocks for threads
333 * calling into OSKext.
335 static IORecursiveLock
* sKextInnerLock
= NULL
;
337 static bool sAutounloadEnabled
= true;
338 static bool sConsiderUnloadsCalled
= false;
339 static bool sConsiderUnloadsPending
= false;
341 static unsigned int sConsiderUnloadDelay
= 60; // seconds
342 static thread_call_t sUnloadCallout
= 0;
343 static thread_call_t sDestroyLinkContextThread
= 0; // one-shot, one-at-a-time thread
344 static bool sSystemSleep
= false; // true when system going to sleep
345 static AbsoluteTime sLastWakeTime
; // last time we woke up
347 /*********************************************************************
348 * Backtraces can be printed at various times so we need a tight lock
349 * on data used for that. sKextSummariesLock protects the variables
350 * declared immediately below.
352 * gLoadedKextSummaries is accessed by other modules, but only during
353 * a panic so the lock isn't needed then.
355 * gLoadedKextSummaries has the "used" attribute in order to ensure
356 * that it remains visible even when we are performing extremely
357 * aggressive optimizations, as it is needed to allow the debugger
358 * to automatically parse the list of loaded kexts.
360 static IOLock
* sKextSummariesLock
= NULL
;
361 extern "C" lck_spin_t vm_allocation_sites_lock
;
362 static IOSimpleLock
* sKextAccountsLock
= &vm_allocation_sites_lock
;
364 void (*sLoadedKextSummariesUpdated
)(void) = OSKextLoadedKextSummariesUpdated
;
365 OSKextLoadedKextSummaryHeader
* gLoadedKextSummaries
__attribute__((used
)) = NULL
;
366 static size_t sLoadedKextSummariesAllocSize
= 0;
368 static OSKextActiveAccount
* sKextAccounts
;
369 static uint32_t sKextAccountsCount
;
372 /*********************************************************************
373 * sKextLoggingLock protects the logging variables declared immediately below.
375 static IOLock
* sKextLoggingLock
= NULL
;
377 static const OSKextLogSpec kDefaultKernelLogFilter
= kOSKextLogBasicLevel
|
378 kOSKextLogVerboseFlagsMask
;
379 static OSKextLogSpec sKernelLogFilter
= kDefaultKernelLogFilter
;
380 static bool sBootArgLogFilterFound
= false;
381 SYSCTL_UINT(_debug
, OID_AUTO
, kextlog
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &sKernelLogFilter
,
382 sKernelLogFilter
, "kernel kext logging");
384 static OSKextLogSpec sUserSpaceKextLogFilter
= kOSKextLogSilentFilter
;
385 static OSArray
* sUserSpaceLogSpecArray
= NULL
;
386 static OSArray
* sUserSpaceLogMessageArray
= NULL
;
389 * End scope for sKextInnerLock-protected variables.
390 *********************************************************************/
393 /*********************************************************************
394 helper function used for collecting PGO data upon unload of a kext
397 static int OSKextGrabPgoDataLocked(OSKext
*kext
,
399 uuid_t instance_uuid
,
402 uint64_t bufferSize
);
404 /**********************************************************************/
409 #pragma mark OSData callbacks (need to move to OSData)
411 /*********************************************************************
412 * C functions used for callbacks.
413 *********************************************************************/
415 void osdata_kmem_free(void * ptr
, unsigned int length
) {
416 kmem_free(kernel_map
, (vm_address_t
)ptr
, length
);
420 void osdata_phys_free(void * ptr
, unsigned int length
) {
421 ml_static_mfree((vm_offset_t
)ptr
, length
);
425 void osdata_vm_deallocate(void * ptr
, unsigned int length
)
427 (void)vm_deallocate(kernel_map
, (vm_offset_t
)ptr
, length
);
431 void osdata_kext_free(void * ptr
, unsigned int length
)
433 (void)kext_free((vm_offset_t
)ptr
, length
);
439 #pragma mark KXLD Allocation Callback
441 /*********************************************************************
442 * KXLD Allocation Callback
443 *********************************************************************/
447 KXLDAllocateFlags
* flags
,
450 vm_address_t result
= 0; // returned
451 kern_return_t mach_result
= KERN_FAILURE
;
452 bool success
= false;
453 OSKext
* theKext
= (OSKext
*)user_data
;
454 u_long roundSize
= round_page(size
);
455 OSData
* linkBuffer
= NULL
; // must release
457 mach_result
= kext_alloc(&result
, roundSize
, /* fixed */ FALSE
);
458 if (mach_result
!= KERN_SUCCESS
) {
460 kOSKextLogErrorLevel
|
461 kOSKextLogGeneralFlag
,
462 "Can't allocate kernel memory to link %s.",
463 theKext
->getIdentifierCString());
467 /* Create an OSData wrapper for the allocated buffer.
469 linkBuffer
= OSData::withBytesNoCopy((void *)result
, roundSize
);
472 kOSKextLogErrorLevel
|
473 kOSKextLogGeneralFlag
,
474 "Can't allocate linked executable wrapper for %s.",
475 theKext
->getIdentifierCString());
478 linkBuffer
->setDeallocFunction(osdata_kext_free
);
480 kOSKextLogProgressLevel
|
481 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
482 "Allocated link buffer for kext %s at %p (%lu bytes).",
483 theKext
->getIdentifierCString(),
484 (void *)result
, (unsigned long)roundSize
);
486 theKext
->setLinkedExecutable(linkBuffer
);
488 *flags
= kKxldAllocateWritable
;
492 if (!success
&& result
) {
493 kext_free(result
, roundSize
);
497 OSSafeRelease(linkBuffer
);
499 return (kxld_addr_t
)result
;
502 /*********************************************************************
503 *********************************************************************/
506 KXLDLogSubsystem subsystem
,
512 OSKext
*theKext
= (OSKext
*) user_data
;
513 OSKextLogSpec logSpec
= 0;
516 case kKxldLogLinking
:
517 logSpec
|= kOSKextLogLinkFlag
;
519 case kKxldLogPatching
:
520 logSpec
|= kOSKextLogPatchFlag
;
525 case kKxldLogExplicit
:
526 logSpec
|= kOSKextLogExplicitLevel
;
529 logSpec
|= kOSKextLogErrorLevel
;
532 logSpec
|= kOSKextLogWarningLevel
;
535 logSpec
|= kOSKextLogProgressLevel
;
538 logSpec
|= kOSKextLogDetailLevel
;
541 logSpec
|= kOSKextLogDebugLevel
;
545 OSKextVLog(theKext
, logSpec
, format
, argList
);
549 #pragma mark IOStatistics defines
554 #define notifyKextLoadObservers(kext, kmod_info) \
556 IOStatistics::onKextLoad(kext, kmod_info); \
559 #define notifyKextUnloadObservers(kext) \
561 IOStatistics::onKextUnload(kext); \
564 #define notifyAddClassObservers(kext, addedClass, flags) \
566 IOStatistics::onClassAdded(kext, addedClass); \
569 #define notifyRemoveClassObservers(kext, removedClass, flags) \
571 IOStatistics::onClassRemoved(kext, removedClass); \
576 #define notifyKextLoadObservers(kext, kmod_info)
577 #define notifyKextUnloadObservers(kext)
578 #define notifyAddClassObservers(kext, addedClass, flags)
579 #define notifyRemoveClassObservers(kext, removedClass, flags)
581 #endif /* IOKITSTATS */
584 #pragma mark Module Config (Startup & Shutdown)
586 /*********************************************************************
587 * Module Config (Class Definition & Class Methods)
588 *********************************************************************/
589 #define super OSObject
590 OSDefineMetaClassAndStructors(OSKext
, OSObject
)
592 /*********************************************************************
593 *********************************************************************/
596 OSKext::initialize(void)
598 OSData
* kernelExecutable
= NULL
; // do not release
599 u_char
* kernelStart
= NULL
; // do not free
600 size_t kernelLength
= 0;
601 OSString
* scratchString
= NULL
; // must release
602 IORegistryEntry
* registryRoot
= NULL
; // do not release
603 OSNumber
* kernelCPUType
= NULL
; // must release
604 OSNumber
* kernelCPUSubtype
= NULL
; // must release
605 OSKextLogSpec bootLogFilter
= kOSKextLogSilentFilter
;
606 bool setResult
= false;
607 uint64_t * timestamp
= 0;
608 char bootArgBuffer
[16]; // for PE_parse_boot_argn w/strings
610 /* This must be the first thing allocated. Everything else grabs this lock.
612 sKextLock
= IORecursiveLockAlloc();
613 sKextInnerLock
= IORecursiveLockAlloc();
614 sKextSummariesLock
= IOLockAlloc();
615 sKextLoggingLock
= IOLockAlloc();
617 assert(sKextInnerLock
);
618 assert(sKextSummariesLock
);
619 assert(sKextLoggingLock
);
621 sKextsByID
= OSDictionary::withCapacity(kOSKextTypicalLoadCount
);
622 sLoadedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
);
623 sUnloadedPrelinkedKexts
= OSArray::withCapacity(kOSKextTypicalLoadCount
/ 10);
624 sKernelRequests
= OSArray::withCapacity(0);
625 sPostedKextLoadIdentifiers
= OSSet::withCapacity(0);
626 sAllKextLoadIdentifiers
= OSSet::withCapacity(kOSKextTypicalLoadCount
);
627 sRequestCallbackRecords
= OSArray::withCapacity(0);
628 assert(sKextsByID
&& sLoadedKexts
&& sKernelRequests
&&
629 sPostedKextLoadIdentifiers
&& sAllKextLoadIdentifiers
&&
630 sRequestCallbackRecords
&& sUnloadedPrelinkedKexts
);
632 /* Read the log flag boot-args and set the log flags.
634 if (PE_parse_boot_argn("kextlog", &bootLogFilter
, sizeof(bootLogFilter
))) {
635 sBootArgLogFilterFound
= true;
636 sKernelLogFilter
= bootLogFilter
;
637 // log this if any flags are set
638 OSKextLog(/* kext */ NULL
,
639 kOSKextLogBasicLevel
|
641 "Kernel kext log filter 0x%x per kextlog boot arg.",
642 (unsigned)sKernelLogFilter
);
645 sSafeBoot
= PE_parse_boot_argn("-x", bootArgBuffer
,
646 sizeof(bootArgBuffer
)) ? true : false;
649 OSKextLog(/* kext */ NULL
,
650 kOSKextLogWarningLevel
|
651 kOSKextLogGeneralFlag
,
652 "SAFE BOOT DETECTED - "
653 "only valid OSBundleRequired kexts will be loaded.");
656 PE_parse_boot_argn("keepsyms", &sKeepSymbols
, sizeof(sKeepSymbols
));
658 /* Set up an OSKext instance to represent the kernel itself.
660 sKernelKext
= new OSKext
;
663 kernelStart
= (u_char
*)&_mh_execute_header
;
664 kernelLength
= getlastaddr() - (vm_offset_t
)kernelStart
;
665 kernelExecutable
= OSData::withBytesNoCopy(
666 kernelStart
, kernelLength
);
667 assert(kernelExecutable
);
670 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu \n",
671 (unsigned long)kernelStart
,
672 (unsigned long)getlastaddr(),
676 sKernelKext
->loadTag
= sNextLoadTag
++; // the kernel is load tag 0
677 sKernelKext
->bundleID
= OSSymbol::withCString(kOSKextKernelIdentifier
);
679 sKernelKext
->version
= OSKextParseVersionString(osrelease
);
680 sKernelKext
->compatibleVersion
= sKernelKext
->version
;
681 sKernelKext
->linkedExecutable
= kernelExecutable
;
683 sKernelKext
->flags
.hasAllDependencies
= 1;
684 sKernelKext
->flags
.kernelComponent
= 1;
685 sKernelKext
->flags
.prelinked
= 0;
686 sKernelKext
->flags
.loaded
= 1;
687 sKernelKext
->flags
.started
= 1;
688 sKernelKext
->flags
.CPPInitialized
= 0;
689 sKernelKext
->flags
.jettisonLinkeditSeg
= 0;
691 sKernelKext
->kmod_info
= &g_kernel_kmod_info
;
692 strlcpy(g_kernel_kmod_info
.version
, osrelease
,
693 sizeof(g_kernel_kmod_info
.version
));
694 g_kernel_kmod_info
.size
= kernelLength
;
695 g_kernel_kmod_info
.id
= sKernelKext
->loadTag
;
697 /* Cons up an info dict, so we don't have to have special-case
700 sKernelKext
->infoDict
= OSDictionary::withCapacity(5);
701 assert(sKernelKext
->infoDict
);
702 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleIdentifierKey
,
703 sKernelKext
->bundleID
);
705 setResult
= sKernelKext
->infoDict
->setObject(kOSKernelResourceKey
,
709 scratchString
= OSString::withCStringNoCopy(osrelease
);
710 assert(scratchString
);
711 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleVersionKey
,
714 OSSafeReleaseNULL(scratchString
);
716 scratchString
= OSString::withCStringNoCopy("mach_kernel");
717 assert(scratchString
);
718 setResult
= sKernelKext
->infoDict
->setObject(kCFBundleNameKey
,
721 OSSafeReleaseNULL(scratchString
);
723 /* Add the kernel kext to the bookkeeping dictionaries. Note that
724 * the kernel kext doesn't have a kmod_info struct. copyInfo()
725 * gathers info from other places anyhow.
727 setResult
= sKextsByID
->setObject(sKernelKext
->bundleID
, sKernelKext
);
729 setResult
= sLoadedKexts
->setObject(sKernelKext
);
731 sKernelKext
->release();
733 registryRoot
= IORegistryEntry::getRegistryRoot();
734 kernelCPUType
= OSNumber::withNumber(
735 (long long unsigned int)_mh_execute_header
.cputype
,
736 8 * sizeof(_mh_execute_header
.cputype
));
737 kernelCPUSubtype
= OSNumber::withNumber(
738 (long long unsigned int)_mh_execute_header
.cpusubtype
,
739 8 * sizeof(_mh_execute_header
.cpusubtype
));
740 assert(registryRoot
&& kernelCPUSubtype
&& kernelCPUType
);
742 registryRoot
->setProperty(kOSKernelCPUTypeKey
, kernelCPUType
);
743 registryRoot
->setProperty(kOSKernelCPUSubtypeKey
, kernelCPUSubtype
);
745 OSSafeRelease(kernelCPUType
);
746 OSSafeRelease(kernelCPUSubtype
);
748 timestamp
= __OSAbsoluteTimePtr(&last_loaded_timestamp
);
750 timestamp
= __OSAbsoluteTimePtr(&last_unloaded_timestamp
);
752 timestamp
= __OSAbsoluteTimePtr(&sLastWakeTime
);
755 OSKextLog(/* kext */ NULL
,
756 kOSKextLogProgressLevel
|
757 kOSKextLogGeneralFlag
,
758 "Kext system initialized.");
760 notifyKextLoadObservers(sKernelKext
, sKernelKext
->kmod_info
);
765 /*********************************************************************
766 * This could be in OSKextLib.cpp but we need to hold a lock
767 * while removing all the segments and sKextLock will do.
768 *********************************************************************/
771 OSKext::removeKextBootstrap(void)
773 OSReturn result
= kOSReturnError
;
775 static bool alreadyDone
= false;
777 const char * dt_kernel_header_name
= "Kernel-__HEADER";
778 const char * dt_kernel_symtab_name
= "Kernel-__SYMTAB";
779 kernel_mach_header_t
* dt_mach_header
= NULL
;
780 int dt_mach_header_size
= 0;
781 struct symtab_command
* dt_symtab
= NULL
;
782 int dt_symtab_size
= 0;
785 kernel_segment_command_t
* seg_to_remove
= NULL
;
788 /* This must be the very first thing done by this function.
790 IORecursiveLockLock(sKextLock
);
792 /* If we already did this, it's a success.
795 result
= kOSReturnSuccess
;
799 OSKextLog(/* kext */ NULL
,
800 kOSKextLogProgressLevel
|
801 kOSKextLogGeneralFlag
,
802 "Jettisoning kext bootstrap segments.");
805 * Dispose of unnecessary stuff that the booter didn't need to load.
807 dt_result
= IODTGetLoaderInfo(dt_kernel_header_name
,
808 (void **)&dt_mach_header
, &dt_mach_header_size
);
809 if (dt_result
== 0 && dt_mach_header
) {
810 IODTFreeLoaderInfo(dt_kernel_header_name
, (void *)dt_mach_header
,
811 round_page_32(dt_mach_header_size
));
813 dt_result
= IODTGetLoaderInfo(dt_kernel_symtab_name
,
814 (void **)&dt_symtab
, &dt_symtab_size
);
815 if (dt_result
== 0 && dt_symtab
) {
816 IODTFreeLoaderInfo(dt_kernel_symtab_name
, (void *)dt_symtab
,
817 round_page_32(dt_symtab_size
));
821 * KLD bootstrap segment.
823 // xxx - should rename KLD segment
824 seg_to_remove
= getsegbyname("__KLD");
826 OSRuntimeUnloadCPPForSegment(seg_to_remove
);
829 #if __i386__ || __x86_64__
830 /* On x86, use the mapping data from the segment load command to
831 * unload KLD directly.
832 * This may invalidate any assumptions about "avail_start"
833 * defining the lower bound for valid physical addresses.
835 if (seg_to_remove
&& seg_to_remove
->vmaddr
&& seg_to_remove
->vmsize
) {
836 // 04/18/11 - gab: <rdar://problem/9236163>
837 // overwrite memory occupied by KLD segment with random data before
839 read_frandom((void *) seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
840 ml_static_mfree(seg_to_remove
->vmaddr
, seg_to_remove
->vmsize
);
846 seg_to_remove
= NULL
;
849 * Prelinked kernel's symtab (if there is one).
851 kernel_section_t
* sect
;
852 sect
= getsectbyname("__PRELINK", "__symtab");
853 if (sect
&& sect
->addr
&& sect
->size
) {
854 ml_static_mfree(sect
->addr
, sect
->size
);
857 seg_to_remove
= (kernel_segment_command_t
*)getsegbyname("__LINKEDIT");
859 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
860 * pageable, unless keepsyms is set. To do that, we have to copy it from
861 * its booter-allocated memory, free the booter memory, reallocate proper
862 * managed memory, then copy the segment back in.
866 kern_return_t mem_result
;
867 void *seg_copy
= NULL
;
868 void *seg_data
= NULL
;
869 vm_map_offset_t seg_offset
= 0;
870 vm_map_offset_t seg_copy_offset
= 0;
871 vm_map_size_t seg_length
= 0;
873 seg_data
= (void *) seg_to_remove
->vmaddr
;
874 seg_offset
= (vm_map_offset_t
) seg_to_remove
->vmaddr
;
875 seg_length
= (vm_map_size_t
) seg_to_remove
->vmsize
;
877 /* Allocate space for the LINKEDIT copy.
879 mem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*) &seg_copy
,
880 seg_length
, VM_KERN_MEMORY_KEXT
);
881 if (mem_result
!= KERN_SUCCESS
) {
882 OSKextLog(/* kext */ NULL
,
883 kOSKextLogErrorLevel
|
884 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
885 "Can't copy __LINKEDIT segment for VM reassign.");
888 seg_copy_offset
= (vm_map_offset_t
) seg_copy
;
892 memcpy(seg_copy
, seg_data
, seg_length
);
894 /* Dump the booter memory.
896 ml_static_mfree(seg_offset
, seg_length
);
898 /* Set up the VM region.
900 mem_result
= vm_map_enter_mem_object(
903 seg_length
, /* mask */ 0,
904 VM_FLAGS_FIXED
| VM_FLAGS_OVERWRITE
,
906 (vm_object_offset_t
) 0,
908 /* cur_protection */ VM_PROT_READ
| VM_PROT_WRITE
,
909 /* max_protection */ VM_PROT_ALL
,
910 /* inheritance */ VM_INHERIT_DEFAULT
);
911 if ((mem_result
!= KERN_SUCCESS
) ||
912 (seg_offset
!= (vm_map_offset_t
) seg_data
))
914 OSKextLog(/* kext */ NULL
,
915 kOSKextLogErrorLevel
|
916 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
917 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
918 seg_data
, seg_length
, mem_result
);
924 memcpy(seg_data
, seg_copy
, seg_length
);
928 kmem_free(kernel_map
, seg_copy_offset
, seg_length
);
930 #else /* we are not CONFIG_KXLD */
931 #error CONFIG_KXLD is expected for this arch
934 * Dump the LINKEDIT segment, unless keepsyms is set.
937 const char *dt_segment_name
= "Kernel-__LINKEDIT";
938 if (0 == IODTGetLoaderInfo(dt_segment_name
,
939 &segment_paddress
, &segment_size
)) {
941 vm_offset_t vmaddr
= ml_static_ptovirt((vm_offset_t
)segment_paddress
);
942 bzero((void*)vmaddr
, segment_size
);
944 IODTFreeLoaderInfo(dt_segment_name
, (void *)segment_paddress
,
948 OSKextLog(/* kext */ NULL
,
949 kOSKextLogBasicLevel
|
950 kOSKextLogGeneralFlag
,
951 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
953 #endif /* CONFIG_KXLD */
955 seg_to_remove
= NULL
;
958 result
= kOSReturnSuccess
;
962 /* This must be the very last thing done before returning.
964 IORecursiveLockUnlock(sKextLock
);
969 /*********************************************************************
970 *********************************************************************/
972 OSKext::flushNonloadedKexts(
973 Boolean flushPrelinkedKexts
)
975 OSSet
* prelinkedKexts
= NULL
; // must release
976 OSCollectionIterator
* kextIterator
= NULL
; // must release
977 OSCollectionIterator
* prelinkIterator
= NULL
; // must release
978 const OSSymbol
* thisID
= NULL
; // do not release
979 OSKext
* thisKext
= NULL
; // do not release
982 IORecursiveLockLock(sKextLock
);
984 OSKextLog(/* kext */ NULL
,
985 kOSKextLogProgressLevel
|
986 kOSKextLogKextBookkeepingFlag
,
987 "Flushing nonloaded kexts and other unused data.");
989 OSKext::considerDestroyingLinkContext();
991 /* If we aren't flushing unused prelinked kexts, we have to put them
992 * aside while we flush everything else so make a container for them.
994 if (!flushPrelinkedKexts
) {
995 prelinkedKexts
= OSSet::withCapacity(0);
996 if (!prelinkedKexts
) {
1001 /* Set aside prelinked kexts (in-use or not) and break
1002 * any lingering inter-kext references for nonloaded kexts
1003 * so they have min. retain counts.
1005 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
1006 if (!kextIterator
) {
1010 while ((thisID
= OSDynamicCast(OSSymbol
,
1011 kextIterator
->getNextObject()))) {
1013 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
1016 if (prelinkedKexts
&& thisKext
->isPrelinked()) {
1017 prelinkedKexts
->setObject(thisKext
);
1019 thisKext
->flushDependencies(/* forceIfLoaded */ false);
1023 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1025 sKextsByID
->flushCollection();
1027 /* Now put the loaded kexts back into the ID dictionary.
1029 count
= sLoadedKexts
->getCount();
1030 for (i
= 0; i
< count
; i
++) {
1031 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
1032 sKextsByID
->setObject(thisKext
->getIdentifierCString(), thisKext
);
1035 /* Finally, put back the prelinked kexts if we saved any.
1037 if (prelinkedKexts
) {
1038 prelinkIterator
= OSCollectionIterator::withCollection(prelinkedKexts
);
1039 if (!prelinkIterator
) {
1043 while ((thisKext
= OSDynamicCast(OSKext
,
1044 prelinkIterator
->getNextObject()))) {
1046 sKextsByID
->setObject(thisKext
->getIdentifierCString(),
1052 IORecursiveLockUnlock(sKextLock
);
1054 OSSafeRelease(prelinkedKexts
);
1055 OSSafeRelease(kextIterator
);
1056 OSSafeRelease(prelinkIterator
);
1061 /*********************************************************************
1062 *********************************************************************/
1065 OSKext::setKextdActive(Boolean active
)
1067 IORecursiveLockLock(sKextLock
);
1068 sKextdActive
= active
;
1069 if (sKernelRequests
->getCount()) {
1070 OSKext::pingKextd();
1072 IORecursiveLockUnlock(sKextLock
);
1077 /*********************************************************************
1078 * OSKextLib.cpp might need access to this someday but for now it's
1080 *********************************************************************/
1082 extern void ipc_port_release_send(ipc_port_t
);
1087 OSKext::pingKextd(void)
1089 OSReturn result
= kOSReturnError
;
1091 mach_port_t kextd_port
= IPC_PORT_NULL
;
1093 if (!sKextdActive
) {
1094 result
= kOSKextReturnDisabled
; // basically unavailable
1098 result
= host_get_kextd_port(host_priv_self(), &kextd_port
);
1099 if (result
!= KERN_SUCCESS
|| !IPC_PORT_VALID(kextd_port
)) {
1100 OSKextLog(/* kext */ NULL
,
1101 kOSKextLogErrorLevel
|
1103 "Can't get kextd port.");
1107 result
= kextd_ping(kextd_port
);
1108 if (result
!= KERN_SUCCESS
) {
1109 OSKextLog(/* kext */ NULL
,
1110 kOSKextLogErrorLevel
|
1112 "kextd ping failed (0x%x).", (int)result
);
1117 if (IPC_PORT_VALID(kextd_port
)) {
1118 ipc_port_release_send(kextd_port
);
1125 /*********************************************************************
1126 *********************************************************************/
1129 OSKext::setDeferredLoadSucceeded(Boolean succeeded
)
1131 IORecursiveLockLock(sKextLock
);
1132 sDeferredLoadSucceeded
= succeeded
;
1133 IORecursiveLockUnlock(sKextLock
);
1138 /*********************************************************************
1139 * Called from IOSystemShutdownNotification.
1140 *********************************************************************/
1143 OSKext::willShutdown(void)
1146 OSReturn checkResult
= kOSReturnError
;
1148 OSDictionary
* exitRequest
= NULL
; // must release
1150 IORecursiveLockLock(sKextLock
);
1152 OSKext::setLoadEnabled(false);
1153 OSKext::setUnloadEnabled(false);
1154 OSKext::setAutounloadsEnabled(false);
1155 OSKext::setKernelRequestsEnabled(false);
1158 OSKextLog(/* kext */ NULL
,
1159 kOSKextLogProgressLevel
|
1160 kOSKextLogGeneralFlag
,
1161 "System shutdown; requesting immediate kextd exit.");
1163 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit
,
1165 if (checkResult
!= kOSReturnSuccess
) {
1168 if (!sKernelRequests
->setObject(exitRequest
)) {
1172 OSKext::pingKextd();
1177 IORecursiveLockUnlock(sKextLock
);
1179 OSSafeRelease(exitRequest
);
1183 /*********************************************************************
1184 *********************************************************************/
1187 OSKext::getLoadEnabled(void)
1191 IORecursiveLockLock(sKextLock
);
1192 result
= sLoadEnabled
;
1193 IORecursiveLockUnlock(sKextLock
);
1197 /*********************************************************************
1198 *********************************************************************/
1201 OSKext::setLoadEnabled(bool flag
)
1205 IORecursiveLockLock(sKextLock
);
1206 result
= sLoadEnabled
;
1207 sLoadEnabled
= (flag
? true : false);
1209 if (sLoadEnabled
!= result
) {
1210 OSKextLog(/* kext */ NULL
,
1211 kOSKextLogBasicLevel
|
1213 "Kext loading now %sabled.", sLoadEnabled
? "en" : "dis");
1216 IORecursiveLockUnlock(sKextLock
);
1221 /*********************************************************************
1222 *********************************************************************/
1225 OSKext::getUnloadEnabled(void)
1229 IORecursiveLockLock(sKextLock
);
1230 result
= sUnloadEnabled
;
1231 IORecursiveLockUnlock(sKextLock
);
1235 /*********************************************************************
1236 *********************************************************************/
1239 OSKext::setUnloadEnabled(bool flag
)
1243 IORecursiveLockLock(sKextLock
);
1244 result
= sUnloadEnabled
;
1245 sUnloadEnabled
= (flag
? true : false);
1246 IORecursiveLockUnlock(sKextLock
);
1248 if (sUnloadEnabled
!= result
) {
1249 OSKextLog(/* kext */ NULL
,
1250 kOSKextLogBasicLevel
|
1251 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1252 "Kext unloading now %sabled.", sUnloadEnabled
? "en" : "dis");
1258 /*********************************************************************
1259 * Do not call any function that takes sKextLock here!
1260 *********************************************************************/
1263 OSKext::getAutounloadEnabled(void)
1267 IORecursiveLockLock(sKextInnerLock
);
1268 result
= sAutounloadEnabled
? true : false;
1269 IORecursiveLockUnlock(sKextInnerLock
);
1273 /*********************************************************************
1274 * Do not call any function that takes sKextLock here!
1275 *********************************************************************/
1278 OSKext::setAutounloadsEnabled(bool flag
)
1282 IORecursiveLockLock(sKextInnerLock
);
1284 result
= sAutounloadEnabled
;
1285 sAutounloadEnabled
= (flag
? true : false);
1286 if (!sAutounloadEnabled
&& sUnloadCallout
) {
1287 thread_call_cancel(sUnloadCallout
);
1290 if (sAutounloadEnabled
!= result
) {
1291 OSKextLog(/* kext */ NULL
,
1292 kOSKextLogBasicLevel
|
1293 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
1294 "Kext autounloading now %sabled.",
1295 sAutounloadEnabled
? "en" : "dis");
1298 IORecursiveLockUnlock(sKextInnerLock
);
1303 /*********************************************************************
1304 *********************************************************************/
1305 /* instance method operating on OSKext field */
1307 OSKext::setAutounloadEnabled(bool flag
)
1309 bool result
= flags
.autounloadEnabled
? true : false;
1310 flags
.autounloadEnabled
= flag
? 1 : 0;
1312 if (result
!= (flag
? true : false)) {
1314 kOSKextLogProgressLevel
|
1315 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
1316 "Autounloading for kext %s now %sabled.",
1317 getIdentifierCString(),
1318 flags
.autounloadEnabled
? "en" : "dis");
1323 /*********************************************************************
1324 *********************************************************************/
1327 OSKext::setKernelRequestsEnabled(bool flag
)
1331 IORecursiveLockLock(sKextLock
);
1332 result
= sKernelRequestsEnabled
;
1333 sKernelRequestsEnabled
= flag
? true : false;
1335 if (sKernelRequestsEnabled
!= result
) {
1336 OSKextLog(/* kext */ NULL
,
1337 kOSKextLogBasicLevel
|
1338 kOSKextLogGeneralFlag
,
1339 "Kernel requests now %sabled.",
1340 sKernelRequestsEnabled
? "en" : "dis");
1342 IORecursiveLockUnlock(sKextLock
);
1346 /*********************************************************************
1347 *********************************************************************/
1350 OSKext::getKernelRequestsEnabled(void)
1354 IORecursiveLockLock(sKextLock
);
1355 result
= sKernelRequestsEnabled
;
1356 IORecursiveLockUnlock(sKextLock
);
1361 #pragma mark Kext Life Cycle
1363 /*********************************************************************
1364 *********************************************************************/
1366 OSKext::withPrelinkedInfoDict(
1367 OSDictionary
* anInfoDict
)
1369 OSKext
* newKext
= new OSKext
;
1371 if (newKext
&& !newKext
->initWithPrelinkedInfoDict(anInfoDict
)) {
1379 /*********************************************************************
1380 *********************************************************************/
1382 OSKext::initWithPrelinkedInfoDict(
1383 OSDictionary
* anInfoDict
)
1385 bool result
= false;
1386 OSString
* kextPath
= NULL
; // do not release
1387 OSNumber
* addressNum
= NULL
; // reused; do not release
1388 OSNumber
* lengthNum
= NULL
; // reused; do not release
1389 void * data
= NULL
; // do not free
1390 void * srcData
= NULL
; // do not free
1391 OSData
* prelinkedExecutable
= NULL
; // must release
1392 uint32_t length
= 0; // reused
1394 if (!super::init()) {
1398 /* Get the path. Don't look for an arch-specific path property.
1400 kextPath
= OSDynamicCast(OSString
,
1401 anInfoDict
->getObject(kPrelinkBundlePathKey
));
1403 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
1406 #if KASLR_KEXT_DEBUG
1407 IOLog("kaslr: kext %s \n", getIdentifierCString());
1410 /* Also get the executable's bundle-relative path if present.
1411 * Don't look for an arch-specific path property.
1413 executableRelPath
= OSDynamicCast(OSString
,
1414 anInfoDict
->getObject(kPrelinkExecutableRelativePathKey
));
1415 if (executableRelPath
) {
1416 executableRelPath
->retain();
1419 /* Don't need the paths to be in the info dictionary any more.
1421 anInfoDict
->removeObject(kPrelinkBundlePathKey
);
1422 anInfoDict
->removeObject(kPrelinkExecutableRelativePathKey
);
1424 /* Create an OSData wrapper around the linked executable.
1426 addressNum
= OSDynamicCast(OSNumber
,
1427 anInfoDict
->getObject(kPrelinkExecutableLoadKey
));
1429 lengthNum
= OSDynamicCast(OSNumber
,
1430 anInfoDict
->getObject(kPrelinkExecutableSizeKey
));
1433 kOSKextLogErrorLevel
|
1434 kOSKextLogArchiveFlag
,
1435 "Kext %s can't find prelinked kext executable size.",
1436 getIdentifierCString());
1440 data
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1441 length
= (uint32_t) (lengthNum
->unsigned32BitValue());
1443 #if KASLR_KEXT_DEBUG
1444 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1445 (unsigned long)VM_KERNEL_UNSLIDE(data
),
1446 (unsigned long)data
,
1450 anInfoDict
->removeObject(kPrelinkExecutableLoadKey
);
1451 anInfoDict
->removeObject(kPrelinkExecutableSizeKey
);
1453 /* If the kext's load address differs from its source address, allocate
1454 * space in the kext map at the load address and copy the kext over.
1456 addressNum
= OSDynamicCast(OSNumber
, anInfoDict
->getObject(kPrelinkExecutableSourceKey
));
1458 srcData
= (void *) ((intptr_t) (addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
1460 #if KASLR_KEXT_DEBUG
1461 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1462 (unsigned long)VM_KERNEL_UNSLIDE(srcData
),
1463 (unsigned long)srcData
);
1466 if (data
!= srcData
) {
1468 kern_return_t alloc_result
;
1470 alloc_result
= kext_alloc((vm_offset_t
*)&data
, length
, /* fixed */ TRUE
);
1471 if (alloc_result
!= KERN_SUCCESS
) {
1473 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1474 "Failed to allocate space for prelinked kext %s.",
1475 getIdentifierCString());
1478 memcpy(data
, srcData
, length
);
1481 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
1482 "Error: prelinked kext %s - source and load addresses "
1483 "differ on ILP32 architecture.",
1484 getIdentifierCString());
1486 #endif /* __LP64__ */
1489 anInfoDict
->removeObject(kPrelinkExecutableSourceKey
);
1492 prelinkedExecutable
= OSData::withBytesNoCopy(data
, length
);
1493 if (!prelinkedExecutable
) {
1495 kOSKextLogErrorLevel
|
1496 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
1497 "Kext %s failed to create executable wrapper.",
1498 getIdentifierCString());
1503 prelinkedExecutable
->setDeallocFunction(osdata_kext_free
);
1505 prelinkedExecutable
->setDeallocFunction(osdata_phys_free
);
1507 setLinkedExecutable(prelinkedExecutable
);
1508 addressNum
= OSDynamicCast(OSNumber
,
1509 anInfoDict
->getObject(kPrelinkKmodInfoKey
));
1512 kOSKextLogErrorLevel
|
1513 kOSKextLogArchiveFlag
,
1514 "Kext %s can't find prelinked kext kmod_info address.",
1515 getIdentifierCString());
1519 if (addressNum
->unsigned64BitValue() != 0) {
1520 kmod_info
= (kmod_info_t
*) (intptr_t) (addressNum
->unsigned64BitValue() + vm_kernel_slide
);
1521 kmod_info
->address
+= vm_kernel_slide
;
1522 #if KASLR_KEXT_DEBUG
1523 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1524 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
),
1525 (unsigned long)kmod_info
);
1526 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1527 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
1528 (unsigned long)kmod_info
->address
);
1532 anInfoDict
->removeObject(kPrelinkKmodInfoKey
);
1535 /* If the plist has a UUID for an interface, save that off.
1537 if (isInterface()) {
1538 interfaceUUID
= OSDynamicCast(OSData
,
1539 anInfoDict
->getObject(kPrelinkInterfaceUUIDKey
));
1540 if (interfaceUUID
) {
1541 interfaceUUID
->retain();
1542 anInfoDict
->removeObject(kPrelinkInterfaceUUIDKey
);
1546 result
= slidePrelinkedExecutable();
1547 if (result
!= kOSReturnSuccess
) {
1551 /* set VM protections now, wire later at kext load */
1552 result
= setVMAttributes(true, false);
1553 if (result
!= KERN_SUCCESS
) {
1557 flags
.prelinked
= true;
1559 /* If we created a kext from prelink info,
1560 * we must be booting from a prelinked kernel.
1562 sPrelinkBoot
= true;
1564 result
= registerIdentifier();
1567 OSSafeRelease(prelinkedExecutable
);
1571 /*********************************************************************
1572 *********************************************************************/
1574 OSKext::withBooterData(
1575 OSString
* deviceTreeName
,
1576 OSData
* booterData
)
1578 OSKext
* newKext
= new OSKext
;
1580 if (newKext
&& !newKext
->initWithBooterData(deviceTreeName
, booterData
)) {
1588 /*********************************************************************
1589 *********************************************************************/
1590 typedef struct _BooterKextFileInfo
{
1591 uint32_t infoDictPhysAddr
;
1592 uint32_t infoDictLength
;
1593 uint32_t executablePhysAddr
;
1594 uint32_t executableLength
;
1595 uint32_t bundlePathPhysAddr
;
1596 uint32_t bundlePathLength
;
1597 } _BooterKextFileInfo
;
1600 OSKext::initWithBooterData(
1601 OSString
* deviceTreeName
,
1602 OSData
* booterData
)
1604 bool result
= false;
1605 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not free
1606 char * infoDictAddr
= NULL
; // do not free
1607 void * executableAddr
= NULL
; // do not free
1608 char * bundlePathAddr
= NULL
; // do not free
1610 OSObject
* parsedXML
= NULL
; // must release
1611 OSDictionary
* theInfoDict
= NULL
; // do not release
1612 OSString
* kextPath
= NULL
; // must release
1613 OSString
* errorString
= NULL
; // must release
1614 OSData
* executable
= NULL
; // must release
1616 if (!super::init()) {
1620 kextFileInfo
= (_BooterKextFileInfo
*)booterData
->getBytesNoCopy();
1621 if (!kextFileInfo
) {
1623 kOSKextLogErrorLevel
|
1624 kOSKextLogGeneralFlag
,
1625 "No booter-provided data for kext device tree entry %s.",
1626 deviceTreeName
->getCStringNoCopy());
1630 /* The info plist must exist or we can't read the kext.
1632 if (!kextFileInfo
->infoDictPhysAddr
|| !kextFileInfo
->infoDictLength
) {
1634 kOSKextLogErrorLevel
|
1635 kOSKextLogGeneralFlag
,
1636 "No kext info dictionary for booter device tree entry %s.",
1637 deviceTreeName
->getCStringNoCopy());
1641 infoDictAddr
= (char *)ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
1642 if (!infoDictAddr
) {
1644 kOSKextLogErrorLevel
|
1645 kOSKextLogGeneralFlag
,
1646 "Can't translate physical address 0x%x of kext info dictionary "
1647 "for device tree entry %s.",
1648 (int)kextFileInfo
->infoDictPhysAddr
,
1649 deviceTreeName
->getCStringNoCopy());
1653 parsedXML
= OSUnserializeXML(infoDictAddr
, &errorString
);
1655 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
1658 const char * errorCString
= "(unknown error)";
1660 if (errorString
&& errorString
->getCStringNoCopy()) {
1661 errorCString
= errorString
->getCStringNoCopy();
1662 } else if (parsedXML
) {
1663 errorCString
= "not a dictionary";
1666 kOSKextLogErrorLevel
|
1667 kOSKextLogGeneralFlag
,
1668 "Error unserializing info dictionary for device tree entry %s: %s.",
1669 deviceTreeName
->getCStringNoCopy(), errorCString
);
1673 /* A bundle path is not mandatory.
1675 if (kextFileInfo
->bundlePathPhysAddr
&& kextFileInfo
->bundlePathLength
) {
1676 bundlePathAddr
= (char *)ml_static_ptovirt(kextFileInfo
->bundlePathPhysAddr
);
1677 if (!bundlePathAddr
) {
1679 kOSKextLogErrorLevel
|
1680 kOSKextLogGeneralFlag
,
1681 "Can't translate physical address 0x%x of kext bundle path "
1682 "for device tree entry %s.",
1683 (int)kextFileInfo
->bundlePathPhysAddr
,
1684 deviceTreeName
->getCStringNoCopy());
1687 bundlePathAddr
[kextFileInfo
->bundlePathLength
-1] = '\0'; // just in case!
1689 kextPath
= OSString::withCString(bundlePathAddr
);
1692 kOSKextLogErrorLevel
|
1693 kOSKextLogGeneralFlag
,
1694 "Failed to create wrapper for device tree entry %s kext path %s.",
1695 deviceTreeName
->getCStringNoCopy(), bundlePathAddr
);
1700 if (!setInfoDictionaryAndPath(theInfoDict
, kextPath
)) {
1704 /* An executable is not mandatory.
1706 if (kextFileInfo
->executablePhysAddr
&& kextFileInfo
->executableLength
) {
1707 executableAddr
= (void *)ml_static_ptovirt(kextFileInfo
->executablePhysAddr
);
1708 if (!executableAddr
) {
1710 kOSKextLogErrorLevel
|
1711 kOSKextLogGeneralFlag
,
1712 "Can't translate physical address 0x%x of kext executable "
1713 "for device tree entry %s.",
1714 (int)kextFileInfo
->executablePhysAddr
,
1715 deviceTreeName
->getCStringNoCopy());
1719 executable
= OSData::withBytesNoCopy(executableAddr
,
1720 kextFileInfo
->executableLength
);
1723 kOSKextLogErrorLevel
|
1724 kOSKextLogGeneralFlag
,
1725 "Failed to create executable wrapper for device tree entry %s.",
1726 deviceTreeName
->getCStringNoCopy());
1730 /* A kext with an executable needs to retain the whole booterData
1731 * object to keep the executable in memory.
1733 if (!setExecutable(executable
, booterData
)) {
1735 kOSKextLogErrorLevel
|
1736 kOSKextLogGeneralFlag
,
1737 "Failed to set kext executable for device tree entry %s.",
1738 deviceTreeName
->getCStringNoCopy());
1743 result
= registerIdentifier();
1746 OSSafeRelease(parsedXML
);
1747 OSSafeRelease(kextPath
);
1748 OSSafeRelease(errorString
);
1749 OSSafeRelease(executable
);
1754 /*********************************************************************
1755 *********************************************************************/
1757 OSKext::registerIdentifier(void)
1759 bool result
= false;
1760 OSKext
* existingKext
= NULL
; // do not release
1761 bool existingIsLoaded
= false;
1762 bool existingIsPrelinked
= false;
1763 OSKextVersion newVersion
= -1;
1764 OSKextVersion existingVersion
= -1;
1765 char newVersionCString
[kOSKextVersionMaxLength
];
1766 char existingVersionCString
[kOSKextVersionMaxLength
];
1767 OSData
* newUUID
= NULL
; // must release
1768 OSData
* existingUUID
= NULL
; // must release
1770 IORecursiveLockLock(sKextLock
);
1772 /* Get the new kext's version for checks & log messages.
1774 newVersion
= getVersion();
1775 OSKextVersionGetString(newVersion
, newVersionCString
,
1776 kOSKextVersionMaxLength
);
1778 /* If we don't have an existing kext with this identifier,
1779 * just record the new kext and we're done!
1781 existingKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(bundleID
));
1782 if (!existingKext
) {
1783 sKextsByID
->setObject(bundleID
, this);
1788 /* Get the existing kext's version for checks & log messages.
1790 existingVersion
= existingKext
->getVersion();
1791 OSKextVersionGetString(existingVersion
,
1792 existingVersionCString
, kOSKextVersionMaxLength
);
1794 existingIsLoaded
= existingKext
->isLoaded();
1795 existingIsPrelinked
= existingKext
->isPrelinked();
1797 /* If we have a kext with this identifier that's already loaded/prelinked,
1798 * we can't use the new one, but let's be really thorough and check how
1799 * the two are related for a precise diagnostic log message.
1801 * Note that user space can't find out about nonloaded prelinked kexts,
1802 * so in this case we log a message when new & existing are equivalent
1803 * at the step rather than warning level, because we are always going
1804 * be getting a copy of the kext in the user load request mkext.
1806 if (existingIsLoaded
|| existingIsPrelinked
) {
1807 bool sameVersion
= (newVersion
== existingVersion
);
1808 bool sameExecutable
= true; // assume true unless we have UUIDs
1810 /* Only get the UUID if the existing kext is loaded. Doing so
1811 * might have to uncompress an mkext executable and we shouldn't
1812 * take that hit when neither kext is loaded.
1814 newUUID
= copyUUID();
1815 existingUUID
= existingKext
->copyUUID();
1817 /* I'm entirely too paranoid about checking equivalence of executables,
1818 * but I remember nasty problems with it in the past.
1820 * - If we have UUIDs for both kexts, compare them.
1821 * - If only one kext has a UUID, they're definitely different.
1823 if (newUUID
&& existingUUID
) {
1824 sameExecutable
= newUUID
->isEqualTo(existingUUID
);
1825 } else if (newUUID
|| existingUUID
) {
1826 sameExecutable
= false;
1829 if (!newUUID
&& !existingUUID
) {
1831 /* If there are no UUIDs, we can't really tell that the executables
1832 * are *different* without a lot of work; the loaded kext's
1833 * unrelocated executable is no longer around (and we never had it
1834 * in-kernel for a prelinked kext). We certainly don't want to do
1835 * a whole fake link for the new kext just to compare, either.
1838 OSKextVersionGetString(version
, newVersionCString
,
1839 sizeof(newVersionCString
));
1841 kOSKextLogWarningLevel
|
1842 kOSKextLogKextBookkeepingFlag
,
1843 "Notice - new kext %s, v%s matches %s kext "
1844 "but can't determine if executables are the same (no UUIDs).",
1845 getIdentifierCString(),
1847 (existingIsLoaded
? "loaded" : "prelinked"));
1850 if (sameVersion
&& sameExecutable
) {
1852 (existingIsLoaded
? kOSKextLogWarningLevel
: kOSKextLogStepLevel
) |
1853 kOSKextLogKextBookkeepingFlag
,
1854 "Refusing new kext %s, v%s: a %s copy is already present "
1855 "(same version and executable).",
1856 getIdentifierCString(), newVersionCString
,
1857 (existingIsLoaded
? "loaded" : "prelinked"));
1860 /* This condition is significant so log it under warnings.
1863 kOSKextLogWarningLevel
|
1864 kOSKextLogKextBookkeepingFlag
,
1865 "Refusing new kext %s, v%s: already have %s v%s.",
1866 getIdentifierCString(),
1868 (existingIsLoaded
? "loaded" : "prelinked"),
1869 existingVersionCString
);
1871 /* This condition is significant so log it under warnings.
1874 kOSKextLogWarningLevel
| kOSKextLogKextBookkeepingFlag
,
1875 "Refusing new kext %s, v%s: a %s copy with a different "
1876 "executable UUID is already present.",
1877 getIdentifierCString(), newVersionCString
,
1878 (existingIsLoaded
? "loaded" : "prelinked"));
1882 } /* if (existingIsLoaded || existingIsPrelinked) */
1884 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
1885 * user loads are happening or if we're still in early boot. User agents are
1886 * supposed to resolve dependencies topside and include only the exact
1887 * kexts needed; so we always accept the new kext (in fact we should never
1888 * see an older unloaded copy hanging around).
1890 if (sUserLoadsActive
) {
1891 sKextsByID
->setObject(bundleID
, this);
1895 kOSKextLogStepLevel
|
1896 kOSKextLogKextBookkeepingFlag
,
1897 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
1898 getIdentifierCString(),
1899 existingVersionCString
,
1905 /* During early boot, the kext with the highest version always wins out.
1906 * Prelinked kernels will never hit this, but mkexts and booter-read
1907 * kexts might have duplicates.
1909 if (newVersion
> existingVersion
) {
1910 sKextsByID
->setObject(bundleID
, this);
1914 kOSKextLogStepLevel
|
1915 kOSKextLogKextBookkeepingFlag
,
1916 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
1917 existingVersionCString
,
1918 getIdentifierCString(),
1923 kOSKextLogStepLevel
|
1924 kOSKextLogKextBookkeepingFlag
,
1925 "Kext %s is already registered with a higher/same version (v%s); "
1926 "dropping newly-added (v%s).",
1927 getIdentifierCString(),
1928 existingVersionCString
,
1932 /* result has been set appropriately by now. */
1936 IORecursiveLockUnlock(sKextLock
);
1940 kOSKextLogStepLevel
|
1941 kOSKextLogKextBookkeepingFlag
,
1942 "Kext %s, v%s registered and available for loading.",
1943 getIdentifierCString(), newVersionCString
);
1946 OSSafeRelease(newUUID
);
1947 OSSafeRelease(existingUUID
);
1952 /*********************************************************************
1953 * Does the bare minimum validation to look up a kext.
1954 * All other validation is done on the spot as needed.
1955 **********************************************************************/
1957 OSKext::setInfoDictionaryAndPath(
1958 OSDictionary
* aDictionary
,
1961 bool result
= false;
1962 OSString
* bundleIDString
= NULL
; // do not release
1963 OSString
* versionString
= NULL
; // do not release
1964 OSString
* compatibleVersionString
= NULL
; // do not release
1965 const char * versionCString
= NULL
; // do not free
1966 const char * compatibleVersionCString
= NULL
; // do not free
1967 OSBoolean
* scratchBool
= NULL
; // do not release
1968 OSDictionary
* scratchDict
= NULL
; // do not release
1971 panic("Attempt to set info dictionary on a kext "
1972 "that already has one (%s).",
1973 getIdentifierCString());
1976 if (!aDictionary
|| !OSDynamicCast(OSDictionary
, aDictionary
)) {
1980 infoDict
= aDictionary
;
1983 /* Check right away if the info dictionary has any log flags.
1985 scratchBool
= OSDynamicCast(OSBoolean
,
1986 getPropertyForHostArch(kOSBundleEnableKextLoggingKey
));
1987 if (scratchBool
== kOSBooleanTrue
) {
1988 flags
.loggingEnabled
= 1;
1991 /* The very next thing to get is the bundle identifier. Unlike
1992 * in user space, a kext with no bundle identifier gets axed
1995 bundleIDString
= OSDynamicCast(OSString
,
1996 getPropertyForHostArch(kCFBundleIdentifierKey
));
1997 if (!bundleIDString
) {
1999 kOSKextLogErrorLevel
|
2000 kOSKextLogValidationFlag
,
2001 "CFBundleIdentifier missing/invalid type in kext %s.",
2002 aPath
? aPath
->getCStringNoCopy() : "(unknown)");
2005 bundleID
= OSSymbol::withString(bundleIDString
);
2008 kOSKextLogErrorLevel
|
2009 kOSKextLogValidationFlag
,
2010 "Can't copy bundle identifier as symbol for kext %s.",
2011 bundleIDString
->getCStringNoCopy());
2015 /* Save the path if we got one (it should always be available but it's
2016 * just something nice to have for bookkeeping).
2024 * Minimal validation to initialize. We'll do other validation on the spot.
2026 if (bundleID
->getLength() >= KMOD_MAX_NAME
) {
2028 kOSKextLogErrorLevel
|
2029 kOSKextLogValidationFlag
,
2030 "Kext %s error - CFBundleIdentifier over max length %d.",
2031 getIdentifierCString(), KMOD_MAX_NAME
- 1);
2035 version
= compatibleVersion
= -1;
2037 versionString
= OSDynamicCast(OSString
,
2038 getPropertyForHostArch(kCFBundleVersionKey
));
2039 if (!versionString
) {
2041 kOSKextLogErrorLevel
|
2042 kOSKextLogValidationFlag
,
2043 "Kext %s error - CFBundleVersion missing/invalid type.",
2044 getIdentifierCString());
2047 versionCString
= versionString
->getCStringNoCopy();
2048 version
= OSKextParseVersionString(versionCString
);
2051 kOSKextLogErrorLevel
|
2052 kOSKextLogValidationFlag
,
2053 "Kext %s error - CFBundleVersion bad value '%s'.",
2054 getIdentifierCString(), versionCString
);
2058 compatibleVersion
= -1; // set to illegal value for kexts that don't have
2060 compatibleVersionString
= OSDynamicCast(OSString
,
2061 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
2062 if (compatibleVersionString
) {
2063 compatibleVersionCString
= compatibleVersionString
->getCStringNoCopy();
2064 compatibleVersion
= OSKextParseVersionString(compatibleVersionCString
);
2065 if (compatibleVersion
< 0) {
2067 kOSKextLogErrorLevel
|
2068 kOSKextLogValidationFlag
,
2069 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2070 getIdentifierCString(), compatibleVersionCString
);
2074 if (compatibleVersion
> version
) {
2076 kOSKextLogErrorLevel
|
2077 kOSKextLogValidationFlag
,
2078 "Kext %s error - %s %s > %s %s (must be <=).",
2079 getIdentifierCString(),
2080 kOSBundleCompatibleVersionKey
, compatibleVersionCString
,
2081 kCFBundleVersionKey
, versionCString
);
2086 /* Check to see if this kext is in exclude list */
2087 if ( isInExcludeList() ) {
2089 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
2090 "Kext %s is in exclude list, not loadable",
2091 getIdentifierCString());
2095 /* Set flags for later use if the infoDict gets flushed. We only
2096 * check for true values, not false ones(!)
2098 scratchBool
= OSDynamicCast(OSBoolean
,
2099 getPropertyForHostArch(kOSBundleIsInterfaceKey
));
2100 if (scratchBool
== kOSBooleanTrue
) {
2101 flags
.interface
= 1;
2104 scratchBool
= OSDynamicCast(OSBoolean
,
2105 getPropertyForHostArch(kOSKernelResourceKey
));
2106 if (scratchBool
== kOSBooleanTrue
) {
2107 flags
.kernelComponent
= 1;
2108 flags
.interface
= 1; // xxx - hm. the kernel itself isn't an interface...
2111 /* A kernel component has one implicit dependency on the kernel.
2113 flags
.hasAllDependencies
= 1;
2116 /* Make sure common string values in personalities are uniqued to OSSymbols.
2118 scratchDict
= OSDynamicCast(OSDictionary
,
2119 getPropertyForHostArch(kIOKitPersonalitiesKey
));
2121 uniquePersonalityProperties(scratchDict
);
2131 /*********************************************************************
2132 * Not used for prelinked kernel boot as there is no unrelocated
2134 *********************************************************************/
2136 OSKext::setExecutable(
2137 OSData
* anExecutable
,
2138 OSData
* externalData
,
2139 bool externalDataIsMkext
)
2141 bool result
= false;
2142 const char * executableKey
= NULL
; // do not free
2144 if (!anExecutable
) {
2145 infoDict
->removeObject(_kOSKextExecutableKey
);
2146 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
2147 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
2152 if (infoDict
->getObject(_kOSKextExecutableKey
) ||
2153 infoDict
->getObject(_kOSKextMkextExecutableReferenceKey
)) {
2155 panic("Attempt to set an executable on a kext "
2156 "that already has one (%s).",
2157 getIdentifierCString());
2161 if (externalDataIsMkext
) {
2162 executableKey
= _kOSKextMkextExecutableReferenceKey
;
2164 executableKey
= _kOSKextExecutableKey
;
2168 infoDict
->setObject(executableKey
, anExecutable
);
2170 infoDict
->setObject(_kOSKextExecutableExternalDataKey
, externalData
);
2180 /*********************************************************************
2181 *********************************************************************/
2183 uniqueStringPlistProperty(OSDictionary
* dict
, const char * key
)
2185 OSString
* stringValue
= NULL
; // do not release
2186 const OSSymbol
* symbolValue
= NULL
; // must release
2188 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2193 symbolValue
= OSSymbol::withString(stringValue
);
2198 dict
->setObject(key
, symbolValue
);
2201 if (symbolValue
) symbolValue
->release();
2206 /*********************************************************************
2207 *********************************************************************/
2209 uniqueStringPlistProperty(OSDictionary
* dict
, const OSString
* key
)
2211 OSString
* stringValue
= NULL
; // do not release
2212 const OSSymbol
* symbolValue
= NULL
; // must release
2214 stringValue
= OSDynamicCast(OSString
, dict
->getObject(key
));
2219 symbolValue
= OSSymbol::withString(stringValue
);
2224 dict
->setObject(key
, symbolValue
);
2227 if (symbolValue
) symbolValue
->release();
2232 /*********************************************************************
2233 * Replace common personality property values with uniqued instances
2234 * to save on wired memory.
2235 *********************************************************************/
2238 OSKext::uniquePersonalityProperties(OSDictionary
* personalityDict
)
2240 /* Properties every personality has.
2242 uniqueStringPlistProperty(personalityDict
, kCFBundleIdentifierKey
);
2243 uniqueStringPlistProperty(personalityDict
, kIOProviderClassKey
);
2244 uniqueStringPlistProperty(personalityDict
, gIOClassKey
);
2246 /* Other commonly used properties.
2248 uniqueStringPlistProperty(personalityDict
, gIOMatchCategoryKey
);
2249 uniqueStringPlistProperty(personalityDict
, gIOResourceMatchKey
);
2250 uniqueStringPlistProperty(personalityDict
, gIOUserClientClassKey
);
2252 uniqueStringPlistProperty(personalityDict
, "HIDDefaultBehavior");
2253 uniqueStringPlistProperty(personalityDict
, "HIDPointerAccelerationType");
2254 uniqueStringPlistProperty(personalityDict
, "HIDRemoteControlType");
2255 uniqueStringPlistProperty(personalityDict
, "HIDScrollAccelerationType");
2256 uniqueStringPlistProperty(personalityDict
, "IOPersonalityPublisher");
2257 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect");
2258 uniqueStringPlistProperty(personalityDict
, "Physical Interconnect Location");
2259 uniqueStringPlistProperty(personalityDict
, "Vendor");
2260 uniqueStringPlistProperty(personalityDict
, "Vendor Identification");
2261 uniqueStringPlistProperty(personalityDict
, "Vendor Name");
2262 uniqueStringPlistProperty(personalityDict
, "bConfigurationValue");
2263 uniqueStringPlistProperty(personalityDict
, "bInterfaceNumber");
2264 uniqueStringPlistProperty(personalityDict
, "idProduct");
2269 /*********************************************************************
2270 *********************************************************************/
2275 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2278 OSSafeRelease(infoDict
);
2279 OSSafeRelease(bundleID
);
2280 OSSafeRelease(path
);
2281 OSSafeRelease(executableRelPath
);
2282 OSSafeRelease(dependencies
);
2283 OSSafeRelease(linkedExecutable
);
2284 OSSafeRelease(metaClasses
);
2285 OSSafeRelease(interfaceUUID
);
2287 if (isInterface() && kmod_info
) {
2288 kfree(kmod_info
, sizeof(kmod_info_t
));
2296 #pragma mark Mkext files
2298 /*********************************************************************
2299 *********************************************************************/
2301 OSKext::readMkextArchive(OSData
* mkextData
,
2302 uint32_t * checksumPtr
)
2304 OSReturn result
= kOSKextReturnBadData
;
2305 uint32_t mkextLength
= 0;
2306 mkext_header
* mkextHeader
= 0; // do not free
2307 uint32_t mkextVersion
= 0;
2309 /* Note default return of kOSKextReturnBadData above.
2311 mkextLength
= mkextData
->getLength();
2312 if (mkextLength
< sizeof(mkext_basic_header
)) {
2313 OSKextLog(/* kext */ NULL
,
2314 kOSKextLogErrorLevel
|
2315 kOSKextLogArchiveFlag
,
2316 "Mkext archive too small to be valid.");
2320 mkextHeader
= (mkext_header
*)mkextData
->getBytesNoCopy();
2322 if (MKEXT_GET_MAGIC(mkextHeader
) != MKEXT_MAGIC
||
2323 MKEXT_GET_SIGNATURE(mkextHeader
) != MKEXT_SIGN
) {
2324 OSKextLog(/* kext */ NULL
,
2325 kOSKextLogErrorLevel
|
2326 kOSKextLogArchiveFlag
,
2327 "Mkext archive has invalid magic or signature.");
2331 if (MKEXT_GET_LENGTH(mkextHeader
) != mkextLength
) {
2332 OSKextLog(/* kext */ NULL
,
2333 kOSKextLogErrorLevel
|
2334 kOSKextLogArchiveFlag
,
2335 "Mkext archive recorded length doesn't match actual file length.");
2339 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2341 if (mkextVersion
== MKEXT_VERS_2
) {
2342 result
= OSKext::readMkext2Archive(mkextData
, NULL
, checksumPtr
);
2344 OSKextLog(/* kext */ NULL
,
2345 kOSKextLogErrorLevel
|
2346 kOSKextLogArchiveFlag
,
2347 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion
);
2348 result
= kOSKextReturnUnsupported
;
2355 /*********************************************************************
2356 * Assumes magic, signature, version, length have been checked.
2357 * xxx - need to add further bounds checking for each file entry
2359 * Should keep track of all kexts created so far, and if we hit a
2360 * fatal error halfway through, remove those kexts. If we've dropped
2361 * an older version that had already been read, whoops! Might want to
2362 * add a level of buffering?
2363 *********************************************************************/
2366 OSKext::readMkext2Archive(
2368 OSDictionary
** mkextPlistOut
,
2369 uint32_t * checksumPtr
)
2371 OSReturn result
= kOSReturnError
;
2372 uint32_t mkextLength
;
2373 mkext2_header
* mkextHeader
= NULL
; // do not free
2374 void * mkextEnd
= NULL
; // do not free
2375 uint32_t mkextVersion
;
2376 uint8_t * crc_address
= NULL
;
2378 uint32_t mkextPlistOffset
;
2379 uint32_t mkextPlistCompressedSize
;
2380 char * mkextPlistEnd
= NULL
; // do not free
2381 uint32_t mkextPlistFullSize
;
2382 OSString
* errorString
= NULL
; // must release
2383 OSData
* mkextPlistUncompressedData
= NULL
; // must release
2384 const char * mkextPlistDataBuffer
= NULL
; // do not free
2385 OSObject
* parsedXML
= NULL
; // must release
2386 OSDictionary
* mkextPlist
= NULL
; // do not release
2387 OSArray
* mkextInfoDictArray
= NULL
; // do not release
2390 mkextLength
= mkextData
->getLength();
2391 mkextHeader
= (mkext2_header
*)mkextData
->getBytesNoCopy();
2392 mkextEnd
= (char *)mkextHeader
+ mkextLength
;
2393 mkextVersion
= MKEXT_GET_VERSION(mkextHeader
);
2395 crc_address
= (u_int8_t
*)&mkextHeader
->version
;
2396 checksum
= mkext_adler32(crc_address
,
2397 (uintptr_t)mkextHeader
+
2398 MKEXT_GET_LENGTH(mkextHeader
) - (uintptr_t)crc_address
);
2400 if (MKEXT_GET_CHECKSUM(mkextHeader
) != checksum
) {
2401 OSKextLog(/* kext */ NULL
,
2402 kOSKextLogErrorLevel
|
2403 kOSKextLogArchiveFlag
,
2404 "Mkext archive has bad checksum.");
2405 result
= kOSKextReturnBadData
;
2410 *checksumPtr
= checksum
;
2413 /* Check that the CPU type & subtype match that of the running kernel. */
2414 if (MKEXT_GET_CPUTYPE(mkextHeader
) == (UInt32
)CPU_TYPE_ANY
) {
2415 OSKextLog(/* kext */ NULL
,
2416 kOSKextLogErrorLevel
|
2417 kOSKextLogArchiveFlag
,
2418 "Mkext archive must have a specific CPU type.");
2419 result
= kOSKextReturnBadData
;
2422 if ((UInt32
)_mh_execute_header
.cputype
!=
2423 MKEXT_GET_CPUTYPE(mkextHeader
)) {
2425 OSKextLog(/* kext */ NULL
,
2426 kOSKextLogErrorLevel
|
2427 kOSKextLogArchiveFlag
,
2428 "Mkext archive does not match the running kernel's CPU type.");
2429 result
= kOSKextReturnArchNotFound
;
2434 mkextPlistOffset
= MKEXT2_GET_PLIST(mkextHeader
);
2435 mkextPlistCompressedSize
= MKEXT2_GET_PLIST_COMPSIZE(mkextHeader
);
2436 mkextPlistEnd
= (char *)mkextHeader
+ mkextPlistOffset
+
2437 mkextPlistCompressedSize
;
2438 if (mkextPlistEnd
> mkextEnd
) {
2439 OSKextLog(/* kext */ NULL
,
2440 kOSKextLogErrorLevel
|
2441 kOSKextLogArchiveFlag
,
2442 "Mkext archive file overrun.");
2443 result
= kOSKextReturnBadData
;
2446 mkextPlistFullSize
= MKEXT2_GET_PLIST_FULLSIZE(mkextHeader
);
2447 if (mkextPlistCompressedSize
) {
2448 mkextPlistUncompressedData
= sKernelKext
->extractMkext2FileData(
2449 (UInt8
*)mkextHeader
+ mkextPlistOffset
,
2451 mkextPlistCompressedSize
, mkextPlistFullSize
);
2452 if (!mkextPlistUncompressedData
) {
2455 mkextPlistDataBuffer
= (const char *)
2456 mkextPlistUncompressedData
->getBytesNoCopy();
2458 mkextPlistDataBuffer
= (const char *)mkextHeader
+ mkextPlistOffset
;
2461 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2463 parsedXML
= OSUnserializeXML(mkextPlistDataBuffer
, &errorString
);
2465 mkextPlist
= OSDynamicCast(OSDictionary
, parsedXML
);
2468 const char * errorCString
= "(unknown error)";
2470 if (errorString
&& errorString
->getCStringNoCopy()) {
2471 errorCString
= errorString
->getCStringNoCopy();
2472 } else if (parsedXML
) {
2473 errorCString
= "not a dictionary";
2475 OSKextLog(/* kext */ NULL
,
2476 kOSKextLogErrorLevel
|
2477 kOSKextLogArchiveFlag
,
2478 "Error unserializing mkext plist: %s.", errorCString
);
2482 /* If the caller needs the plist, hand it back and retain it.
2483 * (This function releases it at the end.)
2485 if (mkextPlistOut
) {
2486 *mkextPlistOut
= mkextPlist
;
2487 (*mkextPlistOut
)->retain();
2490 mkextInfoDictArray
= OSDynamicCast(OSArray
,
2491 mkextPlist
->getObject(kMKEXTInfoDictionariesKey
));
2492 if (!mkextInfoDictArray
) {
2493 OSKextLog(/* kext */ NULL
,
2494 kOSKextLogErrorLevel
|
2495 kOSKextLogArchiveFlag
,
2496 "Mkext archive contains no kext info dictionaries.");
2500 count
= mkextInfoDictArray
->getCount();
2501 for (i
= 0; i
< count
; i
++) {
2502 OSDictionary
* infoDict
;
2505 infoDict
= OSDynamicCast(OSDictionary
,
2506 mkextInfoDictArray
->getObject(i
));
2508 /* Create the kext for the entry, then release it, because the
2509 * kext system keeps them around until explicitly removed.
2510 * Any creation/registration failures are already logged for us.
2513 OSKext
* newKext
= OSKext::withMkext2Info(infoDict
, mkextData
);
2514 OSSafeRelease(newKext
);
2518 /* Even if we didn't keep any kexts from the mkext, we may have a load
2519 * request to process, so we are successful (no errors occurred).
2521 result
= kOSReturnSuccess
;
2525 OSSafeRelease(parsedXML
);
2526 OSSafeRelease(mkextPlistUncompressedData
);
2527 OSSafeRelease(errorString
);
2532 /*********************************************************************
2533 *********************************************************************/
2536 OSKext::withMkext2Info(
2537 OSDictionary
* anInfoDict
,
2540 OSKext
* newKext
= new OSKext
;
2542 if (newKext
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) {
2550 /*********************************************************************
2551 *********************************************************************/
2553 OSKext::initWithMkext2Info(
2554 OSDictionary
* anInfoDict
,
2557 bool result
= false;
2558 OSString
* kextPath
= NULL
; // do not release
2559 OSNumber
* executableOffsetNum
= NULL
; // do not release
2560 OSCollectionIterator
* iterator
= NULL
; // must release
2561 OSData
* executable
= NULL
; // must release
2563 if (anInfoDict
== NULL
|| !super::init()) {
2567 /* Get the path. Don't look for an arch-specific path property.
2569 kextPath
= OSDynamicCast(OSString
,
2570 anInfoDict
->getObject(kMKEXTBundlePathKey
));
2572 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
2576 /* If we have a path to the executable, save it.
2578 executableRelPath
= OSDynamicCast(OSString
,
2579 anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
));
2580 if (executableRelPath
) {
2581 executableRelPath
->retain();
2584 /* Don't need the paths to be in the info dictionary any more.
2586 anInfoDict
->removeObject(kMKEXTBundlePathKey
);
2587 anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
);
2589 executableOffsetNum
= OSDynamicCast(OSNumber
,
2590 infoDict
->getObject(kMKEXTExecutableKey
));
2591 if (executableOffsetNum
) {
2592 executable
= createMkext2FileEntry(mkextData
,
2593 executableOffsetNum
, "executable");
2594 infoDict
->removeObject(kMKEXTExecutableKey
);
2598 if (!setExecutable(executable
, mkextData
, true)) {
2603 result
= registerIdentifier();
2607 OSSafeRelease(executable
);
2608 OSSafeRelease(iterator
);
2612 /*********************************************************************
2613 *********************************************************************/
2615 OSKext::createMkext2FileEntry(
2617 OSNumber
* offsetNum
,
2620 OSData
* result
= NULL
;
2621 MkextEntryRef entryRef
;
2622 uint8_t * mkextBuffer
= (uint8_t *)mkextData
->getBytesNoCopy();
2623 uint32_t entryOffset
= offsetNum
->unsigned32BitValue();
2625 result
= OSData::withCapacity(sizeof(entryRef
));
2630 entryRef
.mkext
= (mkext_basic_header
*)mkextBuffer
;
2631 entryRef
.fileinfo
= mkextBuffer
+ entryOffset
;
2632 if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) {
2633 OSSafeReleaseNULL(result
);
2640 kOSKextLogErrorLevel
|
2641 kOSKextLogArchiveFlag
,
2642 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2643 name
, getIdentifierCString());
2648 /*********************************************************************
2649 *********************************************************************/
2651 static void * z_alloc(void *, u_int items
, u_int size
);
2652 static void z_free(void *, void *ptr
);
2654 typedef struct z_mem
{
2655 uint32_t alloc_size
;
2660 * Space allocation and freeing routines for use by zlib routines.
2663 z_alloc(void * notused __unused
, u_int num_items
, u_int size
)
2665 void * result
= NULL
;
2666 z_mem
* zmem
= NULL
;
2668 uint64_t total
= ((uint64_t)num_items
) * ((uint64_t)size
);
2669 //Check for overflow due to multiplication
2670 if (total
> UINT32_MAX
){
2671 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
2672 notused
, num_items
, size
, num_items
, size
);
2675 uint64_t allocSize64
= total
+ ((uint64_t)sizeof(zmem
));
2676 //Check for overflow due to addition
2677 if (allocSize64
> UINT32_MAX
){
2678 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
2679 notused
, num_items
, size
, (uint32_t)total
, sizeof(zmem
));
2681 uint32_t allocSize
= (uint32_t)allocSize64
;
2683 zmem
= (z_mem
*)kalloc_tag(allocSize
, VM_KERN_MEMORY_OSKEXT
);
2687 zmem
->alloc_size
= allocSize
;
2688 result
= (void *)&(zmem
->data
);
2694 z_free(void * notused __unused
, void * ptr
)
2696 uint32_t * skipper
= (uint32_t *)ptr
- 1;
2697 z_mem
* zmem
= (z_mem
*)skipper
;
2698 kfree((void *)zmem
, zmem
->alloc_size
);
2704 OSKext::extractMkext2FileData(
2707 uint32_t compressedSize
,
2710 OSData
* result
= NULL
;
2712 OSData
* uncompressedData
= NULL
; // release on error
2714 uint8_t * uncompressedDataBuffer
= 0; // do not free
2715 unsigned long uncompressedSize
;
2717 bool zstream_inited
= false;
2720 /* If the file isn't compressed, we want to make a copy
2721 * so that we don't have the tie to the larger mkext file buffer any more.
2723 if (!compressedSize
) {
2724 uncompressedData
= OSData::withBytes(data
, fullSize
);
2725 // xxx - no check for failure?
2726 result
= uncompressedData
;
2730 if (KERN_SUCCESS
!= kmem_alloc(kernel_map
,
2731 (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
, VM_KERN_MEMORY_OSKEXT
)) {
2733 /* How's this for cheesy? The kernel is only asked to extract
2734 * kext plists so we tailor the log messages.
2738 kOSKextLogErrorLevel
|
2739 kOSKextLogArchiveFlag
,
2740 "Allocation failure extracting %s from mkext.", name
);
2743 kOSKextLogErrorLevel
|
2744 kOSKextLogArchiveFlag
,
2745 "Allocation failure extracting %s from mkext for kext %s.",
2746 name
, getIdentifierCString());
2751 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
);
2752 if (!uncompressedData
) {
2755 kOSKextLogErrorLevel
|
2756 kOSKextLogArchiveFlag
,
2757 "Allocation failure extracting %s from mkext.", name
);
2760 kOSKextLogErrorLevel
|
2761 kOSKextLogArchiveFlag
,
2762 "Allocation failure extracting %s from mkext for kext %s.",
2763 name
, getIdentifierCString());
2767 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
2771 kOSKextLogDetailLevel
|
2772 kOSKextLogArchiveFlag
,
2773 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2774 name
, compressedSize
, fullSize
);
2777 kOSKextLogDetailLevel
|
2778 kOSKextLogArchiveFlag
,
2779 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2780 getIdentifierCString(), name
, compressedSize
, fullSize
);
2783 bzero(&zstream
, sizeof(zstream
));
2784 zstream
.next_in
= (UInt8
*)data
;
2785 zstream
.avail_in
= compressedSize
;
2787 zstream
.next_out
= uncompressedDataBuffer
;
2788 zstream
.avail_out
= fullSize
;
2790 zstream
.zalloc
= z_alloc
;
2791 zstream
.zfree
= z_free
;
2793 zlib_result
= inflateInit(&zstream
);
2794 if (Z_OK
!= zlib_result
) {
2797 kOSKextLogErrorLevel
|
2798 kOSKextLogArchiveFlag
,
2799 "Mkext error; zlib inflateInit failed (%d) for %s.",
2803 kOSKextLogErrorLevel
|
2804 kOSKextLogArchiveFlag
,
2805 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2806 getIdentifierCString(), zlib_result
, name
);
2810 zstream_inited
= true;
2813 zlib_result
= inflate(&zstream
, Z_FINISH
);
2815 if (zlib_result
== Z_STREAM_END
|| zlib_result
== Z_OK
) {
2816 uncompressedSize
= zstream
.total_out
;
2820 kOSKextLogErrorLevel
|
2821 kOSKextLogArchiveFlag
,
2822 "Mkext error; zlib inflate failed (%d) for %s.",
2826 kOSKextLogErrorLevel
|
2827 kOSKextLogArchiveFlag
,
2828 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
2829 getIdentifierCString(), zlib_result
, name
);
2833 kOSKextLogErrorLevel
|
2834 kOSKextLogArchiveFlag
,
2835 "zlib error: %s.", zstream
.msg
);
2840 if (uncompressedSize
!= fullSize
) {
2843 kOSKextLogErrorLevel
|
2844 kOSKextLogArchiveFlag
,
2845 "Mkext error; zlib inflate discrepancy for %s, "
2846 "uncompressed size != original size.", name
);
2849 kOSKextLogErrorLevel
|
2850 kOSKextLogArchiveFlag
,
2851 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
2852 "uncompressed size != original size.",
2853 getIdentifierCString(), name
);
2858 result
= uncompressedData
;
2861 /* Don't bother checking return, nothing we can do on fail.
2863 if (zstream_inited
) inflateEnd(&zstream
);
2866 OSSafeRelease(uncompressedData
);
2872 /*********************************************************************
2873 *********************************************************************/
2876 OSKext::loadFromMkext(
2877 OSKextLogSpec clientLogFilter
,
2879 uint32_t mkextBufferLength
,
2881 uint32_t * logInfoLengthOut
)
2883 OSReturn result
= kOSReturnError
;
2884 OSReturn tempResult
= kOSReturnError
;
2886 OSData
* mkextData
= NULL
; // must release
2887 OSDictionary
* mkextPlist
= NULL
; // must release
2889 OSArray
* logInfoArray
= NULL
; // must release
2890 OSSerialize
* serializer
= NULL
; // must release
2892 OSString
* predicate
= NULL
; // do not release
2893 OSDictionary
* requestArgs
= NULL
; // do not release
2895 OSString
* kextIdentifier
= NULL
; // do not release
2896 OSNumber
* startKextExcludeNum
= NULL
; // do not release
2897 OSNumber
* startMatchingExcludeNum
= NULL
; // do not release
2898 OSBoolean
* delayAutounloadBool
= NULL
; // do not release
2899 OSArray
* personalityNames
= NULL
; // do not release
2901 /* Default values for these two options: regular autounload behavior,
2902 * load all kexts, send no personalities.
2904 Boolean delayAutounload
= false;
2905 OSKextExcludeLevel startKextExcludeLevel
= kOSKextExcludeNone
;
2906 OSKextExcludeLevel startMatchingExcludeLevel
= kOSKextExcludeAll
;
2908 IORecursiveLockLock(sKextLock
);
2912 *logInfoLengthOut
= 0;
2915 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
2917 OSKextLog(/* kext */ NULL
,
2918 kOSKextLogDebugLevel
|
2920 "Received kext load request from user space.");
2922 /* Regardless of processing, the fact that we have gotten here means some
2923 * user-space program is up and talking to us, so we'll switch our kext
2924 * registration to reflect that.
2926 if (!sUserLoadsActive
) {
2927 OSKextLog(/* kext */ NULL
,
2928 kOSKextLogProgressLevel
|
2929 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
2930 "Switching to late startup (user-space) kext loading policy.");
2932 sUserLoadsActive
= true;
2935 if (!sLoadEnabled
) {
2936 OSKextLog(/* kext */ NULL
,
2937 kOSKextLogErrorLevel
|
2939 "Kext loading is disabled.");
2940 result
= kOSKextReturnDisabled
;
2944 /* Note that we do not set a dealloc function on this OSData
2945 * object! No references to it can remain after the loadFromMkext()
2946 * call since we are in a MIG function, and will vm_deallocate()
2949 mkextData
= OSData::withBytesNoCopy(mkextBuffer
,
2952 OSKextLog(/* kext */ NULL
,
2953 kOSKextLogErrorLevel
|
2954 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
2955 "Failed to create wrapper for kext load request.");
2956 result
= kOSKextReturnNoMemory
;
2960 result
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
);
2961 if (result
!= kOSReturnSuccess
) {
2962 OSKextLog(/* kext */ NULL
,
2963 kOSKextLogErrorLevel
|
2965 "Failed to read kext load request.");
2969 predicate
= _OSKextGetRequestPredicate(mkextPlist
);
2970 if (!predicate
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) {
2971 OSKextLog(/* kext */ NULL
,
2972 kOSKextLogErrorLevel
|
2974 "Received kext load request with no predicate; skipping.");
2975 result
= kOSKextReturnInvalidArgument
;
2979 requestArgs
= OSDynamicCast(OSDictionary
,
2980 mkextPlist
->getObject(kKextRequestArgumentsKey
));
2981 if (!requestArgs
|| !requestArgs
->getCount()) {
2982 OSKextLog(/* kext */ NULL
,
2983 kOSKextLogErrorLevel
|
2985 "Received kext load request with no arguments.");
2986 result
= kOSKextReturnInvalidArgument
;
2990 kextIdentifier
= OSDynamicCast(OSString
,
2991 requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
));
2992 if (!kextIdentifier
) {
2993 OSKextLog(/* kext */ NULL
,
2994 kOSKextLogErrorLevel
|
2996 "Received kext load request with no kext identifier.");
2997 result
= kOSKextReturnInvalidArgument
;
3001 startKextExcludeNum
= OSDynamicCast(OSNumber
,
3002 requestArgs
->getObject(kKextRequestArgumentStartExcludeKey
));
3003 startMatchingExcludeNum
= OSDynamicCast(OSNumber
,
3004 requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
));
3005 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
3006 requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
));
3007 personalityNames
= OSDynamicCast(OSArray
,
3008 requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
));
3010 if (delayAutounloadBool
) {
3011 delayAutounload
= delayAutounloadBool
->getValue();
3013 if (startKextExcludeNum
) {
3014 startKextExcludeLevel
= startKextExcludeNum
->unsigned8BitValue();
3016 if (startMatchingExcludeNum
) {
3017 startMatchingExcludeLevel
= startMatchingExcludeNum
->unsigned8BitValue();
3020 OSKextLog(/* kext */ NULL
,
3021 kOSKextLogProgressLevel
|
3023 "Received request from user space to load kext %s.",
3024 kextIdentifier
->getCStringNoCopy());
3026 /* Load the kext, with no deferral, since this is a load from outside
3028 * xxx - Would like a better way to handle the default values for the
3029 * xxx - start/match opt args.
3031 result
= OSKext::loadKextWithIdentifier(
3033 /* allowDefer */ false,
3035 startKextExcludeLevel
,
3036 startMatchingExcludeLevel
,
3038 if (result
!= kOSReturnSuccess
) {
3041 /* If the load came down from kextd, it will shortly inform IOCatalogue
3042 * for matching via a separate IOKit calldown.
3047 /* Gather up the collected log messages for user space. Any
3048 * error messages past this call will not make it up as log messages
3049 * but will be in the system log.
3051 logInfoArray
= OSKext::clearUserSpaceLogFilter();
3053 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
3054 tempResult
= OSKext::serializeLogInfo(logInfoArray
,
3055 logInfoOut
, logInfoLengthOut
);
3056 if (tempResult
!= kOSReturnSuccess
) {
3057 result
= tempResult
;
3061 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3063 /* Note: mkextDataObject will have been retained by every kext w/an
3064 * executable in it. That should all have been flushed out at the
3065 * and of the load operation, but you never know....
3067 if (mkextData
&& mkextData
->getRetainCount() > 1) {
3068 OSKextLog(/* kext */ NULL
,
3069 kOSKextLogErrorLevel
|
3070 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3071 "Kext load request buffer from user space still retained by a kext; "
3072 "probable memory leak.");
3075 IORecursiveLockUnlock(sKextLock
);
3077 OSSafeRelease(mkextData
);
3078 OSSafeRelease(mkextPlist
);
3079 OSSafeRelease(serializer
);
3080 OSSafeRelease(logInfoArray
);
3085 /*********************************************************************
3086 *********************************************************************/
3089 OSKext::serializeLogInfo(
3090 OSArray
* logInfoArray
,
3092 uint32_t * logInfoLengthOut
)
3094 OSReturn result
= kOSReturnError
;
3095 char * buffer
= NULL
;
3096 kern_return_t kmem_result
= KERN_FAILURE
;
3097 OSSerialize
* serializer
= NULL
; // must release; reused
3098 char * logInfo
= NULL
; // returned by reference
3099 uint32_t logInfoLength
= 0;
3101 if (!logInfoArray
|| !logInfoOut
|| !logInfoLengthOut
) {
3102 OSKextLog(/* kext */ NULL
,
3103 kOSKextLogErrorLevel
|
3105 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3106 /* Bad programmer. */
3107 result
= kOSKextReturnInvalidArgument
;
3111 serializer
= OSSerialize::withCapacity(0);
3113 OSKextLog(/* kext */ NULL
,
3114 kOSKextLogErrorLevel
|
3116 "Failed to create serializer on log info for request from user space.");
3117 /* Incidental error; we're going to (try to) allow the request
3118 * itself to succeed. */
3121 if (!logInfoArray
->serialize(serializer
)) {
3122 OSKextLog(/* kext */ NULL
,
3123 kOSKextLogErrorLevel
|
3125 "Failed to serialize log info for request from user space.");
3126 /* Incidental error; we're going to (try to) allow the request
3127 * itself to succeed. */
3129 logInfo
= serializer
->text();
3130 logInfoLength
= serializer
->getLength();
3132 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
, round_page(logInfoLength
), VM_KERN_MEMORY_OSKEXT
);
3133 if (kmem_result
!= KERN_SUCCESS
) {
3134 OSKextLog(/* kext */ NULL
,
3135 kOSKextLogErrorLevel
|
3137 "Failed to copy log info for request from user space.");
3138 /* Incidental error; we're going to (try to) allow the request
3141 /* 11981737 - clear uninitialized data in last page */
3142 bzero((void *)(buffer
+ logInfoLength
),
3143 (round_page(logInfoLength
) - logInfoLength
));
3144 memcpy(buffer
, logInfo
, logInfoLength
);
3145 *logInfoOut
= buffer
;
3146 *logInfoLengthOut
= logInfoLength
;
3150 result
= kOSReturnSuccess
;
3152 OSSafeRelease(serializer
);
3157 #pragma mark Instance Management Methods
3159 /*********************************************************************
3160 *********************************************************************/
3162 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
)
3164 OSKext
* foundKext
= NULL
;
3166 IORecursiveLockLock(sKextLock
);
3167 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3169 foundKext
->retain();
3171 IORecursiveLockUnlock(sKextLock
);
3176 /*********************************************************************
3177 *********************************************************************/
3179 OSKext::lookupKextWithIdentifier(OSString
* kextIdentifier
)
3181 return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy());
3184 /*********************************************************************
3185 *********************************************************************/
3187 OSKext::lookupKextWithLoadTag(uint32_t aTag
)
3189 OSKext
* foundKext
= NULL
; // returned
3192 IORecursiveLockLock(sKextLock
);
3194 count
= sLoadedKexts
->getCount();
3195 for (i
= 0; i
< count
; i
++) {
3196 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3197 if (thisKext
->getLoadTag() == aTag
) {
3198 foundKext
= thisKext
;
3199 foundKext
->retain();
3205 IORecursiveLockUnlock(sKextLock
);
3210 /*********************************************************************
3211 *********************************************************************/
3213 OSKext::lookupKextWithAddress(vm_address_t address
)
3215 OSKext
* foundKext
= NULL
; // returned
3218 IORecursiveLockLock(sKextLock
);
3220 count
= sLoadedKexts
->getCount();
3221 for (i
= 0; i
< count
; i
++) {
3222 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3223 if (thisKext
->linkedExecutable
) {
3224 vm_address_t kext_start
=
3225 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy();
3226 vm_address_t kext_end
= kext_start
+
3227 thisKext
->linkedExecutable
->getLength();
3229 if ((kext_start
<= address
) && (address
< kext_end
)) {
3230 foundKext
= thisKext
;
3231 foundKext
->retain();
3238 IORecursiveLockUnlock(sKextLock
);
3244 /*********************************************************************
3245 *********************************************************************/
3247 OSKext::lookupKextWithUUID(uuid_t wanted
)
3249 OSKext
* foundKext
= NULL
; // returned
3252 IORecursiveLockLock(sKextLock
);
3254 count
= sLoadedKexts
->getCount();
3256 for (i
= 0; i
< count
; i
++) {
3257 OSKext
* thisKext
= NULL
;
3259 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3264 OSData
*uuid_data
= thisKext
->copyUUID();
3270 memcpy(&uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
3271 uuid_data
->release();
3273 if (0 == uuid_compare(wanted
, uuid
)) {
3274 foundKext
= thisKext
;
3275 foundKext
->retain();
3282 IORecursiveLockUnlock(sKextLock
);
3290 /*********************************************************************
3291 *********************************************************************/
3293 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
)
3295 bool result
= false;
3296 OSKext
* foundKext
= NULL
; // returned
3298 IORecursiveLockLock(sKextLock
);
3300 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3301 if (foundKext
&& foundKext
->isLoaded()) {
3305 IORecursiveLockUnlock(sKextLock
);
3310 /*********************************************************************
3311 * xxx - should spawn a separate thread so a kext can safely have
3312 * xxx - itself unloaded.
3313 *********************************************************************/
3318 bool terminateServicesAndRemovePersonalitiesFlag
)
3320 OSReturn result
= kOSKextReturnInUse
;
3321 OSKext
* checkKext
= NULL
; // do not release
3323 int macCheckResult
= 0;
3324 kauth_cred_t cred
= NULL
;
3327 IORecursiveLockLock(sKextLock
);
3329 /* If the kext has no identifier, it failed to init
3330 * so isn't in sKextsByID and it isn't loaded.
3332 if (!aKext
->getIdentifier()) {
3333 result
= kOSReturnSuccess
;
3337 checkKext
= OSDynamicCast(OSKext
,
3338 sKextsByID
->getObject(aKext
->getIdentifier()));
3339 if (checkKext
!= aKext
) {
3340 result
= kOSKextReturnNotFound
;
3344 if (aKext
->isLoaded()) {
3346 if (current_task() != kernel_task
) {
3347 cred
= kauth_cred_get_with_ref();
3348 macCheckResult
= mac_kext_check_unload(cred
, aKext
->getIdentifierCString());
3349 kauth_cred_unref(&cred
);
3352 if (macCheckResult
!= 0) {
3353 result
= kOSReturnError
;
3355 kOSKextLogErrorLevel
|
3356 kOSKextLogKextBookkeepingFlag
,
3357 "Failed to remove kext %s (MAC policy error 0x%x).",
3358 aKext
->getIdentifierCString(), macCheckResult
);
3363 /* make sure there are no resource requests in flight - 17187548 */
3364 if (aKext
->countRequestCallbacks()) {
3368 /* If we are terminating, send the request to the IOCatalogue
3369 * (which will actually call us right back but that's ok we have
3370 * a recursive lock don't you know) but do not ask the IOCatalogue
3371 * to call back with an unload, we'll do that right here.
3373 if (terminateServicesAndRemovePersonalitiesFlag
) {
3374 result
= gIOCatalogue
->terminateDriversForModule(
3375 aKext
->getIdentifierCString(), /* unload */ false);
3376 if (result
!= kOSReturnSuccess
) {
3378 kOSKextLogErrorLevel
|
3379 kOSKextLogKextBookkeepingFlag
,
3380 "Can't remove kext %s; services failed to terminate - 0x%x.",
3381 aKext
->getIdentifierCString(), result
);
3386 result
= aKext
->unload();
3387 if (result
!= kOSReturnSuccess
) {
3392 /* Remove personalities as requested. This is a bit redundant for a loaded
3393 * kext as IOCatalogue::terminateDriversForModule() removes driver
3394 * personalities, but it doesn't restart matching, which we always want
3395 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3398 if (terminateServicesAndRemovePersonalitiesFlag
) {
3399 aKext
->removePersonalitiesFromCatalog();
3403 kOSKextLogProgressLevel
|
3404 kOSKextLogKextBookkeepingFlag
,
3405 "Removing kext %s.",
3406 aKext
->getIdentifierCString());
3408 sKextsByID
->removeObject(aKext
->getIdentifier());
3409 result
= kOSReturnSuccess
;
3412 IORecursiveLockUnlock(sKextLock
);
3416 /*********************************************************************
3417 *********************************************************************/
3420 OSKext::removeKextWithIdentifier(
3421 const char * kextIdentifier
,
3422 bool terminateServicesAndRemovePersonalitiesFlag
)
3424 OSReturn result
= kOSReturnError
;
3426 IORecursiveLockLock(sKextLock
);
3428 OSKext
* aKext
= OSDynamicCast(OSKext
,
3429 sKextsByID
->getObject(kextIdentifier
));
3431 result
= kOSKextReturnNotFound
;
3432 OSKextLog(/* kext */ NULL
,
3433 kOSKextLogErrorLevel
|
3434 kOSKextLogKextBookkeepingFlag
,
3435 "Can't remove kext %s - not found.",
3440 result
= OSKext::removeKext(aKext
,
3441 terminateServicesAndRemovePersonalitiesFlag
);
3444 IORecursiveLockUnlock(sKextLock
);
3449 /*********************************************************************
3450 *********************************************************************/
3453 OSKext::removeKextWithLoadTag(
3454 OSKextLoadTag loadTag
,
3455 bool terminateServicesAndRemovePersonalitiesFlag
)
3457 OSReturn result
= kOSReturnError
;
3458 OSKext
* foundKext
= NULL
;
3461 IORecursiveLockLock(sKextLock
);
3463 count
= sLoadedKexts
->getCount();
3464 for (i
= 0; i
< count
; i
++) {
3465 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3466 if (thisKext
->loadTag
== loadTag
) {
3467 foundKext
= thisKext
;
3473 result
= kOSKextReturnNotFound
;
3474 OSKextLog(/* kext */ NULL
,
3475 kOSKextLogErrorLevel
|
3476 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
3477 "Can't remove kext with load tag %d - not found.",
3482 result
= OSKext::removeKext(foundKext
,
3483 terminateServicesAndRemovePersonalitiesFlag
);
3486 IORecursiveLockUnlock(sKextLock
);
3491 /*********************************************************************
3492 *********************************************************************/
3494 OSKext::copyKexts(void)
3496 OSDictionary
* result
;
3498 IORecursiveLockLock(sKextLock
);
3499 result
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection());
3500 IORecursiveLockUnlock(sKextLock
);
3505 /*********************************************************************
3506 *********************************************************************/
3507 #define BOOTER_KEXT_PREFIX "Driver-"
3509 typedef struct _DeviceTreeBuffer
{
3512 } _DeviceTreeBuffer
;
3514 /*********************************************************************
3515 * Create a dictionary of excluded kexts from the given booter data.
3516 *********************************************************************/
3519 OSKext::createExcludeListFromBooterData(
3520 OSDictionary
* theDictionary
,
3521 OSCollectionIterator
* theIterator
)
3523 OSString
* deviceTreeName
= NULL
; // do not release
3524 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not release
3525 char * booterDataPtr
= NULL
; // do not release
3526 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not release
3527 char * infoDictAddr
= NULL
; // do not release
3528 OSObject
* parsedXML
= NULL
; // must release
3529 OSDictionary
* theInfoDict
= NULL
; // do not release
3531 theIterator
->reset();
3533 /* look for AppleKextExcludeList.kext */
3534 while ( (deviceTreeName
=
3535 OSDynamicCast(OSString
, theIterator
->getNextObject())) ) {
3537 const char * devTreeNameCString
;
3538 OSData
* deviceTreeEntry
;
3539 OSString
* myBundleID
; // do not release
3541 OSSafeReleaseNULL(parsedXML
);
3544 OSDynamicCast(OSData
, theDictionary
->getObject(deviceTreeName
));
3545 if (!deviceTreeEntry
) {
3549 /* Make sure it is a kext */
3550 devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
3551 if (strncmp(devTreeNameCString
, BOOTER_KEXT_PREFIX
,
3552 (sizeof(BOOTER_KEXT_PREFIX
) - 1)) != 0) {
3554 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3555 "\"%s\" not a kext",
3556 devTreeNameCString
);
3560 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
3561 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
3562 if (!deviceTreeBuffer
) {
3566 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
3567 if (!booterDataPtr
) {
3571 kextFileInfo
= (_BooterKextFileInfo
*) booterDataPtr
;
3572 if (!kextFileInfo
->infoDictPhysAddr
||
3573 !kextFileInfo
->infoDictLength
) {
3577 infoDictAddr
= (char *)
3578 ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
3579 if (!infoDictAddr
) {
3583 parsedXML
= OSUnserializeXML(infoDictAddr
);
3588 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
3594 OSDynamicCast(OSString
,
3595 theInfoDict
->getObject(kCFBundleIdentifierKey
));
3597 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3599 /* get copy of exclusion list dictionary */
3600 OSDictionary
* myTempDict
; // do not free
3602 myTempDict
= OSDynamicCast(
3604 theInfoDict
->getObject("OSKextExcludeList"));
3606 IORecursiveLockLock(sKextLock
);
3608 /* get rid of old exclusion list */
3609 if (sExcludeListByID
) {
3610 sExcludeListByID
->flushCollection();
3611 OSSafeRelease(sExcludeListByID
);
3613 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3614 IORecursiveLockUnlock(sKextLock
);
3619 } // while ( (deviceTreeName = ...) )
3621 OSSafeReleaseNULL(parsedXML
);
3625 /*********************************************************************
3626 * Create a dictionary of excluded kexts from the given prelink
3627 * info (kernelcache).
3628 *********************************************************************/
3631 OSKext::createExcludeListFromPrelinkInfo( OSArray
* theInfoArray
)
3633 OSDictionary
* myInfoDict
= NULL
; // do not release
3634 OSString
* myBundleID
; // do not release
3637 /* Find com.apple.driver.KextExcludeList. */
3638 for (i
= 0; i
< theInfoArray
->getCount(); i
++) {
3639 myInfoDict
= OSDynamicCast(OSDictionary
, theInfoArray
->getObject(i
));
3644 OSDynamicCast(OSString
,
3645 myInfoDict
->getObject(kCFBundleIdentifierKey
));
3647 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3648 // get copy of exclude list dictionary
3649 OSDictionary
* myTempDict
; // do not free
3650 myTempDict
= OSDynamicCast(OSDictionary
,
3651 myInfoDict
->getObject("OSKextExcludeList"));
3653 IORecursiveLockLock(sKextLock
);
3654 // get rid of old exclude list
3655 if (sExcludeListByID
) {
3656 sExcludeListByID
->flushCollection();
3657 OSSafeRelease(sExcludeListByID
);
3660 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3661 IORecursiveLockUnlock(sKextLock
);
3665 } // for (i = 0; i < theInfoArray->getCount()...
3671 #pragma mark Accessors
3673 /*********************************************************************
3674 *********************************************************************/
3676 OSKext::getIdentifier(void)
3681 /*********************************************************************
3682 * A kext must have a bundle identifier to even survive initialization;
3683 * this is guaranteed to exist past then.
3684 *********************************************************************/
3686 OSKext::getIdentifierCString(void)
3688 return bundleID
->getCStringNoCopy();
3691 /*********************************************************************
3692 *********************************************************************/
3694 OSKext::getVersion(void)
3699 /*********************************************************************
3700 *********************************************************************/
3702 OSKext::getCompatibleVersion(void)
3704 return compatibleVersion
;
3707 /*********************************************************************
3708 *********************************************************************/
3710 OSKext::isLibrary(void)
3712 return (getCompatibleVersion() > 0);
3715 /*********************************************************************
3716 *********************************************************************/
3718 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
)
3720 if ((compatibleVersion
> -1 && version
> -1) &&
3721 (compatibleVersion
<= version
&& aVersion
<= version
)) {
3727 /*********************************************************************
3728 *********************************************************************/
3730 OSKext::declaresExecutable(void)
3732 return (getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
);
3735 /*********************************************************************
3736 *********************************************************************/
3738 OSKext::getExecutable(void)
3740 OSData
* result
= NULL
;
3741 OSData
* extractedExecutable
= NULL
; // must release
3742 OSData
* mkextExecutableRef
= NULL
; // do not release
3744 result
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
));
3749 mkextExecutableRef
= OSDynamicCast(OSData
,
3750 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
));
3752 if (mkextExecutableRef
) {
3754 MkextEntryRef
* mkextEntryRef
= (MkextEntryRef
*)
3755 mkextExecutableRef
->getBytesNoCopy();
3756 uint32_t mkextVersion
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
);
3757 if (mkextVersion
== MKEXT_VERS_2
) {
3758 mkext2_file_entry
* fileinfo
=
3759 (mkext2_file_entry
*)mkextEntryRef
->fileinfo
;
3760 uint32_t compressedSize
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
);
3761 uint32_t fullSize
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
);
3762 extractedExecutable
= extractMkext2FileData(
3763 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable",
3764 compressedSize
, fullSize
);
3766 OSKextLog(this, kOSKextLogErrorLevel
|
3767 kOSKextLogArchiveFlag
,
3768 "Kext %s - unknown mkext version 0x%x for executable.",
3769 getIdentifierCString(), mkextVersion
);
3772 /* Regardless of success, remove the mkext executable,
3773 * and drop one reference on the mkext. (setExecutable() does not
3774 * replace, it removes, or panics if asked to replace.)
3776 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
3777 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
3779 if (extractedExecutable
&& extractedExecutable
->getLength()) {
3780 if (!setExecutable(extractedExecutable
)) {
3783 result
= extractedExecutable
;
3791 OSSafeRelease(extractedExecutable
);
3796 /*********************************************************************
3797 *********************************************************************/
3799 OSKext::isInterface(void)
3801 return flags
.interface
;
3804 /*********************************************************************
3805 *********************************************************************/
3807 OSKext::isKernel(void)
3809 return (this == sKernelKext
);
3812 /*********************************************************************
3813 *********************************************************************/
3815 OSKext::isKernelComponent(void)
3817 return flags
.kernelComponent
? true : false;
3820 /*********************************************************************
3821 *********************************************************************/
3823 OSKext::isExecutable(void)
3825 return (!isKernel() && !isInterface() && declaresExecutable());
3828 /*********************************************************************
3829 * We might want to check this recursively for all dependencies,
3830 * since a subtree of dependencies could get loaded before we hit
3831 * a dependency that isn't safe-boot-loadable.
3833 * xxx - Might want to return false if OSBundleEnableKextLogging or
3834 * OSBundleDebugLevel
3835 * or IOKitDebug is nonzero too (we used to do that, but I don't see
3836 * the point except it's usually development drivers, which might
3837 * cause panics on startup, that have those properties). Heh; could
3838 * use a "kx" boot-arg!
3839 *********************************************************************/
3841 OSKext::isLoadableInSafeBoot(void)
3843 bool result
= false;
3844 OSString
* required
= NULL
; // do not release
3851 required
= OSDynamicCast(OSString
,
3852 getPropertyForHostArch(kOSBundleRequiredKey
));
3856 if (required
->isEqualTo(kOSBundleRequiredRoot
) ||
3857 required
->isEqualTo(kOSBundleRequiredLocalRoot
) ||
3858 required
->isEqualTo(kOSBundleRequiredNetworkRoot
) ||
3859 required
->isEqualTo(kOSBundleRequiredSafeBoot
) ||
3860 required
->isEqualTo(kOSBundleRequiredConsole
)) {
3869 /*********************************************************************
3870 *********************************************************************/
3872 OSKext::isPrelinked(void)
3874 return flags
.prelinked
? true : false;
3877 /*********************************************************************
3878 *********************************************************************/
3879 bool OSKext::isLoaded(void)
3881 return flags
.loaded
? true : false;
3884 /*********************************************************************
3885 *********************************************************************/
3887 OSKext::isStarted(void)
3889 return flags
.started
? true : false;
3892 /*********************************************************************
3893 *********************************************************************/
3895 OSKext::isCPPInitialized(void)
3897 return flags
.CPPInitialized
;
3900 /*********************************************************************
3901 *********************************************************************/
3903 OSKext::setCPPInitialized(bool initialized
)
3905 flags
.CPPInitialized
= initialized
;
3908 /*********************************************************************
3909 *********************************************************************/
3911 OSKext::getLoadTag(void)
3916 /*********************************************************************
3917 *********************************************************************/
3918 void OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
)
3920 if (linkedExecutable
) {
3921 *loadSize
= linkedExecutable
->getLength();
3923 /* If we have a kmod_info struct, calculated the wired size
3924 * from that. Otherwise it's the full load size.
3927 *wiredSize
= *loadSize
- kmod_info
->hdr_size
;
3929 *wiredSize
= *loadSize
;
3938 /*********************************************************************
3939 *********************************************************************/
3941 OSKext::copyUUID(void)
3943 OSData
* result
= NULL
;
3944 OSData
* theExecutable
= NULL
; // do not release
3945 const kernel_mach_header_t
* header
= NULL
;
3946 const struct load_command
* load_cmd
= NULL
;
3947 const struct uuid_command
* uuid_cmd
= NULL
;
3950 /* An interface kext doesn't have a linked executable with an LC_UUID,
3951 * we create one when it's linked.
3953 if (interfaceUUID
) {
3954 result
= interfaceUUID
;
3959 /* For real kexts, try to get the UUID from the linked executable,
3960 * or if is hasn't been linked yet, the unrelocated executable.
3962 theExecutable
= linkedExecutable
;
3963 if (!theExecutable
) {
3964 theExecutable
= getExecutable();
3966 if (!theExecutable
) {
3970 header
= (const kernel_mach_header_t
*)theExecutable
->getBytesNoCopy();
3971 load_cmd
= (const struct load_command
*)&header
[1];
3973 if (header
->magic
!= MH_MAGIC_KERNEL
) {
3975 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3976 "%s: bad header %p",
3982 for (i
= 0; i
< header
->ncmds
; i
++) {
3983 if (load_cmd
->cmd
== LC_UUID
) {
3984 uuid_cmd
= (struct uuid_command
*)load_cmd
;
3985 result
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
));
3988 load_cmd
= (struct load_command
*)((caddr_t
)load_cmd
+ load_cmd
->cmdsize
);
3995 /*********************************************************************
3996 *********************************************************************/
3998 #if defined (__x86_64__)
3999 #define ARCHNAME "x86_64"
4001 #error architecture not supported
4004 #define ARCH_SEPARATOR_CHAR '_'
4006 static char * makeHostArchKey(const char * key
, uint32_t * keySizeOut
)
4008 char * result
= NULL
;
4009 uint32_t keyLength
= strlen(key
);
4012 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4014 keySize
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
);
4015 result
= (char *)kalloc_tag(keySize
, VM_KERN_MEMORY_OSKEXT
);
4019 strlcpy(result
, key
, keySize
);
4020 result
[keyLength
++] = ARCH_SEPARATOR_CHAR
;
4021 result
[keyLength
] = '\0';
4022 strlcat(result
, ARCHNAME
, keySize
);
4023 *keySizeOut
= keySize
;
4029 /*********************************************************************
4030 *********************************************************************/
4032 OSKext::getPropertyForHostArch(const char * key
)
4034 OSObject
* result
= NULL
; // do not release
4035 uint32_t hostArchKeySize
= 0;
4036 char * hostArchKey
= NULL
; // must kfree
4038 if (!key
|| !infoDict
) {
4042 /* Some properties are not allowed to be arch-variant:
4043 * - Any CFBundle... property.
4044 * - OSBundleIsInterface.
4045 * - OSKernelResource.
4047 if (STRING_HAS_PREFIX(key
, "OS") ||
4048 STRING_HAS_PREFIX(key
, "IO")) {
4050 hostArchKey
= makeHostArchKey(key
, &hostArchKeySize
);
4052 OSKextLog(/* kext (this isn't about a kext) */ NULL
,
4053 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4054 "Allocation failure.");
4057 result
= infoDict
->getObject(hostArchKey
);
4061 result
= infoDict
->getObject(key
);
4065 if (hostArchKey
) kfree(hostArchKey
, hostArchKeySize
);
4070 #pragma mark Load/Start/Stop/Unload
4073 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4075 /*********************************************************************
4076 * sExcludeListByID is a dictionary with keys / values of:
4077 * key = bundleID string of kext we will not allow to load
4078 * value = version string(s) of the kext that is to be denied loading.
4079 * The version strings can be comma delimited. For example if kext
4080 * com.foocompany.fookext has two versions that we want to deny
4081 * loading then the version strings might look like:
4083 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4084 * not load the kext.
4086 * Value may also be in the form of "LE 2.0.0" (version numbers
4087 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4088 * number less than 2.0.0 will not load)
4090 * NOTE - we cannot use the characters "<=" or "<" because we have code
4091 * that serializes plists and treats '<' as a special character.
4092 *********************************************************************/
4094 OSKext::isInExcludeList(void)
4096 OSString
* versionString
= NULL
; // do not release
4097 char * versionCString
= NULL
; // do not free
4099 boolean_t wantLessThan
= false;
4100 boolean_t wantLessThanEqualTo
= false;
4103 if (!sExcludeListByID
) {
4106 /* look up by bundleID in our exclude list and if found get version
4107 * string (or strings) that we will not allow to load
4109 versionString
= OSDynamicCast(OSString
, sExcludeListByID
->getObject(bundleID
));
4110 if (versionString
== NULL
|| versionString
->getLength() > (sizeof(myBuffer
) - 1)) {
4114 /* parse version strings */
4115 versionCString
= (char *) versionString
->getCStringNoCopy();
4117 /* look for "LT" or "LE" form of version string, must be in first two
4120 if (*versionCString
== 'L' && *(versionCString
+ 1) == 'T') {
4121 wantLessThan
= true;
4124 else if (*versionCString
== 'L' && *(versionCString
+ 1) == 'E') {
4125 wantLessThanEqualTo
= true;
4129 for (i
= 0; *versionCString
!= 0x00; versionCString
++) {
4130 /* skip whitespace */
4131 if (isWhiteSpace(*versionCString
)) {
4135 /* peek ahead for version string separator or null terminator */
4136 if (*(versionCString
+ 1) == ',' || *(versionCString
+ 1) == 0x00) {
4138 /* OK, we have a version string */
4139 myBuffer
[i
++] = *versionCString
;
4142 OSKextVersion excludeVers
;
4143 excludeVers
= OSKextParseVersionString(myBuffer
);
4145 if (wantLessThanEqualTo
) {
4146 if (version
<= excludeVers
) {
4150 else if (wantLessThan
) {
4151 if (version
< excludeVers
) {
4155 else if ( version
== excludeVers
) {
4159 /* reset for the next (if any) version string */
4161 wantLessThan
= false;
4162 wantLessThanEqualTo
= false;
4165 /* save valid version character */
4166 myBuffer
[i
++] = *versionCString
;
4168 /* make sure bogus version string doesn't overrun local buffer */
4169 if ( i
>= sizeof(myBuffer
) ) {
4178 /*********************************************************************
4179 *********************************************************************/
4182 OSKext::loadKextWithIdentifier(
4183 const char * kextIdentifierCString
,
4184 Boolean allowDeferFlag
,
4185 Boolean delayAutounloadFlag
,
4186 OSKextExcludeLevel startOpt
,
4187 OSKextExcludeLevel startMatchingOpt
,
4188 OSArray
* personalityNames
)
4190 OSReturn result
= kOSReturnError
;
4191 OSString
* kextIdentifier
= NULL
; // must release
4193 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
4194 if (!kextIdentifier
) {
4195 result
= kOSKextReturnNoMemory
;
4198 result
= OSKext::loadKextWithIdentifier(kextIdentifier
,
4199 allowDeferFlag
, delayAutounloadFlag
,
4200 startOpt
, startMatchingOpt
, personalityNames
);
4203 OSSafeRelease(kextIdentifier
);
4207 /*********************************************************************
4208 *********************************************************************/
4210 OSKext::loadKextWithIdentifier(
4211 OSString
* kextIdentifier
,
4212 Boolean allowDeferFlag
,
4213 Boolean delayAutounloadFlag
,
4214 OSKextExcludeLevel startOpt
,
4215 OSKextExcludeLevel startMatchingOpt
,
4216 OSArray
* personalityNames
)
4218 OSReturn result
= kOSReturnError
;
4219 OSReturn pingResult
= kOSReturnError
;
4220 OSKext
* theKext
= NULL
; // do not release
4221 OSDictionary
* loadRequest
= NULL
; // must release
4222 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4224 IORecursiveLockLock(sKextLock
);
4226 if (!kextIdentifier
) {
4227 result
= kOSKextReturnInvalidArgument
;
4231 OSKext::recordIdentifierRequest(kextIdentifier
);
4233 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
4235 if (!allowDeferFlag
) {
4236 OSKextLog(/* kext */ NULL
,
4237 kOSKextLogErrorLevel
|
4239 "Can't load kext %s - not found.",
4240 kextIdentifier
->getCStringNoCopy());
4244 if (!sKernelRequestsEnabled
) {
4246 kOSKextLogErrorLevel
|
4248 "Can't load kext %s - requests to user space are disabled.",
4249 kextIdentifier
->getCStringNoCopy());
4250 result
= kOSKextReturnDisabled
;
4254 /* Create a new request unless one is already sitting
4255 * in sKernelRequests for this bundle identifier
4257 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4258 if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4259 result
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
,
4261 if (result
!= kOSReturnSuccess
) {
4264 if (!_OSKextSetRequestArgument(loadRequest
,
4265 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
4267 result
= kOSKextReturnNoMemory
;
4270 if (!sKernelRequests
->setObject(loadRequest
)) {
4271 result
= kOSKextReturnNoMemory
;
4275 if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4276 result
= kOSKextReturnNoMemory
;
4281 kOSKextLogDebugLevel
|
4283 "Kext %s not found; queued load request to user space.",
4284 kextIdentifier
->getCStringNoCopy());
4287 pingResult
= OSKext::pingKextd();
4288 if (pingResult
== kOSKextReturnDisabled
) {
4289 OSKextLog(/* kext */ NULL
,
4290 ((sPrelinkBoot
) ? kOSKextLogDebugLevel
: kOSKextLogErrorLevel
) |
4292 "Kext %s might not load - kextd is currently unavailable.",
4293 kextIdentifier
->getCStringNoCopy());
4296 result
= kOSKextReturnDeferred
;
4300 result
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
);
4302 if (result
!= kOSReturnSuccess
) {
4304 kOSKextLogErrorLevel
|
4306 "Failed to load kext %s (error 0x%x).",
4307 kextIdentifier
->getCStringNoCopy(), (int)result
);
4309 OSKext::removeKext(theKext
,
4310 /* terminateService/removePersonalities */ true);
4314 if (delayAutounloadFlag
) {
4316 kOSKextLogProgressLevel
|
4317 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4318 "Setting delayed autounload for %s.",
4319 kextIdentifier
->getCStringNoCopy());
4320 theKext
->flags
.delayAutounload
= 1;
4324 OSSafeRelease(loadRequest
);
4325 OSSafeRelease(kextIdentifierSymbol
);
4327 IORecursiveLockUnlock(sKextLock
);
4332 /*********************************************************************
4333 *********************************************************************/
4336 OSKext::recordIdentifierRequest(
4337 OSString
* kextIdentifier
)
4339 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4342 if (!sAllKextLoadIdentifiers
|| !kextIdentifier
) {
4346 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4347 if (!kextIdentifierSymbol
) {
4348 // xxx - this is really a basic alloc failure
4353 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4354 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4357 // xxx - need to find a way to associate this whole func w/the kext
4358 OSKextLog(/* kext */ NULL
,
4359 // xxx - check level
4360 kOSKextLogStepLevel
|
4361 kOSKextLogArchiveFlag
,
4362 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4363 kextIdentifier
->getCStringNoCopy());
4369 OSKextLog(/* kext */ NULL
,
4370 kOSKextLogErrorLevel
|
4371 kOSKextLogArchiveFlag
,
4372 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4373 kextIdentifier
->getCStringNoCopy());
4375 OSSafeRelease(kextIdentifierSymbol
);
4379 /*********************************************************************
4380 *********************************************************************/
4383 OSKextExcludeLevel startOpt
,
4384 OSKextExcludeLevel startMatchingOpt
,
4385 OSArray
* personalityNames
)
4387 OSReturn result
= kOSReturnError
;
4388 kern_return_t kxldResult
;
4389 OSKextExcludeLevel dependenciesStartOpt
= startOpt
;
4390 OSKextExcludeLevel dependenciesStartMatchingOpt
= startMatchingOpt
;
4391 unsigned int i
, count
;
4392 Boolean alreadyLoaded
= false;
4393 OSKext
* lastLoadedKext
= NULL
;
4395 if (isInExcludeList()) {
4397 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
|
4399 "Kext %s is in exclude list, not loadable",
4400 getIdentifierCString());
4402 result
= kOSKextReturnNotLoadable
;
4407 alreadyLoaded
= true;
4408 result
= kOSReturnSuccess
;
4411 kOSKextLogDebugLevel
|
4412 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4413 "Kext %s is already loaded.",
4414 getIdentifierCString());
4419 if (current_task() != kernel_task
) {
4420 int macCheckResult
= 0;
4421 kauth_cred_t cred
= NULL
;
4423 cred
= kauth_cred_get_with_ref();
4424 macCheckResult
= mac_kext_check_load(cred
, getIdentifierCString());
4425 kauth_cred_unref(&cred
);
4427 if (macCheckResult
!= 0) {
4428 result
= kOSReturnError
;
4430 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4431 "Failed to load kext %s (MAC policy error 0x%x).",
4432 getIdentifierCString(), macCheckResult
);
4438 if (!sLoadEnabled
) {
4440 kOSKextLogErrorLevel
|
4442 "Kext loading is disabled (attempt to load kext %s).",
4443 getIdentifierCString());
4444 result
= kOSKextReturnDisabled
;
4448 /* If we've pushed the next available load tag to the invalid value,
4449 * we can't load any more kexts.
4451 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4453 kOSKextLogErrorLevel
|
4455 "Can't load kext %s - no more load tags to assign.",
4456 getIdentifierCString());
4457 result
= kOSKextReturnNoResources
;
4461 /* This is a bit of a hack, because we shouldn't be handling
4462 * personalities within the load function.
4464 if (!declaresExecutable()) {
4465 result
= kOSReturnSuccess
;
4469 /* Are we in safe boot?
4471 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4473 kOSKextLogErrorLevel
|
4475 "Can't load kext %s - not loadable during safe boot.",
4476 getIdentifierCString());
4477 result
= kOSKextReturnBootLevel
;
4482 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4484 getIdentifierCString());
4486 if (!sKxldContext
) {
4487 kxldResult
= kxld_create_context(&sKxldContext
, &kern_allocate
,
4488 &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,
4489 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
4492 kOSKextLogErrorLevel
|
4493 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4494 "Can't load kext %s - failed to create link context.",
4495 getIdentifierCString());
4496 result
= kOSKextReturnNoMemory
;
4501 /* We only need to resolve dependencies once for the whole graph, but
4502 * resolveDependencies will just return if there's no work to do, so it's
4503 * safe to call it more than once.
4505 if (!resolveDependencies()) {
4506 // xxx - check resolveDependencies() for log msg
4508 kOSKextLogErrorLevel
|
4509 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4510 "Can't load kext %s - failed to resolve library dependencies.",
4511 getIdentifierCString());
4512 result
= kOSKextReturnDependencies
;
4516 /* If we are excluding just the kext being loaded now (and not its
4517 * dependencies), drop the exclusion level to none so dependencies
4518 * start and/or add their personalities.
4520 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4521 dependenciesStartOpt
= kOSKextExcludeNone
;
4524 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4525 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4528 /* Load the dependencies, recursively.
4530 count
= getNumDependencies();
4531 for (i
= 0; i
< count
; i
++) {
4532 OSKext
* dependency
= OSDynamicCast(OSKext
,
4533 dependencies
->getObject(i
));
4534 if (dependency
== NULL
) {
4536 kOSKextLogErrorLevel
|
4537 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4538 "Internal error loading kext %s; dependency disappeared.",
4539 getIdentifierCString());
4540 result
= kOSKextReturnInternalError
;
4544 /* Dependencies must be started accorting to the opt,
4545 * but not given the personality names of the main kext.
4547 result
= dependency
->load(dependenciesStartOpt
,
4548 dependenciesStartMatchingOpt
,
4549 /* personalityNames */ NULL
);
4550 if (result
!= KERN_SUCCESS
) {
4552 kOSKextLogErrorLevel
|
4553 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4554 "Dependency %s of kext %s failed to load.",
4555 dependency
->getIdentifierCString(),
4556 getIdentifierCString());
4558 OSKext::removeKext(dependency
,
4559 /* terminateService/removePersonalities */ true);
4560 result
= kOSKextReturnDependencyLoadError
;
4566 result
= loadExecutable();
4567 if (result
!= KERN_SUCCESS
) {
4571 pendingPgoHead
.next
= &pendingPgoHead
;
4572 pendingPgoHead
.prev
= &pendingPgoHead
;
4574 uuid_generate(instance_uuid
);
4575 account
= IONew(OSKextAccount
, 1);
4577 result
= KERN_MEMORY_ERROR
;
4580 bzero(account
, sizeof(*account
));
4581 account
->loadTag
= kmod_info
->id
;
4582 account
->site
.flags
= VM_TAG_KMOD
;
4584 flags
.loaded
= true;
4586 /* Add the kext to the list of loaded kexts and update the kmod_info
4587 * struct to point to that of the last loaded kext (which is the way
4588 * it's always been done, though I'd rather do them in order now).
4590 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
4591 sLoadedKexts
->setObject(this);
4593 /* Keep the kernel itself out of the kmod list.
4595 if (lastLoadedKext
->isKernel()) {
4596 lastLoadedKext
= NULL
;
4599 if (lastLoadedKext
) {
4600 kmod_info
->next
= lastLoadedKext
->kmod_info
;
4603 notifyKextLoadObservers(this, kmod_info
);
4605 /* Make the global kmod list point at the just-loaded kext. Note that the
4606 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4607 * although we do report it in kextstat these days by using the newer
4608 * OSArray of loaded kexts, which does contain it.
4610 * (The OSKext object representing the kernel doesn't even have a kmod_info
4611 * struct, though I suppose we could stick a pointer to it from the
4612 * static struct in OSRuntime.cpp.)
4616 /* Save the list of loaded kexts in case we panic.
4618 OSKext::saveLoadedKextPanicList();
4620 if (isExecutable()) {
4621 OSKext::updateLoadedKextSummaries();
4622 savePanicString(/* isLoading */ true);
4625 registerWithDTrace();
4627 jettisonLinkeditSegment();
4628 #endif /* CONFIG_DTRACE */
4630 #if !VM_MAPPED_KEXTS
4631 /* If there is a page (or more) worth of padding after the end
4632 * of the last data section but before the end of the data segment
4633 * then free it in the same manner the LinkeditSegment is freed
4635 jettisonDATASegmentPadding();
4640 if (isExecutable() && !flags
.started
) {
4641 if (startOpt
== kOSKextExcludeNone
) {
4643 if (result
!= kOSReturnSuccess
) {
4645 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4646 "Kext %s start failed (result 0x%x).",
4647 getIdentifierCString(), result
);
4648 result
= kOSKextReturnStartStopError
;
4653 /* If not excluding matching, send the personalities to the kernel.
4654 * This never affects the result of the load operation.
4655 * This is a bit of a hack, because we shouldn't be handling
4656 * personalities within the load function.
4658 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
4659 result
= sendPersonalitiesToCatalog(true, personalityNames
);
4664 /* More hack! If the kext doesn't declare an executable, even if we
4665 * "loaded" it, we have to remove any personalities naming it, or we'll
4666 * never see the registry go quiet. Errors here do not count for the
4667 * load operation itself.
4669 * Note that in every other regard it's perfectly ok for a kext to
4670 * not declare an executable and serve only as a package for personalities
4671 * naming another kext, so we do have to allow such kexts to be "loaded"
4672 * so that those other personalities get added & matched.
4674 if (!declaresExecutable()) {
4676 kOSKextLogStepLevel
| kOSKextLogLoadFlag
,
4677 "Kext %s has no executable; removing any personalities naming it.",
4678 getIdentifierCString());
4679 removePersonalitiesFromCatalog();
4682 if (result
!= kOSReturnSuccess
) {
4684 kOSKextLogErrorLevel
|
4686 "Kext %s failed to load (0x%x).",
4687 getIdentifierCString(), (int)result
);
4688 } else if (!alreadyLoaded
) {
4690 kOSKextLogProgressLevel
|
4693 getIdentifierCString());
4695 queueKextNotification(kKextRequestPredicateLoadNotification
,
4696 OSDynamicCast(OSString
, bundleID
));
4701 /*********************************************************************
4703 *********************************************************************/
4704 static char * strdup(const char * string
)
4706 char * result
= NULL
;
4713 size
= 1 + strlen(string
);
4714 result
= (char *)kalloc_tag(size
, VM_KERN_MEMORY_OSKEXT
);
4719 memcpy(result
, string
, size
);
4725 /*********************************************************************
4727 *********************************************************************/
4730 OSKext::lookupSection(const char *segname
, const char *secname
)
4732 kernel_section_t
* found_section
= NULL
;
4733 kernel_mach_header_t
* mh
= NULL
;
4734 kernel_segment_command_t
* seg
= NULL
;
4735 kernel_section_t
* sec
= NULL
;
4737 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4739 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4741 if (0 != strcmp(seg
->segname
, segname
)) {
4745 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4747 if (0 == strcmp(sec
->sectname
, secname
)) {
4748 found_section
= sec
;
4755 return found_section
;
4758 /*********************************************************************
4760 *********************************************************************/
4763 OSKext::slidePrelinkedExecutable()
4765 OSReturn result
= kOSKextReturnBadData
;
4766 kernel_mach_header_t
* mh
= NULL
;
4767 kernel_segment_command_t
* seg
= NULL
;
4768 kernel_segment_command_t
* linkeditSeg
= NULL
;
4769 kernel_section_t
* sec
= NULL
;
4770 char * linkeditBase
= NULL
;
4771 bool haveLinkeditBase
= false;
4772 char * relocBase
= NULL
;
4773 bool haveRelocBase
= false;
4774 struct dysymtab_command
* dysymtab
= NULL
;
4775 struct symtab_command
* symtab
= NULL
;
4776 kernel_nlist_t
* sym
= NULL
;
4777 struct relocation_info
* reloc
= NULL
;
4780 vm_offset_t new_kextsize
;
4782 if (linkedExecutable
== NULL
|| vm_kernel_slide
== 0) {
4783 result
= kOSReturnSuccess
;
4787 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4789 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4793 seg
->vmaddr
+= vm_kernel_slide
;
4795 #if KASLR_KEXT_DEBUG
4796 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
4798 (unsigned long)VM_KERNEL_UNSLIDE(seg
->vmaddr
),
4799 (unsigned long)seg
->vmaddr
);
4802 if (!haveRelocBase
) {
4803 relocBase
= (char *) seg
->vmaddr
;
4804 haveRelocBase
= true;
4806 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
4807 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
4808 haveLinkeditBase
= true;
4811 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4812 sec
->addr
+= vm_kernel_slide
;
4814 #if KASLR_KEXT_DEBUG
4815 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
4817 (unsigned long)VM_KERNEL_UNSLIDE(sec
->addr
),
4818 (unsigned long)sec
->addr
);
4823 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
4825 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
4827 if (symtab
!= NULL
) {
4828 /* Some pseudo-kexts have symbol tables without segments.
4830 if (symtab
->nsyms
> 0 && haveLinkeditBase
) {
4831 sym
= (kernel_nlist_t
*) (linkeditBase
+ symtab
->symoff
);
4832 for (i
= 0; i
< symtab
->nsyms
; i
++) {
4833 if (sym
[i
].n_type
& N_STAB
) {
4836 sym
[i
].n_value
+= vm_kernel_slide
;
4838 #if KASLR_KEXT_DEBUG
4839 #define MAX_SYMS_TO_LOG 5
4840 if ( i
< MAX_SYMS_TO_LOG
) {
4841 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
4842 (unsigned long)VM_KERNEL_UNSLIDE(sym
[i
].n_value
),
4843 (unsigned long)sym
[i
].n_value
);
4850 if (dysymtab
!= NULL
) {
4851 if (dysymtab
->nextrel
> 0) {
4853 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4855 "Sliding kext %s: External relocations found.",
4856 getIdentifierCString());
4860 if (dysymtab
->nlocrel
> 0) {
4861 if (!haveLinkeditBase
) {
4863 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4865 "Sliding kext %s: No linkedit segment.",
4866 getIdentifierCString());
4870 if (!haveRelocBase
) {
4872 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4875 "Sliding kext %s: No writable segments.",
4877 "Sliding kext %s: No segments.",
4879 getIdentifierCString());
4883 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
4884 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
4886 for (i
= 0; i
< dysymtab
->nlocrel
; i
++) {
4887 if ( reloc
[i
].r_extern
!= 0
4888 || reloc
[i
].r_type
!= 0
4889 || reloc
[i
].r_length
!= (sizeof(void *) == 8 ? 3 : 2)
4892 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4894 "Sliding kext %s: Unexpected relocation found.",
4895 getIdentifierCString());
4898 if (reloc
[i
].r_pcrel
!= 0) {
4901 *((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)) += vm_kernel_slide
;
4903 #if KASLR_KEXT_DEBUG
4904 #define MAX_DYSYMS_TO_LOG 5
4905 if ( i
< MAX_DYSYMS_TO_LOG
) {
4906 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
4907 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
))),
4908 (unsigned long)*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)));
4913 /* We should free these relocations, not just delete the reference to them.
4914 * <rdar://problem/10535549> Free relocations from PIE kexts.
4916 new_kextsize
= round_page(kmod_info
->size
- reloc_size
);
4918 if ((kmod_info
->size
- new_kextsize
) > PAGE_SIZE
) {
4919 vm_offset_t endofkext
= kmod_info
->address
+ kmod_info
->size
;
4920 vm_offset_t new_endofkext
= kmod_info
->address
+ new_kextsize
;
4921 vm_offset_t endofrelocInfo
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
);
4922 int bytes_remaining
= endofkext
- endofrelocInfo
;
4923 OSData
* new_osdata
= NULL
;
4925 /* fix up symbol offsets if they are after the dsymtab local relocs */
4927 if (dysymtab
->locreloff
< symtab
->symoff
){
4928 symtab
->symoff
-= reloc_size
;
4930 if (dysymtab
->locreloff
< symtab
->stroff
) {
4931 symtab
->stroff
-= reloc_size
;
4934 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
4935 dysymtab
->extreloff
-= reloc_size
;
4938 /* move data behind reloc info down to new offset */
4939 if (endofrelocInfo
< endofkext
) {
4940 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
4943 /* Create a new OSData for the smaller kext object and reflect
4944 * new linkedit segment size.
4946 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
4947 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
4949 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
4951 /* Fix up kmod info and linkedExecutable.
4953 kmod_info
->size
= new_kextsize
;
4955 new_osdata
->setDeallocFunction(osdata_kext_free
);
4957 new_osdata
->setDeallocFunction(osdata_phys_free
);
4959 linkedExecutable
->setDeallocFunction(NULL
);
4960 linkedExecutable
->release();
4961 linkedExecutable
= new_osdata
;
4964 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
4966 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
4970 dysymtab
->nlocrel
= 0;
4971 dysymtab
->locreloff
= 0;
4975 result
= kOSReturnSuccess
;
4980 /*********************************************************************
4981 * called only by load()
4982 *********************************************************************/
4984 OSKext::loadExecutable()
4986 OSReturn result
= kOSReturnError
;
4987 kern_return_t kxldResult
;
4988 KXLDDependency
* kxlddeps
= NULL
; // must kfree
4989 uint32_t num_kxlddeps
= 0;
4990 OSArray
* linkDependencies
= NULL
; // must release
4991 uint32_t numDirectDependencies
= 0;
4992 uint32_t num_kmod_refs
= 0;
4993 struct mach_header
** kxldHeaderPtr
= NULL
; // do not free
4994 struct mach_header
* kxld_header
= NULL
; // xxx - need to free here?
4995 OSData
* theExecutable
= NULL
; // do not release
4996 OSString
* versString
= NULL
; // do not release
4997 const char * versCString
= NULL
; // do not free
4998 const char * string
= NULL
; // do not free
5001 /* We need the version string for a variety of bits below.
5003 versString
= OSDynamicCast(OSString
,
5004 getPropertyForHostArch(kCFBundleVersionKey
));
5008 versCString
= versString
->getCStringNoCopy();
5010 if (isKernelComponent()) {
5011 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
5013 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
5015 kOSKextLogErrorLevel
|
5017 "Kernel component %s has incorrect version %s; "
5019 getIdentifierCString(),
5020 versCString
, KERNEL6_VERSION
);
5021 result
= kOSKextReturnInternalError
;
5023 } else if (strcmp(versCString
, osrelease
)) {
5025 kOSKextLogErrorLevel
|
5027 "Kernel component %s has incorrect version %s; "
5029 getIdentifierCString(),
5030 versCString
, osrelease
);
5031 result
= kOSKextReturnInternalError
;
5037 if (isPrelinked()) {
5041 /* <rdar://problem/21444003> all callers must be entitled */
5042 if (FALSE
== IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management")) {
5044 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5045 "Not entitled to link kext '%s'",
5046 getIdentifierCString());
5047 result
= kOSKextReturnNotPrivileged
;
5051 theExecutable
= getExecutable();
5052 if (!theExecutable
) {
5053 if (declaresExecutable()) {
5055 kOSKextLogErrorLevel
|
5057 "Can't load kext %s - executable is missing.",
5058 getIdentifierCString());
5059 result
= kOSKextReturnValidation
;
5065 if (isInterface()) {
5066 OSData
*executableCopy
= OSData::withData(theExecutable
);
5067 setLinkedExecutable(executableCopy
);
5068 executableCopy
->release();
5072 numDirectDependencies
= getNumDependencies();
5074 if (flags
.hasBleedthrough
) {
5075 linkDependencies
= dependencies
;
5076 linkDependencies
->retain();
5078 linkDependencies
= OSArray::withArray(dependencies
);
5079 if (!linkDependencies
) {
5081 kOSKextLogErrorLevel
|
5082 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5083 "Can't allocate link dependencies to load kext %s.",
5084 getIdentifierCString());
5088 for (i
= 0; i
< numDirectDependencies
; ++i
) {
5089 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
5090 dependencies
->getObject(i
));
5091 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
5095 num_kxlddeps
= linkDependencies
->getCount();
5096 if (!num_kxlddeps
) {
5098 kOSKextLogErrorLevel
|
5099 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
5100 "Can't load kext %s - it has no library dependencies.",
5101 getIdentifierCString());
5105 kxlddeps
= (KXLDDependency
*)kalloc_tag(num_kxlddeps
* sizeof(*kxlddeps
), VM_KERN_MEMORY_OSKEXT
);
5108 kOSKextLogErrorLevel
|
5109 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5110 "Can't allocate link context to load kext %s.",
5111 getIdentifierCString());
5114 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
5116 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5117 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
5119 if (dependency
->isInterface()) {
5120 OSKext
*interfaceTargetKext
= NULL
;
5121 OSData
* interfaceTarget
= NULL
;
5123 if (dependency
->isKernelComponent()) {
5124 interfaceTargetKext
= sKernelKext
;
5125 interfaceTarget
= sKernelKext
->linkedExecutable
;
5127 interfaceTargetKext
= OSDynamicCast(OSKext
,
5128 dependency
->dependencies
->getObject(0));
5130 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
5133 if (!interfaceTarget
) {
5138 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5139 * it will be useful to have them in the debugger.
5140 * strdup() failing isn't critical right here so we don't check that.
5142 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
5143 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
5144 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
5146 kxlddeps
[i
].interface
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5147 kxlddeps
[i
].interface_size
= dependency
->linkedExecutable
->getLength();
5148 kxlddeps
[i
].interface_name
= strdup(dependency
->getIdentifierCString());
5150 kxlddeps
[i
].kext
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5151 kxlddeps
[i
].kext_size
= dependency
->linkedExecutable
->getLength();
5152 kxlddeps
[i
].kext_name
= strdup(dependency
->getIdentifierCString());
5155 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
5158 kxldHeaderPtr
= &kxld_header
;
5162 kOSKextLogExplicitLevel
|
5163 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5164 "Kext %s - calling kxld_link_file:\n"
5165 " kxld_context: %p\n"
5166 " executable: %p executable_length: %d\n"
5168 " kxld_dependencies: %p num_dependencies: %d\n"
5169 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5170 getIdentifierCString(), sKxldContext
,
5171 theExecutable
->getBytesNoCopy(), theExecutable
->getLength(),
5172 this, kxlddeps
, num_kxlddeps
,
5173 kxldHeaderPtr
, &kmod_info
);
5176 /* After this call, the linkedExecutable instance variable
5179 kxldResult
= kxld_link_file(sKxldContext
,
5180 (u_char
*)theExecutable
->getBytesNoCopy(),
5181 theExecutable
->getLength(),
5182 getIdentifierCString(), this, kxlddeps
, num_kxlddeps
,
5183 (u_char
**)kxldHeaderPtr
, (kxld_addr_t
*)&kmod_info
);
5185 if (kxldResult
!= KERN_SUCCESS
) {
5186 // xxx - add kxldResult here?
5188 kOSKextLogErrorLevel
|
5190 "Can't load kext %s - link failed.",
5191 getIdentifierCString());
5192 result
= kOSKextReturnLinkError
;
5196 /* We've written data & instructions into kernel memory, so flush the data
5197 * cache and invalidate the instruction cache.
5198 * I/D caches are coherent on x86
5200 #if !defined(__i386__) && !defined(__x86_64__)
5201 flush_dcache(kmod_info
->address
, kmod_info
->size
, false);
5202 invalidate_icache(kmod_info
->address
, kmod_info
->size
, false);
5206 if (isInterface()) {
5208 /* Whip up a fake kmod_info entry for the interface kext.
5210 kmod_info
= (kmod_info_t
*)kalloc_tag(sizeof(kmod_info_t
), VM_KERN_MEMORY_OSKEXT
);
5212 result
= KERN_MEMORY_ERROR
;
5216 /* A pseudokext has almost nothing in its kmod_info struct.
5218 bzero(kmod_info
, sizeof(kmod_info_t
));
5220 kmod_info
->info_version
= KMOD_INFO_VERSION
;
5222 /* An interface kext doesn't have a linkedExecutable, so save a
5223 * copy of the UUID out of the original executable via copyUUID()
5224 * while we still have the original executable.
5226 interfaceUUID
= copyUUID();
5229 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5230 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5232 /* Stamp the bundle ID and version from the OSKext over anything
5233 * resident inside the kmod_info.
5235 string
= getIdentifierCString();
5236 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5238 string
= versCString
;
5239 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5241 /* Add the dependencies' kmod_info structs as kmod_references.
5243 num_kmod_refs
= getNumDependencies();
5244 if (num_kmod_refs
) {
5245 kmod_info
->reference_list
= (kmod_reference_t
*)kalloc_tag(
5246 num_kmod_refs
* sizeof(kmod_reference_t
), VM_KERN_MEMORY_OSKEXT
);
5247 if (!kmod_info
->reference_list
) {
5248 result
= KERN_MEMORY_ERROR
;
5251 bzero(kmod_info
->reference_list
,
5252 num_kmod_refs
* sizeof(kmod_reference_t
));
5253 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5254 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5255 OSKext
* refKext
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
));
5256 ref
->info
= refKext
->kmod_info
;
5257 ref
->info
->reference_count
++;
5259 if (refIndex
+ 1 < num_kmod_refs
) {
5260 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5265 if (!isInterface() && linkedExecutable
) {
5267 kOSKextLogProgressLevel
|
5269 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5271 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5272 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5273 (unsigned)kmod_info
->id
);
5276 /* if prelinked, VM protections are already set */
5277 result
= setVMAttributes(!isPrelinked(), true);
5278 if (result
!= KERN_SUCCESS
) {
5282 result
= kOSReturnSuccess
;
5285 OSSafeRelease(linkDependencies
);
5287 /* Clear up locally allocated dependency info.
5289 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5292 if (kxlddeps
[i
].kext_name
) {
5293 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5294 kfree(kxlddeps
[i
].kext_name
, size
);
5296 if (kxlddeps
[i
].interface_name
) {
5297 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5298 kfree(kxlddeps
[i
].interface_name
, size
);
5301 if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5303 /* We no longer need the unrelocated executable (which the linker
5304 * has altered anyhow).
5306 setExecutable(NULL
);
5308 if (result
!= kOSReturnSuccess
) {
5310 kOSKextLogErrorLevel
|
5312 "Failed to load executable for kext %s.",
5313 getIdentifierCString());
5315 if (kmod_info
&& kmod_info
->reference_list
) {
5316 kfree(kmod_info
->reference_list
,
5317 num_kmod_refs
* sizeof(kmod_reference_t
));
5319 if (isInterface()) {
5320 kfree(kmod_info
, sizeof(kmod_info_t
));
5323 if (linkedExecutable
) {
5324 linkedExecutable
->release();
5325 linkedExecutable
= NULL
;
5332 /*********************************************************************
5333 * The linkedit segment is used by the kext linker for dependency
5334 * resolution, and by dtrace for probe initialization. We can free it
5335 * for non-library kexts, since no kexts depend on non-library kexts
5336 * by definition, once dtrace has been initialized.
5337 *********************************************************************/
5339 OSKext::jettisonLinkeditSegment(void)
5341 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5342 kernel_segment_command_t
* linkedit
= NULL
;
5344 vm_size_t linkeditsize
, kextsize
;
5345 OSData
* data
= NULL
;
5348 /* We can free symbol tables for all embedded kexts because we don't
5349 * support runtime kext linking.
5351 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5353 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5358 /* Find the linkedit segment. If it's not the last segment, then freeing
5359 * it will fragment the kext into multiple VM regions, which OSKext is not
5360 * designed to handle, so we'll have to skip it.
5362 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5367 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5368 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
))
5373 /* Create a new OSData for the smaller kext object.
5375 linkeditsize
= round_page(linkedit
->vmsize
);
5376 kextsize
= kmod_info
->size
- linkeditsize
;
5377 start
= linkedit
->vmaddr
;
5379 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5384 /* Fix the kmod info and linkedExecutable.
5386 kmod_info
->size
= kextsize
;
5389 data
->setDeallocFunction(osdata_kext_free
);
5391 data
->setDeallocFunction(osdata_phys_free
);
5393 linkedExecutable
->setDeallocFunction(NULL
);
5394 linkedExecutable
->release();
5395 linkedExecutable
= data
;
5396 flags
.jettisonLinkeditSeg
= 1;
5398 /* Free the linkedit segment.
5401 kext_free(start
, linkeditsize
);
5403 ml_static_mfree(start
, linkeditsize
);
5410 /*********************************************************************
5411 * If there are whole pages that are unused betweem the last section
5412 * of the DATA segment and the end of the DATA segment then we can free
5414 *********************************************************************/
5416 OSKext::jettisonDATASegmentPadding(void)
5418 kernel_mach_header_t
* mh
;
5419 kernel_segment_command_t
* dataSeg
;
5420 kernel_section_t
* sec
, * lastSec
;
5421 vm_offset_t dataSegEnd
, lastSecEnd
;
5424 mh
= (kernel_mach_header_t
*)kmod_info
->address
;
5426 dataSeg
= getsegbynamefromheader(mh
, SEG_DATA
);
5427 if (dataSeg
== NULL
) {
5432 sec
= firstsect(dataSeg
);
5433 while (sec
!= NULL
) {
5435 sec
= nextsect(dataSeg
, sec
);
5438 if (lastSec
== NULL
) {
5442 if ((dataSeg
->vmaddr
!= round_page(dataSeg
->vmaddr
)) ||
5443 (dataSeg
->vmsize
!= round_page(dataSeg
->vmsize
))) {
5447 dataSegEnd
= dataSeg
->vmaddr
+ dataSeg
->vmsize
;
5448 lastSecEnd
= round_page(lastSec
->addr
+ lastSec
->size
);
5450 if (dataSegEnd
<= lastSecEnd
) {
5454 padSize
= dataSegEnd
- lastSecEnd
;
5456 if (padSize
>= PAGE_SIZE
) {
5458 kext_free(lastSecEnd
, padSize
);
5460 ml_static_mfree(lastSecEnd
, padSize
);
5465 /*********************************************************************
5466 *********************************************************************/
5468 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5470 if (linkedExecutable
) {
5471 panic("Attempt to set linked executable on kext "
5472 "that already has one (%s).\n",
5473 getIdentifierCString());
5475 linkedExecutable
= anExecutable
;
5476 linkedExecutable
->retain();
5481 /*********************************************************************
5482 * Go through all loaded kexts and tell them to register with dtrace.
5483 * The instance method only registers if necessary.
5484 *********************************************************************/
5487 OSKext::registerKextsWithDTrace(void)
5489 uint32_t count
= sLoadedKexts
->getCount();
5492 IORecursiveLockLock(sKextLock
);
5494 for (i
= 0; i
< count
; i
++) {
5495 OSKext
* thisKext
= NULL
; // do not release
5497 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5498 if (!thisKext
|| !thisKext
->isExecutable()) {
5502 thisKext
->registerWithDTrace();
5505 IORecursiveLockUnlock(sKextLock
);
5511 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5512 extern int (*dtrace_modunload
)(struct kmod_info
*);
5515 /*********************************************************************
5516 *********************************************************************/
5518 OSKext::registerWithDTrace(void)
5520 /* Register kext with dtrace. A dtrace_modload failure should not
5521 * prevent a kext from loading, so we ignore the return code.
5523 if (!flags
.dtraceInitialized
&& (dtrace_modload
!= NULL
)) {
5524 uint32_t modflag
= 0;
5525 OSObject
* forceInit
= getPropertyForHostArch("OSBundleForceDTraceInit");
5526 if (forceInit
== kOSBooleanTrue
) {
5527 modflag
|= KMOD_DTRACE_FORCE_INIT
;
5530 (void)(*dtrace_modload
)(kmod_info
, modflag
);
5531 flags
.dtraceInitialized
= true;
5532 jettisonLinkeditSegment();
5536 /*********************************************************************
5537 *********************************************************************/
5539 OSKext::unregisterWithDTrace(void)
5541 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5542 * prevent a kext from loading, so we ignore the return code.
5544 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
5545 (void)(*dtrace_modunload
)(kmod_info
);
5546 flags
.dtraceInitialized
= false;
5550 #endif /* CONFIG_DTRACE */
5553 /*********************************************************************
5554 * called only by loadExecutable()
5555 *********************************************************************/
5556 #if !VM_MAPPED_KEXTS
5557 #error Unrecognized architecture
5559 static inline kern_return_t
5562 vm_map_offset_t start
,
5563 vm_map_offset_t end
,
5567 if (start
== end
) { // 10538581
5568 return(KERN_SUCCESS
);
5570 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
5573 static inline kern_return_t
5576 vm_map_offset_t start
,
5577 vm_map_offset_t end
,
5578 vm_prot_t access_type
,
5579 boolean_t user_wire
)
5581 return vm_map_wire(map
, start
, end
, access_type
| VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_KEXT
), user_wire
);
5586 OSKext::setVMAttributes(bool protect
, bool wire
)
5588 vm_map_t kext_map
= NULL
;
5589 kernel_segment_command_t
* seg
= NULL
;
5590 vm_map_offset_t start
= 0;
5591 vm_map_offset_t end
= 0;
5592 OSReturn result
= kOSReturnError
;
5594 if (isInterface() || !declaresExecutable()) {
5595 result
= kOSReturnSuccess
;
5599 /* Get the kext's vm map */
5600 kext_map
= kext_get_vm_map(kmod_info
);
5602 result
= KERN_MEMORY_ERROR
;
5606 /* Protect the headers as read-only; they do not need to be wired */
5607 result
= (protect
) ? OSKext_protect(kext_map
, kmod_info
->address
,
5608 kmod_info
->address
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
)
5610 if (result
!= KERN_SUCCESS
) {
5614 /* Set the VM protections and wire down each of the segments */
5615 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5619 start
= round_page(seg
->vmaddr
);
5620 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
5623 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
5624 if (result
!= KERN_SUCCESS
) {
5626 kOSKextLogErrorLevel
|
5628 "Kext %s failed to set maximum VM protections "
5629 "for segment %s - 0x%x.",
5630 getIdentifierCString(), seg
->segname
, (int)result
);
5634 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5635 if (result
!= KERN_SUCCESS
) {
5637 kOSKextLogErrorLevel
|
5639 "Kext %s failed to set initial VM protections "
5640 "for segment %s - 0x%x.",
5641 getIdentifierCString(), seg
->segname
, (int)result
);
5646 if (segmentShouldBeWired(seg
) && wire
) {
5647 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5648 if (result
!= KERN_SUCCESS
) {
5653 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5660 /*********************************************************************
5661 *********************************************************************/
5663 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
5665 return (sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
)));
5668 /*********************************************************************
5669 *********************************************************************/
5671 OSKext::validateKextMapping(bool startFlag
)
5673 OSReturn result
= kOSReturnError
;
5674 const char * whichOp
= startFlag
? "start" : "stop";
5675 kern_return_t kern_result
= 0;
5676 vm_map_t kext_map
= NULL
;
5677 kernel_segment_command_t
* seg
= NULL
;
5678 mach_vm_address_t address
= 0;
5679 mach_vm_size_t size
= 0;
5681 mach_msg_type_number_t count
;
5682 vm_region_submap_short_info_data_64_t info
;
5684 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
5685 bzero(&info
, sizeof(info
));
5687 // xxx - do we need a distinct OSReturn value for these or is "bad data"
5688 // xxx - sufficient?
5690 /* Verify that the kmod_info and start/stop pointers are non-NULL.
5694 kOSKextLogErrorLevel
|
5696 "Kext %s - NULL kmod_info pointer.",
5697 getIdentifierCString());
5698 result
= kOSKextReturnBadData
;
5703 address
= (mach_vm_address_t
)kmod_info
->start
;
5705 address
= (mach_vm_address_t
)kmod_info
->stop
;
5710 kOSKextLogErrorLevel
|
5712 "Kext %s - NULL module %s pointer.",
5713 getIdentifierCString(), whichOp
);
5714 result
= kOSKextReturnBadData
;
5718 kext_map
= kext_get_vm_map(kmod_info
);
5719 depth
= (kernel_map
== kext_map
) ? 1 : 2;
5721 /* Verify that the start/stop function lies within the kext's address range.
5723 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
5724 kmod_info
->address
+ kmod_info
->size
<= address
)
5727 kOSKextLogErrorLevel
|
5729 "Kext %s module %s pointer is outside of kext range "
5730 "(%s %p - kext at %p-%p)..",
5731 getIdentifierCString(),
5734 (void *)VM_KERNEL_UNSLIDE(address
),
5735 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5736 (void *)(VM_KERNEL_UNSLIDE(kmod_info
->address
) + kmod_info
->size
));
5737 result
= kOSKextReturnBadData
;
5741 /* Only do these checks before calling the start function;
5742 * If anything goes wrong with the mapping while the kext is running,
5743 * we'll likely have panicked well before any attempt to stop the kext.
5747 /* Verify that the start/stop function is executable.
5749 kern_result
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
,
5750 (vm_region_recurse_info_t
)&info
, &count
);
5751 if (kern_result
!= KERN_SUCCESS
) {
5753 kOSKextLogErrorLevel
|
5755 "Kext %s - bad %s pointer %p.",
5756 getIdentifierCString(),
5757 whichOp
, (void *)VM_KERNEL_UNSLIDE(address
));
5758 result
= kOSKextReturnBadData
;
5763 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
5765 kOSKextLogErrorLevel
|
5767 "Kext %s - memory region containing module %s function "
5768 "is not executable.",
5769 getIdentifierCString(), whichOp
);
5770 result
= kOSKextReturnBadData
;
5775 /* Verify that the kext's segments are backed by physical memory.
5777 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5779 if (!verifySegmentMapping(seg
)) {
5780 result
= kOSKextReturnBadData
;
5784 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5789 result
= kOSReturnSuccess
;
5794 /*********************************************************************
5795 *********************************************************************/
5797 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
5799 mach_vm_address_t address
= 0;
5801 if (!segmentShouldBeWired(seg
)) return true;
5803 for (address
= seg
->vmaddr
;
5804 address
< round_page(seg
->vmaddr
+ seg
->vmsize
);
5805 address
+= PAGE_SIZE
)
5807 if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) {
5809 kOSKextLogErrorLevel
|
5811 "Kext %s - page %p is not backed by physical memory.",
5812 getIdentifierCString(),
5821 /*********************************************************************
5822 *********************************************************************/
5824 OSKext::start(bool startDependenciesFlag
)
5826 OSReturn result
= kOSReturnError
;
5827 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
5828 unsigned int i
, count
;
5829 void * kmodStartData
= NULL
;
5831 if (isStarted() || isInterface() || isKernelComponent()) {
5832 result
= kOSReturnSuccess
;
5838 kOSKextLogErrorLevel
|
5840 "Attempt to start nonloaded kext %s.",
5841 getIdentifierCString());
5842 result
= kOSKextReturnInvalidArgument
;
5846 if (!sLoadEnabled
) {
5848 kOSKextLogErrorLevel
|
5850 "Kext loading is disabled (attempt to start kext %s).",
5851 getIdentifierCString());
5852 result
= kOSKextReturnDisabled
;
5856 result
= validateKextMapping(/* start? */ true);
5857 if (result
!= kOSReturnSuccess
) {
5861 startfunc
= kmod_info
->start
;
5863 count
= getNumDependencies();
5864 for (i
= 0; i
< count
; i
++) {
5865 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
5866 if (dependency
== NULL
) {
5868 kOSKextLogErrorLevel
|
5870 "Kext %s start - internal error, dependency disappeared.",
5871 getIdentifierCString());
5874 if (!dependency
->isStarted()) {
5875 if (startDependenciesFlag
) {
5876 OSReturn dependencyResult
=
5877 dependency
->start(startDependenciesFlag
);
5878 if (dependencyResult
!= KERN_SUCCESS
) {
5880 kOSKextLogErrorLevel
|
5882 "Kext %s start - dependency %s failed to start (error 0x%x).",
5883 getIdentifierCString(),
5884 dependency
->getIdentifierCString(),
5890 kOSKextLogErrorLevel
|
5892 "Not starting %s - dependency %s not started yet.",
5893 getIdentifierCString(),
5894 dependency
->getIdentifierCString());
5895 result
= kOSKextReturnStartStopError
; // xxx - make new return?
5902 kOSKextLogDetailLevel
|
5904 "Kext %s calling module start function.",
5905 getIdentifierCString());
5909 #if !CONFIG_STATIC_CPPINIT
5910 result
= OSRuntimeInitializeCPP(kmod_info
, NULL
);
5911 if (result
== KERN_SUCCESS
) {
5915 kmodStartData
= GetAppleTEXTHashForKext(this, this->infoDict
);
5918 if (kmodStartData
) {
5920 kOSKextLogErrorLevel
|
5921 kOSKextLogGeneralFlag
,
5922 "Kext %s calling module start function. kmodStartData %p. arch %s",
5923 getIdentifierCString(), kmodStartData
, ARCHNAME
);
5926 #endif // CONFIG_KEC_FIPS
5928 result
= startfunc(kmod_info
, kmodStartData
);
5930 #if !CONFIG_STATIC_CPPINIT
5931 if (result
!= KERN_SUCCESS
) {
5932 (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
);
5939 /* On success overlap the setting of started/starting. On failure just
5942 if (result
== KERN_SUCCESS
) {
5945 // xxx - log start error from kernel?
5947 kOSKextLogProgressLevel
|
5949 "Kext %s is now started.",
5950 getIdentifierCString());
5952 invokeOrCancelRequestCallbacks(
5953 /* result not actually used */ kOSKextReturnStartStopError
,
5954 /* invokeFlag */ false);
5956 kOSKextLogProgressLevel
|
5958 "Kext %s did not start (return code 0x%x).",
5959 getIdentifierCString(), result
);
5966 /*********************************************************************
5967 *********************************************************************/
5969 bool OSKext::canUnloadKextWithIdentifier(
5970 OSString
* kextIdentifier
,
5971 bool checkClassesFlag
)
5973 bool result
= false;
5974 OSKext
* aKext
= NULL
; // do not release
5976 IORecursiveLockLock(sKextLock
);
5978 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
5981 goto finish
; // can't unload what's not loaded
5984 if (aKext
->isLoaded()) {
5985 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
5988 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
5996 IORecursiveLockUnlock(sKextLock
);
6000 /*********************************************************************
6001 *********************************************************************/
6005 OSReturn result
= kOSReturnError
;
6006 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
6008 if (!isStarted() || isInterface()) {
6009 result
= kOSReturnSuccess
;
6015 kOSKextLogErrorLevel
|
6017 "Attempt to stop nonloaded kext %s.",
6018 getIdentifierCString());
6019 result
= kOSKextReturnInvalidArgument
;
6023 /* Refuse to stop if we have clients or instances. It is up to
6024 * the caller to make sure those aren't true.
6026 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6028 kOSKextLogErrorLevel
|
6030 "Kext %s - C++ instances; can't stop.",
6031 getIdentifierCString());
6032 result
= kOSKextReturnInUse
;
6036 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6039 kOSKextLogErrorLevel
|
6041 "Kext %s - has references (linkage or tracking object); "
6043 getIdentifierCString());
6044 result
= kOSKextReturnInUse
;
6048 /* Note: If validateKextMapping fails on the stop & unload path,
6049 * we are in serious trouble and a kernel panic is likely whether
6050 * we stop & unload the kext or not.
6052 result
= validateKextMapping(/* start? */ false);
6053 if (result
!= kOSReturnSuccess
) {
6057 stopfunc
= kmod_info
->stop
;
6060 kOSKextLogDetailLevel
|
6062 "Kext %s calling module stop function.",
6063 getIdentifierCString());
6067 result
= stopfunc(kmod_info
, /* userData */ NULL
);
6068 #if !CONFIG_STATIC_CPPINIT
6069 if (result
== KERN_SUCCESS
) {
6070 result
= OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6076 if (result
== KERN_SUCCESS
) {
6080 kOSKextLogDetailLevel
|
6082 "Kext %s is now stopped and ready to unload.",
6083 getIdentifierCString());
6086 kOSKextLogErrorLevel
|
6088 "Kext %s did not stop (return code 0x%x).",
6089 getIdentifierCString(), result
);
6090 result
= kOSKextReturnStartStopError
;
6098 /*********************************************************************
6099 *********************************************************************/
6101 OSKext::unload(void)
6103 OSReturn result
= kOSReturnError
;
6105 uint32_t num_kmod_refs
= 0;
6106 OSKextAccount
* freeAccount
;
6108 if (!sUnloadEnabled
) {
6110 kOSKextLogErrorLevel
|
6112 "Kext unloading is disabled (%s).",
6113 this->getIdentifierCString());
6115 result
= kOSKextReturnDisabled
;
6119 /* Refuse to unload if we have clients or instances. It is up to
6120 * the caller to make sure those aren't true.
6122 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6123 // xxx - Don't log under errors? this is more of an info thing
6125 kOSKextLogErrorLevel
|
6126 kOSKextLogKextBookkeepingFlag
,
6127 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6128 getIdentifierCString());
6129 result
= kOSKextReturnInUse
;
6133 if (hasOSMetaClassInstances()) {
6135 kOSKextLogErrorLevel
|
6136 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6137 "Can't unload kext %s; classes have instances:",
6138 getIdentifierCString());
6139 reportOSMetaClassInstances(kOSKextLogErrorLevel
|
6140 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
);
6141 result
= kOSKextReturnInUse
;
6146 result
= kOSReturnSuccess
;
6150 if (isKernelComponent()) {
6151 result
= kOSKextReturnInvalidArgument
;
6155 /* Note that the kext is unloading before running any code that
6156 * might be in the kext (request callbacks, module stop function).
6157 * We will deny certain requests made against a kext in the process
6160 flags
.unloading
= 1;
6162 /* Update the string describing the last kext to unload in case we panic.
6164 savePanicString(/* isLoading */ false);
6168 if (result
!= KERN_SUCCESS
) {
6170 kOSKextLogErrorLevel
|
6172 "Kext %s can't unload - module stop returned 0x%x.",
6173 getIdentifierCString(), (unsigned)result
);
6174 result
= kOSKextReturnStartStopError
;
6180 kOSKextLogProgressLevel
|
6182 "Kext %s unloading.",
6183 getIdentifierCString());
6186 struct list_head
*p
;
6187 struct list_head
*prev
;
6188 struct list_head
*next
;
6189 for (p
= pendingPgoHead
.next
; p
!= &pendingPgoHead
; p
= next
) {
6190 OSKextGrabPgoStruct
*s
= container_of(p
, OSKextGrabPgoStruct
, list_head
);
6191 s
->err
= OSKextGrabPgoDataLocked(this, s
->metadata
, instance_uuid
, s
->pSize
, s
->pBuffer
, s
->bufferSize
);
6198 IORecursiveLockWakeup(sKextLock
, s
, false);
6203 /* Even if we don't call the stop function, we want to be sure we
6204 * have no OSMetaClass references before unloading the kext executable
6205 * from memory. OSMetaClasses may have pointers into the kext executable
6206 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6209 metaClasses
->flushCollection();
6212 /* Remove the kext from the list of loaded kexts, patch the gap
6213 * in the kmod_info_t linked list, and reset "kmod" to point to the
6214 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6216 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
6217 if (index
!= (unsigned int)-1) {
6219 sLoadedKexts
->removeObject(index
);
6221 OSKext
* nextKext
= OSDynamicCast(OSKext
,
6222 sLoadedKexts
->getObject(index
));
6226 OSKext
* gapKext
= OSDynamicCast(OSKext
,
6227 sLoadedKexts
->getObject(index
- 1));
6229 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
6231 } else /* index == 0 */ {
6232 nextKext
->kmod_info
->next
= NULL
;
6236 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
6237 if (lastKext
&& !lastKext
->isKernel()) {
6238 kmod
= lastKext
->kmod_info
;
6240 kmod
= NULL
; // clear the global kmod variable
6244 /* Clear out the kmod references that we're keeping for compatibility
6245 * with current panic backtrace code & kgmacros.
6246 * xxx - will want to update those bits sometime and remove this.
6248 num_kmod_refs
= getNumDependencies();
6249 if (num_kmod_refs
&& kmod_info
&& kmod_info
->reference_list
) {
6250 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
6251 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
6252 ref
->info
->reference_count
--;
6254 kfree(kmod_info
->reference_list
,
6255 num_kmod_refs
* sizeof(kmod_reference_t
));
6259 unregisterWithDTrace();
6260 #endif /* CONFIG_DTRACE */
6262 notifyKextUnloadObservers(this);
6265 IOSimpleLockLock(sKextAccountsLock
);
6266 if (account
->site
.tag
) account
->site
.flags
|= VM_TAG_UNLOAD
;
6267 else freeAccount
= account
;
6268 IOSimpleLockUnlock(sKextAccountsLock
);
6269 if (freeAccount
) IODelete(freeAccount
, OSKextAccount
, 1);
6271 /* Unwire and free the linked executable.
6273 if (linkedExecutable
) {
6275 if (!isInterface()) {
6276 kernel_segment_command_t
*seg
= NULL
;
6277 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6281 kOSKextLogErrorLevel
|
6283 "Failed to free kext %s; couldn't find the kext map.",
6284 getIdentifierCString());
6285 result
= kOSKextReturnInternalError
;
6290 kOSKextLogProgressLevel
|
6292 "Kext %s unwiring and unmapping linked executable.",
6293 getIdentifierCString());
6295 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6297 if (segmentShouldBeWired(seg
)) {
6298 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6299 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6300 if (result
!= KERN_SUCCESS
) {
6302 kOSKextLogErrorLevel
|
6304 "Failed to unwire kext %s.",
6305 getIdentifierCString());
6306 result
= kOSKextReturnInternalError
;
6311 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6315 OSSafeReleaseNULL(linkedExecutable
);
6318 /* An interface kext has a fake kmod_info that was allocated,
6319 * so we have to free it.
6321 if (isInterface()) {
6322 kfree(kmod_info
, sizeof(kmod_info_t
));
6327 flags
.loaded
= false;
6328 flushDependencies();
6330 /* save a copy of the bundle ID for us to check when deciding to
6331 * rebuild the kernel cache file. If a kext was already in the kernel
6332 * cache and unloaded then later loaded we do not need to rebuild the
6333 * kernel cache. 9055303
6335 if (isPrelinked()) {
6336 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6337 IORecursiveLockLock(sKextLock
);
6338 if (sUnloadedPrelinkedKexts
) {
6339 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6341 IORecursiveLockUnlock(sKextLock
);
6346 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6347 "Kext %s unloaded.", getIdentifierCString());
6349 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6350 OSDynamicCast(OSString
, bundleID
));
6353 OSKext::saveLoadedKextPanicList();
6354 OSKext::updateLoadedKextSummaries();
6356 flags
.unloading
= 0;
6360 /*********************************************************************
6361 * Assumes sKextLock is held.
6362 *********************************************************************/
6365 OSKext::queueKextNotification(
6366 const char * notificationName
,
6367 OSString
* kextIdentifier
)
6369 OSReturn result
= kOSReturnError
;
6370 OSDictionary
* loadRequest
= NULL
; // must release
6372 if (!kextIdentifier
) {
6373 result
= kOSKextReturnInvalidArgument
;
6377 /* Create a new request unless one is already sitting
6378 * in sKernelRequests for this bundle identifier
6380 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6381 if (result
!= kOSReturnSuccess
) {
6384 if (!_OSKextSetRequestArgument(loadRequest
,
6385 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6387 result
= kOSKextReturnNoMemory
;
6390 if (!sKernelRequests
->setObject(loadRequest
)) {
6391 result
= kOSKextReturnNoMemory
;
6395 /* We might want to only queue the notification if kextd is active,
6396 * but that wouldn't work for embedded. Note that we don't care if
6397 * the ping immediately succeeds here so don't do anything with the
6398 * result of this call.
6400 OSKext::pingKextd();
6402 result
= kOSReturnSuccess
;
6405 OSSafeRelease(loadRequest
);
6410 /*********************************************************************
6411 *********************************************************************/
6413 _OSKextConsiderDestroyingLinkContext(
6414 __unused thread_call_param_t p0
,
6415 __unused thread_call_param_t p1
)
6417 /* Take multiple locks in the correct order.
6419 IORecursiveLockLock(sKextLock
);
6420 IORecursiveLockLock(sKextInnerLock
);
6422 /* The first time we destroy the kxldContext is in the first
6423 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6424 * before calling this function. Thereafter any call to this function
6425 * will actually destroy the context.
6427 if (sConsiderUnloadsCalled
&& sKxldContext
) {
6428 kxld_destroy_context(sKxldContext
);
6429 sKxldContext
= NULL
;
6432 /* Free the thread_call that was allocated to execute this function.
6434 if (sDestroyLinkContextThread
) {
6435 if (!thread_call_free(sDestroyLinkContextThread
)) {
6436 OSKextLog(/* kext */ NULL
,
6437 kOSKextLogErrorLevel
|
6438 kOSKextLogGeneralFlag
,
6439 "thread_call_free() failed for kext link context.");
6441 sDestroyLinkContextThread
= 0;
6444 IORecursiveLockUnlock(sKextInnerLock
);
6445 IORecursiveLockUnlock(sKextLock
);
6450 /*********************************************************************
6451 * Destroying the kxldContext requires checking variables under both
6452 * sKextInnerLock and sKextLock, so we do it on a separate thread
6453 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6454 * call relationship.
6456 * This function must be invoked with sKextInnerLock held.
6457 * Do not call any function that takes sKextLock here!
6458 *********************************************************************/
6461 OSKext::considerDestroyingLinkContext(void)
6463 IORecursiveLockLock(sKextInnerLock
);
6465 /* If we have already queued a thread to destroy the link context,
6466 * don't bother resetting; that thread will take care of it.
6468 if (sDestroyLinkContextThread
) {
6472 /* The function to be invoked in the thread will deallocate
6473 * this thread_call, so don't share it around.
6475 sDestroyLinkContextThread
= thread_call_allocate(
6476 &_OSKextConsiderDestroyingLinkContext
, 0);
6477 if (!sDestroyLinkContextThread
) {
6478 OSKextLog(/* kext */ NULL
,
6479 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
| kOSKextLogLinkFlag
,
6480 "Can't create thread to destroy kext link context.");
6484 thread_call_enter(sDestroyLinkContextThread
);
6487 IORecursiveLockUnlock(sKextInnerLock
);
6492 #pragma mark Autounload
6494 /*********************************************************************
6495 * This is a static method because the kext will be deallocated if it
6497 *********************************************************************/
6500 OSKext::autounloadKext(OSKext
* aKext
)
6502 OSReturn result
= kOSKextReturnInUse
;
6504 /* Check for external references to this kext (usu. dependents),
6505 * instances of defined classes (or classes derived from them),
6506 * outstanding requests.
6508 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
6509 !aKext
->flags
.autounloadEnabled
||
6510 aKext
->isKernelComponent()) {
6515 /* Skip a delay-autounload kext, once.
6517 if (aKext
->flags
.delayAutounload
) {
6519 kOSKextLogProgressLevel
|
6520 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6521 "Kext %s has delayed autounload set; skipping and clearing flag.",
6522 aKext
->getIdentifierCString());
6523 aKext
->flags
.delayAutounload
= 0;
6527 if (aKext
->hasOSMetaClassInstances() ||
6528 aKext
->countRequestCallbacks()) {
6532 result
= OSKext::removeKext(aKext
);
6538 /*********************************************************************
6539 *********************************************************************/
6541 _OSKextConsiderUnloads(
6542 __unused thread_call_param_t p0
,
6543 __unused thread_call_param_t p1
)
6545 bool didUnload
= false;
6546 unsigned int count
, i
;
6548 /* Take multiple locks in the correct order
6549 * (note also sKextSummaries lock further down).
6551 IORecursiveLockLock(sKextLock
);
6552 IORecursiveLockLock(sKextInnerLock
);
6554 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6556 /* If the system is powering down, don't try to unload anything.
6562 OSKextLog(/* kext */ NULL
,
6563 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6564 "Checking for unused kexts to autounload.");
6567 * Remove any request callbacks marked as stale,
6568 * and mark as stale any currently in flight.
6570 count
= sRequestCallbackRecords
->getCount();
6574 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
6575 sRequestCallbackRecords
->getObject(i
));
6576 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
6577 callbackRecord
->getObject(kKextRequestStaleKey
));
6579 if (stale
== kOSBooleanTrue
) {
6580 OSKext::invokeRequestCallback(callbackRecord
,
6581 kOSKextReturnTimeout
);
6583 callbackRecord
->setObject(kKextRequestStaleKey
,
6590 * Make multiple passes through the array of loaded kexts until
6591 * we don't unload any. This handles unwinding of dependency
6592 * chains. We have to go *backwards* through the array because
6593 * kexts are removed from it when unloaded, and we cannot make
6594 * a copy or we'll mess up the retain counts we rely on to
6595 * check whether a kext will unload. If only we could have
6596 * nonretaining collections like CF has....
6601 count
= sLoadedKexts
->getCount();
6605 OSKext
* thisKext
= OSDynamicCast(OSKext
,
6606 sLoadedKexts
->getObject(i
));
6607 didUnload
|= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
6610 } while (didUnload
);
6613 sConsiderUnloadsPending
= false;
6614 sConsiderUnloadsExecuted
= true;
6616 (void) OSKext::considerRebuildOfPrelinkedKernel();
6618 IORecursiveLockUnlock(sKextInnerLock
);
6619 IORecursiveLockUnlock(sKextLock
);
6624 /*********************************************************************
6625 * Do not call any function that takes sKextLock here!
6626 *********************************************************************/
6627 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
6631 IORecursiveLockLock(sKextInnerLock
);
6633 if (!sUnloadCallout
) {
6634 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, 0);
6637 /* we only reset delay value for unloading if we already have something
6638 * pending. rescheduleOnlyFlag should not start the count down.
6640 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
6644 thread_call_cancel(sUnloadCallout
);
6645 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
6646 clock_interval_to_deadline(sConsiderUnloadDelay
,
6647 1000 * 1000 * 1000, &when
);
6649 OSKextLog(/* kext */ NULL
,
6650 kOSKextLogProgressLevel
|
6652 "%scheduling %sscan for unused kexts in %lu seconds.",
6653 sConsiderUnloadsPending
? "Res" : "S",
6654 sConsiderUnloadsCalled
? "" : "initial ",
6655 (unsigned long)sConsiderUnloadDelay
);
6657 sConsiderUnloadsPending
= true;
6658 thread_call_enter_delayed(sUnloadCallout
, when
);
6662 /* The kxld context should be reused throughout boot. We mark the end of
6663 * period as the first time considerUnloads() is called, and we destroy
6664 * the first kxld context in that function. Afterwards, it will be
6665 * destroyed in flushNonloadedKexts.
6667 if (!sConsiderUnloadsCalled
) {
6668 sConsiderUnloadsCalled
= true;
6669 OSKext::considerDestroyingLinkContext();
6672 IORecursiveLockUnlock(sKextInnerLock
);
6676 /*********************************************************************
6677 * Do not call any function that takes sKextLock here!
6678 *********************************************************************/
6681 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
)
6683 IORecursiveLockLock(sKextInnerLock
);
6685 /* If the system is going to sleep, cancel the reaper thread timer,
6686 * and note that we're in a sleep state in case it just fired but hasn't
6687 * taken the lock yet. If we are coming back from sleep, just
6688 * clear the sleep flag; IOService's normal operation will cause
6689 * unloads to be considered soon enough.
6691 if (messageType
== kIOMessageSystemWillSleep
) {
6692 if (sUnloadCallout
) {
6693 thread_call_cancel(sUnloadCallout
);
6695 sSystemSleep
= true;
6696 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
6697 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
6698 sSystemSleep
= false;
6699 clock_get_uptime(&sLastWakeTime
);
6701 IORecursiveLockUnlock(sKextInnerLock
);
6703 return kIOReturnSuccess
;
6710 #pragma mark Prelinked Kernel
6712 /*********************************************************************
6713 * Do not access sConsiderUnloads... variables other than
6714 * sConsiderUnloadsExecuted in this function. They are guarded by a
6716 *********************************************************************/
6719 OSKext::considerRebuildOfPrelinkedKernel(void)
6721 static bool requestedPrelink
= false;
6722 OSReturn checkResult
= kOSReturnError
;
6723 OSDictionary
* prelinkRequest
= NULL
; // must release
6724 OSCollectionIterator
* kextIterator
= NULL
; // must release
6725 const OSSymbol
* thisID
= NULL
; // do not release
6726 bool doRebuild
= false;
6727 AbsoluteTime my_abstime
;
6731 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
6732 if (requestedPrelink
|| !sPrelinkBoot
) {
6736 /* no direct return from this point */
6737 IORecursiveLockLock(sKextLock
);
6739 /* We need to wait for kextd to get up and running with unloads already done
6740 * and any new startup kexts loaded.
6742 if (!sConsiderUnloadsExecuted
||
6743 !sDeferredLoadSucceeded
) {
6747 /* we really only care about boot / system start up related kexts so bail
6748 * if we're here after REBUILD_MAX_TIME.
6750 if (!_OSKextInPrelinkRebuildWindow()) {
6751 OSKextLog(/* kext */ NULL
,
6752 kOSKextLogArchiveFlag
,
6753 "%s prebuild rebuild has expired",
6755 requestedPrelink
= true;
6759 /* we do not want to trigger a rebuild if we get here too close to waking
6760 * up. (see radar 10233768)
6762 IORecursiveLockLock(sKextInnerLock
);
6764 clock_get_uptime(&my_abstime
);
6765 delta_secs
= MINIMUM_WAKEUP_SECONDS
+ 1;
6766 if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) {
6767 SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
);
6768 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
6769 delta_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
6771 IORecursiveLockUnlock(sKextInnerLock
);
6773 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
6774 /* too close to time of last wake from sleep */
6777 requestedPrelink
= true;
6779 /* Now it's time to see if we have a reason to rebuild. We may have done
6780 * some loads and unloads but the kernel cache didn't actually change.
6781 * We will rebuild if any kext is not marked prelinked AND is not in our
6782 * list of prelinked kexts that got unloaded. (see radar 9055303)
6784 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
6785 if (!kextIterator
) {
6789 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
6790 OSKext
* thisKext
; // do not release
6792 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
6793 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
6797 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
6800 /* kext is loaded and was not in current kernel cache so let's rebuild
6803 OSKextLog(/* kext */ NULL
,
6804 kOSKextLogArchiveFlag
,
6805 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
6806 thisKext
->bundleID
->getCStringNoCopy());
6809 sUnloadedPrelinkedKexts
->flushCollection();
6815 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
6817 if (checkResult
!= kOSReturnSuccess
) {
6821 if (!sKernelRequests
->setObject(prelinkRequest
)) {
6825 OSKext::pingKextd();
6828 IORecursiveLockUnlock(sKextLock
);
6829 OSSafeRelease(prelinkRequest
);
6830 OSSafeRelease(kextIterator
);
6836 #pragma mark Dependencies
6838 /*********************************************************************
6839 *********************************************************************/
6841 OSKext::resolveDependencies(
6842 OSArray
* loopStack
)
6844 bool result
= false;
6845 OSArray
* localLoopStack
= NULL
; // must release
6846 bool addedToLoopStack
= false;
6847 OSDictionary
* libraries
= NULL
; // do not release
6848 OSCollectionIterator
* libraryIterator
= NULL
; // must release
6849 OSString
* libraryID
= NULL
; // do not release
6850 OSString
* infoString
= NULL
; // do not release
6851 OSString
* readableString
= NULL
; // do not release
6852 OSKext
* libraryKext
= NULL
; // do not release
6853 bool hasRawKernelDependency
= false;
6854 bool hasKernelDependency
= false;
6855 bool hasKPIDependency
= false;
6856 bool hasPrivateKPIDependency
= false;
6859 /* A kernel component will automatically have this flag set,
6860 * and a loaded kext should also have it set (as should all its
6861 * loaded dependencies).
6863 if (flags
.hasAllDependencies
) {
6868 /* Check for loops in the dependency graph.
6871 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
6873 kOSKextLogErrorLevel
|
6874 kOSKextLogDependenciesFlag
,
6875 "Kext %s has a dependency loop; can't resolve dependencies.",
6876 getIdentifierCString());
6881 kOSKextLogStepLevel
|
6882 kOSKextLogDependenciesFlag
,
6883 "Kext %s resolving dependencies.",
6884 getIdentifierCString());
6886 loopStack
= OSArray::withCapacity(6); // any small capacity will do
6889 kOSKextLogErrorLevel
|
6890 kOSKextLogDependenciesFlag
,
6891 "Kext %s can't create bookkeeping stack to resolve dependencies.",
6892 getIdentifierCString());
6895 localLoopStack
= loopStack
;
6897 if (!loopStack
->setObject(this)) {
6899 kOSKextLogErrorLevel
|
6900 kOSKextLogDependenciesFlag
,
6901 "Kext %s - internal error resolving dependencies.",
6902 getIdentifierCString());
6905 addedToLoopStack
= true;
6907 /* Purge any existing kexts in the dependency list and start over.
6909 flushDependencies();
6912 kOSKextLogErrorLevel
|
6913 kOSKextLogDependenciesFlag
,
6914 "Kext %s - internal error resolving dependencies.",
6915 getIdentifierCString());
6918 libraries
= OSDynamicCast(OSDictionary
,
6919 getPropertyForHostArch(kOSBundleLibrariesKey
));
6920 if (libraries
== NULL
|| libraries
->getCount() == 0) {
6922 kOSKextLogErrorLevel
|
6923 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6924 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
6925 getIdentifierCString(), kOSBundleLibrariesKey
);
6929 /* Make a new array to hold the dependencies (flush freed the old one).
6931 dependencies
= OSArray::withCapacity(libraries
->getCount());
6932 if (!dependencies
) {
6934 kOSKextLogErrorLevel
|
6935 kOSKextLogDependenciesFlag
,
6936 "Kext %s - can't allocate dependencies array.",
6937 getIdentifierCString());
6941 // xxx - compat: We used to add an implicit dependency on kernel 6.0
6942 // xxx - compat: if none were declared.
6944 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
6945 if (!libraryIterator
) {
6947 kOSKextLogErrorLevel
|
6948 kOSKextLogDependenciesFlag
,
6949 "Kext %s - can't allocate dependencies iterator.",
6950 getIdentifierCString());
6954 while ((libraryID
= OSDynamicCast(OSString
,
6955 libraryIterator
->getNextObject()))) {
6957 const char * library_id
= libraryID
->getCStringNoCopy();
6959 OSString
* libraryVersion
= OSDynamicCast(OSString
,
6960 libraries
->getObject(libraryID
));
6961 if (libraryVersion
== NULL
) {
6963 kOSKextLogErrorLevel
|
6964 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6965 "Kext %s - illegal type in OSBundleLibraries.",
6966 getIdentifierCString());
6970 OSKextVersion libraryVers
=
6971 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
6972 if (libraryVers
== -1) {
6974 kOSKextLogErrorLevel
|
6975 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6976 "Kext %s - invalid library version %s.",
6977 getIdentifierCString(),
6978 libraryVersion
->getCStringNoCopy());
6982 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
6983 if (libraryKext
== NULL
) {
6985 kOSKextLogErrorLevel
|
6986 kOSKextLogDependenciesFlag
,
6987 "Kext %s - library kext %s not found.",
6988 getIdentifierCString(), library_id
);
6992 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
6994 kOSKextLogErrorLevel
|
6995 kOSKextLogDependenciesFlag
,
6996 "Kext %s - library kext %s not compatible "
6997 "with requested version %s.",
6998 getIdentifierCString(), library_id
,
6999 libraryVersion
->getCStringNoCopy());
7003 /* If a nonprelinked library somehow got into the mix for a
7004 * prelinked kext, at any point in the chain, we must fail
7005 * because the prelinked relocs for the library will be all wrong.
7007 if (this->isPrelinked() &&
7008 libraryKext
->declaresExecutable() &&
7009 !libraryKext
->isPrelinked()) {
7012 kOSKextLogErrorLevel
|
7013 kOSKextLogDependenciesFlag
,
7014 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7015 getIdentifierCString(), library_id
,
7016 libraryVersion
->getCStringNoCopy());
7020 if (!libraryKext
->resolveDependencies(loopStack
)) {
7024 /* Add the library directly only if it has an executable to link.
7025 * Otherwise it's just used to collect other dependencies, so put
7026 * *its* dependencies on the list for this kext.
7028 // xxx - We are losing info here; would like to make fake entries or
7029 // xxx - keep these in the dependency graph for loaded kexts.
7030 // xxx - I really want to make kernel components not a special case!
7031 if (libraryKext
->declaresExecutable() ||
7032 libraryKext
->isInterface()) {
7034 if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) {
7035 dependencies
->setObject(libraryKext
);
7038 kOSKextLogDetailLevel
|
7039 kOSKextLogDependenciesFlag
,
7040 "Kext %s added dependency %s.",
7041 getIdentifierCString(),
7042 libraryKext
->getIdentifierCString());
7045 int numLibDependencies
= libraryKext
->getNumDependencies();
7046 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
7049 if (numLibDependencies
) {
7050 // xxx - this msg level should be 1 lower than the per-kext one
7052 kOSKextLogDetailLevel
|
7053 kOSKextLogDependenciesFlag
,
7054 "Kext %s pulling %d dependencies from codeless library %s.",
7055 getIdentifierCString(),
7057 libraryKext
->getIdentifierCString());
7059 for (index
= 0; index
< numLibDependencies
; index
++) {
7060 OSKext
* thisLibDependency
= OSDynamicCast(OSKext
,
7061 libraryDependencies
->getObject(index
));
7062 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) {
7063 dependencies
->setObject(thisLibDependency
);
7065 kOSKextLogDetailLevel
|
7066 kOSKextLogDependenciesFlag
,
7067 "Kext %s added dependency %s from codeless library %s.",
7068 getIdentifierCString(),
7069 thisLibDependency
->getIdentifierCString(),
7070 libraryKext
->getIdentifierCString());
7075 if ((strlen(library_id
) == strlen(KERNEL_LIB
)) &&
7076 0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) {
7078 hasRawKernelDependency
= true;
7079 } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) {
7080 hasKernelDependency
= true;
7081 } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) {
7082 hasKPIDependency
= true;
7083 if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) {
7084 hasPrivateKPIDependency
= true;
7089 if (hasRawKernelDependency
) {
7091 kOSKextLogErrorLevel
|
7092 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7093 "Error - kext %s declares a dependency on %s, which is not permitted.",
7094 getIdentifierCString(), KERNEL_LIB
);
7098 if (hasKernelDependency
) {
7100 kOSKextLogErrorLevel
|
7101 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7102 "Error - kext %s declares %s dependencies. "
7103 "Only %s* dependencies are supported for 64-bit kexts.",
7104 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7107 if (!hasKPIDependency
) {
7109 kOSKextLogWarningLevel
|
7110 kOSKextLogDependenciesFlag
,
7111 "Warning - kext %s declares no %s* dependencies. "
7112 "If it uses any KPIs, the link may fail with undefined symbols.",
7113 getIdentifierCString(), KPI_LIB_PREFIX
);
7115 #else /* __LP64__ */
7116 // xxx - will change to flatly disallow "kernel" dependencies at some point
7117 // xxx - is it invalid to do both "com.apple.kernel" and any
7118 // xxx - "com.apple.kernel.*"?
7120 if (hasKernelDependency
&& hasKPIDependency
) {
7122 kOSKextLogWarningLevel
|
7123 kOSKextLogDependenciesFlag
,
7124 "Warning - kext %s has immediate dependencies on both "
7125 "%s* and %s* components; use only one style.",
7126 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7129 if (!hasKernelDependency
&& !hasKPIDependency
) {
7130 // xxx - do we want to use validation flag for these too?
7132 kOSKextLogWarningLevel
|
7133 kOSKextLogDependenciesFlag
,
7134 "Warning - %s declares no kernel dependencies; using %s.",
7135 getIdentifierCString(), KERNEL6_LIB
);
7136 OSKext
* kernelKext
= OSDynamicCast(OSKext
,
7137 sKextsByID
->getObject(KERNEL6_LIB
));
7139 dependencies
->setObject(kernelKext
);
7142 kOSKextLogErrorLevel
|
7143 kOSKextLogDependenciesFlag
,
7144 "Error - Library %s not found for %s.",
7145 KERNEL6_LIB
, getIdentifierCString());
7149 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7150 * its indirect dependencies to simulate old-style linking. XXX - Should
7151 * check for duplicates.
7153 if (!hasKPIDependency
) {
7156 flags
.hasBleedthrough
= true;
7158 count
= getNumDependencies();
7160 /* We add to the dependencies array in this loop, but do not iterate
7161 * past its original count.
7163 for (i
= 0; i
< count
; i
++) {
7164 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
7165 dependencies
->getObject(i
));
7166 dependencyKext
->addBleedthroughDependencies(dependencies
);
7169 #endif /* __LP64__ */
7171 if (hasPrivateKPIDependency
) {
7172 bool hasApplePrefix
= false;
7173 bool infoCopyrightIsValid
= false;
7174 bool readableCopyrightIsValid
= false;
7176 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
7179 infoString
= OSDynamicCast(OSString
,
7180 getPropertyForHostArch("CFBundleGetInfoString"));
7182 infoCopyrightIsValid
=
7183 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
7186 readableString
= OSDynamicCast(OSString
,
7187 getPropertyForHostArch("NSHumanReadableCopyright"));
7188 if (readableString
) {
7189 readableCopyrightIsValid
=
7190 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
7193 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
7195 kOSKextLogErrorLevel
|
7196 kOSKextLogDependenciesFlag
,
7197 "Error - kext %s declares a dependency on %s. "
7198 "Only Apple kexts may declare a dependency on %s.",
7199 getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
);
7205 flags
.hasAllDependencies
= 1;
7209 if (addedToLoopStack
) {
7210 count
= loopStack
->getCount();
7211 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
7212 loopStack
->removeObject(count
- 1);
7215 kOSKextLogErrorLevel
|
7216 kOSKextLogDependenciesFlag
,
7217 "Kext %s - internal error resolving dependencies.",
7218 getIdentifierCString());
7222 if (result
&& localLoopStack
) {
7224 kOSKextLogStepLevel
|
7225 kOSKextLogDependenciesFlag
,
7226 "Kext %s successfully resolved dependencies.",
7227 getIdentifierCString());
7230 OSSafeRelease(localLoopStack
);
7231 OSSafeRelease(libraryIterator
);
7236 /*********************************************************************
7237 *********************************************************************/
7239 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
7241 bool result
= false;
7242 unsigned int dependencyIndex
, dependencyCount
;
7244 dependencyCount
= getNumDependencies();
7246 for (dependencyIndex
= 0;
7247 dependencyIndex
< dependencyCount
;
7248 dependencyIndex
++) {
7250 OSKext
* dependency
= OSDynamicCast(OSKext
,
7251 dependencies
->getObject(dependencyIndex
));
7254 kOSKextLogErrorLevel
|
7255 kOSKextLogDependenciesFlag
,
7256 "Kext %s - internal error propagating compatibility dependencies.",
7257 getIdentifierCString());
7260 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7261 anArray
->setObject(dependency
);
7263 dependency
->addBleedthroughDependencies(anArray
);
7272 /*********************************************************************
7273 *********************************************************************/
7275 OSKext::flushDependencies(bool forceFlag
)
7277 bool result
= false;
7279 /* Only clear the dependencies if the kext isn't loaded;
7280 * we need the info for loaded kexts to track references.
7282 if (!isLoaded() || forceFlag
) {
7284 // xxx - check level
7286 kOSKextLogProgressLevel
|
7287 kOSKextLogDependenciesFlag
,
7288 "Kext %s flushing dependencies.",
7289 getIdentifierCString());
7290 OSSafeReleaseNULL(dependencies
);
7293 if (!isKernelComponent()) {
7294 flags
.hasAllDependencies
= 0;
7302 /*********************************************************************
7303 *********************************************************************/
7305 OSKext::getNumDependencies(void)
7307 if (!dependencies
) {
7310 return dependencies
->getCount();
7313 /*********************************************************************
7314 *********************************************************************/
7316 OSKext::getDependencies(void)
7318 return dependencies
;
7322 #pragma mark OSMetaClass Support
7324 /*********************************************************************
7325 *********************************************************************/
7328 OSMetaClass
* aClass
,
7329 uint32_t numClasses
)
7331 OSReturn result
= kOSMetaClassNoInsKModSet
;
7334 metaClasses
= OSSet::withCapacity(numClasses
);
7340 if (metaClasses
->containsObject(aClass
)) {
7342 kOSKextLogWarningLevel
|
7344 "Notice - kext %s has already registered class %s.",
7345 getIdentifierCString(),
7346 aClass
->getClassName());
7347 result
= kOSReturnSuccess
;
7351 if (!metaClasses
->setObject(aClass
)) {
7355 kOSKextLogDetailLevel
|
7357 "Kext %s registered class %s.",
7358 getIdentifierCString(),
7359 aClass
->getClassName());
7362 if (!flags
.autounloadEnabled
) {
7363 const OSMetaClass
* metaScan
= NULL
; // do not release
7365 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7366 if (metaScan
== OSTypeID(IOService
)) {
7369 kOSKextLogProgressLevel
|
7371 "Kext %s has IOService subclass %s; enabling autounload.",
7372 getIdentifierCString(),
7373 aClass
->getClassName());
7375 flags
.autounloadEnabled
= 1;
7381 notifyAddClassObservers(this, aClass
, flags
);
7383 result
= kOSReturnSuccess
;
7386 if (result
!= kOSReturnSuccess
) {
7388 kOSKextLogErrorLevel
|
7390 "Kext %s failed to register class %s.",
7391 getIdentifierCString(),
7392 aClass
->getClassName());
7398 /*********************************************************************
7399 *********************************************************************/
7401 OSKext::removeClass(
7402 OSMetaClass
* aClass
)
7404 OSReturn result
= kOSMetaClassNoKModSet
;
7410 if (!metaClasses
->containsObject(aClass
)) {
7412 kOSKextLogWarningLevel
|
7414 "Notice - kext %s asked to unregister unknown class %s.",
7415 getIdentifierCString(),
7416 aClass
->getClassName());
7417 result
= kOSReturnSuccess
;
7422 kOSKextLogDetailLevel
|
7424 "Kext %s unregistering class %s.",
7425 getIdentifierCString(),
7426 aClass
->getClassName());
7428 metaClasses
->removeObject(aClass
);
7430 notifyRemoveClassObservers(this, aClass
, flags
);
7432 result
= kOSReturnSuccess
;
7435 if (result
!= kOSReturnSuccess
) {
7437 kOSKextLogErrorLevel
|
7439 "Failed to unregister kext %s class %s.",
7440 getIdentifierCString(),
7441 aClass
->getClassName());
7446 /*********************************************************************
7447 *********************************************************************/
7449 OSKext::getMetaClasses(void)
7454 /*********************************************************************
7455 *********************************************************************/
7457 OSKext::hasOSMetaClassInstances(void)
7459 bool result
= false;
7460 OSCollectionIterator
* classIterator
= NULL
; // must release
7461 OSMetaClass
* checkClass
= NULL
; // do not release
7467 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7468 if (!classIterator
) {
7469 // xxx - log alloc failure?
7472 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7473 if (checkClass
->getInstanceCount()) {
7481 OSSafeRelease(classIterator
);
7485 /*********************************************************************
7486 *********************************************************************/
7489 OSKext::reportOSMetaClassInstances(
7490 const char * kextIdentifier
,
7491 OSKextLogSpec msgLogSpec
)
7493 OSKext
* theKext
= NULL
; // must release
7495 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
7500 theKext
->reportOSMetaClassInstances(msgLogSpec
);
7502 OSSafeRelease(theKext
);
7506 /*********************************************************************
7507 *********************************************************************/
7509 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
7511 OSCollectionIterator
* classIterator
= NULL
; // must release
7512 OSMetaClass
* checkClass
= NULL
; // do not release
7518 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7519 if (!classIterator
) {
7522 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7523 if (checkClass
->getInstanceCount()) {
7526 " Kext %s class %s has %d instance%s.",
7527 getIdentifierCString(),
7528 checkClass
->getClassName(),
7529 checkClass
->getInstanceCount(),
7530 checkClass
->getInstanceCount() == 1 ? "" : "s");
7535 OSSafeRelease(classIterator
);
7540 #pragma mark User-Space Requests
7542 /*********************************************************************
7543 * XXX - this function is a big ugly mess
7544 *********************************************************************/
7547 OSKext::handleRequest(
7548 host_priv_t hostPriv
,
7549 OSKextLogSpec clientLogFilter
,
7550 char * requestBuffer
,
7551 uint32_t requestLength
,
7552 char ** responseOut
,
7553 uint32_t * responseLengthOut
,
7555 uint32_t * logInfoLengthOut
)
7557 OSReturn result
= kOSReturnError
;
7558 kern_return_t kmem_result
= KERN_FAILURE
;
7560 char * response
= NULL
; // returned by reference
7561 uint32_t responseLength
= 0;
7563 OSObject
* parsedXML
= NULL
; // must release
7564 OSDictionary
* requestDict
= NULL
; // do not release
7565 OSString
* errorString
= NULL
; // must release
7567 OSObject
* responseObject
= NULL
; // must release
7569 OSSerialize
* serializer
= NULL
; // must release
7571 OSArray
* logInfoArray
= NULL
; // must release
7573 OSString
* predicate
= NULL
; // do not release
7574 OSString
* kextIdentifier
= NULL
; // do not release
7575 OSArray
* kextIdentifiers
= NULL
; // do not release
7576 OSKext
* theKext
= NULL
; // do not release
7577 OSBoolean
* boolArg
= NULL
; // do not release
7579 IORecursiveLockLock(sKextLock
);
7582 *responseOut
= NULL
;
7583 *responseLengthOut
= 0;
7587 *logInfoLengthOut
= 0;
7590 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
7592 /* XML must be nul-terminated.
7594 if (requestBuffer
[requestLength
- 1] != '\0') {
7595 OSKextLog(/* kext */ NULL
,
7596 kOSKextLogErrorLevel
|
7598 "Invalid request from user space (not nul-terminated).");
7599 result
= kOSKextReturnBadData
;
7602 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
7604 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
7607 const char * errorCString
= "(unknown error)";
7609 if (errorString
&& errorString
->getCStringNoCopy()) {
7610 errorCString
= errorString
->getCStringNoCopy();
7611 } else if (parsedXML
) {
7612 errorCString
= "not a dictionary";
7614 OSKextLog(/* kext */ NULL
,
7615 kOSKextLogErrorLevel
|
7617 "Error unserializing request from user space: %s.",
7619 result
= kOSKextReturnSerialization
;
7623 predicate
= _OSKextGetRequestPredicate(requestDict
);
7625 OSKextLog(/* kext */ NULL
,
7626 kOSKextLogErrorLevel
|
7628 "Recieved kext request from user space with no predicate.");
7629 result
= kOSKextReturnInvalidArgument
;
7633 OSKextLog(/* kext */ NULL
,
7634 kOSKextLogDebugLevel
|
7636 "Received '%s' request from user space.",
7637 predicate
->getCStringNoCopy());
7639 result
= kOSKextReturnNotPrivileged
;
7640 if (hostPriv
== HOST_PRIV_NULL
) {
7641 /* must be root to use these kext requests */
7642 if (predicate
->isEqualTo(kKextRequestPredicateUnload
) ||
7643 predicate
->isEqualTo(kKextRequestPredicateStart
) ||
7644 predicate
->isEqualTo(kKextRequestPredicateStop
) ||
7645 predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
) ||
7646 predicate
->isEqualTo(kKextRequestPredicateSendResource
) ) {
7647 OSKextLog(/* kext */ NULL
,
7648 kOSKextLogErrorLevel
|
7650 "Access Failure - must be root user.");
7655 /* Get common args in anticipation of use.
7657 kextIdentifier
= OSDynamicCast(OSString
, _OSKextGetRequestArgument(
7658 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7659 kextIdentifiers
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument(
7660 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7661 if (kextIdentifier
) {
7662 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
7664 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
7665 requestDict
, kKextRequestArgumentValueKey
));
7667 result
= kOSKextReturnInvalidArgument
;
7669 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
7670 if (!kextIdentifier
) {
7671 OSKextLog(/* kext */ NULL
,
7672 kOSKextLogErrorLevel
|
7674 "Invalid arguments to kext start request.");
7675 } else if (!theKext
) {
7676 OSKextLog(/* kext */ NULL
,
7677 kOSKextLogErrorLevel
|
7679 "Kext %s not found for start request.",
7680 kextIdentifier
->getCStringNoCopy());
7681 result
= kOSKextReturnNotFound
;
7683 result
= theKext
->start();
7686 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
7687 if (!kextIdentifier
) {
7688 OSKextLog(/* kext */ NULL
,
7689 kOSKextLogErrorLevel
|
7691 "Invalid arguments to kext stop request.");
7692 } else if (!theKext
) {
7693 OSKextLog(/* kext */ NULL
,
7694 kOSKextLogErrorLevel
|
7696 "Kext %s not found for stop request.",
7697 kextIdentifier
->getCStringNoCopy());
7698 result
= kOSKextReturnNotFound
;
7700 result
= theKext
->stop();
7703 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
7704 if (!kextIdentifier
) {
7705 OSKextLog(/* kext */ NULL
,
7706 kOSKextLogErrorLevel
|
7708 "Invalid arguments to kext unload request.");
7709 } else if (!theKext
) {
7710 OSKextLog(/* kext */ NULL
,
7711 kOSKextLogErrorLevel
|
7713 "Kext %s not found for unload request.",
7714 kextIdentifier
->getCStringNoCopy());
7715 result
= kOSKextReturnNotFound
;
7717 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
7718 _OSKextGetRequestArgument(requestDict
,
7719 kKextRequestArgumentTerminateIOServicesKey
));
7720 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
7723 } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
7724 result
= OSKext::dispatchResource(requestDict
);
7726 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
7727 OSBoolean
* delayAutounloadBool
= NULL
;
7728 OSObject
* infoKeysRaw
= NULL
;
7729 OSArray
* infoKeys
= NULL
;
7730 uint32_t infoKeysCount
= 0;
7732 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
7733 _OSKextGetRequestArgument(requestDict
,
7734 kKextRequestArgumentDelayAutounloadKey
));
7736 /* If asked to delay autounload, reset the timer if it's currently set.
7737 * (That is, don't schedule an unload if one isn't already pending.
7739 if (delayAutounloadBool
== kOSBooleanTrue
) {
7740 OSKext::considerUnloads(/* rescheduleOnly? */ true);
7743 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
7744 kKextRequestArgumentInfoKeysKey
);
7745 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
7746 if (infoKeysRaw
&& !infoKeys
) {
7747 OSKextLog(/* kext */ NULL
,
7748 kOSKextLogErrorLevel
|
7750 "Invalid arguments to kext info request.");
7755 infoKeysCount
= infoKeys
->getCount();
7756 for (uint32_t i
= 0; i
< infoKeysCount
; i
++) {
7757 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) {
7758 OSKextLog(/* kext */ NULL
,
7759 kOSKextLogErrorLevel
|
7761 "Invalid arguments to kext info request.");
7767 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
7768 if (!responseObject
) {
7769 result
= kOSKextReturnInternalError
;
7771 OSKextLog(/* kext */ NULL
,
7772 kOSKextLogDebugLevel
|
7774 "Returning loaded kext info.");
7775 result
= kOSReturnSuccess
;
7777 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) {
7779 /* Hand the current sKernelRequests array to the caller
7780 * (who must release it), and make a new one.
7782 responseObject
= sKernelRequests
;
7783 sKernelRequests
= OSArray::withCapacity(0);
7784 sPostedKextLoadIdentifiers
->flushCollection();
7785 OSKextLog(/* kext */ NULL
,
7786 kOSKextLogDebugLevel
|
7788 "Returning kernel requests.");
7789 result
= kOSReturnSuccess
;
7791 } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) {
7793 /* Return the set of all requested bundle identifiers */
7794 responseObject
= sAllKextLoadIdentifiers
;
7795 responseObject
->retain();
7796 OSKextLog(/* kext */ NULL
,
7797 kOSKextLogDebugLevel
|
7799 "Returning load requests.");
7800 result
= kOSReturnSuccess
;
7803 OSKextLog(/* kext */ NULL
,
7804 kOSKextLogDebugLevel
|
7806 "Received '%s' invalid request from user space.",
7807 predicate
->getCStringNoCopy());
7812 * Now we have handle the request, or not. Gather up the response & logging
7813 * info to ship to user space.
7816 /* Note: Nothing in OSKext is supposed to retain requestDict,
7817 * but you never know....
7819 if (requestDict
->getRetainCount() > 1) {
7820 OSKextLog(/* kext */ NULL
,
7821 kOSKextLogWarningLevel
|
7823 "Request from user space still retained by a kext; "
7824 "probable memory leak.");
7827 if (responseOut
&& responseObject
) {
7828 serializer
= OSSerialize::withCapacity(0);
7830 result
= kOSKextReturnNoMemory
;
7834 if (!responseObject
->serialize(serializer
)) {
7835 OSKextLog(/* kext */ NULL
,
7836 kOSKextLogGeneralFlag
| kOSKextLogErrorLevel
,
7837 "Failed to serialize response to request from user space.");
7838 result
= kOSKextReturnSerialization
;
7842 response
= (char *)serializer
->text();
7843 responseLength
= serializer
->getLength();
7846 if (responseOut
&& response
) {
7849 /* This kmem_alloc sets the return value of the function.
7851 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
,
7852 round_page(responseLength
), VM_KERN_MEMORY_OSKEXT
);
7853 if (kmem_result
!= KERN_SUCCESS
) {
7854 OSKextLog(/* kext */ NULL
,
7855 kOSKextLogErrorLevel
|
7857 "Failed to copy response to request from user space.");
7858 result
= kmem_result
;
7861 /* 11981737 - clear uninitialized data in last page */
7862 bzero((void *)(buffer
+ responseLength
),
7863 (round_page(responseLength
) - responseLength
));
7864 memcpy(buffer
, response
, responseLength
);
7865 *responseOut
= buffer
;
7866 *responseLengthOut
= responseLength
;
7872 /* Gather up the collected log messages for user space. Any messages
7873 * messages past this call will not make it up as log messages but
7874 * will be in the system log. Note that we ignore the return of the
7875 * serialize; it has no bearing on the operation at hand even if we
7876 * fail to get the log messages.
7878 logInfoArray
= OSKext::clearUserSpaceLogFilter();
7880 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
7881 (void)OSKext::serializeLogInfo(logInfoArray
,
7882 logInfoOut
, logInfoLengthOut
);
7885 IORecursiveLockUnlock(sKextLock
);
7887 OSSafeRelease(parsedXML
);
7888 OSSafeRelease(errorString
);
7889 OSSafeRelease(responseObject
);
7890 OSSafeRelease(serializer
);
7891 OSSafeRelease(logInfoArray
);
7897 // #include <InstrProfiling.h>
7900 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin
,
7901 const char *DataEnd
,
7902 const char *CountersBegin
,
7903 const char *CountersEnd
,
7904 const char *NamesBegin
,
7905 const char *NamesEnd
);
7906 int __llvm_profile_write_buffer_internal(char *Buffer
,
7907 const char *DataBegin
,
7908 const char *DataEnd
,
7909 const char *CountersBegin
,
7910 const char *CountersEnd
,
7911 const char *NamesBegin
,
7912 const char *NamesEnd
);
7917 void OSKextPgoMetadataPut(char *pBuffer
,
7920 uint32_t *num_pairs
,
7924 size_t strlen_key
= strlen(key
);
7925 size_t strlen_value
= strlen(value
);
7926 size_t len
= strlen(key
) + 1 + strlen(value
) + 1;
7927 char *pos
= pBuffer
+ *position
;
7929 if (pBuffer
&& bufferSize
&& *position
<= bufferSize
) {
7930 memcpy(pos
, key
, strlen_key
); pos
+= strlen_key
;
7932 memcpy(pos
, value
, strlen_value
); pos
+= strlen_value
;
7942 void OSKextPgoMetadataPutMax(size_t *position
, const char *key
, size_t value_max
)
7944 *position
+= strlen(key
) + 1 + value_max
+ 1;
7949 void OSKextPgoMetadataPutAll(OSKext
*kext
,
7950 uuid_t instance_uuid
,
7954 uint32_t *num_pairs
)
7956 assert_static(sizeof(clock_sec_t
) % 2 == 0);
7957 //log_10 2^16 ≈ 4.82
7958 const size_t max_secs_string_size
= 5 * sizeof(clock_sec_t
)/2;
7959 const size_t max_timestamp_string_size
= max_secs_string_size
+ 1 + 6;
7962 OSKextPgoMetadataPutMax(position
, "INSTANCE", 36);
7963 OSKextPgoMetadataPutMax(position
, "UUID", 36);
7964 OSKextPgoMetadataPutMax(position
, "TIMESTAMP", max_timestamp_string_size
);
7966 uuid_string_t instance_uuid_string
;
7967 uuid_unparse(instance_uuid
, instance_uuid_string
);
7968 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
7969 "INSTANCE", instance_uuid_string
);
7973 uuid_string_t uuid_string
;
7974 uuid_data
= kext
->copyUUID();
7976 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
7977 OSSafeRelease(uuid_data
);
7978 uuid_unparse(uuid
, uuid_string
);
7979 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
7980 "UUID", uuid_string
);
7985 clock_get_calendar_microtime(&secs
, &usecs
);
7986 assert(usecs
< 1000000);
7987 char timestamp
[max_timestamp_string_size
+ 1];
7988 assert_static(sizeof(long) >= sizeof(clock_sec_t
));
7989 snprintf(timestamp
, sizeof(timestamp
), "%lu.%06d", (unsigned long)secs
, (int)usecs
);
7990 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
7991 "TIMESTAMP", timestamp
);
7994 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
7995 "NAME", kext
->getIdentifierCString());
7997 char versionCString
[kOSKextVersionMaxLength
];
7998 OSKextVersionGetString(kext
->getVersion(), versionCString
, kOSKextVersionMaxLength
);
7999 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
8000 "VERSION", versionCString
);
8005 size_t OSKextPgoMetadataSize(OSKext
*kext
)
8007 size_t position
= 0;
8008 uuid_t fakeuuid
= {};
8009 OSKextPgoMetadataPutAll(kext
, fakeuuid
, NULL
, &position
, 0, NULL
);
8014 int OSKextGrabPgoDataLocked(OSKext
*kext
,
8016 uuid_t instance_uuid
,
8019 uint64_t bufferSize
)
8024 kernel_section_t
*sect_prf_data
= NULL
;
8025 kernel_section_t
*sect_prf_name
= NULL
;
8026 kernel_section_t
*sect_prf_cnts
= NULL
;
8028 size_t metadata_size
= 0;
8030 sect_prf_data
= kext
->lookupSection("__DATA", "__llvm_prf_data");
8031 sect_prf_name
= kext
->lookupSection("__DATA", "__llvm_prf_name");
8032 sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8034 if (!sect_prf_data
|| !sect_prf_name
|| !sect_prf_cnts
) {
8039 size
= __llvm_profile_get_size_for_buffer_internal(
8040 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8041 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8042 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8045 metadata_size
= OSKextPgoMetadataSize(kext
);
8046 size
+= metadata_size
;
8047 size
+= sizeof(pgo_metadata_footer
);
8055 if (pBuffer
&& bufferSize
) {
8056 if (bufferSize
< size
) {
8061 err
= __llvm_profile_write_buffer_internal(
8063 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8064 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8065 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8073 char *end_of_buffer
= pBuffer
+ size
;
8074 struct pgo_metadata_footer
*footerp
= (struct pgo_metadata_footer
*) (end_of_buffer
- sizeof(struct pgo_metadata_footer
));
8075 char *metadata_buffer
= end_of_buffer
- (sizeof(struct pgo_metadata_footer
) + metadata_size
);
8077 size_t metadata_position
= 0;
8078 uint32_t num_pairs
= 0;
8079 OSKextPgoMetadataPutAll(kext
, instance_uuid
, metadata_buffer
, &metadata_position
, metadata_size
, &num_pairs
);
8080 while (metadata_position
< metadata_size
) {
8081 metadata_buffer
[metadata_position
++] = 0;
8084 struct pgo_metadata_footer footer
;
8085 footer
.magic
= htonl(0x6d657461);
8086 footer
.number_of_pairs
= htonl( num_pairs
);
8087 footer
.offset_to_pairs
= htonl( sizeof(struct pgo_metadata_footer
) + metadata_size
);
8088 memcpy(footerp
, &footer
, sizeof(footer
));
8099 OSKextGrabPgoData(uuid_t uuid
,
8102 uint64_t bufferSize
,
8103 int wait_for_unload
,
8107 OSKext
*kext
= NULL
;
8110 IORecursiveLockLock(sKextLock
);
8112 kext
= OSKext::lookupKextWithUUID(uuid
);
8118 if (wait_for_unload
) {
8119 OSKextGrabPgoStruct s
;
8121 s
.metadata
= metadata
;
8123 s
.pBuffer
= pBuffer
;
8124 s
.bufferSize
= bufferSize
;
8127 struct list_head
*prev
= &kext
->pendingPgoHead
;
8128 struct list_head
*next
= kext
->pendingPgoHead
.next
;
8130 s
.list_head
.prev
= prev
;
8131 s
.list_head
.next
= next
;
8133 prev
->next
= &s
.list_head
;
8134 next
->prev
= &s
.list_head
;
8139 IORecursiveLockSleep(sKextLock
, &s
, THREAD_ABORTSAFE
);
8141 prev
= s
.list_head
.prev
;
8142 next
= s
.list_head
.next
;
8150 err
= OSKextGrabPgoDataLocked(kext
, metadata
, kext
->instance_uuid
, pSize
, pBuffer
, bufferSize
);
8158 IORecursiveLockUnlock(sKextLock
);
8164 /*********************************************************************
8165 *********************************************************************/
8168 OSKext::copyLoadedKextInfo(
8169 OSArray
* kextIdentifiers
,
8172 OSDictionary
* result
= NULL
;
8173 OSDictionary
* kextInfo
= NULL
; // must release
8175 uint32_t idCount
= 0;
8176 uint32_t idIndex
= 0;
8178 IORecursiveLockLock(sKextLock
);
8181 /* Is the calling process allowed to query kext info? */
8182 if (current_task() != kernel_task
) {
8183 int macCheckResult
= 0;
8184 kauth_cred_t cred
= NULL
;
8186 cred
= kauth_cred_get_with_ref();
8187 macCheckResult
= mac_kext_check_query(cred
);
8188 kauth_cred_unref(&cred
);
8190 if (macCheckResult
!= 0) {
8191 OSKextLog(/* kext */ NULL
,
8192 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8193 "Failed to query kext info (MAC policy error 0x%x).",
8200 /* Empty list of bundle ids is equivalent to no list (get all).
8202 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8203 kextIdentifiers
= NULL
;
8204 } else if (kextIdentifiers
) {
8205 idCount
= kextIdentifiers
->getCount();
8210 if (infoKeys
&& !infoKeys
->getCount()) {
8214 count
= sLoadedKexts
->getCount();
8215 result
= OSDictionary::withCapacity(count
);
8221 OSKextLog(/* kext */ NULL
,
8222 kOSKextLogErrorLevel
|
8223 kOSKextLogGeneralFlag
,
8224 "kaslr: vm_kernel_slide 0x%lx \n",
8226 OSKextLog(/* kext */ NULL
,
8227 kOSKextLogErrorLevel
|
8228 kOSKextLogGeneralFlag
,
8229 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
8230 vm_kernel_stext
, vm_kernel_etext
);
8231 OSKextLog(/* kext */ NULL
,
8232 kOSKextLogErrorLevel
|
8233 kOSKextLogGeneralFlag
,
8234 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
8235 vm_kernel_base
, vm_kernel_top
);
8236 OSKextLog(/* kext */ NULL
,
8237 kOSKextLogErrorLevel
|
8238 kOSKextLogGeneralFlag
,
8239 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
8240 vm_kext_base
, vm_kext_top
);
8241 OSKextLog(/* kext */ NULL
,
8242 kOSKextLogErrorLevel
|
8243 kOSKextLogGeneralFlag
,
8244 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
8245 vm_prelink_stext
, vm_prelink_etext
);
8246 OSKextLog(/* kext */ NULL
,
8247 kOSKextLogErrorLevel
|
8248 kOSKextLogGeneralFlag
,
8249 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
8250 vm_prelink_sinfo
, vm_prelink_einfo
);
8251 OSKextLog(/* kext */ NULL
,
8252 kOSKextLogErrorLevel
|
8253 kOSKextLogGeneralFlag
,
8254 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
8255 vm_slinkedit
, vm_elinkedit
);
8258 for (i
= 0; i
< count
; i
++) {
8259 OSKext
* thisKext
= NULL
; // do not release
8260 Boolean includeThis
= true;
8263 kextInfo
->release();
8266 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8271 /* Skip current kext if we have a list of bundle IDs and
8272 * it isn't in the list.
8274 if (kextIdentifiers
) {
8275 const OSString
* thisKextID
= thisKext
->getIdentifier();
8277 includeThis
= false;
8279 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8280 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
8281 kextIdentifiers
->getObject(idIndex
));
8282 if (thisKextID
->isEqualTo(thisRequestID
)) {
8293 kextInfo
= thisKext
->copyInfo(infoKeys
);
8295 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
8300 IORecursiveLockUnlock(sKextLock
);
8302 if (kextInfo
) kextInfo
->release();
8307 /*********************************************************************
8308 * Any info that needs to do allocations must goto finish on alloc
8309 * failure. Info that is just a lookup should just not set the object
8310 * if the info does not exist.
8311 *********************************************************************/
8312 #define _OSKextLoadInfoDictCapacity (12)
8315 OSKext::copyInfo(OSArray
* infoKeys
)
8317 OSDictionary
* result
= NULL
;
8318 bool success
= false;
8319 OSData
* headerData
= NULL
; // must release
8320 OSNumber
* cpuTypeNumber
= NULL
; // must release
8321 OSNumber
* cpuSubtypeNumber
= NULL
; // must release
8322 OSString
* versionString
= NULL
; // do not release
8323 uint32_t executablePathCStringSize
= 0;
8324 char * executablePathCString
= NULL
; // must release
8325 OSString
* executablePathString
= NULL
; // must release
8326 OSData
* uuid
= NULL
; // must release
8327 OSNumber
* scratchNumber
= NULL
; // must release
8328 OSArray
* dependencyLoadTags
= NULL
; // must release
8329 OSCollectionIterator
* metaClassIterator
= NULL
; // must release
8330 OSArray
* metaClassInfo
= NULL
; // must release
8331 OSDictionary
* metaClassDict
= NULL
; // must release
8332 OSMetaClass
* thisMetaClass
= NULL
; // do not release
8333 OSString
* metaClassName
= NULL
; // must release
8334 OSString
* superclassName
= NULL
; // must release
8337 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
8343 /* Empty keys means no keys, but NULL is quicker to check.
8345 if (infoKeys
&& !infoKeys
->getCount()) {
8349 /* Headers, CPU type, and CPU subtype.
8352 _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) ||
8353 _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) ||
8354 _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
))
8357 if (linkedExecutable
&& !isInterface()) {
8359 kernel_mach_header_t
*kext_mach_hdr
= (kernel_mach_header_t
*)
8360 linkedExecutable
->getBytesNoCopy();
8363 // do not return macho header info on shipping iOS - 19095897
8364 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) {
8365 kernel_mach_header_t
* temp_kext_mach_hdr
;
8366 struct load_command
* lcp
;
8368 headerData
= OSData::withBytes(kext_mach_hdr
,
8369 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
8374 // unslide any vmaddrs we return to userspace - 10726716
8375 temp_kext_mach_hdr
= (kernel_mach_header_t
*)
8376 headerData
->getBytesNoCopy();
8377 if (temp_kext_mach_hdr
== NULL
) {
8381 lcp
= (struct load_command
*) (temp_kext_mach_hdr
+ 1);
8382 for (i
= 0; i
< temp_kext_mach_hdr
->ncmds
; i
++) {
8383 if (lcp
->cmd
== LC_SEGMENT_KERNEL
) {
8384 kernel_segment_command_t
* segp
;
8385 kernel_section_t
* secp
;
8387 segp
= (kernel_segment_command_t
*) lcp
;
8388 // 10543468 - if we jettisoned __LINKEDIT clear size info
8389 if (flags
.jettisonLinkeditSeg
) {
8390 if (strncmp(segp
->segname
, SEG_LINKEDIT
, sizeof(segp
->segname
)) == 0) {
8397 OSKextLog(/* kext */ NULL
,
8398 kOSKextLogErrorLevel
|
8399 kOSKextLogGeneralFlag
,
8400 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
8401 __FUNCTION__
, segp
->segname
, segp
->vmaddr
,
8402 VM_KERNEL_UNSLIDE(segp
->vmaddr
),
8403 segp
->vmsize
, segp
->nsects
);
8404 if ( (VM_KERNEL_IS_SLID(segp
->vmaddr
) == false) &&
8405 (VM_KERNEL_IS_KEXT(segp
->vmaddr
) == false) &&
8406 (VM_KERNEL_IS_PRELINKTEXT(segp
->vmaddr
) == false) &&
8407 (VM_KERNEL_IS_PRELINKINFO(segp
->vmaddr
) == false) &&
8408 (VM_KERNEL_IS_KEXT_LINKEDIT(segp
->vmaddr
) == false) ) {
8409 OSKextLog(/* kext */ NULL
,
8410 kOSKextLogErrorLevel
|
8411 kOSKextLogGeneralFlag
,
8412 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
8413 __FUNCTION__
, segp
->vmaddr
, vm_kext_base
, vm_kext_top
);
8416 segp
->vmaddr
= VM_KERNEL_UNSLIDE(segp
->vmaddr
);
8418 for (secp
= firstsect(segp
); secp
!= NULL
; secp
= nextsect(segp
, secp
)) {
8419 secp
->addr
= VM_KERNEL_UNSLIDE(secp
->addr
);
8422 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
8424 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
8426 #endif // SECURE_KERNEL
8428 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) {
8429 cpuTypeNumber
= OSNumber::withNumber(
8430 (uint64_t) kext_mach_hdr
->cputype
,
8431 8 * sizeof(kext_mach_hdr
->cputype
));
8432 if (!cpuTypeNumber
) {
8435 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
8438 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
8439 cpuSubtypeNumber
= OSNumber::withNumber(
8440 (uint64_t) kext_mach_hdr
->cpusubtype
,
8441 8 * sizeof(kext_mach_hdr
->cpusubtype
));
8442 if (!cpuSubtypeNumber
) {
8445 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
8450 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
8452 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
8456 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
8457 versionString
= OSDynamicCast(OSString
,
8458 getPropertyForHostArch(kCFBundleVersionKey
));
8459 if (versionString
) {
8460 result
->setObject(kCFBundleVersionKey
, versionString
);
8464 /* OSBundleCompatibleVersion.
8466 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
8467 versionString
= OSDynamicCast(OSString
,
8468 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
8469 if (versionString
) {
8470 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
8476 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
8478 result
->setObject(kOSBundlePathKey
, path
);
8483 /* OSBundleExecutablePath.
8485 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
8486 if (path
&& executableRelPath
) {
8488 uint32_t pathLength
= path
->getLength(); // gets incremented below
8490 // +1 for slash, +1 for \0
8491 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
8493 executablePathCString
= (char *)kalloc_tag((executablePathCStringSize
) *
8494 sizeof(char), VM_KERN_MEMORY_OSKEXT
); // +1 for \0
8495 if (!executablePathCString
) {
8498 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
8499 executablePathCStringSize
);
8500 executablePathCString
[pathLength
++] = '/';
8501 executablePathCString
[pathLength
++] = '\0';
8502 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
8503 executablePathCStringSize
);
8505 executablePathString
= OSString::withCString(executablePathCString
);
8507 if (!executablePathCString
) {
8511 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
8515 /* UUID, if the kext has one.
8517 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
8520 result
->setObject(kOSBundleUUIDKey
, uuid
);
8525 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
8527 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSKernelResourceKey
)) {
8528 result
->setObject(kOSKernelResourceKey
,
8529 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
8532 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
8533 result
->setObject(kOSBundleIsInterfaceKey
,
8534 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
8537 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
8538 result
->setObject(kOSBundlePrelinkedKey
,
8539 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
8542 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
8543 result
->setObject(kOSBundleStartedKey
,
8544 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
8549 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
8550 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
8551 /* numBits */ 8 * sizeof(loadTag
));
8552 if (!scratchNumber
) {
8555 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
8556 OSSafeReleaseNULL(scratchNumber
);
8559 /* LoadAddress, LoadSize.
8562 _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) ||
8563 _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) ||
8564 _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
))
8566 if (isInterface() || linkedExecutable
) {
8567 /* These go to userspace via serialization, so we don't want any doubts
8570 uint64_t loadAddress
= 0;
8571 uint32_t loadSize
= 0;
8572 uint32_t wiredSize
= 0;
8574 /* Interfaces always report 0 load address & size.
8575 * Just the way they roll.
8577 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
8578 * xxx - shouldn't have one!
8580 if (linkedExecutable
/* && !isInterface() */) {
8581 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
8582 loadAddress
= VM_KERNEL_UNSLIDE(loadAddress
);
8583 loadSize
= linkedExecutable
->getLength();
8585 /* If we have a kmod_info struct, calculated the wired size
8586 * from that. Otherwise it's the full load size.
8589 wiredSize
= loadSize
- kmod_info
->hdr_size
;
8591 wiredSize
= loadSize
;
8595 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
8596 scratchNumber
= OSNumber::withNumber(
8597 (unsigned long long)(loadAddress
),
8598 /* numBits */ 8 * sizeof(loadAddress
));
8599 if (!scratchNumber
) {
8602 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
8603 OSSafeReleaseNULL(scratchNumber
);
8605 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
8606 scratchNumber
= OSNumber::withNumber(
8607 (unsigned long long)(loadSize
),
8608 /* numBits */ 8 * sizeof(loadSize
));
8609 if (!scratchNumber
) {
8612 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
8613 OSSafeReleaseNULL(scratchNumber
);
8615 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
8616 scratchNumber
= OSNumber::withNumber(
8617 (unsigned long long)(wiredSize
),
8618 /* numBits */ 8 * sizeof(wiredSize
));
8619 if (!scratchNumber
) {
8622 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
8623 OSSafeReleaseNULL(scratchNumber
);
8628 /* OSBundleDependencies. In descending order for
8629 * easy compatibility with kextstat(8).
8631 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
8632 if ((count
= getNumDependencies())) {
8633 dependencyLoadTags
= OSArray::withCapacity(count
);
8634 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
8638 OSKext
* dependency
= OSDynamicCast(OSKext
,
8639 dependencies
->getObject(i
));
8641 OSSafeReleaseNULL(scratchNumber
);
8646 scratchNumber
= OSNumber::withNumber(
8647 (unsigned long long)dependency
->getLoadTag(),
8648 /* numBits*/ 8 * sizeof(loadTag
));
8649 if (!scratchNumber
) {
8652 dependencyLoadTags
->setObject(scratchNumber
);
8657 OSSafeReleaseNULL(scratchNumber
);
8659 /* OSBundleMetaClasses.
8661 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) {
8662 if (metaClasses
&& metaClasses
->getCount()) {
8663 metaClassIterator
= OSCollectionIterator::withCollection(metaClasses
);
8664 metaClassInfo
= OSArray::withCapacity(metaClasses
->getCount());
8665 if (!metaClassIterator
|| !metaClassInfo
) {
8668 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
8670 while ( (thisMetaClass
= OSDynamicCast(OSMetaClass
,
8671 metaClassIterator
->getNextObject())) ) {
8673 OSSafeReleaseNULL(metaClassDict
);
8674 OSSafeReleaseNULL(scratchNumber
);
8675 OSSafeReleaseNULL(metaClassName
);
8676 OSSafeReleaseNULL(superclassName
);
8678 metaClassDict
= OSDictionary::withCapacity(3);
8679 if (!metaClassDict
) {
8683 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
8684 if (thisMetaClass
->getSuperClass()) {
8685 superclassName
= OSString::withCString(
8686 thisMetaClass
->getSuperClass()->getClassName());
8688 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
8689 8 * sizeof(unsigned int));
8691 /* Bail if any of the essentials is missing. The root class lacks a superclass,
8694 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
8698 metaClassInfo
->setObject(metaClassDict
);
8699 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
8700 if (superclassName
) {
8701 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
8703 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
8708 /* OSBundleRetainCount.
8710 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
8711 OSSafeReleaseNULL(scratchNumber
);
8713 int kextRetainCount
= getRetainCount() - 1;
8717 scratchNumber
= OSNumber::withNumber(
8718 (int)kextRetainCount
,
8719 /* numBits*/ 8 * sizeof(int));
8720 if (scratchNumber
) {
8721 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
8729 OSSafeRelease(headerData
);
8730 OSSafeRelease(cpuTypeNumber
);
8731 OSSafeRelease(cpuSubtypeNumber
);
8732 OSSafeRelease(executablePathString
);
8733 if (executablePathString
) kfree(executablePathCString
, executablePathCStringSize
);
8734 OSSafeRelease(uuid
);
8735 OSSafeRelease(scratchNumber
);
8736 OSSafeRelease(dependencyLoadTags
);
8737 OSSafeRelease(metaClassIterator
);
8738 OSSafeRelease(metaClassInfo
);
8739 OSSafeRelease(metaClassDict
);
8740 OSSafeRelease(metaClassName
);
8741 OSSafeRelease(superclassName
);
8743 OSSafeReleaseNULL(result
);
8748 /*********************************************************************
8749 *********************************************************************/
8752 OSKext::requestResource(
8753 const char * kextIdentifierCString
,
8754 const char * resourceNameCString
,
8755 OSKextRequestResourceCallback callback
,
8757 OSKextRequestTag
* requestTagOut
)
8759 OSReturn result
= kOSReturnError
;
8760 OSKext
* callbackKext
= NULL
; // must release (looked up)
8762 OSKextRequestTag requestTag
= -1;
8763 OSNumber
* requestTagNum
= NULL
; // must release
8765 OSDictionary
* requestDict
= NULL
; // must release
8766 OSString
* kextIdentifier
= NULL
; // must release
8767 OSString
* resourceName
= NULL
; // must release
8769 OSDictionary
* callbackRecord
= NULL
; // must release
8770 OSData
* callbackWrapper
= NULL
; // must release
8772 OSData
* contextWrapper
= NULL
; // must release
8774 IORecursiveLockLock(sKextLock
);
8776 if (requestTagOut
) {
8777 *requestTagOut
= kOSKextRequestTagInvalid
;
8780 /* If requests to user space are disabled, don't go any further */
8781 if (!sKernelRequestsEnabled
) {
8782 OSKextLog(/* kext */ NULL
,
8783 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8784 "Can't request resource %s for %s - requests to user space are disabled.",
8785 resourceNameCString
,
8786 kextIdentifierCString
);
8787 result
= kOSKextReturnDisabled
;
8791 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
8792 result
= kOSKextReturnInvalidArgument
;
8796 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
8797 if (!callbackKext
) {
8798 OSKextLog(/* kext */ NULL
,
8799 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8800 "Resource request has bad callback address.");
8801 result
= kOSKextReturnInvalidArgument
;
8804 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
8805 OSKextLog(/* kext */ NULL
,
8806 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8807 "Resource request callback is in a kext that is not started.");
8808 result
= kOSKextReturnInvalidArgument
;
8812 /* Do not allow any new requests to be made on a kext that is unloading.
8814 if (callbackKext
->flags
.stopping
) {
8815 result
= kOSKextReturnStopping
;
8819 /* If we're wrapped the next available request tag around to the negative
8820 * numbers, we can't service any more requests.
8822 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
8823 OSKextLog(/* kext */ NULL
,
8824 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8825 "No more request tags available; restart required.");
8826 result
= kOSKextReturnNoResources
;
8829 requestTag
= sNextRequestTag
++;
8831 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
8833 if (result
!= kOSReturnSuccess
) {
8837 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
8838 resourceName
= OSString::withCString(resourceNameCString
);
8839 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
8840 8 * sizeof(requestTag
));
8841 if (!kextIdentifier
||
8844 !_OSKextSetRequestArgument(requestDict
,
8845 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
8846 !_OSKextSetRequestArgument(requestDict
,
8847 kKextRequestArgumentNameKey
, resourceName
) ||
8848 !_OSKextSetRequestArgument(requestDict
,
8849 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
8851 result
= kOSKextReturnNoMemory
;
8855 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
8856 if (!callbackRecord
) {
8857 result
= kOSKextReturnNoMemory
;
8860 // we validate callback address at call time
8861 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
8863 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
8865 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
8866 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
8868 result
= kOSKextReturnNoMemory
;
8873 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
8874 kKextRequestArgumentContextKey
, contextWrapper
)) {
8876 result
= kOSKextReturnNoMemory
;
8881 /* Only post the requests after all the other potential failure points
8884 if (!sKernelRequests
->setObject(requestDict
) ||
8885 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
8887 result
= kOSKextReturnNoMemory
;
8891 OSKext::pingKextd();
8893 result
= kOSReturnSuccess
;
8894 if (requestTagOut
) {
8895 *requestTagOut
= requestTag
;
8900 /* If we didn't succeed, yank the request & callback
8901 * from their holding arrays.
8903 if (result
!= kOSReturnSuccess
) {
8906 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
8907 if (index
!= (unsigned int)-1) {
8908 sKernelRequests
->removeObject(index
);
8910 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
8911 if (index
!= (unsigned int)-1) {
8912 sRequestCallbackRecords
->removeObject(index
);
8916 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8918 IORecursiveLockUnlock(sKextLock
);
8920 if (callbackKext
) callbackKext
->release();
8921 if (requestTagNum
) requestTagNum
->release();
8923 if (requestDict
) requestDict
->release();
8924 if (kextIdentifier
) kextIdentifier
->release();
8925 if (resourceName
) resourceName
->release();
8927 if (callbackRecord
) callbackRecord
->release();
8928 if (callbackWrapper
) callbackWrapper
->release();
8929 if (contextWrapper
) contextWrapper
->release();
8934 /*********************************************************************
8935 * Assumes sKextLock is held.
8936 *********************************************************************/
8939 OSKext::dequeueCallbackForRequestTag(
8940 OSKextRequestTag requestTag
,
8941 OSDictionary
** callbackRecordOut
)
8943 OSReturn result
= kOSReturnError
;
8944 OSNumber
* requestTagNum
= NULL
; // must release
8946 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
8947 8 * sizeof(requestTag
));
8948 if (!requestTagNum
) {
8952 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
8956 OSSafeRelease(requestTagNum
);
8961 /*********************************************************************
8962 * Assumes sKextLock is held.
8963 *********************************************************************/
8966 OSKext::dequeueCallbackForRequestTag(
8967 OSNumber
* requestTagNum
,
8968 OSDictionary
** callbackRecordOut
)
8970 OSReturn result
= kOSKextReturnInvalidArgument
;
8971 OSDictionary
* callbackRecord
= NULL
; // retain if matched!
8972 OSNumber
* callbackTagNum
= NULL
; // do not release
8973 unsigned int count
, i
;
8975 result
= kOSReturnError
;
8976 count
= sRequestCallbackRecords
->getCount();
8977 for (i
= 0; i
< count
; i
++) {
8978 callbackRecord
= OSDynamicCast(OSDictionary
,
8979 sRequestCallbackRecords
->getObject(i
));
8980 if (!callbackRecord
) {
8984 /* If we don't find a tag, we basically have a leak here. Maybe
8985 * we should just remove it.
8987 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
8988 callbackRecord
, kKextRequestArgumentRequestTagKey
));
8989 if (!callbackTagNum
) {
8993 /* We could be even more paranoid and check that all the incoming
8994 * args match what's in the callback record.
8996 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
8997 if (callbackRecordOut
) {
8998 *callbackRecordOut
= callbackRecord
;
8999 callbackRecord
->retain();
9001 sRequestCallbackRecords
->removeObject(i
);
9002 result
= kOSReturnSuccess
;
9006 result
= kOSKextReturnNotFound
;
9012 /*********************************************************************
9013 * Assumes sKextLock is held.
9014 *********************************************************************/
9017 OSKext::dispatchResource(OSDictionary
* requestDict
)
9019 OSReturn result
= kOSReturnError
;
9020 OSDictionary
* callbackRecord
= NULL
; // must release
9021 OSNumber
* requestTag
= NULL
; // do not release
9022 OSNumber
* requestResult
= NULL
; // do not release
9023 OSData
* dataObj
= NULL
; // do not release
9024 uint32_t dataLength
= 0;
9025 const void * dataPtr
= NULL
; // do not free
9026 OSData
* callbackWrapper
= NULL
; // do not release
9027 OSKextRequestResourceCallback callback
= NULL
;
9028 OSData
* contextWrapper
= NULL
; // do not release
9029 void * context
= NULL
; // do not free
9030 OSKext
* callbackKext
= NULL
; // must release (looked up)
9032 /* Get the args from the request. Right now we need the tag
9033 * to look up the callback record, and the result for invoking the callback.
9035 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9036 kKextRequestArgumentRequestTagKey
));
9037 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9038 kKextRequestArgumentResultKey
));
9039 if (!requestTag
|| !requestResult
) {
9040 result
= kOSKextReturnInvalidArgument
;
9044 /* Look for a callback record matching this request's tag.
9046 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
9047 if (result
!= kOSReturnSuccess
) {
9052 * Get the context pointer of the callback record (if there is one).
9054 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
9055 kKextRequestArgumentContextKey
));
9056 context
= _OSKextExtractPointer(contextWrapper
);
9057 if (contextWrapper
&& !context
) {
9061 callbackWrapper
= OSDynamicCast(OSData
,
9062 _OSKextGetRequestArgument(callbackRecord
,
9063 kKextRequestArgumentCallbackKey
));
9064 callback
= (OSKextRequestResourceCallback
)
9065 _OSKextExtractPointer(callbackWrapper
);
9070 /* Check for a data obj. We might not have one and that's ok, that means
9071 * we didn't find the requested resource, and we still have to tell the
9072 * caller that via the callback.
9074 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
9075 kKextRequestArgumentValueKey
));
9077 dataPtr
= dataObj
->getBytesNoCopy();
9078 dataLength
= dataObj
->getLength();
9081 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9082 if (!callbackKext
) {
9083 OSKextLog(/* kext */ NULL
,
9084 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9085 "Can't invoke callback for resource request; ");
9088 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9089 OSKextLog(/* kext */ NULL
,
9090 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9091 "Can't invoke kext resource callback; ");
9095 (void)callback(requestTag
->unsigned32BitValue(),
9096 (OSReturn
)requestResult
->unsigned32BitValue(),
9097 dataPtr
, dataLength
, context
);
9099 result
= kOSReturnSuccess
;
9102 if (callbackKext
) callbackKext
->release();
9103 if (callbackRecord
) callbackRecord
->release();
9108 /*********************************************************************
9109 *********************************************************************/
9112 OSKext::invokeRequestCallback(
9113 OSDictionary
* callbackRecord
,
9114 OSReturn callbackResult
)
9116 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
9117 OSNumber
* resultNum
= NULL
; // must release
9123 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
9124 8 * sizeof(callbackResult
));
9129 /* Insert the result into the callback record and dispatch it as if it
9130 * were the reply coming down from user space.
9132 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
9135 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
9136 /* This removes the pending callback record.
9138 OSKext::dispatchResource(callbackRecord
);
9142 if (resultNum
) resultNum
->release();
9146 /*********************************************************************
9147 * Assumes sKextLock is held.
9148 *********************************************************************/
9151 OSKext::cancelRequest(
9152 OSKextRequestTag requestTag
,
9155 OSReturn result
= kOSKextReturnNoMemory
;
9156 OSDictionary
* callbackRecord
= NULL
; // must release
9157 OSData
* contextWrapper
= NULL
; // do not release
9159 IORecursiveLockLock(sKextLock
);
9160 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
9162 IORecursiveLockUnlock(sKextLock
);
9164 if (result
== kOSReturnSuccess
&& contextOut
) {
9165 contextWrapper
= OSDynamicCast(OSData
,
9166 _OSKextGetRequestArgument(callbackRecord
,
9167 kKextRequestArgumentContextKey
));
9168 *contextOut
= _OSKextExtractPointer(contextWrapper
);
9171 if (callbackRecord
) callbackRecord
->release();
9176 /*********************************************************************
9177 * Assumes sKextLock is held.
9178 *********************************************************************/
9180 OSKext::invokeOrCancelRequestCallbacks(
9181 OSReturn callbackResult
,
9184 unsigned int count
, i
;
9186 count
= sRequestCallbackRecords
->getCount();
9193 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9194 sRequestCallbackRecords
->getObject(i
));
9199 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9200 _OSKextGetRequestArgument(request
,
9201 kKextRequestArgumentCallbackKey
));
9203 if (!callbackWrapper
) {
9204 sRequestCallbackRecords
->removeObject(i
);
9208 vm_address_t callbackAddress
= (vm_address_t
)
9209 _OSKextExtractPointer(callbackWrapper
);
9211 if ((kmod_info
->address
<= callbackAddress
) &&
9212 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9215 /* This removes the callback record.
9217 invokeRequestCallback(request
, callbackResult
);
9219 sRequestCallbackRecords
->removeObject(i
);
9228 /*********************************************************************
9229 * Assumes sKextLock is held.
9230 *********************************************************************/
9232 OSKext::countRequestCallbacks(void)
9234 uint32_t result
= 0;
9235 unsigned int count
, i
;
9237 count
= sRequestCallbackRecords
->getCount();
9244 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9245 sRequestCallbackRecords
->getObject(i
));
9250 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9251 _OSKextGetRequestArgument(request
,
9252 kKextRequestArgumentCallbackKey
));
9254 if (!callbackWrapper
) {
9258 vm_address_t callbackAddress
= (vm_address_t
)
9259 _OSKextExtractPointer(callbackWrapper
);
9261 if ((kmod_info
->address
<= callbackAddress
) &&
9262 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9272 /*********************************************************************
9273 *********************************************************************/
9274 static OSReturn
_OSKextCreateRequest(
9275 const char * predicate
,
9276 OSDictionary
** requestP
)
9278 OSReturn result
= kOSKextReturnNoMemory
;
9279 OSDictionary
* request
= NULL
; // must release on error
9281 request
= OSDictionary::withCapacity(2);
9285 result
= _OSDictionarySetCStringValue(request
,
9286 kKextRequestPredicateKey
, predicate
);
9287 if (result
!= kOSReturnSuccess
) {
9290 result
= kOSReturnSuccess
;
9293 if (result
!= kOSReturnSuccess
) {
9294 if (request
) request
->release();
9296 *requestP
= request
;
9302 /*********************************************************************
9303 *********************************************************************/
9304 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
9306 return OSDynamicCast(OSString
,
9307 requestDict
->getObject(kKextRequestPredicateKey
));
9310 /*********************************************************************
9311 *********************************************************************/
9312 static OSObject
* _OSKextGetRequestArgument(
9313 OSDictionary
* requestDict
,
9314 const char * argName
)
9316 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9317 requestDict
->getObject(kKextRequestArgumentsKey
));
9319 return args
->getObject(argName
);
9324 /*********************************************************************
9325 *********************************************************************/
9326 static bool _OSKextSetRequestArgument(
9327 OSDictionary
* requestDict
,
9328 const char * argName
,
9331 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9332 requestDict
->getObject(kKextRequestArgumentsKey
));
9334 args
= OSDictionary::withCapacity(2);
9338 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
9342 return args
->setObject(argName
, value
);
9348 /*********************************************************************
9349 *********************************************************************/
9350 static void * _OSKextExtractPointer(OSData
* wrapper
)
9352 void * result
= NULL
;
9353 const void * resultPtr
= NULL
;
9358 resultPtr
= wrapper
->getBytesNoCopy();
9359 result
= *(void **)resultPtr
;
9364 /*********************************************************************
9365 *********************************************************************/
9366 static OSReturn
_OSDictionarySetCStringValue(
9367 OSDictionary
* dict
,
9369 const char * cValue
)
9371 OSReturn result
= kOSKextReturnNoMemory
;
9372 const OSSymbol
* key
= NULL
; // must release
9373 OSString
* value
= NULL
; // must release
9375 key
= OSSymbol::withCString(cKey
);
9376 value
= OSString::withCString(cValue
);
9377 if (!key
|| !value
) {
9380 if (dict
->setObject(key
, value
)) {
9381 result
= kOSReturnSuccess
;
9385 if (key
) key
->release();
9386 if (value
) value
->release();
9391 /*********************************************************************
9392 *********************************************************************/
9393 static bool _OSArrayContainsCString(
9395 const char * cString
)
9397 bool result
= false;
9398 const OSSymbol
* symbol
= NULL
;
9401 if (!array
|| !cString
) {
9405 symbol
= OSSymbol::withCStringNoCopy(cString
);
9410 count
= array
->getCount();
9411 for (i
= 0; i
< count
; i
++) {
9412 OSObject
* thisObject
= array
->getObject(i
);
9413 if (symbol
->isEqualTo(thisObject
)) {
9420 if (symbol
) symbol
->release();
9424 /*********************************************************************
9425 * We really only care about boot / system start up related kexts.
9426 * We return true if we're less than REBUILD_MAX_TIME since start up,
9427 * otherwise return false.
9428 *********************************************************************/
9429 bool _OSKextInPrelinkRebuildWindow(void)
9431 static bool outside_the_window
= false;
9432 AbsoluteTime my_abstime
;
9436 if (outside_the_window
) {
9439 clock_get_uptime(&my_abstime
);
9440 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
9441 my_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
9442 if (my_secs
> REBUILD_MAX_TIME
) {
9443 outside_the_window
= true;
9449 /*********************************************************************
9450 *********************************************************************/
9451 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
9453 int unLoadedCount
, i
;
9454 bool result
= false;
9456 IORecursiveLockLock(sKextLock
);
9458 if (sUnloadedPrelinkedKexts
== NULL
) {
9461 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
9462 if (unLoadedCount
== 0) {
9466 for (i
= 0; i
< unLoadedCount
; i
++) {
9467 const OSSymbol
* myBundleID
; // do not release
9469 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
9470 if (!myBundleID
) continue;
9471 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
9477 IORecursiveLockUnlock(sKextLock
);
9482 #pragma mark Personalities (IOKit Drivers)
9484 /*********************************************************************
9485 *********************************************************************/
9488 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
9490 OSArray
* result
= NULL
; // returned
9491 OSCollectionIterator
* kextIterator
= NULL
; // must release
9492 OSArray
* personalities
= NULL
; // must release
9493 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
9495 OSString
* kextID
= NULL
; // do not release
9496 OSKext
* theKext
= NULL
; // do not release
9498 IORecursiveLockLock(sKextLock
);
9500 /* Let's conservatively guess that any given kext has around 3
9501 * personalities for now.
9503 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
9508 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
9509 if (!kextIterator
) {
9513 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
9514 if (personalitiesIterator
) {
9515 personalitiesIterator
->release();
9516 personalitiesIterator
= NULL
;
9518 if (personalities
) {
9519 personalities
->release();
9520 personalities
= NULL
;
9523 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
9524 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
9525 personalities
= theKext
->copyPersonalitiesArray();
9526 if (!personalities
) {
9529 result
->merge(personalities
);
9531 // xxx - check for better place to put this log msg
9533 kOSKextLogWarningLevel
|
9535 "Kext %s is not loadable during safe boot; "
9536 "omitting its personalities.",
9537 theKext
->getIdentifierCString());
9543 IORecursiveLockUnlock(sKextLock
);
9545 if (kextIterator
) kextIterator
->release();
9546 if (personalitiesIterator
) personalitiesIterator
->release();
9547 if (personalities
) personalities
->release();
9552 /*********************************************************************
9553 *********************************************************************/
9556 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
9558 int numPersonalities
= 0;
9560 OSKextLog(/* kext */ NULL
,
9561 kOSKextLogStepLevel
|
9563 "Sending all eligible registered kexts' personalities "
9564 "to the IOCatalogue %s.",
9565 startMatching
? "and starting matching" : "but not starting matching");
9567 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
9568 /* filterSafeBootFlag */ true);
9570 if (personalities
) {
9571 gIOCatalogue
->addDrivers(personalities
, startMatching
);
9572 numPersonalities
= personalities
->getCount();
9573 personalities
->release();
9576 OSKextLog(/* kext */ NULL
,
9577 kOSKextLogStepLevel
|
9579 "%d kext personalit%s sent to the IOCatalogue; %s.",
9580 numPersonalities
, numPersonalities
> 0 ? "ies" : "y",
9581 startMatching
? "matching started" : "matching not started");
9585 /*********************************************************************
9586 * Do not make a deep copy, just convert the IOKitPersonalities dict
9587 * to an array for sending to the IOCatalogue.
9588 *********************************************************************/
9590 OSKext::copyPersonalitiesArray(void)
9592 OSArray
* result
= NULL
;
9593 OSDictionary
* personalities
= NULL
; // do not release
9594 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
9596 OSString
* personalityName
= NULL
; // do not release
9597 OSString
* personalityBundleIdentifier
= NULL
; // do not release
9599 personalities
= OSDynamicCast(OSDictionary
,
9600 getPropertyForHostArch(kIOKitPersonalitiesKey
));
9601 if (!personalities
) {
9605 result
= OSArray::withCapacity(personalities
->getCount());
9610 personalitiesIterator
=
9611 OSCollectionIterator::withCollection(personalities
);
9612 if (!personalitiesIterator
) {
9615 while ((personalityName
= OSDynamicCast(OSString
,
9616 personalitiesIterator
->getNextObject()))) {
9618 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
9619 personalities
->getObject(personalityName
));
9622 * If the personality doesn't have a CFBundleIdentifier, or if it
9623 * differs from the kext's, insert the kext's ID so we can find it.
9624 * The publisher ID is used to remove personalities from bundles
9627 personalityBundleIdentifier
= OSDynamicCast(OSString
,
9628 personality
->getObject(kCFBundleIdentifierKey
));
9630 if (!personalityBundleIdentifier
) {
9631 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
9632 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
9633 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
9636 result
->setObject(personality
);
9640 if (personalitiesIterator
) personalitiesIterator
->release();
9645 /*********************************************************************
9646 Might want to change this to a bool return?
9647 *********************************************************************/
9649 OSKext::sendPersonalitiesToCatalog(
9651 OSArray
* personalityNames
)
9653 OSReturn result
= kOSReturnSuccess
;
9654 OSArray
* personalitiesToSend
= NULL
; // must release
9655 OSDictionary
* kextPersonalities
= NULL
; // do not release
9658 if (!sLoadEnabled
) {
9660 kOSKextLogErrorLevel
|
9662 "Kext loading is disabled (attempt to start matching for kext %s).",
9663 getIdentifierCString());
9664 result
= kOSKextReturnDisabled
;
9668 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
9670 kOSKextLogErrorLevel
|
9672 "Kext %s is not loadable during safe boot; "
9673 "not sending personalities to the IOCatalogue.",
9674 getIdentifierCString());
9675 result
= kOSKextReturnNotLoadable
;
9679 if (!personalityNames
|| !personalityNames
->getCount()) {
9680 personalitiesToSend
= copyPersonalitiesArray();
9682 kextPersonalities
= OSDynamicCast(OSDictionary
,
9683 getPropertyForHostArch(kIOKitPersonalitiesKey
));
9684 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
9688 personalitiesToSend
= OSArray::withCapacity(0);
9689 if (!personalitiesToSend
) {
9690 result
= kOSKextReturnNoMemory
;
9693 count
= personalityNames
->getCount();
9694 for (i
= 0; i
< count
; i
++) {
9695 OSString
* name
= OSDynamicCast(OSString
,
9696 personalityNames
->getObject(i
));
9700 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
9701 kextPersonalities
->getObject(name
));
9703 personalitiesToSend
->setObject(personality
);
9707 if (personalitiesToSend
) {
9708 unsigned numPersonalities
= personalitiesToSend
->getCount();
9710 kOSKextLogStepLevel
|
9712 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
9713 getIdentifierCString(),
9715 numPersonalities
> 1 ? "ies" : "y",
9716 startMatching
? " and starting matching" : " but not starting matching");
9717 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
9720 if (personalitiesToSend
) {
9721 personalitiesToSend
->release();
9726 /*********************************************************************
9727 * xxx - We should allow removing the kext's declared personalities,
9728 * xxx - even with other bundle identifiers.
9729 *********************************************************************/
9731 OSKext::removePersonalitiesFromCatalog(void)
9733 OSDictionary
* personality
= NULL
; // do not release
9735 personality
= OSDictionary::withCapacity(1);
9739 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
9742 kOSKextLogStepLevel
|
9744 "Kext %s removing all personalities naming it from the IOCatalogue.",
9745 getIdentifierCString());
9747 /* Have the IOCatalog remove all personalities matching this kext's
9748 * bundle ID and trigger matching anew.
9750 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
9753 if (personality
) personality
->release();
9760 #pragma mark Logging
9762 /*********************************************************************
9763 * Do not call any function that takes sKextLock here!
9764 *********************************************************************/
9767 OSKext::setUserSpaceLogFilter(
9768 OSKextLogSpec newUserLogFilter
,
9771 OSKextLogSpec result
;
9772 bool allocError
= false;
9774 /* Do not call any function that takes sKextLoggingLock during
9775 * this critical block. That means do logging after.
9777 IOLockLock(sKextLoggingLock
);
9779 result
= sUserSpaceKextLogFilter
;
9780 sUserSpaceKextLogFilter
= newUserLogFilter
;
9782 if (newUserLogFilter
&& captureFlag
&&
9783 !sUserSpaceLogSpecArray
&& !sUserSpaceLogMessageArray
) {
9785 // xxx - do some measurements for a good initial capacity?
9786 sUserSpaceLogSpecArray
= OSArray::withCapacity(0);
9787 sUserSpaceLogMessageArray
= OSArray::withCapacity(0);
9789 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
9790 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
9791 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
9796 IOLockUnlock(sKextLoggingLock
);
9798 /* If the config flag itself is changing, log the state change
9799 * going both ways, before setting up the user-space log arrays,
9800 * so that this is only logged in the kernel.
9802 if (result
!= newUserLogFilter
) {
9803 OSKextLog(/* kext */ NULL
,
9804 kOSKextLogDebugLevel
|
9805 kOSKextLogGeneralFlag
,
9806 "User-space log flags changed from 0x%x to 0x%x.",
9807 result
, newUserLogFilter
);
9810 OSKextLog(/* kext */ NULL
,
9811 kOSKextLogErrorLevel
|
9812 kOSKextLogGeneralFlag
,
9813 "Failed to allocate user-space log message arrays.");
9819 /*********************************************************************
9820 * Do not call any function that takes sKextLock here!
9821 *********************************************************************/
9824 OSKext::clearUserSpaceLogFilter(void)
9826 OSArray
* result
= NULL
;
9827 OSKextLogSpec oldLogFilter
;
9828 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
9830 /* Do not call any function that takes sKextLoggingLock during
9831 * this critical block. That means do logging after.
9833 IOLockLock(sKextLoggingLock
);
9835 result
= OSArray::withCapacity(2);
9837 result
->setObject(sUserSpaceLogSpecArray
);
9838 result
->setObject(sUserSpaceLogMessageArray
);
9840 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
9841 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
9843 oldLogFilter
= sUserSpaceKextLogFilter
;
9844 sUserSpaceKextLogFilter
= newLogFilter
;
9846 IOLockUnlock(sKextLoggingLock
);
9848 /* If the config flag itself is changing, log the state change
9849 * going both ways, after tearing down the user-space log
9850 * arrays, so this is only logged within the kernel.
9852 if (oldLogFilter
!= newLogFilter
) {
9853 OSKextLog(/* kext */ NULL
,
9854 kOSKextLogDebugLevel
|
9855 kOSKextLogGeneralFlag
,
9856 "User-space log flags changed from 0x%x to 0x%x.",
9857 oldLogFilter
, newLogFilter
);
9864 /*********************************************************************
9865 * Do not call any function that takes sKextLock here!
9866 *********************************************************************/
9869 OSKext::getUserSpaceLogFilter(void)
9871 OSKextLogSpec result
;
9873 IOLockLock(sKextLoggingLock
);
9874 result
= sUserSpaceKextLogFilter
;
9875 IOLockUnlock(sKextLoggingLock
);
9880 /*********************************************************************
9881 * This function is called by OSMetaClass during kernel C++ setup.
9882 * Be careful what you access here; assume only OSKext::initialize()
9885 * Do not call any function that takes sKextLock here!
9886 *********************************************************************/
9887 #define VTRESET "\033[0m"
9889 #define VTBOLD "\033[1m"
9890 #define VTUNDER "\033[4m"
9892 #define VTRED "\033[31m"
9893 #define VTGREEN "\033[32m"
9894 #define VTYELLOW "\033[33m"
9895 #define VTBLUE "\033[34m"
9896 #define VTMAGENTA "\033[35m"
9897 #define VTCYAN "\033[36m"
9899 inline const char * colorForFlags(OSKextLogSpec flags
)
9901 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
9904 case kOSKextLogErrorLevel
:
9905 return VTRED VTBOLD
;
9907 case kOSKextLogWarningLevel
:
9910 case kOSKextLogBasicLevel
:
9911 return VTYELLOW VTUNDER
;
9913 case kOSKextLogProgressLevel
:
9916 case kOSKextLogStepLevel
:
9919 case kOSKextLogDetailLevel
:
9922 case kOSKextLogDebugLevel
:
9932 inline bool logSpecMatch(
9933 OSKextLogSpec msgLogSpec
,
9934 OSKextLogSpec logFilter
)
9936 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
9937 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
9938 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
9940 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
9941 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
9942 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
9944 /* Explicit messages always get logged.
9946 if (msgLevel
== kOSKextLogExplicitLevel
) {
9950 /* Warnings and errors are logged regardless of the flags.
9952 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
9956 /* A verbose message that isn't for a logging-enabled kext and isn't global
9957 * does *not* get logged.
9959 if (!msgKextGlobal
&& !filterKextGlobal
) {
9963 /* Warnings and errors are logged regardless of the flags.
9964 * All other messages must fit the flags and
9965 * have a level at or below the filter.
9968 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
9979 OSKextLogSpec msgLogSpec
,
9980 const char * format
, ...)
9984 va_start(argList
, format
);
9985 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
9992 OSKextLogSpec msgLogSpec
,
9993 const char * format
,
9996 extern int disableConsoleOutput
;
9998 bool logForKernel
= false;
9999 bool logForUser
= false;
10001 char stackBuffer
[120];
10002 uint32_t length
= 0;
10003 char * allocBuffer
= NULL
; // must kfree
10004 OSNumber
* logSpecNum
= NULL
; // must release
10005 OSString
* logString
= NULL
; // must release
10006 char * buffer
= stackBuffer
; // do not free
10008 IOLockLock(sKextLoggingLock
);
10010 /* Set the kext/global bit in the message spec if we have no
10011 * kext or if the kext requests logging.
10013 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
10014 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
10017 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
10018 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10019 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
10022 if (! (logForKernel
|| logForUser
) ) {
10026 /* No goto from here until past va_end()!
10028 va_copy(argList
, srcArgList
);
10029 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
10032 if (length
+ 1 >= sizeof(stackBuffer
)) {
10033 allocBuffer
= (char *)kalloc_tag((length
+ 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT
);
10034 if (!allocBuffer
) {
10038 /* No goto from here until past va_end()!
10040 va_copy(argList
, srcArgList
);
10041 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
10044 buffer
= allocBuffer
;
10047 /* If user space wants the log message, queue it up.
10049 if (logForUser
&& sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10050 logSpecNum
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
));
10051 logString
= OSString::withCString(buffer
);
10052 if (logSpecNum
&& logString
) {
10053 sUserSpaceLogSpecArray
->setObject(logSpecNum
);
10054 sUserSpaceLogMessageArray
->setObject(logString
);
10058 /* Always log messages from the kernel according to the kernel's
10061 if (logForKernel
) {
10063 /* If we are in console mode and have a custom log filter,
10064 * colorize the log message.
10066 if (!disableConsoleOutput
&& sBootArgLogFilterFound
) {
10067 const char * color
= ""; // do not free
10068 color
= colorForFlags(msgLogSpec
);
10069 printf("%s%s%s\n", colorForFlags(msgLogSpec
),
10070 buffer
, color
[0] ? VTRESET
: "");
10072 printf("%s\n", buffer
);
10077 IOLockUnlock(sKextLoggingLock
);
10080 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
10082 OSSafeRelease(logString
);
10083 OSSafeRelease(logSpecNum
);
10087 #if KASLR_IOREG_DEBUG
10089 #define IOLOG_INDENT( the_indention ) \
10092 for ( i = 0; i < (the_indention); i++ ) { \
10097 extern vm_offset_t vm_kernel_stext
;
10098 extern vm_offset_t vm_kernel_etext
;
10099 extern mach_vm_offset_t kext_alloc_base
;
10100 extern mach_vm_offset_t kext_alloc_max
;
10102 bool ScanForAddrInObject(OSObject
* theObject
,
10105 bool ScanForAddrInObject(OSObject
* theObject
,
10108 const OSMetaClass
* myTypeID
;
10109 OSCollectionIterator
* myIter
;
10111 OSObject
* myValue
;
10112 bool myResult
= false;
10114 if ( theObject
== NULL
) {
10115 IOLog("%s: theObject is NULL \n",
10120 myTypeID
= OSTypeIDInst(theObject
);
10122 if ( myTypeID
== OSTypeID(OSDictionary
) ) {
10123 OSDictionary
* myDictionary
;
10125 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
10126 myIter
= OSCollectionIterator::withCollection( myDictionary
);
10127 if ( myIter
== NULL
)
10131 while ( (myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject())) ) {
10134 myValue
= myDictionary
->getObject(myKey
);
10135 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10136 if (myTempResult
) {
10137 // if we ever get a true result return true
10139 IOLOG_INDENT(indent
);
10140 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
10145 else if ( myTypeID
== OSTypeID(OSArray
) ) {
10148 myArray
= OSDynamicCast(OSArray
, theObject
);
10149 myIter
= OSCollectionIterator::withCollection(myArray
);
10150 if ( myIter
== NULL
)
10154 while ( (myValue
= myIter
->getNextObject()) ) {
10156 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10157 if (myTempResult
) {
10158 // if we ever get a true result return true
10160 IOLOG_INDENT(indent
);
10161 IOLog("OSArray: \n");
10166 else if ( myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
) ) {
10168 // should we look for addresses in strings?
10170 else if ( myTypeID
== OSTypeID(OSData
) ) {
10173 unsigned int myLen
;
10174 OSData
* myDataObj
;
10176 myDataObj
= OSDynamicCast(OSData
, theObject
);
10177 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
10178 myLen
= myDataObj
->getLength();
10180 if (myPtrPtr
&& myLen
&& myLen
> 7) {
10182 int myPtrCount
= (myLen
/ sizeof(void *));
10184 for (i
= 0; i
< myPtrCount
; i
++) {
10185 UInt64 numberValue
= (UInt64
) *(myPtrPtr
);
10187 if ( kext_alloc_max
!= 0 &&
10188 numberValue
>= kext_alloc_base
&&
10189 numberValue
< kext_alloc_max
) {
10191 OSKext
* myKext
= NULL
; // must release (looked up)
10192 // IOLog("found OSData %p in kext map %p to %p \n",
10194 // (void *) kext_alloc_base,
10195 // (void *) kext_alloc_max);
10197 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) *(myPtrPtr
) );
10199 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
10201 myKext
->getIdentifierCString());
10206 if ( vm_kernel_etext
!= 0 &&
10207 numberValue
>= vm_kernel_stext
&&
10208 numberValue
< vm_kernel_etext
) {
10209 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
10211 (void *) vm_kernel_stext
,
10212 (void *) vm_kernel_etext
);
10219 else if ( myTypeID
== OSTypeID(OSBoolean
) ) {
10221 // do nothing here...
10223 else if ( myTypeID
== OSTypeID(OSNumber
) ) {
10225 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
10227 UInt64 numberValue
= number
->unsigned64BitValue();
10229 if ( kext_alloc_max
!= 0 &&
10230 numberValue
>= kext_alloc_base
&&
10231 numberValue
< kext_alloc_max
) {
10233 OSKext
* myKext
= NULL
; // must release (looked up)
10234 IOLog("found OSNumber in kext map %p to %p \n",
10235 (void *) kext_alloc_base
,
10236 (void *) kext_alloc_max
);
10237 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10239 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) numberValue
);
10241 IOLog("found in kext \"%s\" \n",
10242 myKext
->getIdentifierCString());
10248 if ( vm_kernel_etext
!= 0 &&
10249 numberValue
>= vm_kernel_stext
&&
10250 numberValue
< vm_kernel_etext
) {
10251 IOLog("found OSNumber in kernel text segment %p to %p \n",
10252 (void *) vm_kernel_stext
,
10253 (void *) vm_kernel_etext
);
10254 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10260 const OSMetaClass
* myMetaClass
= NULL
;
10262 myMetaClass
= theObject
->getMetaClass();
10263 if ( myMetaClass
) {
10264 IOLog("class %s \n", myMetaClass
->getClassName() );
10267 IOLog("Unknown object \n" );
10274 #endif // KASLR_KEXT_DEBUG
10276 }; /* extern "C" */
10279 #pragma mark Backtrace Dump & kmod_get_info() support
10281 /*********************************************************************
10282 * This function must be safe to call in panic context.
10283 *********************************************************************/
10286 OSKext::printKextsInBacktrace(
10287 vm_offset_t
* addr
,
10289 int (* printf_func
)(const char *fmt
, ...),
10293 addr64_t summary_page
= 0;
10294 addr64_t last_summary_page
= 0;
10295 bool found_kmod
= false;
10299 if (!sKextSummariesLock
) return;
10300 IOLockLock(sKextSummariesLock
);
10303 if (!gLoadedKextSummaries
) {
10304 (*printf_func
)(" can't perform kext scan: no kext summary");
10308 summary_page
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
);
10309 last_summary_page
= round_page(summary_page
+ sLoadedKextSummariesAllocSize
);
10310 for (; summary_page
< last_summary_page
; summary_page
+= PAGE_SIZE
) {
10311 if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) {
10312 (*printf_func
)(" can't perform kext scan: "
10313 "missing kext summary page %p", summary_page
);
10318 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10319 OSKextLoadedKextSummary
* summary
;
10321 summary
= gLoadedKextSummaries
->summaries
+ i
;
10322 if (!summary
->address
) {
10326 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
10331 (*printf_func
)(" Kernel Extensions in backtrace:\n");
10335 printSummary(summary
, printf_func
, doUnslide
);
10340 IOLockUnlock(sKextSummariesLock
);
10346 /*********************************************************************
10347 * This function must be safe to call in panic context.
10348 *********************************************************************/
10351 OSKext::summaryIsInBacktrace(
10352 OSKextLoadedKextSummary
* summary
,
10353 vm_offset_t
* addr
,
10358 for (i
= 0; i
< cnt
; i
++) {
10359 vm_offset_t kscan_addr
= addr
[i
];
10360 if ((kscan_addr
>= summary
->address
) &&
10361 (kscan_addr
< (summary
->address
+ summary
->size
)))
10370 /*********************************************************************
10371 * scan list of loaded kext summaries looking for a load address match and if
10372 * found return the UUID C string. If not found then set empty string.
10373 *********************************************************************/
10374 static void findSummaryUUID(
10376 uuid_string_t uuid
);
10378 static void findSummaryUUID(
10380 uuid_string_t uuid
)
10384 uuid
[0] = 0x00; // default to no UUID
10386 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10387 OSKextLoadedKextSummary
* summary
;
10389 summary
= gLoadedKextSummaries
->summaries
+ i
;
10391 if (summary
->loadTag
== tag_ID
) {
10392 (void) uuid_unparse(summary
->uuid
, uuid
);
10399 /*********************************************************************
10400 * This function must be safe to call in panic context.
10401 *********************************************************************/
10402 void OSKext::printSummary(
10403 OSKextLoadedKextSummary
* summary
,
10404 int (* printf_func
)(const char *fmt
, ...),
10407 kmod_reference_t
* kmod_ref
= NULL
;
10408 uuid_string_t uuid
;
10409 char version
[kOSKextVersionMaxLength
];
10412 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
10413 strlcpy(version
, "unknown version", sizeof(version
));
10415 (void) uuid_unparse(summary
->uuid
, uuid
);
10418 tmpAddr
= VM_KERNEL_UNSLIDE(summary
->address
);
10421 tmpAddr
= summary
->address
;
10423 (*printf_func
)(" %s(%s)[%s]@0x%llx->0x%llx\n",
10424 summary
->name
, version
, uuid
,
10425 tmpAddr
, tmpAddr
+ summary
->size
- 1);
10427 /* print dependency info */
10428 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
10430 kmod_ref
= kmod_ref
->next
) {
10431 kmod_info_t
* rinfo
;
10433 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) {
10434 (*printf_func
)(" kmod dependency scan stopped "
10435 "due to missing dependency page: %p\n", kmod_ref
);
10438 rinfo
= kmod_ref
->info
;
10440 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) {
10441 (*printf_func
)(" kmod dependency scan stopped "
10442 "due to missing kmod page: %p\n", rinfo
);
10446 if (!rinfo
->address
) {
10447 continue; // skip fake entries for built-ins
10450 /* locate UUID in gLoadedKextSummaries */
10451 findSummaryUUID(rinfo
->id
, uuid
);
10454 tmpAddr
= VM_KERNEL_UNSLIDE(rinfo
->address
);
10457 tmpAddr
= rinfo
->address
;
10459 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
10460 rinfo
->name
, rinfo
->version
, uuid
, tmpAddr
);
10466 /*******************************************************************************
10467 * substitute() looks at an input string (a pointer within a larger buffer)
10468 * for a match to a substring, and on match it writes the marker & substitution
10469 * character to an output string, updating the scan (from) and
10470 * output (to) indexes as appropriate.
10471 *******************************************************************************/
10472 static int substitute(
10473 const char * scan_string
,
10475 uint32_t * to_index
,
10476 uint32_t * from_index
,
10477 const char * substring
,
10479 char substitution
);
10481 /* string_out must be at least KMOD_MAX_NAME bytes.
10485 const char * scan_string
,
10487 uint32_t * to_index
,
10488 uint32_t * from_index
,
10489 const char * substring
,
10493 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
10495 /* On a substring match, append the marker (if there is one) and then
10496 * the substitution character, updating the output (to) index accordingly.
10497 * Then update the input (from) length by the length of the substring
10498 * that got replaced.
10500 if (!strncmp(scan_string
, substring
, substring_length
)) {
10502 string_out
[(*to_index
)++] = marker
;
10504 string_out
[(*to_index
)++] = substitution
;
10505 (*from_index
) += substring_length
;
10511 /*******************************************************************************
10512 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
10513 * KMOD_MAX_NAME characters and performs various substitutions of common
10514 * prefixes & substrings as defined by tables in kext_panic_report.h.
10515 *******************************************************************************/
10516 static void compactIdentifier(
10517 const char * identifier
,
10518 char * identifier_out
,
10519 char ** identifier_out_end
);
10523 const char * identifier
,
10524 char * identifier_out
,
10525 char ** identifier_out_end
)
10527 uint32_t from_index
, to_index
;
10528 uint32_t scan_from_index
= 0;
10529 uint32_t scan_to_index
= 0;
10530 subs_entry_t
* subs_entry
= NULL
;
10533 from_index
= to_index
= 0;
10534 identifier_out
[0] = '\0';
10536 /* Replace certain identifier prefixes with shorter @+character sequences.
10537 * Check the return value of substitute() so we only replace the prefix.
10539 for (subs_entry
= &kext_identifier_prefix_subs
[0];
10540 subs_entry
->substring
&& !did_sub
;
10543 did_sub
= substitute(identifier
, identifier_out
,
10544 &scan_to_index
, &scan_from_index
,
10545 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
10549 /* Now scan through the identifier looking for the common substrings
10550 * and replacing them with shorter !+character sequences via substitute().
10552 for (/* see above */;
10553 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
10556 const char * scan_string
= &identifier
[scan_from_index
];
10560 if (scan_from_index
) {
10561 for (subs_entry
= &kext_identifier_substring_subs
[0];
10562 subs_entry
->substring
&& !did_sub
;
10565 did_sub
= substitute(scan_string
, identifier_out
,
10566 &scan_to_index
, &scan_from_index
,
10567 subs_entry
->substring
, '!', subs_entry
->substitute
);
10571 /* If we didn't substitute, copy the input character to the output.
10574 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
10578 identifier_out
[scan_to_index
] = '\0';
10579 if (identifier_out_end
) {
10580 *identifier_out_end
= &identifier_out
[scan_to_index
];
10586 /*******************************************************************************
10587 * assemble_identifier_and_version() adds to a string buffer a compacted
10588 * bundle identifier followed by a version string.
10589 *******************************************************************************/
10591 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
10593 static int assemble_identifier_and_version(
10594 kmod_info_t
* kmod_info
,
10595 char * identPlusVers
,
10599 assemble_identifier_and_version(
10600 kmod_info_t
* kmod_info
,
10601 char * identPlusVers
,
10606 compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
);
10607 result
= strnlen(identPlusVers
, KMOD_MAX_NAME
- 1);
10608 identPlusVers
[result
++] = '\t'; // increment for real char
10609 identPlusVers
[result
] = '\0'; // don't increment for nul char
10610 result
= strlcat(identPlusVers
, kmod_info
->version
, bufSize
);
10611 if (result
>= bufSize
) {
10612 identPlusVers
[bufSize
- 1] = '\0';
10613 result
= bufSize
- 1;
10619 /*******************************************************************************
10620 * Assumes sKextLock is held.
10621 *******************************************************************************/
10624 OSKext::saveLoadedKextPanicListTyped(
10625 const char * prefix
,
10629 uint32_t list_size
)
10632 unsigned int count
, i
;
10634 count
= sLoadedKexts
->getCount();
10641 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
10642 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
10644 uint32_t identPlusVersLength
;
10646 char identPlusVers
[2*KMOD_MAX_NAME
];
10649 printf("OSKext::saveLoadedKextPanicListTyped - "
10650 "NULL kext in loaded kext list; continuing\n");
10655 printf("OSKext::saveLoadedKextPanicListTyped - "
10656 "Kext type cast failed in loaded kext list; continuing\n");
10660 /* Skip all built-in kexts.
10662 if (theKext
->isKernelComponent()) {
10666 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
10668 /* Filter for kmod name (bundle identifier).
10670 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
10671 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
10675 /* Filter for libraries (kexts that have a compatible version).
10677 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
10678 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
10684 !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) {
10686 printf("kext scan stopped due to missing kmod_info page: %p\n",
10691 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
10693 sizeof(identPlusVers
));
10694 if (!identPlusVersLength
) {
10695 printf("error saving loaded kext info\n");
10699 /* make sure everything fits and we null terminate.
10701 tempLen
= strlcat(paniclist
, identPlusVers
, list_size
);
10702 if (tempLen
>= list_size
) {
10703 // panic list is full, keep it and null terminate
10704 paniclist
[list_size
- 1] = 0x00;
10708 tempLen
= strlcat(paniclist
, "\n", list_size
);
10709 if (tempLen
>= list_size
) {
10710 // panic list is full, keep it and null terminate
10711 paniclist
[list_size
- 1] = 0x00;
10723 /*********************************************************************
10724 *********************************************************************/
10727 OSKext::saveLoadedKextPanicList(void)
10729 char * newlist
= NULL
;
10730 uint32_t newlist_size
= 0;
10732 newlist_size
= KEXT_PANICLIST_SIZE
;
10733 newlist
= (char *)kalloc_tag(newlist_size
, VM_KERN_MEMORY_OSKEXT
);
10736 OSKextLog(/* kext */ NULL
,
10737 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
10738 "Couldn't allocate kext panic log buffer.");
10744 // non-"com.apple." kexts
10745 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
10746 /* libs? */ -1, newlist
, newlist_size
) != 0) {
10750 // "com.apple." nonlibrary kexts
10751 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10752 /* libs? */ 0, newlist
, newlist_size
) != 0) {
10756 // "com.apple." library kexts
10757 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10758 /* libs? */ 1, newlist
, newlist_size
) != 0) {
10763 if (loaded_kext_paniclist
) {
10764 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
10766 loaded_kext_paniclist
= newlist
;
10768 loaded_kext_paniclist_size
= newlist_size
;
10772 kfree(newlist
, newlist_size
);
10777 /*********************************************************************
10778 * Assumes sKextLock is held.
10779 *********************************************************************/
10781 OSKext::savePanicString(bool isLoading
)
10786 return; // do not goto finish here b/c of lock
10789 len
= assemble_identifier_and_version( kmod_info
,
10790 (isLoading
) ? last_loaded_str_buf
: last_unloaded_str_buf
,
10791 (isLoading
) ? sizeof(last_loaded_str_buf
) : sizeof(last_unloaded_str_buf
) );
10793 printf("error saving unloaded kext info\n");
10798 last_loaded_strlen
= len
;
10799 last_loaded_address
= (void *)kmod_info
->address
;
10800 last_loaded_size
= kmod_info
->size
;
10801 clock_get_uptime(&last_loaded_timestamp
);
10803 last_unloaded_strlen
= len
;
10804 last_unloaded_address
= (void *)kmod_info
->address
;
10805 last_unloaded_size
= kmod_info
->size
;
10806 clock_get_uptime(&last_unloaded_timestamp
);
10813 /*********************************************************************
10814 *********************************************************************/
10817 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
10819 if (last_loaded_strlen
) {
10820 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
10821 AbsoluteTime_to_scalar(&last_loaded_timestamp
),
10822 last_loaded_strlen
, last_loaded_str_buf
,
10823 last_loaded_address
, last_loaded_size
);
10826 if (last_unloaded_strlen
) {
10827 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
10828 AbsoluteTime_to_scalar(&last_unloaded_timestamp
),
10829 last_unloaded_strlen
, last_unloaded_str_buf
,
10830 last_unloaded_address
, last_unloaded_size
);
10833 printf_func("loaded kexts:\n");
10834 if (loaded_kext_paniclist
&&
10835 pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) &&
10836 loaded_kext_paniclist
[0]) {
10838 printf_func("%.*s",
10839 strnlen(loaded_kext_paniclist
, loaded_kext_paniclist_size
),
10840 loaded_kext_paniclist
);
10842 printf_func("(none)\n");
10847 /*********************************************************************
10848 * Assumes sKextLock is held.
10849 *********************************************************************/
10852 OSKext::updateLoadedKextSummaries(void)
10854 kern_return_t result
= KERN_FAILURE
;
10855 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
10856 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
10858 vm_map_offset_t start
, end
;
10859 size_t summarySize
= 0;
10864 OSKextActiveAccount
* accountingList
;
10865 OSKextActiveAccount
* prevAccountingList
;
10866 uint32_t idx
, accountingListAlloc
, accountingListCount
, prevAccountingListCount
;
10868 prevAccountingList
= NULL
;
10869 prevAccountingListCount
= 0;
10871 #if DEVELOPMENT || DEBUG
10872 if (IORecursiveLockHaveLock(sKextLock
) == false) {
10873 panic("sKextLock must be held");
10877 IOLockLock(sKextSummariesLock
);
10879 count
= sLoadedKexts
->getCount();
10880 for (i
= 0, maxKexts
= 0; i
< count
; ++i
) {
10881 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10882 maxKexts
+= (aKext
&& aKext
->isExecutable());
10885 if (!maxKexts
) goto finish
;
10886 if (maxKexts
< kOSKextTypicalLoadCount
) maxKexts
= kOSKextTypicalLoadCount
;
10888 /* Calculate the size needed for the new summary headers.
10891 size
= sizeof(*gLoadedKextSummaries
);
10892 size
+= maxKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
10893 size
= round_page(size
);
10895 if (gLoadedKextSummaries
== NULL
|| sLoadedKextSummariesAllocSize
< size
) {
10896 if (gLoadedKextSummaries
) {
10897 kmem_free(kernel_map
,
10898 (vm_offset_t
)gLoadedKextSummaries
,
10899 sLoadedKextSummariesAllocSize
);
10900 gLoadedKextSummaries
= NULL
;
10901 sLoadedKextSummariesAllocSize
= 0;
10903 result
= kmem_alloc(kernel_map
,
10904 (vm_offset_t
*)&summaryHeaderAlloc
,
10905 size
, VM_KERN_MEMORY_OSKEXT
);
10906 if (result
!= KERN_SUCCESS
) goto finish
;
10907 summaryHeader
= summaryHeaderAlloc
;
10908 summarySize
= size
;
10911 summaryHeader
= gLoadedKextSummaries
;
10912 summarySize
= sLoadedKextSummariesAllocSize
;
10914 start
= (vm_map_offset_t
) summaryHeader
;
10915 end
= start
+ summarySize
;
10916 result
= vm_map_protect(kernel_map
,
10921 if (result
!= KERN_SUCCESS
) goto finish
;
10924 /* Populate the summary header.
10927 bzero(summaryHeader
, summarySize
);
10928 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
10929 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
10931 /* Populate each kext summary.
10934 count
= sLoadedKexts
->getCount();
10935 accountingListAlloc
= 0;
10936 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
10937 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10938 if (!aKext
|| !aKext
->isExecutable()) {
10942 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
10943 summaryHeader
->numSummaries
++;
10944 accountingListAlloc
++;
10947 accountingList
= IONew(typeof(accountingList
[0]), accountingListAlloc
);
10948 accountingListCount
= 0;
10949 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
10950 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10951 if (!aKext
|| !aKext
->isExecutable()) {
10955 OSKextActiveAccount activeAccount
;
10956 aKext
->updateActiveAccount(&activeAccount
);
10957 // order by address
10958 for (idx
= 0; idx
< accountingListCount
; idx
++)
10960 if (activeAccount
.address
< accountingList
[idx
].address
) break;
10962 bcopy(&accountingList
[idx
], &accountingList
[idx
+ 1], (accountingListCount
- idx
) * sizeof(accountingList
[0]));
10963 accountingList
[idx
] = activeAccount
;
10964 accountingListCount
++;
10966 assert(accountingListCount
== accountingListAlloc
);
10967 /* Write protect the buffer and move it into place.
10970 start
= (vm_map_offset_t
) summaryHeader
;
10971 end
= start
+ summarySize
;
10973 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_READ
, FALSE
);
10974 if (result
!= KERN_SUCCESS
) goto finish
;
10976 gLoadedKextSummaries
= summaryHeader
;
10977 sLoadedKextSummariesAllocSize
= summarySize
;
10978 summaryHeaderAlloc
= NULL
;
10980 /* Call the magic breakpoint function through a static function pointer so
10981 * the compiler can't optimize the function away.
10983 if (sLoadedKextSummariesUpdated
) (*sLoadedKextSummariesUpdated
)();
10985 IOSimpleLockLock(sKextAccountsLock
);
10986 prevAccountingList
= sKextAccounts
;
10987 prevAccountingListCount
= sKextAccountsCount
;
10988 sKextAccounts
= accountingList
;
10989 sKextAccountsCount
= accountingListCount
;
10990 IOSimpleLockUnlock(sKextAccountsLock
);
10993 IOLockUnlock(sKextSummariesLock
);
10995 /* If we had to allocate a new buffer but failed to generate the summaries,
10998 if (summaryHeaderAlloc
) {
10999 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
11001 if (prevAccountingList
) {
11002 IODelete(prevAccountingList
, typeof(accountingList
[0]), prevAccountingListCount
);
11008 /*********************************************************************
11009 *********************************************************************/
11011 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
11015 strlcpy(summary
->name
, getIdentifierCString(),
11016 sizeof(summary
->name
));
11020 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
11021 OSSafeRelease(uuid
);
11024 summary
->address
= kmod_info
->address
;
11025 summary
->size
= kmod_info
->size
;
11026 summary
->version
= getVersion();
11027 summary
->loadTag
= kmod_info
->id
;
11028 summary
->flags
= 0;
11029 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
11034 /*********************************************************************
11035 *********************************************************************/
11038 OSKext::updateActiveAccount(OSKextActiveAccount
*account
)
11040 bzero(account
, sizeof(*account
));
11041 account
->address
= kmod_info
->address
;
11042 if (account
->address
) {
11043 account
->address_end
= kmod_info
->address
+ kmod_info
->size
;
11045 account
->account
= this->account
;
11048 extern "C" const vm_allocation_site_t
*
11049 OSKextGetAllocationSiteForCaller(uintptr_t address
)
11051 OSKextActiveAccount
* active
;
11052 vm_allocation_site_t
* site
;
11056 IOSimpleLockLock(sKextAccountsLock
);
11058 // bsearch sKextAccounts list
11059 for (baseIdx
= 0, lim
= sKextAccountsCount
; lim
; lim
>>= 1)
11061 active
= &sKextAccounts
[baseIdx
+ (lim
>> 1)];
11062 if ((address
>= active
->address
) && (address
< active
->address_end
))
11064 site
= &active
->account
->site
;
11065 if (!site
->tag
) vm_tag_alloc_locked(site
);
11068 else if (address
> active
->address
)
11071 baseIdx
+= (lim
>> 1) + 1;
11076 IOSimpleLockUnlock(sKextAccountsLock
);
11081 extern "C" uint32_t
11082 OSKextGetKmodIDForSite(vm_allocation_site_t
* site
)
11084 OSKextAccount
* account
= (typeof(account
)) site
;
11085 return (account
->loadTag
);
11089 OSKextFreeSite(vm_allocation_site_t
* site
)
11091 OSKextAccount
* freeAccount
= (typeof(freeAccount
)) site
;
11092 IODelete(freeAccount
, OSKextAccount
, 1);
11095 /*********************************************************************
11096 *********************************************************************/
11098 #if CONFIG_KEC_FIPS
11101 #pragma mark Kernel External Components for FIPS compliance
11104 /*********************************************************************
11105 * Kernel External Components for FIPS compliance (KEC_FIPS)
11106 *********************************************************************/
11108 GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
)
11110 AppleTEXTHash_t my_ath
= {1, 0, NULL
};
11111 AppleTEXTHash_t
* my_athp
= NULL
; // do not release
11112 OSDictionary
* textHashDict
= NULL
; // do not release
11113 OSData
* segmentHash
= NULL
; // do not release
11115 if (theKext
== NULL
|| theInfoDict
== NULL
) {
11119 textHashDict
= OSDynamicCast(OSDictionary
, theInfoDict
->getObject(kAppleTextHashesKey
));
11120 if (textHashDict
== NULL
) {
11124 segmentHash
= OSDynamicCast(OSData
,
11125 textHashDict
->getObject(ARCHNAME
));
11126 if (segmentHash
== NULL
) {
11130 // KEC_FIPS type kexts never unload so we don't have to clean up our
11132 if (kmem_alloc(kernel_map
, (vm_offset_t
*) &my_athp
,
11133 sizeof(AppleTEXTHash_t
), VM_KERN_MEMORY_OSKEXT
) != KERN_SUCCESS
) {
11137 memcpy(my_athp
, &my_ath
, sizeof(my_ath
));
11138 my_athp
->ath_length
= segmentHash
->getLength();
11139 if (my_athp
->ath_length
> 0) {
11140 my_athp
->ath_hash
= (void *)segmentHash
->getBytesNoCopy();
11145 kOSKextLogErrorLevel
|
11146 kOSKextLogGeneralFlag
,
11147 "Kext %s ath_version %d ath_length %d ath_hash %p",
11148 theKext
->getIdentifierCString(),
11149 my_athp
->ath_version
,
11150 my_athp
->ath_length
,
11151 my_athp
->ath_hash
);
11154 return( (void *) my_athp
);
11157 #endif // CONFIG_KEC_FIPS