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.
2512 OSKext
* newKext
= OSKext::withMkext2Info(infoDict
, mkextData
);
2513 OSSafeRelease(newKext
);
2516 /* Even if we didn't keep any kexts from the mkext, we may have a load
2517 * request to process, so we are successful (no errors occurred).
2519 result
= kOSReturnSuccess
;
2523 OSSafeRelease(parsedXML
);
2524 OSSafeRelease(mkextPlistUncompressedData
);
2525 OSSafeRelease(errorString
);
2530 /*********************************************************************
2531 *********************************************************************/
2534 OSKext::withMkext2Info(
2535 OSDictionary
* anInfoDict
,
2538 OSKext
* newKext
= new OSKext
;
2540 if (newKext
&& !newKext
->initWithMkext2Info(anInfoDict
, mkextData
)) {
2548 /*********************************************************************
2549 *********************************************************************/
2551 OSKext::initWithMkext2Info(
2552 OSDictionary
* anInfoDict
,
2555 bool result
= false;
2556 OSString
* kextPath
= NULL
; // do not release
2557 OSNumber
* executableOffsetNum
= NULL
; // do not release
2558 OSCollectionIterator
* iterator
= NULL
; // must release
2559 OSData
* executable
= NULL
; // must release
2561 if (!super::init()) {
2565 /* Get the path. Don't look for an arch-specific path property.
2567 kextPath
= OSDynamicCast(OSString
,
2568 anInfoDict
->getObject(kMKEXTBundlePathKey
));
2570 if (!setInfoDictionaryAndPath(anInfoDict
, kextPath
)) {
2574 /* If we have a path to the executable, save it.
2576 executableRelPath
= OSDynamicCast(OSString
,
2577 anInfoDict
->getObject(kMKEXTExecutableRelativePathKey
));
2578 if (executableRelPath
) {
2579 executableRelPath
->retain();
2582 /* Don't need the paths to be in the info dictionary any more.
2584 anInfoDict
->removeObject(kMKEXTBundlePathKey
);
2585 anInfoDict
->removeObject(kMKEXTExecutableRelativePathKey
);
2587 executableOffsetNum
= OSDynamicCast(OSNumber
,
2588 infoDict
->getObject(kMKEXTExecutableKey
));
2589 if (executableOffsetNum
) {
2590 executable
= createMkext2FileEntry(mkextData
,
2591 executableOffsetNum
, "executable");
2592 infoDict
->removeObject(kMKEXTExecutableKey
);
2596 if (!setExecutable(executable
, mkextData
, true)) {
2601 result
= registerIdentifier();
2605 OSSafeRelease(executable
);
2606 OSSafeRelease(iterator
);
2610 /*********************************************************************
2611 *********************************************************************/
2613 OSKext::createMkext2FileEntry(
2615 OSNumber
* offsetNum
,
2618 OSData
* result
= NULL
;
2619 MkextEntryRef entryRef
;
2620 uint8_t * mkextBuffer
= (uint8_t *)mkextData
->getBytesNoCopy();
2621 uint32_t entryOffset
= offsetNum
->unsigned32BitValue();
2623 result
= OSData::withCapacity(sizeof(entryRef
));
2628 entryRef
.mkext
= (mkext_basic_header
*)mkextBuffer
;
2629 entryRef
.fileinfo
= mkextBuffer
+ entryOffset
;
2630 if (!result
->appendBytes(&entryRef
, sizeof(entryRef
))) {
2631 OSSafeReleaseNULL(result
);
2638 kOSKextLogErrorLevel
|
2639 kOSKextLogArchiveFlag
,
2640 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2641 name
, getIdentifierCString());
2646 /*********************************************************************
2647 *********************************************************************/
2649 static void * z_alloc(void *, u_int items
, u_int size
);
2650 static void z_free(void *, void *ptr
);
2652 typedef struct z_mem
{
2653 uint32_t alloc_size
;
2658 * Space allocation and freeing routines for use by zlib routines.
2661 z_alloc(void * notused __unused
, u_int num_items
, u_int size
)
2663 void * result
= NULL
;
2664 z_mem
* zmem
= NULL
;
2666 uint64_t total
= ((uint64_t)num_items
) * ((uint64_t)size
);
2667 //Check for overflow due to multiplication
2668 if (total
> UINT32_MAX
){
2669 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
2670 notused
, num_items
, size
, num_items
, size
);
2673 uint64_t allocSize64
= total
+ ((uint64_t)sizeof(zmem
));
2674 //Check for overflow due to addition
2675 if (allocSize64
> UINT32_MAX
){
2676 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
2677 notused
, num_items
, size
, (uint32_t)total
, sizeof(zmem
));
2679 uint32_t allocSize
= (uint32_t)allocSize64
;
2681 zmem
= (z_mem
*)kalloc_tag(allocSize
, VM_KERN_MEMORY_OSKEXT
);
2685 zmem
->alloc_size
= allocSize
;
2686 result
= (void *)&(zmem
->data
);
2692 z_free(void * notused __unused
, void * ptr
)
2694 uint32_t * skipper
= (uint32_t *)ptr
- 1;
2695 z_mem
* zmem
= (z_mem
*)skipper
;
2696 kfree((void *)zmem
, zmem
->alloc_size
);
2702 OSKext::extractMkext2FileData(
2705 uint32_t compressedSize
,
2708 OSData
* result
= NULL
;
2710 OSData
* uncompressedData
= NULL
; // release on error
2712 uint8_t * uncompressedDataBuffer
= 0; // do not free
2713 unsigned long uncompressedSize
;
2715 bool zstream_inited
= false;
2718 /* If the file isn't compressed, we want to make a copy
2719 * so that we don't have the tie to the larger mkext file buffer any more.
2721 if (!compressedSize
) {
2722 uncompressedData
= OSData::withBytes(data
, fullSize
);
2723 // xxx - no check for failure?
2724 result
= uncompressedData
;
2728 if (KERN_SUCCESS
!= kmem_alloc(kernel_map
,
2729 (vm_offset_t
*)&uncompressedDataBuffer
, fullSize
, VM_KERN_MEMORY_OSKEXT
)) {
2731 /* How's this for cheesy? The kernel is only asked to extract
2732 * kext plists so we tailor the log messages.
2736 kOSKextLogErrorLevel
|
2737 kOSKextLogArchiveFlag
,
2738 "Allocation failure extracting %s from mkext.", name
);
2741 kOSKextLogErrorLevel
|
2742 kOSKextLogArchiveFlag
,
2743 "Allocation failure extracting %s from mkext for kext %s.",
2744 name
, getIdentifierCString());
2749 uncompressedData
= OSData::withBytesNoCopy(uncompressedDataBuffer
, fullSize
);
2750 if (!uncompressedData
) {
2753 kOSKextLogErrorLevel
|
2754 kOSKextLogArchiveFlag
,
2755 "Allocation failure extracting %s from mkext.", name
);
2758 kOSKextLogErrorLevel
|
2759 kOSKextLogArchiveFlag
,
2760 "Allocation failure extracting %s from mkext for kext %s.",
2761 name
, getIdentifierCString());
2765 uncompressedData
->setDeallocFunction(&osdata_kmem_free
);
2769 kOSKextLogDetailLevel
|
2770 kOSKextLogArchiveFlag
,
2771 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2772 name
, compressedSize
, fullSize
);
2775 kOSKextLogDetailLevel
|
2776 kOSKextLogArchiveFlag
,
2777 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2778 getIdentifierCString(), name
, compressedSize
, fullSize
);
2781 bzero(&zstream
, sizeof(zstream
));
2782 zstream
.next_in
= (UInt8
*)data
;
2783 zstream
.avail_in
= compressedSize
;
2785 zstream
.next_out
= uncompressedDataBuffer
;
2786 zstream
.avail_out
= fullSize
;
2788 zstream
.zalloc
= z_alloc
;
2789 zstream
.zfree
= z_free
;
2791 zlib_result
= inflateInit(&zstream
);
2792 if (Z_OK
!= zlib_result
) {
2795 kOSKextLogErrorLevel
|
2796 kOSKextLogArchiveFlag
,
2797 "Mkext error; zlib inflateInit failed (%d) for %s.",
2801 kOSKextLogErrorLevel
|
2802 kOSKextLogArchiveFlag
,
2803 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2804 getIdentifierCString(), zlib_result
, name
);
2808 zstream_inited
= true;
2811 zlib_result
= inflate(&zstream
, Z_FINISH
);
2813 if (zlib_result
== Z_STREAM_END
|| zlib_result
== Z_OK
) {
2814 uncompressedSize
= zstream
.total_out
;
2818 kOSKextLogErrorLevel
|
2819 kOSKextLogArchiveFlag
,
2820 "Mkext error; zlib inflate failed (%d) for %s.",
2824 kOSKextLogErrorLevel
|
2825 kOSKextLogArchiveFlag
,
2826 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
2827 getIdentifierCString(), zlib_result
, name
);
2831 kOSKextLogErrorLevel
|
2832 kOSKextLogArchiveFlag
,
2833 "zlib error: %s.", zstream
.msg
);
2838 if (uncompressedSize
!= fullSize
) {
2841 kOSKextLogErrorLevel
|
2842 kOSKextLogArchiveFlag
,
2843 "Mkext error; zlib inflate discrepancy for %s, "
2844 "uncompressed size != original size.", name
);
2847 kOSKextLogErrorLevel
|
2848 kOSKextLogArchiveFlag
,
2849 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
2850 "uncompressed size != original size.",
2851 getIdentifierCString(), name
);
2856 result
= uncompressedData
;
2859 /* Don't bother checking return, nothing we can do on fail.
2861 if (zstream_inited
) inflateEnd(&zstream
);
2864 OSSafeRelease(uncompressedData
);
2870 /*********************************************************************
2871 *********************************************************************/
2874 OSKext::loadFromMkext(
2875 OSKextLogSpec clientLogFilter
,
2877 uint32_t mkextBufferLength
,
2879 uint32_t * logInfoLengthOut
)
2881 OSReturn result
= kOSReturnError
;
2882 OSReturn tempResult
= kOSReturnError
;
2884 OSData
* mkextData
= NULL
; // must release
2885 OSDictionary
* mkextPlist
= NULL
; // must release
2887 OSArray
* logInfoArray
= NULL
; // must release
2888 OSSerialize
* serializer
= NULL
; // must release
2890 OSString
* predicate
= NULL
; // do not release
2891 OSDictionary
* requestArgs
= NULL
; // do not release
2893 OSString
* kextIdentifier
= NULL
; // do not release
2894 OSNumber
* startKextExcludeNum
= NULL
; // do not release
2895 OSNumber
* startMatchingExcludeNum
= NULL
; // do not release
2896 OSBoolean
* delayAutounloadBool
= NULL
; // do not release
2897 OSArray
* personalityNames
= NULL
; // do not release
2899 /* Default values for these two options: regular autounload behavior,
2900 * load all kexts, send no personalities.
2902 Boolean delayAutounload
= false;
2903 OSKextExcludeLevel startKextExcludeLevel
= kOSKextExcludeNone
;
2904 OSKextExcludeLevel startMatchingExcludeLevel
= kOSKextExcludeAll
;
2906 IORecursiveLockLock(sKextLock
);
2910 *logInfoLengthOut
= 0;
2913 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
2915 OSKextLog(/* kext */ NULL
,
2916 kOSKextLogDebugLevel
|
2918 "Received kext load request from user space.");
2920 /* Regardless of processing, the fact that we have gotten here means some
2921 * user-space program is up and talking to us, so we'll switch our kext
2922 * registration to reflect that.
2924 if (!sUserLoadsActive
) {
2925 OSKextLog(/* kext */ NULL
,
2926 kOSKextLogProgressLevel
|
2927 kOSKextLogGeneralFlag
| kOSKextLogLoadFlag
,
2928 "Switching to late startup (user-space) kext loading policy.");
2930 sUserLoadsActive
= true;
2933 if (!sLoadEnabled
) {
2934 OSKextLog(/* kext */ NULL
,
2935 kOSKextLogErrorLevel
|
2937 "Kext loading is disabled.");
2938 result
= kOSKextReturnDisabled
;
2942 /* Note that we do not set a dealloc function on this OSData
2943 * object! No references to it can remain after the loadFromMkext()
2944 * call since we are in a MIG function, and will vm_deallocate()
2947 mkextData
= OSData::withBytesNoCopy(mkextBuffer
,
2950 OSKextLog(/* kext */ NULL
,
2951 kOSKextLogErrorLevel
|
2952 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
2953 "Failed to create wrapper for kext load request.");
2954 result
= kOSKextReturnNoMemory
;
2958 result
= readMkext2Archive(mkextData
, &mkextPlist
, NULL
);
2959 if (result
!= kOSReturnSuccess
) {
2960 OSKextLog(/* kext */ NULL
,
2961 kOSKextLogErrorLevel
|
2963 "Failed to read kext load request.");
2967 predicate
= _OSKextGetRequestPredicate(mkextPlist
);
2968 if (!predicate
|| !predicate
->isEqualTo(kKextRequestPredicateLoad
)) {
2969 OSKextLog(/* kext */ NULL
,
2970 kOSKextLogErrorLevel
|
2972 "Received kext load request with no predicate; skipping.");
2973 result
= kOSKextReturnInvalidArgument
;
2977 requestArgs
= OSDynamicCast(OSDictionary
,
2978 mkextPlist
->getObject(kKextRequestArgumentsKey
));
2979 if (!requestArgs
|| !requestArgs
->getCount()) {
2980 OSKextLog(/* kext */ NULL
,
2981 kOSKextLogErrorLevel
|
2983 "Received kext load request with no arguments.");
2984 result
= kOSKextReturnInvalidArgument
;
2988 kextIdentifier
= OSDynamicCast(OSString
,
2989 requestArgs
->getObject(kKextRequestArgumentBundleIdentifierKey
));
2990 if (!kextIdentifier
) {
2991 OSKextLog(/* kext */ NULL
,
2992 kOSKextLogErrorLevel
|
2994 "Received kext load request with no kext identifier.");
2995 result
= kOSKextReturnInvalidArgument
;
2999 startKextExcludeNum
= OSDynamicCast(OSNumber
,
3000 requestArgs
->getObject(kKextRequestArgumentStartExcludeKey
));
3001 startMatchingExcludeNum
= OSDynamicCast(OSNumber
,
3002 requestArgs
->getObject(kKextRequestArgumentStartMatchingExcludeKey
));
3003 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
3004 requestArgs
->getObject(kKextRequestArgumentDelayAutounloadKey
));
3005 personalityNames
= OSDynamicCast(OSArray
,
3006 requestArgs
->getObject(kKextRequestArgumentPersonalityNamesKey
));
3008 if (delayAutounloadBool
) {
3009 delayAutounload
= delayAutounloadBool
->getValue();
3011 if (startKextExcludeNum
) {
3012 startKextExcludeLevel
= startKextExcludeNum
->unsigned8BitValue();
3014 if (startMatchingExcludeNum
) {
3015 startMatchingExcludeLevel
= startMatchingExcludeNum
->unsigned8BitValue();
3018 OSKextLog(/* kext */ NULL
,
3019 kOSKextLogProgressLevel
|
3021 "Received request from user space to load kext %s.",
3022 kextIdentifier
->getCStringNoCopy());
3024 /* Load the kext, with no deferral, since this is a load from outside
3026 * xxx - Would like a better way to handle the default values for the
3027 * xxx - start/match opt args.
3029 result
= OSKext::loadKextWithIdentifier(
3031 /* allowDefer */ false,
3033 startKextExcludeLevel
,
3034 startMatchingExcludeLevel
,
3036 if (result
!= kOSReturnSuccess
) {
3039 /* If the load came down from kextd, it will shortly inform IOCatalogue
3040 * for matching via a separate IOKit calldown.
3045 /* Gather up the collected log messages for user space. Any
3046 * error messages past this call will not make it up as log messages
3047 * but will be in the system log.
3049 logInfoArray
= OSKext::clearUserSpaceLogFilter();
3051 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
3052 tempResult
= OSKext::serializeLogInfo(logInfoArray
,
3053 logInfoOut
, logInfoLengthOut
);
3054 if (tempResult
!= kOSReturnSuccess
) {
3055 result
= tempResult
;
3059 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3061 /* Note: mkextDataObject will have been retained by every kext w/an
3062 * executable in it. That should all have been flushed out at the
3063 * and of the load operation, but you never know....
3065 if (mkextData
&& mkextData
->getRetainCount() > 1) {
3066 OSKextLog(/* kext */ NULL
,
3067 kOSKextLogErrorLevel
|
3068 kOSKextLogLoadFlag
| kOSKextLogIPCFlag
,
3069 "Kext load request buffer from user space still retained by a kext; "
3070 "probable memory leak.");
3073 IORecursiveLockUnlock(sKextLock
);
3075 OSSafeRelease(mkextData
);
3076 OSSafeRelease(mkextPlist
);
3077 OSSafeRelease(serializer
);
3078 OSSafeRelease(logInfoArray
);
3083 /*********************************************************************
3084 *********************************************************************/
3087 OSKext::serializeLogInfo(
3088 OSArray
* logInfoArray
,
3090 uint32_t * logInfoLengthOut
)
3092 OSReturn result
= kOSReturnError
;
3093 char * buffer
= NULL
;
3094 kern_return_t kmem_result
= KERN_FAILURE
;
3095 OSSerialize
* serializer
= NULL
; // must release; reused
3096 char * logInfo
= NULL
; // returned by reference
3097 uint32_t logInfoLength
= 0;
3099 if (!logInfoArray
|| !logInfoOut
|| !logInfoLengthOut
) {
3100 OSKextLog(/* kext */ NULL
,
3101 kOSKextLogErrorLevel
|
3103 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3104 /* Bad programmer. */
3105 result
= kOSKextReturnInvalidArgument
;
3109 serializer
= OSSerialize::withCapacity(0);
3111 OSKextLog(/* kext */ NULL
,
3112 kOSKextLogErrorLevel
|
3114 "Failed to create serializer on log info for request from user space.");
3115 /* Incidental error; we're going to (try to) allow the request
3116 * itself to succeed. */
3119 if (!logInfoArray
->serialize(serializer
)) {
3120 OSKextLog(/* kext */ NULL
,
3121 kOSKextLogErrorLevel
|
3123 "Failed to serialize log info for request from user space.");
3124 /* Incidental error; we're going to (try to) allow the request
3125 * itself to succeed. */
3127 logInfo
= serializer
->text();
3128 logInfoLength
= serializer
->getLength();
3130 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
, round_page(logInfoLength
), VM_KERN_MEMORY_OSKEXT
);
3131 if (kmem_result
!= KERN_SUCCESS
) {
3132 OSKextLog(/* kext */ NULL
,
3133 kOSKextLogErrorLevel
|
3135 "Failed to copy log info for request from user space.");
3136 /* Incidental error; we're going to (try to) allow the request
3139 /* 11981737 - clear uninitialized data in last page */
3140 bzero((void *)(buffer
+ logInfoLength
),
3141 (round_page(logInfoLength
) - logInfoLength
));
3142 memcpy(buffer
, logInfo
, logInfoLength
);
3143 *logInfoOut
= buffer
;
3144 *logInfoLengthOut
= logInfoLength
;
3148 result
= kOSReturnSuccess
;
3150 OSSafeRelease(serializer
);
3155 #pragma mark Instance Management Methods
3157 /*********************************************************************
3158 *********************************************************************/
3160 OSKext::lookupKextWithIdentifier(const char * kextIdentifier
)
3162 OSKext
* foundKext
= NULL
;
3164 IORecursiveLockLock(sKextLock
);
3165 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3167 foundKext
->retain();
3169 IORecursiveLockUnlock(sKextLock
);
3174 /*********************************************************************
3175 *********************************************************************/
3177 OSKext::lookupKextWithIdentifier(OSString
* kextIdentifier
)
3179 return OSKext::lookupKextWithIdentifier(kextIdentifier
->getCStringNoCopy());
3182 /*********************************************************************
3183 *********************************************************************/
3185 OSKext::lookupKextWithLoadTag(uint32_t aTag
)
3187 OSKext
* foundKext
= NULL
; // returned
3190 IORecursiveLockLock(sKextLock
);
3192 count
= sLoadedKexts
->getCount();
3193 for (i
= 0; i
< count
; i
++) {
3194 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3195 if (thisKext
->getLoadTag() == aTag
) {
3196 foundKext
= thisKext
;
3197 foundKext
->retain();
3203 IORecursiveLockUnlock(sKextLock
);
3208 /*********************************************************************
3209 *********************************************************************/
3211 OSKext::lookupKextWithAddress(vm_address_t address
)
3213 OSKext
* foundKext
= NULL
; // returned
3216 IORecursiveLockLock(sKextLock
);
3218 count
= sLoadedKexts
->getCount();
3219 for (i
= 0; i
< count
; i
++) {
3220 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3221 if (thisKext
->linkedExecutable
) {
3222 vm_address_t kext_start
=
3223 (vm_address_t
)thisKext
->linkedExecutable
->getBytesNoCopy();
3224 vm_address_t kext_end
= kext_start
+
3225 thisKext
->linkedExecutable
->getLength();
3227 if ((kext_start
<= address
) && (address
< kext_end
)) {
3228 foundKext
= thisKext
;
3229 foundKext
->retain();
3236 IORecursiveLockUnlock(sKextLock
);
3242 /*********************************************************************
3243 *********************************************************************/
3245 OSKext::lookupKextWithUUID(uuid_t wanted
)
3247 OSKext
* foundKext
= NULL
; // returned
3250 IORecursiveLockLock(sKextLock
);
3252 count
= sLoadedKexts
->getCount();
3254 for (i
= 0; i
< count
; i
++) {
3255 OSKext
* thisKext
= NULL
;
3257 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3262 OSData
*uuid_data
= thisKext
->copyUUID();
3268 memcpy(&uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
3269 uuid_data
->release();
3271 if (0 == uuid_compare(wanted
, uuid
)) {
3272 foundKext
= thisKext
;
3273 foundKext
->retain();
3280 IORecursiveLockUnlock(sKextLock
);
3288 /*********************************************************************
3289 *********************************************************************/
3291 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier
)
3293 bool result
= false;
3294 OSKext
* foundKext
= NULL
; // returned
3296 IORecursiveLockLock(sKextLock
);
3298 foundKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
3299 if (foundKext
&& foundKext
->isLoaded()) {
3303 IORecursiveLockUnlock(sKextLock
);
3308 /*********************************************************************
3309 * xxx - should spawn a separate thread so a kext can safely have
3310 * xxx - itself unloaded.
3311 *********************************************************************/
3316 bool terminateServicesAndRemovePersonalitiesFlag
)
3318 OSReturn result
= kOSKextReturnInUse
;
3319 OSKext
* checkKext
= NULL
; // do not release
3321 int macCheckResult
= 0;
3322 kauth_cred_t cred
= NULL
;
3325 IORecursiveLockLock(sKextLock
);
3327 /* If the kext has no identifier, it failed to init
3328 * so isn't in sKextsByID and it isn't loaded.
3330 if (!aKext
->getIdentifier()) {
3331 result
= kOSReturnSuccess
;
3335 checkKext
= OSDynamicCast(OSKext
,
3336 sKextsByID
->getObject(aKext
->getIdentifier()));
3337 if (checkKext
!= aKext
) {
3338 result
= kOSKextReturnNotFound
;
3342 if (aKext
->isLoaded()) {
3344 if (current_task() != kernel_task
) {
3345 cred
= kauth_cred_get_with_ref();
3346 macCheckResult
= mac_kext_check_unload(cred
, aKext
->getIdentifierCString());
3347 kauth_cred_unref(&cred
);
3350 if (macCheckResult
!= 0) {
3351 result
= kOSReturnError
;
3353 kOSKextLogErrorLevel
|
3354 kOSKextLogKextBookkeepingFlag
,
3355 "Failed to remove kext %s (MAC policy error 0x%x).",
3356 aKext
->getIdentifierCString(), macCheckResult
);
3361 /* make sure there are no resource requests in flight - 17187548 */
3362 if (aKext
->countRequestCallbacks()) {
3366 /* If we are terminating, send the request to the IOCatalogue
3367 * (which will actually call us right back but that's ok we have
3368 * a recursive lock don't you know) but do not ask the IOCatalogue
3369 * to call back with an unload, we'll do that right here.
3371 if (terminateServicesAndRemovePersonalitiesFlag
) {
3372 result
= gIOCatalogue
->terminateDriversForModule(
3373 aKext
->getIdentifierCString(), /* unload */ false);
3374 if (result
!= kOSReturnSuccess
) {
3376 kOSKextLogErrorLevel
|
3377 kOSKextLogKextBookkeepingFlag
,
3378 "Can't remove kext %s; services failed to terminate - 0x%x.",
3379 aKext
->getIdentifierCString(), result
);
3384 result
= aKext
->unload();
3385 if (result
!= kOSReturnSuccess
) {
3390 /* Remove personalities as requested. This is a bit redundant for a loaded
3391 * kext as IOCatalogue::terminateDriversForModule() removes driver
3392 * personalities, but it doesn't restart matching, which we always want
3393 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3396 if (terminateServicesAndRemovePersonalitiesFlag
) {
3397 aKext
->removePersonalitiesFromCatalog();
3401 kOSKextLogProgressLevel
|
3402 kOSKextLogKextBookkeepingFlag
,
3403 "Removing kext %s.",
3404 aKext
->getIdentifierCString());
3406 sKextsByID
->removeObject(aKext
->getIdentifier());
3407 result
= kOSReturnSuccess
;
3410 IORecursiveLockUnlock(sKextLock
);
3414 /*********************************************************************
3415 *********************************************************************/
3418 OSKext::removeKextWithIdentifier(
3419 const char * kextIdentifier
,
3420 bool terminateServicesAndRemovePersonalitiesFlag
)
3422 OSReturn result
= kOSReturnError
;
3424 IORecursiveLockLock(sKextLock
);
3426 OSKext
* aKext
= OSDynamicCast(OSKext
,
3427 sKextsByID
->getObject(kextIdentifier
));
3429 result
= kOSKextReturnNotFound
;
3430 OSKextLog(/* kext */ NULL
,
3431 kOSKextLogErrorLevel
|
3432 kOSKextLogKextBookkeepingFlag
,
3433 "Can't remove kext %s - not found.",
3438 result
= OSKext::removeKext(aKext
,
3439 terminateServicesAndRemovePersonalitiesFlag
);
3442 IORecursiveLockUnlock(sKextLock
);
3447 /*********************************************************************
3448 *********************************************************************/
3451 OSKext::removeKextWithLoadTag(
3452 OSKextLoadTag loadTag
,
3453 bool terminateServicesAndRemovePersonalitiesFlag
)
3455 OSReturn result
= kOSReturnError
;
3456 OSKext
* foundKext
= NULL
;
3459 IORecursiveLockLock(sKextLock
);
3461 count
= sLoadedKexts
->getCount();
3462 for (i
= 0; i
< count
; i
++) {
3463 OSKext
* thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
3464 if (thisKext
->loadTag
== loadTag
) {
3465 foundKext
= thisKext
;
3471 result
= kOSKextReturnNotFound
;
3472 OSKextLog(/* kext */ NULL
,
3473 kOSKextLogErrorLevel
|
3474 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
3475 "Can't remove kext with load tag %d - not found.",
3480 result
= OSKext::removeKext(foundKext
,
3481 terminateServicesAndRemovePersonalitiesFlag
);
3484 IORecursiveLockUnlock(sKextLock
);
3489 /*********************************************************************
3490 *********************************************************************/
3492 OSKext::copyKexts(void)
3494 OSDictionary
* result
;
3496 IORecursiveLockLock(sKextLock
);
3497 result
= OSDynamicCast(OSDictionary
, sKextsByID
->copyCollection());
3498 IORecursiveLockUnlock(sKextLock
);
3503 /*********************************************************************
3504 *********************************************************************/
3505 #define BOOTER_KEXT_PREFIX "Driver-"
3507 typedef struct _DeviceTreeBuffer
{
3510 } _DeviceTreeBuffer
;
3512 /*********************************************************************
3513 * Create a dictionary of excluded kexts from the given booter data.
3514 *********************************************************************/
3517 OSKext::createExcludeListFromBooterData(
3518 OSDictionary
* theDictionary
,
3519 OSCollectionIterator
* theIterator
)
3521 OSString
* deviceTreeName
= NULL
; // do not release
3522 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not release
3523 char * booterDataPtr
= NULL
; // do not release
3524 _BooterKextFileInfo
* kextFileInfo
= NULL
; // do not release
3525 char * infoDictAddr
= NULL
; // do not release
3526 OSObject
* parsedXML
= NULL
; // must release
3527 OSDictionary
* theInfoDict
= NULL
; // do not release
3529 theIterator
->reset();
3531 /* look for AppleKextExcludeList.kext */
3532 while ( (deviceTreeName
=
3533 OSDynamicCast(OSString
, theIterator
->getNextObject())) ) {
3535 const char * devTreeNameCString
;
3536 OSData
* deviceTreeEntry
;
3537 OSString
* myBundleID
; // do not release
3539 OSSafeReleaseNULL(parsedXML
);
3542 OSDynamicCast(OSData
, theDictionary
->getObject(deviceTreeName
));
3543 if (!deviceTreeEntry
) {
3547 /* Make sure it is a kext */
3548 devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
3549 if (strncmp(devTreeNameCString
, BOOTER_KEXT_PREFIX
,
3550 (sizeof(BOOTER_KEXT_PREFIX
) - 1)) != 0) {
3552 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3553 "\"%s\" not a kext",
3554 devTreeNameCString
);
3558 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
3559 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
3560 if (!deviceTreeBuffer
) {
3564 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
3565 if (!booterDataPtr
) {
3569 kextFileInfo
= (_BooterKextFileInfo
*) booterDataPtr
;
3570 if (!kextFileInfo
->infoDictPhysAddr
||
3571 !kextFileInfo
->infoDictLength
) {
3575 infoDictAddr
= (char *)
3576 ml_static_ptovirt(kextFileInfo
->infoDictPhysAddr
);
3577 if (!infoDictAddr
) {
3581 parsedXML
= OSUnserializeXML(infoDictAddr
);
3586 theInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
3592 OSDynamicCast(OSString
,
3593 theInfoDict
->getObject(kCFBundleIdentifierKey
));
3595 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3597 /* get copy of exclusion list dictionary */
3598 OSDictionary
* myTempDict
; // do not free
3600 myTempDict
= OSDynamicCast(
3602 theInfoDict
->getObject("OSKextExcludeList"));
3604 IORecursiveLockLock(sKextLock
);
3606 /* get rid of old exclusion list */
3607 if (sExcludeListByID
) {
3608 sExcludeListByID
->flushCollection();
3609 OSSafeRelease(sExcludeListByID
);
3611 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3612 IORecursiveLockUnlock(sKextLock
);
3617 } // while ( (deviceTreeName = ...) )
3619 OSSafeReleaseNULL(parsedXML
);
3623 /*********************************************************************
3624 * Create a dictionary of excluded kexts from the given prelink
3625 * info (kernelcache).
3626 *********************************************************************/
3629 OSKext::createExcludeListFromPrelinkInfo( OSArray
* theInfoArray
)
3631 OSDictionary
* myInfoDict
= NULL
; // do not release
3632 OSString
* myBundleID
; // do not release
3635 /* Find com.apple.driver.KextExcludeList. */
3636 for (i
= 0; i
< theInfoArray
->getCount(); i
++) {
3637 myInfoDict
= OSDynamicCast(OSDictionary
, theInfoArray
->getObject(i
));
3642 OSDynamicCast(OSString
,
3643 myInfoDict
->getObject(kCFBundleIdentifierKey
));
3645 strcmp( myBundleID
->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3646 // get copy of exclude list dictionary
3647 OSDictionary
* myTempDict
; // do not free
3648 myTempDict
= OSDynamicCast(OSDictionary
,
3649 myInfoDict
->getObject("OSKextExcludeList"));
3651 IORecursiveLockLock(sKextLock
);
3652 // get rid of old exclude list
3653 if (sExcludeListByID
) {
3654 sExcludeListByID
->flushCollection();
3655 OSSafeRelease(sExcludeListByID
);
3658 sExcludeListByID
= OSDictionary::withDictionary(myTempDict
, 0);
3659 IORecursiveLockUnlock(sKextLock
);
3663 } // for (i = 0; i < theInfoArray->getCount()...
3669 #pragma mark Accessors
3671 /*********************************************************************
3672 *********************************************************************/
3674 OSKext::getIdentifier(void)
3679 /*********************************************************************
3680 * A kext must have a bundle identifier to even survive initialization;
3681 * this is guaranteed to exist past then.
3682 *********************************************************************/
3684 OSKext::getIdentifierCString(void)
3686 return bundleID
->getCStringNoCopy();
3689 /*********************************************************************
3690 *********************************************************************/
3692 OSKext::getVersion(void)
3697 /*********************************************************************
3698 *********************************************************************/
3700 OSKext::getCompatibleVersion(void)
3702 return compatibleVersion
;
3705 /*********************************************************************
3706 *********************************************************************/
3708 OSKext::isLibrary(void)
3710 return (getCompatibleVersion() > 0);
3713 /*********************************************************************
3714 *********************************************************************/
3716 OSKext::isCompatibleWithVersion(OSKextVersion aVersion
)
3718 if ((compatibleVersion
> -1 && version
> -1) &&
3719 (compatibleVersion
<= version
&& aVersion
<= version
)) {
3725 /*********************************************************************
3726 *********************************************************************/
3728 OSKext::declaresExecutable(void)
3730 return (getPropertyForHostArch(kCFBundleExecutableKey
) != NULL
);
3733 /*********************************************************************
3734 *********************************************************************/
3736 OSKext::getExecutable(void)
3738 OSData
* result
= NULL
;
3739 OSData
* extractedExecutable
= NULL
; // must release
3740 OSData
* mkextExecutableRef
= NULL
; // do not release
3742 result
= OSDynamicCast(OSData
, infoDict
->getObject(_kOSKextExecutableKey
));
3747 mkextExecutableRef
= OSDynamicCast(OSData
,
3748 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey
));
3750 if (mkextExecutableRef
) {
3752 MkextEntryRef
* mkextEntryRef
= (MkextEntryRef
*)
3753 mkextExecutableRef
->getBytesNoCopy();
3754 uint32_t mkextVersion
= MKEXT_GET_VERSION(mkextEntryRef
->mkext
);
3755 if (mkextVersion
== MKEXT_VERS_2
) {
3756 mkext2_file_entry
* fileinfo
=
3757 (mkext2_file_entry
*)mkextEntryRef
->fileinfo
;
3758 uint32_t compressedSize
= MKEXT2_GET_ENTRY_COMPSIZE(fileinfo
);
3759 uint32_t fullSize
= MKEXT2_GET_ENTRY_FULLSIZE(fileinfo
);
3760 extractedExecutable
= extractMkext2FileData(
3761 MKEXT2_GET_ENTRY_DATA(fileinfo
), "executable",
3762 compressedSize
, fullSize
);
3764 OSKextLog(this, kOSKextLogErrorLevel
|
3765 kOSKextLogArchiveFlag
,
3766 "Kext %s - unknown mkext version 0x%x for executable.",
3767 getIdentifierCString(), mkextVersion
);
3770 /* Regardless of success, remove the mkext executable,
3771 * and drop one reference on the mkext. (setExecutable() does not
3772 * replace, it removes, or panics if asked to replace.)
3774 infoDict
->removeObject(_kOSKextMkextExecutableReferenceKey
);
3775 infoDict
->removeObject(_kOSKextExecutableExternalDataKey
);
3777 if (extractedExecutable
&& extractedExecutable
->getLength()) {
3778 if (!setExecutable(extractedExecutable
)) {
3781 result
= extractedExecutable
;
3789 OSSafeRelease(extractedExecutable
);
3794 /*********************************************************************
3795 *********************************************************************/
3797 OSKext::isInterface(void)
3799 return flags
.interface
;
3802 /*********************************************************************
3803 *********************************************************************/
3805 OSKext::isKernel(void)
3807 return (this == sKernelKext
);
3810 /*********************************************************************
3811 *********************************************************************/
3813 OSKext::isKernelComponent(void)
3815 return flags
.kernelComponent
? true : false;
3818 /*********************************************************************
3819 *********************************************************************/
3821 OSKext::isExecutable(void)
3823 return (!isKernel() && !isInterface() && declaresExecutable());
3826 /*********************************************************************
3827 * We might want to check this recursively for all dependencies,
3828 * since a subtree of dependencies could get loaded before we hit
3829 * a dependency that isn't safe-boot-loadable.
3831 * xxx - Might want to return false if OSBundleEnableKextLogging or
3832 * OSBundleDebugLevel
3833 * or IOKitDebug is nonzero too (we used to do that, but I don't see
3834 * the point except it's usually development drivers, which might
3835 * cause panics on startup, that have those properties). Heh; could
3836 * use a "kx" boot-arg!
3837 *********************************************************************/
3839 OSKext::isLoadableInSafeBoot(void)
3841 bool result
= false;
3842 OSString
* required
= NULL
; // do not release
3849 required
= OSDynamicCast(OSString
,
3850 getPropertyForHostArch(kOSBundleRequiredKey
));
3854 if (required
->isEqualTo(kOSBundleRequiredRoot
) ||
3855 required
->isEqualTo(kOSBundleRequiredLocalRoot
) ||
3856 required
->isEqualTo(kOSBundleRequiredNetworkRoot
) ||
3857 required
->isEqualTo(kOSBundleRequiredSafeBoot
) ||
3858 required
->isEqualTo(kOSBundleRequiredConsole
)) {
3867 /*********************************************************************
3868 *********************************************************************/
3870 OSKext::isPrelinked(void)
3872 return flags
.prelinked
? true : false;
3875 /*********************************************************************
3876 *********************************************************************/
3877 bool OSKext::isLoaded(void)
3879 return flags
.loaded
? true : false;
3882 /*********************************************************************
3883 *********************************************************************/
3885 OSKext::isStarted(void)
3887 return flags
.started
? true : false;
3890 /*********************************************************************
3891 *********************************************************************/
3893 OSKext::isCPPInitialized(void)
3895 return flags
.CPPInitialized
;
3898 /*********************************************************************
3899 *********************************************************************/
3901 OSKext::setCPPInitialized(bool initialized
)
3903 flags
.CPPInitialized
= initialized
;
3906 /*********************************************************************
3907 *********************************************************************/
3909 OSKext::getLoadTag(void)
3914 /*********************************************************************
3915 *********************************************************************/
3916 void OSKext::getSizeInfo(uint32_t *loadSize
, uint32_t *wiredSize
)
3918 if (linkedExecutable
) {
3919 *loadSize
= linkedExecutable
->getLength();
3921 /* If we have a kmod_info struct, calculated the wired size
3922 * from that. Otherwise it's the full load size.
3925 *wiredSize
= *loadSize
- kmod_info
->hdr_size
;
3927 *wiredSize
= *loadSize
;
3936 /*********************************************************************
3937 *********************************************************************/
3939 OSKext::copyUUID(void)
3941 OSData
* result
= NULL
;
3942 OSData
* theExecutable
= NULL
; // do not release
3943 const kernel_mach_header_t
* header
= NULL
;
3944 const struct load_command
* load_cmd
= NULL
;
3945 const struct uuid_command
* uuid_cmd
= NULL
;
3948 /* An interface kext doesn't have a linked executable with an LC_UUID,
3949 * we create one when it's linked.
3951 if (interfaceUUID
) {
3952 result
= interfaceUUID
;
3957 /* For real kexts, try to get the UUID from the linked executable,
3958 * or if is hasn't been linked yet, the unrelocated executable.
3960 theExecutable
= linkedExecutable
;
3961 if (!theExecutable
) {
3962 theExecutable
= getExecutable();
3964 if (!theExecutable
) {
3968 header
= (const kernel_mach_header_t
*)theExecutable
->getBytesNoCopy();
3969 load_cmd
= (const struct load_command
*)&header
[1];
3971 if (header
->magic
!= MH_MAGIC_KERNEL
) {
3973 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
3974 "%s: bad header %p",
3980 for (i
= 0; i
< header
->ncmds
; i
++) {
3981 if (load_cmd
->cmd
== LC_UUID
) {
3982 uuid_cmd
= (struct uuid_command
*)load_cmd
;
3983 result
= OSData::withBytes(uuid_cmd
->uuid
, sizeof(uuid_cmd
->uuid
));
3986 load_cmd
= (struct load_command
*)((caddr_t
)load_cmd
+ load_cmd
->cmdsize
);
3993 /*********************************************************************
3994 *********************************************************************/
3996 #if defined (__x86_64__)
3997 #define ARCHNAME "x86_64"
3999 #error architecture not supported
4002 #define ARCH_SEPARATOR_CHAR '_'
4004 static char * makeHostArchKey(const char * key
, uint32_t * keySizeOut
)
4006 char * result
= NULL
;
4007 uint32_t keyLength
= strlen(key
);
4010 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4012 keySize
= 1 + 1 + strlen(key
) + strlen(ARCHNAME
);
4013 result
= (char *)kalloc_tag(keySize
, VM_KERN_MEMORY_OSKEXT
);
4017 strlcpy(result
, key
, keySize
);
4018 result
[keyLength
++] = ARCH_SEPARATOR_CHAR
;
4019 result
[keyLength
] = '\0';
4020 strlcat(result
, ARCHNAME
, keySize
);
4021 *keySizeOut
= keySize
;
4027 /*********************************************************************
4028 *********************************************************************/
4030 OSKext::getPropertyForHostArch(const char * key
)
4032 OSObject
* result
= NULL
; // do not release
4033 uint32_t hostArchKeySize
= 0;
4034 char * hostArchKey
= NULL
; // must kfree
4036 if (!key
|| !infoDict
) {
4040 /* Some properties are not allowed to be arch-variant:
4041 * - Any CFBundle... property.
4042 * - OSBundleIsInterface.
4043 * - OSKernelResource.
4045 if (STRING_HAS_PREFIX(key
, "OS") ||
4046 STRING_HAS_PREFIX(key
, "IO")) {
4048 hostArchKey
= makeHostArchKey(key
, &hostArchKeySize
);
4050 OSKextLog(/* kext (this isn't about a kext) */ NULL
,
4051 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
4052 "Allocation failure.");
4055 result
= infoDict
->getObject(hostArchKey
);
4059 result
= infoDict
->getObject(key
);
4063 if (hostArchKey
) kfree(hostArchKey
, hostArchKeySize
);
4068 #pragma mark Load/Start/Stop/Unload
4071 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4073 /*********************************************************************
4074 * sExcludeListByID is a dictionary with keys / values of:
4075 * key = bundleID string of kext we will not allow to load
4076 * value = version string(s) of the kext that is to be denied loading.
4077 * The version strings can be comma delimited. For example if kext
4078 * com.foocompany.fookext has two versions that we want to deny
4079 * loading then the version strings might look like:
4081 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4082 * not load the kext.
4084 * Value may also be in the form of "LE 2.0.0" (version numbers
4085 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4086 * number less than 2.0.0 will not load)
4088 * NOTE - we cannot use the characters "<=" or "<" because we have code
4089 * that serializes plists and treats '<' as a special character.
4090 *********************************************************************/
4092 OSKext::isInExcludeList(void)
4094 OSString
* versionString
= NULL
; // do not release
4095 char * versionCString
= NULL
; // do not free
4097 boolean_t wantLessThan
= false;
4098 boolean_t wantLessThanEqualTo
= false;
4101 if (!sExcludeListByID
) {
4104 /* look up by bundleID in our exclude list and if found get version
4105 * string (or strings) that we will not allow to load
4107 versionString
= OSDynamicCast(OSString
, sExcludeListByID
->getObject(bundleID
));
4108 if (versionString
== NULL
|| versionString
->getLength() > (sizeof(myBuffer
) - 1)) {
4112 /* parse version strings */
4113 versionCString
= (char *) versionString
->getCStringNoCopy();
4115 /* look for "LT" or "LE" form of version string, must be in first two
4118 if (*versionCString
== 'L' && *(versionCString
+ 1) == 'T') {
4119 wantLessThan
= true;
4122 else if (*versionCString
== 'L' && *(versionCString
+ 1) == 'E') {
4123 wantLessThanEqualTo
= true;
4127 for (i
= 0; *versionCString
!= 0x00; versionCString
++) {
4128 /* skip whitespace */
4129 if (isWhiteSpace(*versionCString
)) {
4133 /* peek ahead for version string separator or null terminator */
4134 if (*(versionCString
+ 1) == ',' || *(versionCString
+ 1) == 0x00) {
4136 /* OK, we have a version string */
4137 myBuffer
[i
++] = *versionCString
;
4140 OSKextVersion excludeVers
;
4141 excludeVers
= OSKextParseVersionString(myBuffer
);
4143 if (wantLessThanEqualTo
) {
4144 if (version
<= excludeVers
) {
4148 else if (wantLessThan
) {
4149 if (version
< excludeVers
) {
4153 else if ( version
== excludeVers
) {
4157 /* reset for the next (if any) version string */
4159 wantLessThan
= false;
4160 wantLessThanEqualTo
= false;
4163 /* save valid version character */
4164 myBuffer
[i
++] = *versionCString
;
4166 /* make sure bogus version string doesn't overrun local buffer */
4167 if ( i
>= sizeof(myBuffer
) ) {
4176 /*********************************************************************
4177 *********************************************************************/
4180 OSKext::loadKextWithIdentifier(
4181 const char * kextIdentifierCString
,
4182 Boolean allowDeferFlag
,
4183 Boolean delayAutounloadFlag
,
4184 OSKextExcludeLevel startOpt
,
4185 OSKextExcludeLevel startMatchingOpt
,
4186 OSArray
* personalityNames
)
4188 OSReturn result
= kOSReturnError
;
4189 OSString
* kextIdentifier
= NULL
; // must release
4191 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
4192 if (!kextIdentifier
) {
4193 result
= kOSKextReturnNoMemory
;
4196 result
= OSKext::loadKextWithIdentifier(kextIdentifier
,
4197 allowDeferFlag
, delayAutounloadFlag
,
4198 startOpt
, startMatchingOpt
, personalityNames
);
4201 OSSafeRelease(kextIdentifier
);
4205 /*********************************************************************
4206 *********************************************************************/
4208 OSKext::loadKextWithIdentifier(
4209 OSString
* kextIdentifier
,
4210 Boolean allowDeferFlag
,
4211 Boolean delayAutounloadFlag
,
4212 OSKextExcludeLevel startOpt
,
4213 OSKextExcludeLevel startMatchingOpt
,
4214 OSArray
* personalityNames
)
4216 OSReturn result
= kOSReturnError
;
4217 OSReturn pingResult
= kOSReturnError
;
4218 OSKext
* theKext
= NULL
; // do not release
4219 OSDictionary
* loadRequest
= NULL
; // must release
4220 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4222 IORecursiveLockLock(sKextLock
);
4224 if (!kextIdentifier
) {
4225 result
= kOSKextReturnInvalidArgument
;
4229 OSKext::recordIdentifierRequest(kextIdentifier
);
4231 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
4233 if (!allowDeferFlag
) {
4234 OSKextLog(/* kext */ NULL
,
4235 kOSKextLogErrorLevel
|
4237 "Can't load kext %s - not found.",
4238 kextIdentifier
->getCStringNoCopy());
4242 if (!sKernelRequestsEnabled
) {
4244 kOSKextLogErrorLevel
|
4246 "Can't load kext %s - requests to user space are disabled.",
4247 kextIdentifier
->getCStringNoCopy());
4248 result
= kOSKextReturnDisabled
;
4252 /* Create a new request unless one is already sitting
4253 * in sKernelRequests for this bundle identifier
4255 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4256 if (!sPostedKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4257 result
= _OSKextCreateRequest(kKextRequestPredicateRequestLoad
,
4259 if (result
!= kOSReturnSuccess
) {
4262 if (!_OSKextSetRequestArgument(loadRequest
,
4263 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
4265 result
= kOSKextReturnNoMemory
;
4268 if (!sKernelRequests
->setObject(loadRequest
)) {
4269 result
= kOSKextReturnNoMemory
;
4273 if (!sPostedKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4274 result
= kOSKextReturnNoMemory
;
4279 kOSKextLogDebugLevel
|
4281 "Kext %s not found; queued load request to user space.",
4282 kextIdentifier
->getCStringNoCopy());
4285 pingResult
= OSKext::pingKextd();
4286 if (pingResult
== kOSKextReturnDisabled
) {
4287 OSKextLog(/* kext */ NULL
,
4288 ((sPrelinkBoot
) ? kOSKextLogDebugLevel
: kOSKextLogErrorLevel
) |
4290 "Kext %s might not load - kextd is currently unavailable.",
4291 kextIdentifier
->getCStringNoCopy());
4294 result
= kOSKextReturnDeferred
;
4298 result
= theKext
->load(startOpt
, startMatchingOpt
, personalityNames
);
4300 if (result
!= kOSReturnSuccess
) {
4302 kOSKextLogErrorLevel
|
4304 "Failed to load kext %s (error 0x%x).",
4305 kextIdentifier
->getCStringNoCopy(), (int)result
);
4307 OSKext::removeKext(theKext
,
4308 /* terminateService/removePersonalities */ true);
4312 if (delayAutounloadFlag
) {
4314 kOSKextLogProgressLevel
|
4315 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4316 "Setting delayed autounload for %s.",
4317 kextIdentifier
->getCStringNoCopy());
4318 theKext
->flags
.delayAutounload
= 1;
4322 OSSafeRelease(loadRequest
);
4323 OSSafeRelease(kextIdentifierSymbol
);
4325 IORecursiveLockUnlock(sKextLock
);
4330 /*********************************************************************
4331 *********************************************************************/
4334 OSKext::recordIdentifierRequest(
4335 OSString
* kextIdentifier
)
4337 const OSSymbol
* kextIdentifierSymbol
= NULL
; // must release
4340 if (!sAllKextLoadIdentifiers
|| !kextIdentifier
) {
4344 kextIdentifierSymbol
= OSSymbol::withString(kextIdentifier
);
4345 if (!kextIdentifierSymbol
) {
4346 // xxx - this is really a basic alloc failure
4351 if (!sAllKextLoadIdentifiers
->containsObject(kextIdentifierSymbol
)) {
4352 if (!sAllKextLoadIdentifiers
->setObject(kextIdentifierSymbol
)) {
4355 // xxx - need to find a way to associate this whole func w/the kext
4356 OSKextLog(/* kext */ NULL
,
4357 // xxx - check level
4358 kOSKextLogStepLevel
|
4359 kOSKextLogArchiveFlag
,
4360 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4361 kextIdentifier
->getCStringNoCopy());
4367 OSKextLog(/* kext */ NULL
,
4368 kOSKextLogErrorLevel
|
4369 kOSKextLogArchiveFlag
,
4370 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4371 kextIdentifier
->getCStringNoCopy());
4373 OSSafeRelease(kextIdentifierSymbol
);
4377 /*********************************************************************
4378 *********************************************************************/
4381 OSKextExcludeLevel startOpt
,
4382 OSKextExcludeLevel startMatchingOpt
,
4383 OSArray
* personalityNames
)
4385 OSReturn result
= kOSReturnError
;
4386 kern_return_t kxldResult
;
4387 OSKextExcludeLevel dependenciesStartOpt
= startOpt
;
4388 OSKextExcludeLevel dependenciesStartMatchingOpt
= startMatchingOpt
;
4389 unsigned int i
, count
;
4390 Boolean alreadyLoaded
= false;
4391 OSKext
* lastLoadedKext
= NULL
;
4393 if (isInExcludeList()) {
4395 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
|
4397 "Kext %s is in exclude list, not loadable",
4398 getIdentifierCString());
4400 result
= kOSKextReturnNotLoadable
;
4405 alreadyLoaded
= true;
4406 result
= kOSReturnSuccess
;
4409 kOSKextLogDebugLevel
|
4410 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
4411 "Kext %s is already loaded.",
4412 getIdentifierCString());
4417 if (current_task() != kernel_task
) {
4418 int macCheckResult
= 0;
4419 kauth_cred_t cred
= NULL
;
4421 cred
= kauth_cred_get_with_ref();
4422 macCheckResult
= mac_kext_check_load(cred
, getIdentifierCString());
4423 kauth_cred_unref(&cred
);
4425 if (macCheckResult
!= 0) {
4426 result
= kOSReturnError
;
4428 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4429 "Failed to load kext %s (MAC policy error 0x%x).",
4430 getIdentifierCString(), macCheckResult
);
4436 if (!sLoadEnabled
) {
4438 kOSKextLogErrorLevel
|
4440 "Kext loading is disabled (attempt to load kext %s).",
4441 getIdentifierCString());
4442 result
= kOSKextReturnDisabled
;
4446 /* If we've pushed the next available load tag to the invalid value,
4447 * we can't load any more kexts.
4449 if (sNextLoadTag
== kOSKextInvalidLoadTag
) {
4451 kOSKextLogErrorLevel
|
4453 "Can't load kext %s - no more load tags to assign.",
4454 getIdentifierCString());
4455 result
= kOSKextReturnNoResources
;
4459 /* This is a bit of a hack, because we shouldn't be handling
4460 * personalities within the load function.
4462 if (!declaresExecutable()) {
4463 result
= kOSReturnSuccess
;
4467 /* Are we in safe boot?
4469 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
4471 kOSKextLogErrorLevel
|
4473 "Can't load kext %s - not loadable during safe boot.",
4474 getIdentifierCString());
4475 result
= kOSKextReturnBootLevel
;
4480 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
4482 getIdentifierCString());
4484 if (!sKxldContext
) {
4485 kxldResult
= kxld_create_context(&sKxldContext
, &kern_allocate
,
4486 &kxld_log_callback
, /* Flags */ (KXLDFlags
) 0,
4487 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
4490 kOSKextLogErrorLevel
|
4491 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
4492 "Can't load kext %s - failed to create link context.",
4493 getIdentifierCString());
4494 result
= kOSKextReturnNoMemory
;
4499 /* We only need to resolve dependencies once for the whole graph, but
4500 * resolveDependencies will just return if there's no work to do, so it's
4501 * safe to call it more than once.
4503 if (!resolveDependencies()) {
4504 // xxx - check resolveDependencies() for log msg
4506 kOSKextLogErrorLevel
|
4507 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4508 "Can't load kext %s - failed to resolve library dependencies.",
4509 getIdentifierCString());
4510 result
= kOSKextReturnDependencies
;
4514 /* If we are excluding just the kext being loaded now (and not its
4515 * dependencies), drop the exclusion level to none so dependencies
4516 * start and/or add their personalities.
4518 if (dependenciesStartOpt
== kOSKextExcludeKext
) {
4519 dependenciesStartOpt
= kOSKextExcludeNone
;
4522 if (dependenciesStartMatchingOpt
== kOSKextExcludeKext
) {
4523 dependenciesStartMatchingOpt
= kOSKextExcludeNone
;
4526 /* Load the dependencies, recursively.
4528 count
= getNumDependencies();
4529 for (i
= 0; i
< count
; i
++) {
4530 OSKext
* dependency
= OSDynamicCast(OSKext
,
4531 dependencies
->getObject(i
));
4532 if (dependency
== NULL
) {
4534 kOSKextLogErrorLevel
|
4535 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4536 "Internal error loading kext %s; dependency disappeared.",
4537 getIdentifierCString());
4538 result
= kOSKextReturnInternalError
;
4542 /* Dependencies must be started accorting to the opt,
4543 * but not given the personality names of the main kext.
4545 result
= dependency
->load(dependenciesStartOpt
,
4546 dependenciesStartMatchingOpt
,
4547 /* personalityNames */ NULL
);
4548 if (result
!= KERN_SUCCESS
) {
4550 kOSKextLogErrorLevel
|
4551 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
4552 "Dependency %s of kext %s failed to load.",
4553 dependency
->getIdentifierCString(),
4554 getIdentifierCString());
4556 OSKext::removeKext(dependency
,
4557 /* terminateService/removePersonalities */ true);
4558 result
= kOSKextReturnDependencyLoadError
;
4564 result
= loadExecutable();
4565 if (result
!= KERN_SUCCESS
) {
4569 pendingPgoHead
.next
= &pendingPgoHead
;
4570 pendingPgoHead
.prev
= &pendingPgoHead
;
4572 uuid_generate(instance_uuid
);
4573 account
= IONew(OSKextAccount
, 1);
4575 result
= KERN_MEMORY_ERROR
;
4578 bzero(account
, sizeof(*account
));
4579 account
->loadTag
= kmod_info
->id
;
4580 account
->site
.flags
= VM_TAG_KMOD
;
4582 flags
.loaded
= true;
4584 /* Add the kext to the list of loaded kexts and update the kmod_info
4585 * struct to point to that of the last loaded kext (which is the way
4586 * it's always been done, though I'd rather do them in order now).
4588 lastLoadedKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
4589 sLoadedKexts
->setObject(this);
4591 /* Keep the kernel itself out of the kmod list.
4593 if (lastLoadedKext
->isKernel()) {
4594 lastLoadedKext
= NULL
;
4597 if (lastLoadedKext
) {
4598 kmod_info
->next
= lastLoadedKext
->kmod_info
;
4601 notifyKextLoadObservers(this, kmod_info
);
4603 /* Make the global kmod list point at the just-loaded kext. Note that the
4604 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4605 * although we do report it in kextstat these days by using the newer
4606 * OSArray of loaded kexts, which does contain it.
4608 * (The OSKext object representing the kernel doesn't even have a kmod_info
4609 * struct, though I suppose we could stick a pointer to it from the
4610 * static struct in OSRuntime.cpp.)
4614 /* Save the list of loaded kexts in case we panic.
4616 OSKext::saveLoadedKextPanicList();
4618 if (isExecutable()) {
4619 OSKext::updateLoadedKextSummaries();
4620 savePanicString(/* isLoading */ true);
4623 registerWithDTrace();
4625 jettisonLinkeditSegment();
4626 #endif /* CONFIG_DTRACE */
4628 #if !VM_MAPPED_KEXTS
4629 /* If there is a page (or more) worth of padding after the end
4630 * of the last data section but before the end of the data segment
4631 * then free it in the same manner the LinkeditSegment is freed
4633 jettisonDATASegmentPadding();
4638 if (isExecutable() && !flags
.started
) {
4639 if (startOpt
== kOSKextExcludeNone
) {
4641 if (result
!= kOSReturnSuccess
) {
4643 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
4644 "Kext %s start failed (result 0x%x).",
4645 getIdentifierCString(), result
);
4646 result
= kOSKextReturnStartStopError
;
4651 /* If not excluding matching, send the personalities to the kernel.
4652 * This never affects the result of the load operation.
4653 * This is a bit of a hack, because we shouldn't be handling
4654 * personalities within the load function.
4656 if (result
== kOSReturnSuccess
&& startMatchingOpt
== kOSKextExcludeNone
) {
4657 result
= sendPersonalitiesToCatalog(true, personalityNames
);
4662 /* More hack! If the kext doesn't declare an executable, even if we
4663 * "loaded" it, we have to remove any personalities naming it, or we'll
4664 * never see the registry go quiet. Errors here do not count for the
4665 * load operation itself.
4667 * Note that in every other regard it's perfectly ok for a kext to
4668 * not declare an executable and serve only as a package for personalities
4669 * naming another kext, so we do have to allow such kexts to be "loaded"
4670 * so that those other personalities get added & matched.
4672 if (!declaresExecutable()) {
4674 kOSKextLogStepLevel
| kOSKextLogLoadFlag
,
4675 "Kext %s has no executable; removing any personalities naming it.",
4676 getIdentifierCString());
4677 removePersonalitiesFromCatalog();
4680 if (result
!= kOSReturnSuccess
) {
4682 kOSKextLogErrorLevel
|
4684 "Kext %s failed to load (0x%x).",
4685 getIdentifierCString(), (int)result
);
4686 } else if (!alreadyLoaded
) {
4688 kOSKextLogProgressLevel
|
4691 getIdentifierCString());
4693 queueKextNotification(kKextRequestPredicateLoadNotification
,
4694 OSDynamicCast(OSString
, bundleID
));
4699 /*********************************************************************
4701 *********************************************************************/
4702 static char * strdup(const char * string
)
4704 char * result
= NULL
;
4711 size
= 1 + strlen(string
);
4712 result
= (char *)kalloc_tag(size
, VM_KERN_MEMORY_OSKEXT
);
4717 memcpy(result
, string
, size
);
4723 /*********************************************************************
4725 *********************************************************************/
4728 OSKext::lookupSection(const char *segname
, const char *secname
)
4730 kernel_section_t
* found_section
= NULL
;
4731 kernel_mach_header_t
* mh
= NULL
;
4732 kernel_segment_command_t
* seg
= NULL
;
4733 kernel_section_t
* sec
= NULL
;
4735 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4737 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4739 if (0 != strcmp(seg
->segname
, segname
)) {
4743 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4745 if (0 == strcmp(sec
->sectname
, secname
)) {
4746 found_section
= sec
;
4753 return found_section
;
4756 /*********************************************************************
4758 *********************************************************************/
4761 OSKext::slidePrelinkedExecutable()
4763 OSReturn result
= kOSKextReturnBadData
;
4764 kernel_mach_header_t
* mh
= NULL
;
4765 kernel_segment_command_t
* seg
= NULL
;
4766 kernel_segment_command_t
* linkeditSeg
= NULL
;
4767 kernel_section_t
* sec
= NULL
;
4768 char * linkeditBase
= NULL
;
4769 bool haveLinkeditBase
= false;
4770 char * relocBase
= NULL
;
4771 bool haveRelocBase
= false;
4772 struct dysymtab_command
* dysymtab
= NULL
;
4773 struct symtab_command
* symtab
= NULL
;
4774 kernel_nlist_t
* sym
= NULL
;
4775 struct relocation_info
* reloc
= NULL
;
4778 vm_offset_t new_kextsize
;
4780 if (linkedExecutable
== NULL
|| vm_kernel_slide
== 0) {
4781 result
= kOSReturnSuccess
;
4785 mh
= (kernel_mach_header_t
*)linkedExecutable
->getBytesNoCopy();
4787 for (seg
= firstsegfromheader(mh
); seg
!= NULL
; seg
= nextsegfromheader(mh
, seg
)) {
4791 seg
->vmaddr
+= vm_kernel_slide
;
4793 #if KASLR_KEXT_DEBUG
4794 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
4796 (unsigned long)VM_KERNEL_UNSLIDE(seg
->vmaddr
),
4797 (unsigned long)seg
->vmaddr
);
4800 if (!haveRelocBase
) {
4801 relocBase
= (char *) seg
->vmaddr
;
4802 haveRelocBase
= true;
4804 if (!strcmp(seg
->segname
, "__LINKEDIT")) {
4805 linkeditBase
= (char *) seg
->vmaddr
- seg
->fileoff
;
4806 haveLinkeditBase
= true;
4809 for (sec
= firstsect(seg
); sec
!= NULL
; sec
= nextsect(seg
, sec
)) {
4810 sec
->addr
+= vm_kernel_slide
;
4812 #if KASLR_KEXT_DEBUG
4813 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
4815 (unsigned long)VM_KERNEL_UNSLIDE(sec
->addr
),
4816 (unsigned long)sec
->addr
);
4821 dysymtab
= (struct dysymtab_command
*) getcommandfromheader(mh
, LC_DYSYMTAB
);
4823 symtab
= (struct symtab_command
*) getcommandfromheader(mh
, LC_SYMTAB
);
4825 if (symtab
!= NULL
) {
4826 /* Some pseudo-kexts have symbol tables without segments.
4828 if (symtab
->nsyms
> 0 && haveLinkeditBase
) {
4829 sym
= (kernel_nlist_t
*) (linkeditBase
+ symtab
->symoff
);
4830 for (i
= 0; i
< symtab
->nsyms
; i
++) {
4831 if (sym
[i
].n_type
& N_STAB
) {
4834 sym
[i
].n_value
+= vm_kernel_slide
;
4836 #if KASLR_KEXT_DEBUG
4837 #define MAX_SYMS_TO_LOG 5
4838 if ( i
< MAX_SYMS_TO_LOG
) {
4839 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
4840 (unsigned long)VM_KERNEL_UNSLIDE(sym
[i
].n_value
),
4841 (unsigned long)sym
[i
].n_value
);
4848 if (dysymtab
!= NULL
) {
4849 if (dysymtab
->nextrel
> 0) {
4851 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4853 "Sliding kext %s: External relocations found.",
4854 getIdentifierCString());
4858 if (dysymtab
->nlocrel
> 0) {
4859 if (!haveLinkeditBase
) {
4861 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4863 "Sliding kext %s: No linkedit segment.",
4864 getIdentifierCString());
4868 if (!haveRelocBase
) {
4870 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4873 "Sliding kext %s: No writable segments.",
4875 "Sliding kext %s: No segments.",
4877 getIdentifierCString());
4881 reloc
= (struct relocation_info
*) (linkeditBase
+ dysymtab
->locreloff
);
4882 reloc_size
= dysymtab
->nlocrel
* sizeof(struct relocation_info
);
4884 for (i
= 0; i
< dysymtab
->nlocrel
; i
++) {
4885 if ( reloc
[i
].r_extern
!= 0
4886 || reloc
[i
].r_type
!= 0
4887 || reloc
[i
].r_length
!= (sizeof(void *) == 8 ? 3 : 2)
4890 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
|
4892 "Sliding kext %s: Unexpected relocation found.",
4893 getIdentifierCString());
4896 if (reloc
[i
].r_pcrel
!= 0) {
4899 *((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)) += vm_kernel_slide
;
4901 #if KASLR_KEXT_DEBUG
4902 #define MAX_DYSYMS_TO_LOG 5
4903 if ( i
< MAX_DYSYMS_TO_LOG
) {
4904 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
4905 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
))),
4906 (unsigned long)*((uintptr_t *)(relocBase
+ reloc
[i
].r_address
)));
4911 /* We should free these relocations, not just delete the reference to them.
4912 * <rdar://problem/10535549> Free relocations from PIE kexts.
4914 new_kextsize
= round_page(kmod_info
->size
- reloc_size
);
4916 if ((kmod_info
->size
- new_kextsize
) > PAGE_SIZE
) {
4917 vm_offset_t endofkext
= kmod_info
->address
+ kmod_info
->size
;
4918 vm_offset_t new_endofkext
= kmod_info
->address
+ new_kextsize
;
4919 vm_offset_t endofrelocInfo
= (vm_offset_t
) (((uint8_t *)reloc
) + reloc_size
);
4920 int bytes_remaining
= endofkext
- endofrelocInfo
;
4921 OSData
* new_osdata
= NULL
;
4923 /* fix up symbol offsets if they are after the dsymtab local relocs */
4925 if (dysymtab
->locreloff
< symtab
->symoff
){
4926 symtab
->symoff
-= reloc_size
;
4928 if (dysymtab
->locreloff
< symtab
->stroff
) {
4929 symtab
->stroff
-= reloc_size
;
4932 if (dysymtab
->locreloff
< dysymtab
->extreloff
) {
4933 dysymtab
->extreloff
-= reloc_size
;
4936 /* move data behind reloc info down to new offset */
4937 if (endofrelocInfo
< endofkext
) {
4938 memcpy(reloc
, (void *)endofrelocInfo
, bytes_remaining
);
4941 /* Create a new OSData for the smaller kext object and reflect
4942 * new linkedit segment size.
4944 linkeditSeg
->vmsize
= round_page(linkeditSeg
->vmsize
- reloc_size
);
4945 linkeditSeg
->filesize
= linkeditSeg
->vmsize
;
4947 new_osdata
= OSData::withBytesNoCopy((void *)kmod_info
->address
, new_kextsize
);
4949 /* Fix up kmod info and linkedExecutable.
4951 kmod_info
->size
= new_kextsize
;
4953 new_osdata
->setDeallocFunction(osdata_kext_free
);
4955 new_osdata
->setDeallocFunction(osdata_phys_free
);
4957 linkedExecutable
->setDeallocFunction(NULL
);
4958 linkedExecutable
->release();
4959 linkedExecutable
= new_osdata
;
4962 kext_free(new_endofkext
, (endofkext
- new_endofkext
));
4964 ml_static_mfree(new_endofkext
, (endofkext
- new_endofkext
));
4968 dysymtab
->nlocrel
= 0;
4969 dysymtab
->locreloff
= 0;
4973 result
= kOSReturnSuccess
;
4978 /*********************************************************************
4979 * called only by load()
4980 *********************************************************************/
4982 OSKext::loadExecutable()
4984 OSReturn result
= kOSReturnError
;
4985 kern_return_t kxldResult
;
4986 KXLDDependency
* kxlddeps
= NULL
; // must kfree
4987 uint32_t num_kxlddeps
= 0;
4988 OSArray
* linkDependencies
= NULL
; // must release
4989 uint32_t numDirectDependencies
= 0;
4990 uint32_t num_kmod_refs
= 0;
4991 struct mach_header
** kxldHeaderPtr
= NULL
; // do not free
4992 struct mach_header
* kxld_header
= NULL
; // xxx - need to free here?
4993 OSData
* theExecutable
= NULL
; // do not release
4994 OSString
* versString
= NULL
; // do not release
4995 const char * versCString
= NULL
; // do not free
4996 const char * string
= NULL
; // do not free
4999 /* We need the version string for a variety of bits below.
5001 versString
= OSDynamicCast(OSString
,
5002 getPropertyForHostArch(kCFBundleVersionKey
));
5006 versCString
= versString
->getCStringNoCopy();
5008 if (isKernelComponent()) {
5009 if (STRING_HAS_PREFIX(versCString
, KERNEL_LIB_PREFIX
)) {
5011 if (strncmp(versCString
, KERNEL6_VERSION
, strlen(KERNEL6_VERSION
))) {
5013 kOSKextLogErrorLevel
|
5015 "Kernel component %s has incorrect version %s; "
5017 getIdentifierCString(),
5018 versCString
, KERNEL6_VERSION
);
5019 result
= kOSKextReturnInternalError
;
5021 } else if (strcmp(versCString
, osrelease
)) {
5023 kOSKextLogErrorLevel
|
5025 "Kernel component %s has incorrect version %s; "
5027 getIdentifierCString(),
5028 versCString
, osrelease
);
5029 result
= kOSKextReturnInternalError
;
5035 if (isPrelinked()) {
5039 /* <rdar://problem/21444003> all callers must be entitled */
5040 if (FALSE
== IOTaskHasEntitlement(current_task(), "com.apple.rootless.kext-management")) {
5042 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
5043 "Not entitled to link kext '%s'",
5044 getIdentifierCString());
5045 result
= kOSKextReturnNotPrivileged
;
5049 theExecutable
= getExecutable();
5050 if (!theExecutable
) {
5051 if (declaresExecutable()) {
5053 kOSKextLogErrorLevel
|
5055 "Can't load kext %s - executable is missing.",
5056 getIdentifierCString());
5057 result
= kOSKextReturnValidation
;
5063 if (isInterface()) {
5064 OSData
*executableCopy
= OSData::withData(theExecutable
);
5065 setLinkedExecutable(executableCopy
);
5066 executableCopy
->release();
5070 numDirectDependencies
= getNumDependencies();
5072 if (flags
.hasBleedthrough
) {
5073 linkDependencies
= dependencies
;
5074 linkDependencies
->retain();
5076 linkDependencies
= OSArray::withArray(dependencies
);
5077 if (!linkDependencies
) {
5079 kOSKextLogErrorLevel
|
5080 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5081 "Can't allocate link dependencies to load kext %s.",
5082 getIdentifierCString());
5086 for (i
= 0; i
< numDirectDependencies
; ++i
) {
5087 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
5088 dependencies
->getObject(i
));
5089 dependencyKext
->addBleedthroughDependencies(linkDependencies
);
5093 num_kxlddeps
= linkDependencies
->getCount();
5094 if (!num_kxlddeps
) {
5096 kOSKextLogErrorLevel
|
5097 kOSKextLogLoadFlag
| kOSKextLogDependenciesFlag
,
5098 "Can't load kext %s - it has no library dependencies.",
5099 getIdentifierCString());
5103 kxlddeps
= (KXLDDependency
*)kalloc_tag(num_kxlddeps
* sizeof(*kxlddeps
), VM_KERN_MEMORY_OSKEXT
);
5106 kOSKextLogErrorLevel
|
5107 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5108 "Can't allocate link context to load kext %s.",
5109 getIdentifierCString());
5112 bzero(kxlddeps
, num_kxlddeps
* sizeof(*kxlddeps
));
5114 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5115 OSKext
* dependency
= OSDynamicCast(OSKext
, linkDependencies
->getObject(i
));
5117 if (dependency
->isInterface()) {
5118 OSKext
*interfaceTargetKext
= NULL
;
5119 OSData
* interfaceTarget
= NULL
;
5121 if (dependency
->isKernelComponent()) {
5122 interfaceTargetKext
= sKernelKext
;
5123 interfaceTarget
= sKernelKext
->linkedExecutable
;
5125 interfaceTargetKext
= OSDynamicCast(OSKext
,
5126 dependency
->dependencies
->getObject(0));
5128 interfaceTarget
= interfaceTargetKext
->linkedExecutable
;
5131 if (!interfaceTarget
) {
5136 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5137 * it will be useful to have them in the debugger.
5138 * strdup() failing isn't critical right here so we don't check that.
5140 kxlddeps
[i
].kext
= (u_char
*) interfaceTarget
->getBytesNoCopy();
5141 kxlddeps
[i
].kext_size
= interfaceTarget
->getLength();
5142 kxlddeps
[i
].kext_name
= strdup(interfaceTargetKext
->getIdentifierCString());
5144 kxlddeps
[i
].interface
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5145 kxlddeps
[i
].interface_size
= dependency
->linkedExecutable
->getLength();
5146 kxlddeps
[i
].interface_name
= strdup(dependency
->getIdentifierCString());
5148 kxlddeps
[i
].kext
= (u_char
*) dependency
->linkedExecutable
->getBytesNoCopy();
5149 kxlddeps
[i
].kext_size
= dependency
->linkedExecutable
->getLength();
5150 kxlddeps
[i
].kext_name
= strdup(dependency
->getIdentifierCString());
5153 kxlddeps
[i
].is_direct_dependency
= (i
< numDirectDependencies
);
5156 kxldHeaderPtr
= &kxld_header
;
5160 kOSKextLogExplicitLevel
|
5161 kOSKextLogLoadFlag
| kOSKextLogLinkFlag
,
5162 "Kext %s - calling kxld_link_file:\n"
5163 " kxld_context: %p\n"
5164 " executable: %p executable_length: %d\n"
5166 " kxld_dependencies: %p num_dependencies: %d\n"
5167 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5168 getIdentifierCString(), sKxldContext
,
5169 theExecutable
->getBytesNoCopy(), theExecutable
->getLength(),
5170 this, kxlddeps
, num_kxlddeps
,
5171 kxldHeaderPtr
, &kmod_info
);
5174 /* After this call, the linkedExecutable instance variable
5177 kxldResult
= kxld_link_file(sKxldContext
,
5178 (u_char
*)theExecutable
->getBytesNoCopy(),
5179 theExecutable
->getLength(),
5180 getIdentifierCString(), this, kxlddeps
, num_kxlddeps
,
5181 (u_char
**)kxldHeaderPtr
, (kxld_addr_t
*)&kmod_info
);
5183 if (kxldResult
!= KERN_SUCCESS
) {
5184 // xxx - add kxldResult here?
5186 kOSKextLogErrorLevel
|
5188 "Can't load kext %s - link failed.",
5189 getIdentifierCString());
5190 result
= kOSKextReturnLinkError
;
5194 /* We've written data & instructions into kernel memory, so flush the data
5195 * cache and invalidate the instruction cache.
5196 * I/D caches are coherent on x86
5198 #if !defined(__i386__) && !defined(__x86_64__)
5199 flush_dcache(kmod_info
->address
, kmod_info
->size
, false);
5200 invalidate_icache(kmod_info
->address
, kmod_info
->size
, false);
5204 if (isInterface()) {
5206 /* Whip up a fake kmod_info entry for the interface kext.
5208 kmod_info
= (kmod_info_t
*)kalloc_tag(sizeof(kmod_info_t
), VM_KERN_MEMORY_OSKEXT
);
5210 result
= KERN_MEMORY_ERROR
;
5214 /* A pseudokext has almost nothing in its kmod_info struct.
5216 bzero(kmod_info
, sizeof(kmod_info_t
));
5218 kmod_info
->info_version
= KMOD_INFO_VERSION
;
5220 /* An interface kext doesn't have a linkedExecutable, so save a
5221 * copy of the UUID out of the original executable via copyUUID()
5222 * while we still have the original executable.
5224 interfaceUUID
= copyUUID();
5227 kmod_info
->id
= loadTag
= sNextLoadTag
++;
5228 kmod_info
->reference_count
= 0; // KMOD_DECL... sets it to -1 (invalid).
5230 /* Stamp the bundle ID and version from the OSKext over anything
5231 * resident inside the kmod_info.
5233 string
= getIdentifierCString();
5234 strlcpy(kmod_info
->name
, string
, sizeof(kmod_info
->name
));
5236 string
= versCString
;
5237 strlcpy(kmod_info
->version
, string
, sizeof(kmod_info
->version
));
5239 /* Add the dependencies' kmod_info structs as kmod_references.
5241 num_kmod_refs
= getNumDependencies();
5242 if (num_kmod_refs
) {
5243 kmod_info
->reference_list
= (kmod_reference_t
*)kalloc_tag(
5244 num_kmod_refs
* sizeof(kmod_reference_t
), VM_KERN_MEMORY_OSKEXT
);
5245 if (!kmod_info
->reference_list
) {
5246 result
= KERN_MEMORY_ERROR
;
5249 bzero(kmod_info
->reference_list
,
5250 num_kmod_refs
* sizeof(kmod_reference_t
));
5251 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
5252 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
5253 OSKext
* refKext
= OSDynamicCast(OSKext
, dependencies
->getObject(refIndex
));
5254 ref
->info
= refKext
->kmod_info
;
5255 ref
->info
->reference_count
++;
5257 if (refIndex
+ 1 < num_kmod_refs
) {
5258 ref
->next
= kmod_info
->reference_list
+ refIndex
+ 1;
5263 if (!isInterface() && linkedExecutable
) {
5265 kOSKextLogProgressLevel
|
5267 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5269 (unsigned)kmod_info
->size
/ PAGE_SIZE
,
5270 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5271 (unsigned)kmod_info
->id
);
5274 /* if prelinked, VM protections are already set */
5275 result
= setVMAttributes(!isPrelinked(), true);
5276 if (result
!= KERN_SUCCESS
) {
5280 result
= kOSReturnSuccess
;
5283 OSSafeRelease(linkDependencies
);
5285 /* Clear up locally allocated dependency info.
5287 for (i
= 0; i
< num_kxlddeps
; ++i
) {
5290 if (kxlddeps
[i
].kext_name
) {
5291 size
= 1 + strlen(kxlddeps
[i
].kext_name
);
5292 kfree(kxlddeps
[i
].kext_name
, size
);
5294 if (kxlddeps
[i
].interface_name
) {
5295 size
= 1 + strlen(kxlddeps
[i
].interface_name
);
5296 kfree(kxlddeps
[i
].interface_name
, size
);
5299 if (kxlddeps
) kfree(kxlddeps
, (num_kxlddeps
* sizeof(*kxlddeps
)));
5301 /* We no longer need the unrelocated executable (which the linker
5302 * has altered anyhow).
5304 setExecutable(NULL
);
5306 if (result
!= kOSReturnSuccess
) {
5308 kOSKextLogErrorLevel
|
5310 "Failed to load executable for kext %s.",
5311 getIdentifierCString());
5313 if (kmod_info
&& kmod_info
->reference_list
) {
5314 kfree(kmod_info
->reference_list
,
5315 num_kmod_refs
* sizeof(kmod_reference_t
));
5317 if (isInterface()) {
5318 kfree(kmod_info
, sizeof(kmod_info_t
));
5321 if (linkedExecutable
) {
5322 linkedExecutable
->release();
5323 linkedExecutable
= NULL
;
5330 /*********************************************************************
5331 * The linkedit segment is used by the kext linker for dependency
5332 * resolution, and by dtrace for probe initialization. We can free it
5333 * for non-library kexts, since no kexts depend on non-library kexts
5334 * by definition, once dtrace has been initialized.
5335 *********************************************************************/
5337 OSKext::jettisonLinkeditSegment(void)
5339 kernel_mach_header_t
* machhdr
= (kernel_mach_header_t
*)kmod_info
->address
;
5340 kernel_segment_command_t
* linkedit
= NULL
;
5342 vm_size_t linkeditsize
, kextsize
;
5343 OSData
* data
= NULL
;
5346 /* We can free symbol tables for all embedded kexts because we don't
5347 * support runtime kext linking.
5349 if (sKeepSymbols
|| !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5351 if (sKeepSymbols
|| isLibrary() || !isExecutable() || !linkedExecutable
|| flags
.jettisonLinkeditSeg
) {
5356 /* Find the linkedit segment. If it's not the last segment, then freeing
5357 * it will fragment the kext into multiple VM regions, which OSKext is not
5358 * designed to handle, so we'll have to skip it.
5360 linkedit
= getsegbynamefromheader(machhdr
, SEG_LINKEDIT
);
5365 if (round_page(kmod_info
->address
+ kmod_info
->size
) !=
5366 round_page(linkedit
->vmaddr
+ linkedit
->vmsize
))
5371 /* Create a new OSData for the smaller kext object.
5373 linkeditsize
= round_page(linkedit
->vmsize
);
5374 kextsize
= kmod_info
->size
- linkeditsize
;
5375 start
= linkedit
->vmaddr
;
5377 data
= OSData::withBytesNoCopy((void *)kmod_info
->address
, kextsize
);
5382 /* Fix the kmod info and linkedExecutable.
5384 kmod_info
->size
= kextsize
;
5387 data
->setDeallocFunction(osdata_kext_free
);
5389 data
->setDeallocFunction(osdata_phys_free
);
5391 linkedExecutable
->setDeallocFunction(NULL
);
5392 linkedExecutable
->release();
5393 linkedExecutable
= data
;
5394 flags
.jettisonLinkeditSeg
= 1;
5396 /* Free the linkedit segment.
5399 kext_free(start
, linkeditsize
);
5401 ml_static_mfree(start
, linkeditsize
);
5408 /*********************************************************************
5409 * If there are whole pages that are unused betweem the last section
5410 * of the DATA segment and the end of the DATA segment then we can free
5412 *********************************************************************/
5414 OSKext::jettisonDATASegmentPadding(void)
5416 kernel_mach_header_t
* mh
;
5417 kernel_segment_command_t
* dataSeg
;
5418 kernel_section_t
* sec
, * lastSec
;
5419 vm_offset_t dataSegEnd
, lastSecEnd
;
5422 mh
= (kernel_mach_header_t
*)kmod_info
->address
;
5424 dataSeg
= getsegbynamefromheader(mh
, SEG_DATA
);
5425 if (dataSeg
== NULL
) {
5430 sec
= firstsect(dataSeg
);
5431 while (sec
!= NULL
) {
5433 sec
= nextsect(dataSeg
, sec
);
5436 if (lastSec
== NULL
) {
5440 if ((dataSeg
->vmaddr
!= round_page(dataSeg
->vmaddr
)) ||
5441 (dataSeg
->vmsize
!= round_page(dataSeg
->vmsize
))) {
5445 dataSegEnd
= dataSeg
->vmaddr
+ dataSeg
->vmsize
;
5446 lastSecEnd
= round_page(lastSec
->addr
+ lastSec
->size
);
5448 if (dataSegEnd
<= lastSecEnd
) {
5452 padSize
= dataSegEnd
- lastSecEnd
;
5454 if (padSize
>= PAGE_SIZE
) {
5456 kext_free(lastSecEnd
, padSize
);
5458 ml_static_mfree(lastSecEnd
, padSize
);
5463 /*********************************************************************
5464 *********************************************************************/
5466 OSKext::setLinkedExecutable(OSData
* anExecutable
)
5468 if (linkedExecutable
) {
5469 panic("Attempt to set linked executable on kext "
5470 "that already has one (%s).\n",
5471 getIdentifierCString());
5473 linkedExecutable
= anExecutable
;
5474 linkedExecutable
->retain();
5479 /*********************************************************************
5480 * Go through all loaded kexts and tell them to register with dtrace.
5481 * The instance method only registers if necessary.
5482 *********************************************************************/
5485 OSKext::registerKextsWithDTrace(void)
5487 uint32_t count
= sLoadedKexts
->getCount();
5490 IORecursiveLockLock(sKextLock
);
5492 for (i
= 0; i
< count
; i
++) {
5493 OSKext
* thisKext
= NULL
; // do not release
5495 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
5496 if (!thisKext
|| !thisKext
->isExecutable()) {
5500 thisKext
->registerWithDTrace();
5503 IORecursiveLockUnlock(sKextLock
);
5509 extern int (*dtrace_modload
)(struct kmod_info
*, uint32_t);
5510 extern int (*dtrace_modunload
)(struct kmod_info
*);
5513 /*********************************************************************
5514 *********************************************************************/
5516 OSKext::registerWithDTrace(void)
5518 /* Register kext with dtrace. A dtrace_modload failure should not
5519 * prevent a kext from loading, so we ignore the return code.
5521 if (!flags
.dtraceInitialized
&& (dtrace_modload
!= NULL
)) {
5522 uint32_t modflag
= 0;
5523 OSObject
* forceInit
= getPropertyForHostArch("OSBundleForceDTraceInit");
5524 if (forceInit
== kOSBooleanTrue
) {
5525 modflag
|= KMOD_DTRACE_FORCE_INIT
;
5528 (void)(*dtrace_modload
)(kmod_info
, modflag
);
5529 flags
.dtraceInitialized
= true;
5530 jettisonLinkeditSegment();
5534 /*********************************************************************
5535 *********************************************************************/
5537 OSKext::unregisterWithDTrace(void)
5539 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5540 * prevent a kext from loading, so we ignore the return code.
5542 if (flags
.dtraceInitialized
&& (dtrace_modunload
!= NULL
)) {
5543 (void)(*dtrace_modunload
)(kmod_info
);
5544 flags
.dtraceInitialized
= false;
5548 #endif /* CONFIG_DTRACE */
5551 /*********************************************************************
5552 * called only by loadExecutable()
5553 *********************************************************************/
5554 #if !VM_MAPPED_KEXTS
5555 #error Unrecognized architecture
5557 static inline kern_return_t
5560 vm_map_offset_t start
,
5561 vm_map_offset_t end
,
5565 if (start
== end
) { // 10538581
5566 return(KERN_SUCCESS
);
5568 return vm_map_protect(map
, start
, end
, new_prot
, set_max
);
5571 static inline kern_return_t
5574 vm_map_offset_t start
,
5575 vm_map_offset_t end
,
5576 vm_prot_t access_type
,
5577 boolean_t user_wire
)
5579 return vm_map_wire(map
, start
, end
, access_type
| VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_KEXT
), user_wire
);
5584 OSKext::setVMAttributes(bool protect
, bool wire
)
5586 vm_map_t kext_map
= NULL
;
5587 kernel_segment_command_t
* seg
= NULL
;
5588 vm_map_offset_t start
= 0;
5589 vm_map_offset_t end
= 0;
5590 OSReturn result
= kOSReturnError
;
5592 if (isInterface() || !declaresExecutable()) {
5593 result
= kOSReturnSuccess
;
5597 /* Get the kext's vm map */
5598 kext_map
= kext_get_vm_map(kmod_info
);
5600 result
= KERN_MEMORY_ERROR
;
5604 /* Protect the headers as read-only; they do not need to be wired */
5605 result
= (protect
) ? OSKext_protect(kext_map
, kmod_info
->address
,
5606 kmod_info
->address
+ kmod_info
->hdr_size
, VM_PROT_READ
, TRUE
)
5608 if (result
!= KERN_SUCCESS
) {
5612 /* Set the VM protections and wire down each of the segments */
5613 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5617 start
= round_page(seg
->vmaddr
);
5618 end
= trunc_page(seg
->vmaddr
+ seg
->vmsize
);
5621 result
= OSKext_protect(kext_map
, start
, end
, seg
->maxprot
, TRUE
);
5622 if (result
!= KERN_SUCCESS
) {
5624 kOSKextLogErrorLevel
|
5626 "Kext %s failed to set maximum VM protections "
5627 "for segment %s - 0x%x.",
5628 getIdentifierCString(), seg
->segname
, (int)result
);
5632 result
= OSKext_protect(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5633 if (result
!= KERN_SUCCESS
) {
5635 kOSKextLogErrorLevel
|
5637 "Kext %s failed to set initial VM protections "
5638 "for segment %s - 0x%x.",
5639 getIdentifierCString(), seg
->segname
, (int)result
);
5644 if (segmentShouldBeWired(seg
) && wire
) {
5645 result
= OSKext_wire(kext_map
, start
, end
, seg
->initprot
, FALSE
);
5646 if (result
!= KERN_SUCCESS
) {
5651 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5658 /*********************************************************************
5659 *********************************************************************/
5661 OSKext::segmentShouldBeWired(kernel_segment_command_t
*seg
)
5663 return (sKeepSymbols
|| strncmp(seg
->segname
, SEG_LINKEDIT
, sizeof(seg
->segname
)));
5666 /*********************************************************************
5667 *********************************************************************/
5669 OSKext::validateKextMapping(bool startFlag
)
5671 OSReturn result
= kOSReturnError
;
5672 const char * whichOp
= startFlag
? "start" : "stop";
5673 kern_return_t kern_result
= 0;
5674 vm_map_t kext_map
= NULL
;
5675 kernel_segment_command_t
* seg
= NULL
;
5676 mach_vm_address_t address
= 0;
5677 mach_vm_size_t size
= 0;
5679 mach_msg_type_number_t count
;
5680 vm_region_submap_short_info_data_64_t info
;
5682 count
= VM_REGION_SUBMAP_SHORT_INFO_COUNT_64
;
5683 bzero(&info
, sizeof(info
));
5685 // xxx - do we need a distinct OSReturn value for these or is "bad data"
5686 // xxx - sufficient?
5688 /* Verify that the kmod_info and start/stop pointers are non-NULL.
5692 kOSKextLogErrorLevel
|
5694 "Kext %s - NULL kmod_info pointer.",
5695 getIdentifierCString());
5696 result
= kOSKextReturnBadData
;
5701 address
= (mach_vm_address_t
)kmod_info
->start
;
5703 address
= (mach_vm_address_t
)kmod_info
->stop
;
5708 kOSKextLogErrorLevel
|
5710 "Kext %s - NULL module %s pointer.",
5711 getIdentifierCString(), whichOp
);
5712 result
= kOSKextReturnBadData
;
5716 kext_map
= kext_get_vm_map(kmod_info
);
5717 depth
= (kernel_map
== kext_map
) ? 1 : 2;
5719 /* Verify that the start/stop function lies within the kext's address range.
5721 if (address
< kmod_info
->address
+ kmod_info
->hdr_size
||
5722 kmod_info
->address
+ kmod_info
->size
<= address
)
5725 kOSKextLogErrorLevel
|
5727 "Kext %s module %s pointer is outside of kext range "
5728 "(%s %p - kext at %p-%p)..",
5729 getIdentifierCString(),
5732 (void *)VM_KERNEL_UNSLIDE(address
),
5733 (void *)VM_KERNEL_UNSLIDE(kmod_info
->address
),
5734 (void *)(VM_KERNEL_UNSLIDE(kmod_info
->address
) + kmod_info
->size
));
5735 result
= kOSKextReturnBadData
;
5739 /* Only do these checks before calling the start function;
5740 * If anything goes wrong with the mapping while the kext is running,
5741 * we'll likely have panicked well before any attempt to stop the kext.
5745 /* Verify that the start/stop function is executable.
5747 kern_result
= mach_vm_region_recurse(kernel_map
, &address
, &size
, &depth
,
5748 (vm_region_recurse_info_t
)&info
, &count
);
5749 if (kern_result
!= KERN_SUCCESS
) {
5751 kOSKextLogErrorLevel
|
5753 "Kext %s - bad %s pointer %p.",
5754 getIdentifierCString(),
5755 whichOp
, (void *)VM_KERNEL_UNSLIDE(address
));
5756 result
= kOSKextReturnBadData
;
5761 if (!(info
.protection
& VM_PROT_EXECUTE
)) {
5763 kOSKextLogErrorLevel
|
5765 "Kext %s - memory region containing module %s function "
5766 "is not executable.",
5767 getIdentifierCString(), whichOp
);
5768 result
= kOSKextReturnBadData
;
5773 /* Verify that the kext's segments are backed by physical memory.
5775 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
5777 if (!verifySegmentMapping(seg
)) {
5778 result
= kOSKextReturnBadData
;
5782 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
5787 result
= kOSReturnSuccess
;
5792 /*********************************************************************
5793 *********************************************************************/
5795 OSKext::verifySegmentMapping(kernel_segment_command_t
*seg
)
5797 mach_vm_address_t address
= 0;
5799 if (!segmentShouldBeWired(seg
)) return true;
5801 for (address
= seg
->vmaddr
;
5802 address
< round_page(seg
->vmaddr
+ seg
->vmsize
);
5803 address
+= PAGE_SIZE
)
5805 if (!pmap_find_phys(kernel_pmap
, (vm_offset_t
)address
)) {
5807 kOSKextLogErrorLevel
|
5809 "Kext %s - page %p is not backed by physical memory.",
5810 getIdentifierCString(),
5819 /*********************************************************************
5820 *********************************************************************/
5822 OSKext::start(bool startDependenciesFlag
)
5824 OSReturn result
= kOSReturnError
;
5825 kern_return_t (* startfunc
)(kmod_info_t
*, void *);
5826 unsigned int i
, count
;
5827 void * kmodStartData
= NULL
;
5829 if (isStarted() || isInterface() || isKernelComponent()) {
5830 result
= kOSReturnSuccess
;
5836 kOSKextLogErrorLevel
|
5838 "Attempt to start nonloaded kext %s.",
5839 getIdentifierCString());
5840 result
= kOSKextReturnInvalidArgument
;
5844 if (!sLoadEnabled
) {
5846 kOSKextLogErrorLevel
|
5848 "Kext loading is disabled (attempt to start kext %s).",
5849 getIdentifierCString());
5850 result
= kOSKextReturnDisabled
;
5854 result
= validateKextMapping(/* start? */ true);
5855 if (result
!= kOSReturnSuccess
) {
5859 startfunc
= kmod_info
->start
;
5861 count
= getNumDependencies();
5862 for (i
= 0; i
< count
; i
++) {
5863 OSKext
* dependency
= OSDynamicCast(OSKext
, dependencies
->getObject(i
));
5864 if (dependency
== NULL
) {
5866 kOSKextLogErrorLevel
|
5868 "Kext %s start - internal error, dependency disappeared.",
5869 getIdentifierCString());
5872 if (!dependency
->isStarted()) {
5873 if (startDependenciesFlag
) {
5874 OSReturn dependencyResult
=
5875 dependency
->start(startDependenciesFlag
);
5876 if (dependencyResult
!= KERN_SUCCESS
) {
5878 kOSKextLogErrorLevel
|
5880 "Kext %s start - dependency %s failed to start (error 0x%x).",
5881 getIdentifierCString(),
5882 dependency
->getIdentifierCString(),
5888 kOSKextLogErrorLevel
|
5890 "Not starting %s - dependency %s not started yet.",
5891 getIdentifierCString(),
5892 dependency
->getIdentifierCString());
5893 result
= kOSKextReturnStartStopError
; // xxx - make new return?
5900 kOSKextLogDetailLevel
|
5902 "Kext %s calling module start function.",
5903 getIdentifierCString());
5907 #if !CONFIG_STATIC_CPPINIT
5908 result
= OSRuntimeInitializeCPP(kmod_info
, NULL
);
5909 if (result
== KERN_SUCCESS
) {
5913 kmodStartData
= GetAppleTEXTHashForKext(this, this->infoDict
);
5916 if (kmodStartData
) {
5918 kOSKextLogErrorLevel
|
5919 kOSKextLogGeneralFlag
,
5920 "Kext %s calling module start function. kmodStartData %p. arch %s",
5921 getIdentifierCString(), kmodStartData
, ARCHNAME
);
5924 #endif // CONFIG_KEC_FIPS
5926 result
= startfunc(kmod_info
, kmodStartData
);
5928 #if !CONFIG_STATIC_CPPINIT
5929 if (result
!= KERN_SUCCESS
) {
5930 (void) OSRuntimeFinalizeCPP(kmod_info
, NULL
);
5937 /* On success overlap the setting of started/starting. On failure just
5940 if (result
== KERN_SUCCESS
) {
5943 // xxx - log start error from kernel?
5945 kOSKextLogProgressLevel
|
5947 "Kext %s is now started.",
5948 getIdentifierCString());
5950 invokeOrCancelRequestCallbacks(
5951 /* result not actually used */ kOSKextReturnStartStopError
,
5952 /* invokeFlag */ false);
5954 kOSKextLogProgressLevel
|
5956 "Kext %s did not start (return code 0x%x).",
5957 getIdentifierCString(), result
);
5964 /*********************************************************************
5965 *********************************************************************/
5967 bool OSKext::canUnloadKextWithIdentifier(
5968 OSString
* kextIdentifier
,
5969 bool checkClassesFlag
)
5971 bool result
= false;
5972 OSKext
* aKext
= NULL
; // do not release
5974 IORecursiveLockLock(sKextLock
);
5976 aKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
5979 goto finish
; // can't unload what's not loaded
5982 if (aKext
->isLoaded()) {
5983 if (aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) {
5986 if (checkClassesFlag
&& aKext
->hasOSMetaClassInstances()) {
5994 IORecursiveLockUnlock(sKextLock
);
5998 /*********************************************************************
5999 *********************************************************************/
6003 OSReturn result
= kOSReturnError
;
6004 kern_return_t (*stopfunc
)(kmod_info_t
*, void *);
6006 if (!isStarted() || isInterface()) {
6007 result
= kOSReturnSuccess
;
6013 kOSKextLogErrorLevel
|
6015 "Attempt to stop nonloaded kext %s.",
6016 getIdentifierCString());
6017 result
= kOSKextReturnInvalidArgument
;
6021 /* Refuse to stop if we have clients or instances. It is up to
6022 * the caller to make sure those aren't true.
6024 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6026 kOSKextLogErrorLevel
|
6028 "Kext %s - C++ instances; can't stop.",
6029 getIdentifierCString());
6030 result
= kOSKextReturnInUse
;
6034 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6037 kOSKextLogErrorLevel
|
6039 "Kext %s - has references (linkage or tracking object); "
6041 getIdentifierCString());
6042 result
= kOSKextReturnInUse
;
6046 /* Note: If validateKextMapping fails on the stop & unload path,
6047 * we are in serious trouble and a kernel panic is likely whether
6048 * we stop & unload the kext or not.
6050 result
= validateKextMapping(/* start? */ false);
6051 if (result
!= kOSReturnSuccess
) {
6055 stopfunc
= kmod_info
->stop
;
6058 kOSKextLogDetailLevel
|
6060 "Kext %s calling module stop function.",
6061 getIdentifierCString());
6065 result
= stopfunc(kmod_info
, /* userData */ NULL
);
6066 #if !CONFIG_STATIC_CPPINIT
6067 if (result
== KERN_SUCCESS
) {
6068 result
= OSRuntimeFinalizeCPP(kmod_info
, NULL
);
6074 if (result
== KERN_SUCCESS
) {
6078 kOSKextLogDetailLevel
|
6080 "Kext %s is now stopped and ready to unload.",
6081 getIdentifierCString());
6084 kOSKextLogErrorLevel
|
6086 "Kext %s did not stop (return code 0x%x).",
6087 getIdentifierCString(), result
);
6088 result
= kOSKextReturnStartStopError
;
6096 /*********************************************************************
6097 *********************************************************************/
6099 OSKext::unload(void)
6101 OSReturn result
= kOSReturnError
;
6103 uint32_t num_kmod_refs
= 0;
6104 OSKextAccount
* freeAccount
;
6106 if (!sUnloadEnabled
) {
6108 kOSKextLogErrorLevel
|
6110 "Kext unloading is disabled (%s).",
6111 this->getIdentifierCString());
6113 result
= kOSKextReturnDisabled
;
6117 /* Refuse to unload if we have clients or instances. It is up to
6118 * the caller to make sure those aren't true.
6120 if (getRetainCount() > kOSKextMinLoadedRetainCount
) {
6121 // xxx - Don't log under errors? this is more of an info thing
6123 kOSKextLogErrorLevel
|
6124 kOSKextLogKextBookkeepingFlag
,
6125 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6126 getIdentifierCString());
6127 result
= kOSKextReturnInUse
;
6131 if (hasOSMetaClassInstances()) {
6133 kOSKextLogErrorLevel
|
6134 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6135 "Can't unload kext %s; classes have instances:",
6136 getIdentifierCString());
6137 reportOSMetaClassInstances(kOSKextLogErrorLevel
|
6138 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
);
6139 result
= kOSKextReturnInUse
;
6144 result
= kOSReturnSuccess
;
6148 if (isKernelComponent()) {
6149 result
= kOSKextReturnInvalidArgument
;
6153 /* Note that the kext is unloading before running any code that
6154 * might be in the kext (request callbacks, module stop function).
6155 * We will deny certain requests made against a kext in the process
6158 flags
.unloading
= 1;
6160 /* Update the string describing the last kext to unload in case we panic.
6162 savePanicString(/* isLoading */ false);
6166 if (result
!= KERN_SUCCESS
) {
6168 kOSKextLogErrorLevel
|
6170 "Kext %s can't unload - module stop returned 0x%x.",
6171 getIdentifierCString(), (unsigned)result
);
6172 result
= kOSKextReturnStartStopError
;
6178 kOSKextLogProgressLevel
|
6180 "Kext %s unloading.",
6181 getIdentifierCString());
6184 struct list_head
*p
;
6185 struct list_head
*prev
;
6186 struct list_head
*next
;
6187 for (p
= pendingPgoHead
.next
; p
!= &pendingPgoHead
; p
= next
) {
6188 OSKextGrabPgoStruct
*s
= container_of(p
, OSKextGrabPgoStruct
, list_head
);
6189 s
->err
= OSKextGrabPgoDataLocked(this, s
->metadata
, instance_uuid
, s
->pSize
, s
->pBuffer
, s
->bufferSize
);
6196 IORecursiveLockWakeup(sKextLock
, s
, false);
6201 /* Even if we don't call the stop function, we want to be sure we
6202 * have no OSMetaClass references before unloading the kext executable
6203 * from memory. OSMetaClasses may have pointers into the kext executable
6204 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6207 metaClasses
->flushCollection();
6210 /* Remove the kext from the list of loaded kexts, patch the gap
6211 * in the kmod_info_t linked list, and reset "kmod" to point to the
6212 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6214 index
= sLoadedKexts
->getNextIndexOfObject(this, 0);
6215 if (index
!= (unsigned int)-1) {
6217 sLoadedKexts
->removeObject(index
);
6219 OSKext
* nextKext
= OSDynamicCast(OSKext
,
6220 sLoadedKexts
->getObject(index
));
6224 OSKext
* gapKext
= OSDynamicCast(OSKext
,
6225 sLoadedKexts
->getObject(index
- 1));
6227 nextKext
->kmod_info
->next
= gapKext
->kmod_info
;
6229 } else /* index == 0 */ {
6230 nextKext
->kmod_info
->next
= NULL
;
6234 OSKext
* lastKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getLastObject());
6235 if (lastKext
&& !lastKext
->isKernel()) {
6236 kmod
= lastKext
->kmod_info
;
6238 kmod
= NULL
; // clear the global kmod variable
6242 /* Clear out the kmod references that we're keeping for compatibility
6243 * with current panic backtrace code & kgmacros.
6244 * xxx - will want to update those bits sometime and remove this.
6246 num_kmod_refs
= getNumDependencies();
6247 if (num_kmod_refs
&& kmod_info
&& kmod_info
->reference_list
) {
6248 for (uint32_t refIndex
= 0; refIndex
< num_kmod_refs
; refIndex
++) {
6249 kmod_reference_t
* ref
= &(kmod_info
->reference_list
[refIndex
]);
6250 ref
->info
->reference_count
--;
6252 kfree(kmod_info
->reference_list
,
6253 num_kmod_refs
* sizeof(kmod_reference_t
));
6257 unregisterWithDTrace();
6258 #endif /* CONFIG_DTRACE */
6260 notifyKextUnloadObservers(this);
6263 IOSimpleLockLock(sKextAccountsLock
);
6264 if (account
->site
.tag
) account
->site
.flags
|= VM_TAG_UNLOAD
;
6265 else freeAccount
= account
;
6266 IOSimpleLockUnlock(sKextAccountsLock
);
6267 if (freeAccount
) IODelete(freeAccount
, OSKextAccount
, 1);
6269 /* Unwire and free the linked executable.
6271 if (linkedExecutable
) {
6273 if (!isInterface()) {
6274 kernel_segment_command_t
*seg
= NULL
;
6275 vm_map_t kext_map
= kext_get_vm_map(kmod_info
);
6279 kOSKextLogErrorLevel
|
6281 "Failed to free kext %s; couldn't find the kext map.",
6282 getIdentifierCString());
6283 result
= kOSKextReturnInternalError
;
6288 kOSKextLogProgressLevel
|
6290 "Kext %s unwiring and unmapping linked executable.",
6291 getIdentifierCString());
6293 seg
= firstsegfromheader((kernel_mach_header_t
*)kmod_info
->address
);
6295 if (segmentShouldBeWired(seg
)) {
6296 result
= vm_map_unwire(kext_map
, seg
->vmaddr
,
6297 seg
->vmaddr
+ seg
->vmsize
, FALSE
);
6298 if (result
!= KERN_SUCCESS
) {
6300 kOSKextLogErrorLevel
|
6302 "Failed to unwire kext %s.",
6303 getIdentifierCString());
6304 result
= kOSKextReturnInternalError
;
6309 seg
= nextsegfromheader((kernel_mach_header_t
*) kmod_info
->address
, seg
);
6313 OSSafeReleaseNULL(linkedExecutable
);
6316 /* An interface kext has a fake kmod_info that was allocated,
6317 * so we have to free it.
6319 if (isInterface()) {
6320 kfree(kmod_info
, sizeof(kmod_info_t
));
6325 flags
.loaded
= false;
6326 flushDependencies();
6328 /* save a copy of the bundle ID for us to check when deciding to
6329 * rebuild the kernel cache file. If a kext was already in the kernel
6330 * cache and unloaded then later loaded we do not need to rebuild the
6331 * kernel cache. 9055303
6333 if (isPrelinked()) {
6334 if (!_OSKextInUnloadedPrelinkedKexts(bundleID
)) {
6335 IORecursiveLockLock(sKextLock
);
6336 if (sUnloadedPrelinkedKexts
) {
6337 sUnloadedPrelinkedKexts
->setObject(bundleID
);
6339 IORecursiveLockUnlock(sKextLock
);
6344 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6345 "Kext %s unloaded.", getIdentifierCString());
6347 queueKextNotification(kKextRequestPredicateUnloadNotification
,
6348 OSDynamicCast(OSString
, bundleID
));
6351 OSKext::saveLoadedKextPanicList();
6352 OSKext::updateLoadedKextSummaries();
6354 flags
.unloading
= 0;
6358 /*********************************************************************
6359 * Assumes sKextLock is held.
6360 *********************************************************************/
6363 OSKext::queueKextNotification(
6364 const char * notificationName
,
6365 OSString
* kextIdentifier
)
6367 OSReturn result
= kOSReturnError
;
6368 OSDictionary
* loadRequest
= NULL
; // must release
6370 if (!kextIdentifier
) {
6371 result
= kOSKextReturnInvalidArgument
;
6375 /* Create a new request unless one is already sitting
6376 * in sKernelRequests for this bundle identifier
6378 result
= _OSKextCreateRequest(notificationName
, &loadRequest
);
6379 if (result
!= kOSReturnSuccess
) {
6382 if (!_OSKextSetRequestArgument(loadRequest
,
6383 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
)) {
6385 result
= kOSKextReturnNoMemory
;
6388 if (!sKernelRequests
->setObject(loadRequest
)) {
6389 result
= kOSKextReturnNoMemory
;
6393 /* We might want to only queue the notification if kextd is active,
6394 * but that wouldn't work for embedded. Note that we don't care if
6395 * the ping immediately succeeds here so don't do anything with the
6396 * result of this call.
6398 OSKext::pingKextd();
6400 result
= kOSReturnSuccess
;
6403 OSSafeRelease(loadRequest
);
6408 /*********************************************************************
6409 *********************************************************************/
6411 _OSKextConsiderDestroyingLinkContext(
6412 __unused thread_call_param_t p0
,
6413 __unused thread_call_param_t p1
)
6415 /* Take multiple locks in the correct order.
6417 IORecursiveLockLock(sKextLock
);
6418 IORecursiveLockLock(sKextInnerLock
);
6420 /* The first time we destroy the kxldContext is in the first
6421 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6422 * before calling this function. Thereafter any call to this function
6423 * will actually destroy the context.
6425 if (sConsiderUnloadsCalled
&& sKxldContext
) {
6426 kxld_destroy_context(sKxldContext
);
6427 sKxldContext
= NULL
;
6430 /* Free the thread_call that was allocated to execute this function.
6432 if (sDestroyLinkContextThread
) {
6433 if (!thread_call_free(sDestroyLinkContextThread
)) {
6434 OSKextLog(/* kext */ NULL
,
6435 kOSKextLogErrorLevel
|
6436 kOSKextLogGeneralFlag
,
6437 "thread_call_free() failed for kext link context.");
6439 sDestroyLinkContextThread
= 0;
6442 IORecursiveLockUnlock(sKextInnerLock
);
6443 IORecursiveLockUnlock(sKextLock
);
6448 /*********************************************************************
6449 * Destroying the kxldContext requires checking variables under both
6450 * sKextInnerLock and sKextLock, so we do it on a separate thread
6451 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6452 * call relationship.
6454 * This function must be invoked with sKextInnerLock held.
6455 * Do not call any function that takes sKextLock here!
6456 *********************************************************************/
6459 OSKext::considerDestroyingLinkContext(void)
6461 IORecursiveLockLock(sKextInnerLock
);
6463 /* If we have already queued a thread to destroy the link context,
6464 * don't bother resetting; that thread will take care of it.
6466 if (sDestroyLinkContextThread
) {
6470 /* The function to be invoked in the thread will deallocate
6471 * this thread_call, so don't share it around.
6473 sDestroyLinkContextThread
= thread_call_allocate(
6474 &_OSKextConsiderDestroyingLinkContext
, 0);
6475 if (!sDestroyLinkContextThread
) {
6476 OSKextLog(/* kext */ NULL
,
6477 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
| kOSKextLogLinkFlag
,
6478 "Can't create thread to destroy kext link context.");
6482 thread_call_enter(sDestroyLinkContextThread
);
6485 IORecursiveLockUnlock(sKextInnerLock
);
6490 #pragma mark Autounload
6492 /*********************************************************************
6493 * This is a static method because the kext will be deallocated if it
6495 *********************************************************************/
6498 OSKext::autounloadKext(OSKext
* aKext
)
6500 OSReturn result
= kOSKextReturnInUse
;
6502 /* Check for external references to this kext (usu. dependents),
6503 * instances of defined classes (or classes derived from them),
6504 * outstanding requests.
6506 if ((aKext
->getRetainCount() > kOSKextMinLoadedRetainCount
) ||
6507 !aKext
->flags
.autounloadEnabled
||
6508 aKext
->isKernelComponent()) {
6513 /* Skip a delay-autounload kext, once.
6515 if (aKext
->flags
.delayAutounload
) {
6517 kOSKextLogProgressLevel
|
6518 kOSKextLogLoadFlag
| kOSKextLogKextBookkeepingFlag
,
6519 "Kext %s has delayed autounload set; skipping and clearing flag.",
6520 aKext
->getIdentifierCString());
6521 aKext
->flags
.delayAutounload
= 0;
6525 if (aKext
->hasOSMetaClassInstances() ||
6526 aKext
->countRequestCallbacks()) {
6530 result
= OSKext::removeKext(aKext
);
6536 /*********************************************************************
6537 *********************************************************************/
6539 _OSKextConsiderUnloads(
6540 __unused thread_call_param_t p0
,
6541 __unused thread_call_param_t p1
)
6543 bool didUnload
= false;
6544 unsigned int count
, i
;
6546 /* Take multiple locks in the correct order
6547 * (note also sKextSummaries lock further down).
6549 IORecursiveLockLock(sKextLock
);
6550 IORecursiveLockLock(sKextInnerLock
);
6552 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6554 /* If the system is powering down, don't try to unload anything.
6560 OSKextLog(/* kext */ NULL
,
6561 kOSKextLogProgressLevel
| kOSKextLogLoadFlag
,
6562 "Checking for unused kexts to autounload.");
6565 * Remove any request callbacks marked as stale,
6566 * and mark as stale any currently in flight.
6568 count
= sRequestCallbackRecords
->getCount();
6572 OSDictionary
* callbackRecord
= OSDynamicCast(OSDictionary
,
6573 sRequestCallbackRecords
->getObject(i
));
6574 OSBoolean
* stale
= OSDynamicCast(OSBoolean
,
6575 callbackRecord
->getObject(kKextRequestStaleKey
));
6577 if (stale
== kOSBooleanTrue
) {
6578 OSKext::invokeRequestCallback(callbackRecord
,
6579 kOSKextReturnTimeout
);
6581 callbackRecord
->setObject(kKextRequestStaleKey
,
6588 * Make multiple passes through the array of loaded kexts until
6589 * we don't unload any. This handles unwinding of dependency
6590 * chains. We have to go *backwards* through the array because
6591 * kexts are removed from it when unloaded, and we cannot make
6592 * a copy or we'll mess up the retain counts we rely on to
6593 * check whether a kext will unload. If only we could have
6594 * nonretaining collections like CF has....
6599 count
= sLoadedKexts
->getCount();
6603 OSKext
* thisKext
= OSDynamicCast(OSKext
,
6604 sLoadedKexts
->getObject(i
));
6605 didUnload
|= (kOSReturnSuccess
== OSKext::autounloadKext(thisKext
));
6608 } while (didUnload
);
6611 sConsiderUnloadsPending
= false;
6612 sConsiderUnloadsExecuted
= true;
6614 (void) OSKext::considerRebuildOfPrelinkedKernel();
6616 IORecursiveLockUnlock(sKextInnerLock
);
6617 IORecursiveLockUnlock(sKextLock
);
6622 /*********************************************************************
6623 * Do not call any function that takes sKextLock here!
6624 *********************************************************************/
6625 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag
)
6629 IORecursiveLockLock(sKextInnerLock
);
6631 if (!sUnloadCallout
) {
6632 sUnloadCallout
= thread_call_allocate(&_OSKextConsiderUnloads
, 0);
6635 /* we only reset delay value for unloading if we already have something
6636 * pending. rescheduleOnlyFlag should not start the count down.
6638 if (rescheduleOnlyFlag
&& !sConsiderUnloadsPending
) {
6642 thread_call_cancel(sUnloadCallout
);
6643 if (OSKext::getAutounloadEnabled() && !sSystemSleep
) {
6644 clock_interval_to_deadline(sConsiderUnloadDelay
,
6645 1000 * 1000 * 1000, &when
);
6647 OSKextLog(/* kext */ NULL
,
6648 kOSKextLogProgressLevel
|
6650 "%scheduling %sscan for unused kexts in %lu seconds.",
6651 sConsiderUnloadsPending
? "Res" : "S",
6652 sConsiderUnloadsCalled
? "" : "initial ",
6653 (unsigned long)sConsiderUnloadDelay
);
6655 sConsiderUnloadsPending
= true;
6656 thread_call_enter_delayed(sUnloadCallout
, when
);
6660 /* The kxld context should be reused throughout boot. We mark the end of
6661 * period as the first time considerUnloads() is called, and we destroy
6662 * the first kxld context in that function. Afterwards, it will be
6663 * destroyed in flushNonloadedKexts.
6665 if (!sConsiderUnloadsCalled
) {
6666 sConsiderUnloadsCalled
= true;
6667 OSKext::considerDestroyingLinkContext();
6670 IORecursiveLockUnlock(sKextInnerLock
);
6674 /*********************************************************************
6675 * Do not call any function that takes sKextLock here!
6676 *********************************************************************/
6679 IOReturn
OSKextSystemSleepOrWake(UInt32 messageType
)
6681 IORecursiveLockLock(sKextInnerLock
);
6683 /* If the system is going to sleep, cancel the reaper thread timer,
6684 * and note that we're in a sleep state in case it just fired but hasn't
6685 * taken the lock yet. If we are coming back from sleep, just
6686 * clear the sleep flag; IOService's normal operation will cause
6687 * unloads to be considered soon enough.
6689 if (messageType
== kIOMessageSystemWillSleep
) {
6690 if (sUnloadCallout
) {
6691 thread_call_cancel(sUnloadCallout
);
6693 sSystemSleep
= true;
6694 AbsoluteTime_to_scalar(&sLastWakeTime
) = 0;
6695 } else if (messageType
== kIOMessageSystemHasPoweredOn
) {
6696 sSystemSleep
= false;
6697 clock_get_uptime(&sLastWakeTime
);
6699 IORecursiveLockUnlock(sKextInnerLock
);
6701 return kIOReturnSuccess
;
6708 #pragma mark Prelinked Kernel
6710 /*********************************************************************
6711 * Do not access sConsiderUnloads... variables other than
6712 * sConsiderUnloadsExecuted in this function. They are guarded by a
6714 *********************************************************************/
6717 OSKext::considerRebuildOfPrelinkedKernel(void)
6719 static bool requestedPrelink
= false;
6720 OSReturn checkResult
= kOSReturnError
;
6721 OSDictionary
* prelinkRequest
= NULL
; // must release
6722 OSCollectionIterator
* kextIterator
= NULL
; // must release
6723 const OSSymbol
* thisID
= NULL
; // do not release
6724 bool doRebuild
= false;
6725 AbsoluteTime my_abstime
;
6729 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
6730 if (requestedPrelink
|| !sPrelinkBoot
) {
6734 /* no direct return from this point */
6735 IORecursiveLockLock(sKextLock
);
6737 /* We need to wait for kextd to get up and running with unloads already done
6738 * and any new startup kexts loaded.
6740 if (!sConsiderUnloadsExecuted
||
6741 !sDeferredLoadSucceeded
) {
6745 /* we really only care about boot / system start up related kexts so bail
6746 * if we're here after REBUILD_MAX_TIME.
6748 if (!_OSKextInPrelinkRebuildWindow()) {
6749 OSKextLog(/* kext */ NULL
,
6750 kOSKextLogArchiveFlag
,
6751 "%s prebuild rebuild has expired",
6753 requestedPrelink
= true;
6757 /* we do not want to trigger a rebuild if we get here too close to waking
6758 * up. (see radar 10233768)
6760 IORecursiveLockLock(sKextInnerLock
);
6762 clock_get_uptime(&my_abstime
);
6763 delta_secs
= MINIMUM_WAKEUP_SECONDS
+ 1;
6764 if (AbsoluteTime_to_scalar(&sLastWakeTime
) != 0) {
6765 SUB_ABSOLUTETIME(&my_abstime
, &sLastWakeTime
);
6766 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
6767 delta_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
6769 IORecursiveLockUnlock(sKextInnerLock
);
6771 if (delta_secs
< MINIMUM_WAKEUP_SECONDS
) {
6772 /* too close to time of last wake from sleep */
6775 requestedPrelink
= true;
6777 /* Now it's time to see if we have a reason to rebuild. We may have done
6778 * some loads and unloads but the kernel cache didn't actually change.
6779 * We will rebuild if any kext is not marked prelinked AND is not in our
6780 * list of prelinked kexts that got unloaded. (see radar 9055303)
6782 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
6783 if (!kextIterator
) {
6787 while ((thisID
= OSDynamicCast(OSSymbol
, kextIterator
->getNextObject()))) {
6788 OSKext
* thisKext
; // do not release
6790 thisKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(thisID
));
6791 if (!thisKext
|| thisKext
->isPrelinked() || thisKext
->isKernel()) {
6795 if (_OSKextInUnloadedPrelinkedKexts(thisKext
->bundleID
)) {
6798 /* kext is loaded and was not in current kernel cache so let's rebuild
6801 OSKextLog(/* kext */ NULL
,
6802 kOSKextLogArchiveFlag
,
6803 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
6804 thisKext
->bundleID
->getCStringNoCopy());
6807 sUnloadedPrelinkedKexts
->flushCollection();
6813 checkResult
= _OSKextCreateRequest(kKextRequestPredicateRequestPrelink
,
6815 if (checkResult
!= kOSReturnSuccess
) {
6819 if (!sKernelRequests
->setObject(prelinkRequest
)) {
6823 OSKext::pingKextd();
6826 IORecursiveLockUnlock(sKextLock
);
6827 OSSafeRelease(prelinkRequest
);
6828 OSSafeRelease(kextIterator
);
6834 #pragma mark Dependencies
6836 /*********************************************************************
6837 *********************************************************************/
6839 OSKext::resolveDependencies(
6840 OSArray
* loopStack
)
6842 bool result
= false;
6843 OSArray
* localLoopStack
= NULL
; // must release
6844 bool addedToLoopStack
= false;
6845 OSDictionary
* libraries
= NULL
; // do not release
6846 OSCollectionIterator
* libraryIterator
= NULL
; // must release
6847 OSString
* libraryID
= NULL
; // do not release
6848 OSString
* infoString
= NULL
; // do not release
6849 OSString
* readableString
= NULL
; // do not release
6850 OSKext
* libraryKext
= NULL
; // do not release
6851 bool hasRawKernelDependency
= false;
6852 bool hasKernelDependency
= false;
6853 bool hasKPIDependency
= false;
6854 bool hasPrivateKPIDependency
= false;
6857 /* A kernel component will automatically have this flag set,
6858 * and a loaded kext should also have it set (as should all its
6859 * loaded dependencies).
6861 if (flags
.hasAllDependencies
) {
6866 /* Check for loops in the dependency graph.
6869 if (loopStack
->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
6871 kOSKextLogErrorLevel
|
6872 kOSKextLogDependenciesFlag
,
6873 "Kext %s has a dependency loop; can't resolve dependencies.",
6874 getIdentifierCString());
6879 kOSKextLogStepLevel
|
6880 kOSKextLogDependenciesFlag
,
6881 "Kext %s resolving dependencies.",
6882 getIdentifierCString());
6884 loopStack
= OSArray::withCapacity(6); // any small capacity will do
6887 kOSKextLogErrorLevel
|
6888 kOSKextLogDependenciesFlag
,
6889 "Kext %s can't create bookkeeping stack to resolve dependencies.",
6890 getIdentifierCString());
6893 localLoopStack
= loopStack
;
6895 if (!loopStack
->setObject(this)) {
6897 kOSKextLogErrorLevel
|
6898 kOSKextLogDependenciesFlag
,
6899 "Kext %s - internal error resolving dependencies.",
6900 getIdentifierCString());
6903 addedToLoopStack
= true;
6905 /* Purge any existing kexts in the dependency list and start over.
6907 flushDependencies();
6910 kOSKextLogErrorLevel
|
6911 kOSKextLogDependenciesFlag
,
6912 "Kext %s - internal error resolving dependencies.",
6913 getIdentifierCString());
6916 libraries
= OSDynamicCast(OSDictionary
,
6917 getPropertyForHostArch(kOSBundleLibrariesKey
));
6918 if (libraries
== NULL
|| libraries
->getCount() == 0) {
6920 kOSKextLogErrorLevel
|
6921 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6922 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
6923 getIdentifierCString(), kOSBundleLibrariesKey
);
6927 /* Make a new array to hold the dependencies (flush freed the old one).
6929 dependencies
= OSArray::withCapacity(libraries
->getCount());
6930 if (!dependencies
) {
6932 kOSKextLogErrorLevel
|
6933 kOSKextLogDependenciesFlag
,
6934 "Kext %s - can't allocate dependencies array.",
6935 getIdentifierCString());
6939 // xxx - compat: We used to add an implicit dependency on kernel 6.0
6940 // xxx - compat: if none were declared.
6942 libraryIterator
= OSCollectionIterator::withCollection(libraries
);
6943 if (!libraryIterator
) {
6945 kOSKextLogErrorLevel
|
6946 kOSKextLogDependenciesFlag
,
6947 "Kext %s - can't allocate dependencies iterator.",
6948 getIdentifierCString());
6952 while ((libraryID
= OSDynamicCast(OSString
,
6953 libraryIterator
->getNextObject()))) {
6955 const char * library_id
= libraryID
->getCStringNoCopy();
6957 OSString
* libraryVersion
= OSDynamicCast(OSString
,
6958 libraries
->getObject(libraryID
));
6959 if (libraryVersion
== NULL
) {
6961 kOSKextLogErrorLevel
|
6962 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6963 "Kext %s - illegal type in OSBundleLibraries.",
6964 getIdentifierCString());
6968 OSKextVersion libraryVers
=
6969 OSKextParseVersionString(libraryVersion
->getCStringNoCopy());
6970 if (libraryVers
== -1) {
6972 kOSKextLogErrorLevel
|
6973 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
6974 "Kext %s - invalid library version %s.",
6975 getIdentifierCString(),
6976 libraryVersion
->getCStringNoCopy());
6980 libraryKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(libraryID
));
6981 if (libraryKext
== NULL
) {
6983 kOSKextLogErrorLevel
|
6984 kOSKextLogDependenciesFlag
,
6985 "Kext %s - library kext %s not found.",
6986 getIdentifierCString(), library_id
);
6990 if (!libraryKext
->isCompatibleWithVersion(libraryVers
)) {
6992 kOSKextLogErrorLevel
|
6993 kOSKextLogDependenciesFlag
,
6994 "Kext %s - library kext %s not compatible "
6995 "with requested version %s.",
6996 getIdentifierCString(), library_id
,
6997 libraryVersion
->getCStringNoCopy());
7001 /* If a nonprelinked library somehow got into the mix for a
7002 * prelinked kext, at any point in the chain, we must fail
7003 * because the prelinked relocs for the library will be all wrong.
7005 if (this->isPrelinked() &&
7006 libraryKext
->declaresExecutable() &&
7007 !libraryKext
->isPrelinked()) {
7010 kOSKextLogErrorLevel
|
7011 kOSKextLogDependenciesFlag
,
7012 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7013 getIdentifierCString(), library_id
,
7014 libraryVersion
->getCStringNoCopy());
7018 if (!libraryKext
->resolveDependencies(loopStack
)) {
7022 /* Add the library directly only if it has an executable to link.
7023 * Otherwise it's just used to collect other dependencies, so put
7024 * *its* dependencies on the list for this kext.
7026 // xxx - We are losing info here; would like to make fake entries or
7027 // xxx - keep these in the dependency graph for loaded kexts.
7028 // xxx - I really want to make kernel components not a special case!
7029 if (libraryKext
->declaresExecutable() ||
7030 libraryKext
->isInterface()) {
7032 if (dependencies
->getNextIndexOfObject(libraryKext
, 0) == (unsigned)-1) {
7033 dependencies
->setObject(libraryKext
);
7036 kOSKextLogDetailLevel
|
7037 kOSKextLogDependenciesFlag
,
7038 "Kext %s added dependency %s.",
7039 getIdentifierCString(),
7040 libraryKext
->getIdentifierCString());
7043 int numLibDependencies
= libraryKext
->getNumDependencies();
7044 OSArray
* libraryDependencies
= libraryKext
->getDependencies();
7047 if (numLibDependencies
) {
7048 // xxx - this msg level should be 1 lower than the per-kext one
7050 kOSKextLogDetailLevel
|
7051 kOSKextLogDependenciesFlag
,
7052 "Kext %s pulling %d dependencies from codeless library %s.",
7053 getIdentifierCString(),
7055 libraryKext
->getIdentifierCString());
7057 for (index
= 0; index
< numLibDependencies
; index
++) {
7058 OSKext
* thisLibDependency
= OSDynamicCast(OSKext
,
7059 libraryDependencies
->getObject(index
));
7060 if (dependencies
->getNextIndexOfObject(thisLibDependency
, 0) == (unsigned)-1) {
7061 dependencies
->setObject(thisLibDependency
);
7063 kOSKextLogDetailLevel
|
7064 kOSKextLogDependenciesFlag
,
7065 "Kext %s added dependency %s from codeless library %s.",
7066 getIdentifierCString(),
7067 thisLibDependency
->getIdentifierCString(),
7068 libraryKext
->getIdentifierCString());
7073 if ((strlen(library_id
) == strlen(KERNEL_LIB
)) &&
7074 0 == strncmp(library_id
, KERNEL_LIB
, sizeof(KERNEL_LIB
)-1)) {
7076 hasRawKernelDependency
= true;
7077 } else if (STRING_HAS_PREFIX(library_id
, KERNEL_LIB_PREFIX
)) {
7078 hasKernelDependency
= true;
7079 } else if (STRING_HAS_PREFIX(library_id
, KPI_LIB_PREFIX
)) {
7080 hasKPIDependency
= true;
7081 if (!strncmp(library_id
, PRIVATE_KPI
, sizeof(PRIVATE_KPI
)-1)) {
7082 hasPrivateKPIDependency
= true;
7087 if (hasRawKernelDependency
) {
7089 kOSKextLogErrorLevel
|
7090 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7091 "Error - kext %s declares a dependency on %s, which is not permitted.",
7092 getIdentifierCString(), KERNEL_LIB
);
7096 if (hasKernelDependency
) {
7098 kOSKextLogErrorLevel
|
7099 kOSKextLogValidationFlag
| kOSKextLogDependenciesFlag
,
7100 "Error - kext %s declares %s dependencies. "
7101 "Only %s* dependencies are supported for 64-bit kexts.",
7102 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7105 if (!hasKPIDependency
) {
7107 kOSKextLogWarningLevel
|
7108 kOSKextLogDependenciesFlag
,
7109 "Warning - kext %s declares no %s* dependencies. "
7110 "If it uses any KPIs, the link may fail with undefined symbols.",
7111 getIdentifierCString(), KPI_LIB_PREFIX
);
7113 #else /* __LP64__ */
7114 // xxx - will change to flatly disallow "kernel" dependencies at some point
7115 // xxx - is it invalid to do both "com.apple.kernel" and any
7116 // xxx - "com.apple.kernel.*"?
7118 if (hasKernelDependency
&& hasKPIDependency
) {
7120 kOSKextLogWarningLevel
|
7121 kOSKextLogDependenciesFlag
,
7122 "Warning - kext %s has immediate dependencies on both "
7123 "%s* and %s* components; use only one style.",
7124 getIdentifierCString(), KERNEL_LIB
, KPI_LIB_PREFIX
);
7127 if (!hasKernelDependency
&& !hasKPIDependency
) {
7128 // xxx - do we want to use validation flag for these too?
7130 kOSKextLogWarningLevel
|
7131 kOSKextLogDependenciesFlag
,
7132 "Warning - %s declares no kernel dependencies; using %s.",
7133 getIdentifierCString(), KERNEL6_LIB
);
7134 OSKext
* kernelKext
= OSDynamicCast(OSKext
,
7135 sKextsByID
->getObject(KERNEL6_LIB
));
7137 dependencies
->setObject(kernelKext
);
7140 kOSKextLogErrorLevel
|
7141 kOSKextLogDependenciesFlag
,
7142 "Error - Library %s not found for %s.",
7143 KERNEL6_LIB
, getIdentifierCString());
7147 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7148 * its indirect dependencies to simulate old-style linking. XXX - Should
7149 * check for duplicates.
7151 if (!hasKPIDependency
) {
7154 flags
.hasBleedthrough
= true;
7156 count
= getNumDependencies();
7158 /* We add to the dependencies array in this loop, but do not iterate
7159 * past its original count.
7161 for (i
= 0; i
< count
; i
++) {
7162 OSKext
* dependencyKext
= OSDynamicCast(OSKext
,
7163 dependencies
->getObject(i
));
7164 dependencyKext
->addBleedthroughDependencies(dependencies
);
7167 #endif /* __LP64__ */
7169 if (hasPrivateKPIDependency
) {
7170 bool hasApplePrefix
= false;
7171 bool infoCopyrightIsValid
= false;
7172 bool readableCopyrightIsValid
= false;
7174 hasApplePrefix
= STRING_HAS_PREFIX(getIdentifierCString(),
7177 infoString
= OSDynamicCast(OSString
,
7178 getPropertyForHostArch("CFBundleGetInfoString"));
7180 infoCopyrightIsValid
=
7181 kxld_validate_copyright_string(infoString
->getCStringNoCopy());
7184 readableString
= OSDynamicCast(OSString
,
7185 getPropertyForHostArch("NSHumanReadableCopyright"));
7186 if (readableString
) {
7187 readableCopyrightIsValid
=
7188 kxld_validate_copyright_string(readableString
->getCStringNoCopy());
7191 if (!hasApplePrefix
|| (!infoCopyrightIsValid
&& !readableCopyrightIsValid
)) {
7193 kOSKextLogErrorLevel
|
7194 kOSKextLogDependenciesFlag
,
7195 "Error - kext %s declares a dependency on %s. "
7196 "Only Apple kexts may declare a dependency on %s.",
7197 getIdentifierCString(), PRIVATE_KPI
, PRIVATE_KPI
);
7203 flags
.hasAllDependencies
= 1;
7207 if (addedToLoopStack
) {
7208 count
= loopStack
->getCount();
7209 if (count
> 0 && (this == loopStack
->getObject(count
- 1))) {
7210 loopStack
->removeObject(count
- 1);
7213 kOSKextLogErrorLevel
|
7214 kOSKextLogDependenciesFlag
,
7215 "Kext %s - internal error resolving dependencies.",
7216 getIdentifierCString());
7220 if (result
&& localLoopStack
) {
7222 kOSKextLogStepLevel
|
7223 kOSKextLogDependenciesFlag
,
7224 "Kext %s successfully resolved dependencies.",
7225 getIdentifierCString());
7228 OSSafeRelease(localLoopStack
);
7229 OSSafeRelease(libraryIterator
);
7234 /*********************************************************************
7235 *********************************************************************/
7237 OSKext::addBleedthroughDependencies(OSArray
* anArray
)
7239 bool result
= false;
7240 unsigned int dependencyIndex
, dependencyCount
;
7242 dependencyCount
= getNumDependencies();
7244 for (dependencyIndex
= 0;
7245 dependencyIndex
< dependencyCount
;
7246 dependencyIndex
++) {
7248 OSKext
* dependency
= OSDynamicCast(OSKext
,
7249 dependencies
->getObject(dependencyIndex
));
7252 kOSKextLogErrorLevel
|
7253 kOSKextLogDependenciesFlag
,
7254 "Kext %s - internal error propagating compatibility dependencies.",
7255 getIdentifierCString());
7258 if (anArray
->getNextIndexOfObject(dependency
, 0) == (unsigned int)-1) {
7259 anArray
->setObject(dependency
);
7261 dependency
->addBleedthroughDependencies(anArray
);
7270 /*********************************************************************
7271 *********************************************************************/
7273 OSKext::flushDependencies(bool forceFlag
)
7275 bool result
= false;
7277 /* Only clear the dependencies if the kext isn't loaded;
7278 * we need the info for loaded kexts to track references.
7280 if (!isLoaded() || forceFlag
) {
7282 // xxx - check level
7284 kOSKextLogProgressLevel
|
7285 kOSKextLogDependenciesFlag
,
7286 "Kext %s flushing dependencies.",
7287 getIdentifierCString());
7288 OSSafeReleaseNULL(dependencies
);
7291 if (!isKernelComponent()) {
7292 flags
.hasAllDependencies
= 0;
7300 /*********************************************************************
7301 *********************************************************************/
7303 OSKext::getNumDependencies(void)
7305 if (!dependencies
) {
7308 return dependencies
->getCount();
7311 /*********************************************************************
7312 *********************************************************************/
7314 OSKext::getDependencies(void)
7316 return dependencies
;
7320 #pragma mark OSMetaClass Support
7322 /*********************************************************************
7323 *********************************************************************/
7326 OSMetaClass
* aClass
,
7327 uint32_t numClasses
)
7329 OSReturn result
= kOSMetaClassNoInsKModSet
;
7332 metaClasses
= OSSet::withCapacity(numClasses
);
7338 if (metaClasses
->containsObject(aClass
)) {
7340 kOSKextLogWarningLevel
|
7342 "Notice - kext %s has already registered class %s.",
7343 getIdentifierCString(),
7344 aClass
->getClassName());
7345 result
= kOSReturnSuccess
;
7349 if (!metaClasses
->setObject(aClass
)) {
7353 kOSKextLogDetailLevel
|
7355 "Kext %s registered class %s.",
7356 getIdentifierCString(),
7357 aClass
->getClassName());
7360 if (!flags
.autounloadEnabled
) {
7361 const OSMetaClass
* metaScan
= NULL
; // do not release
7363 for (metaScan
= aClass
; metaScan
; metaScan
= metaScan
->getSuperClass()) {
7364 if (metaScan
== OSTypeID(IOService
)) {
7367 kOSKextLogProgressLevel
|
7369 "Kext %s has IOService subclass %s; enabling autounload.",
7370 getIdentifierCString(),
7371 aClass
->getClassName());
7373 flags
.autounloadEnabled
= 1;
7379 notifyAddClassObservers(this, aClass
, flags
);
7381 result
= kOSReturnSuccess
;
7384 if (result
!= kOSReturnSuccess
) {
7386 kOSKextLogErrorLevel
|
7388 "Kext %s failed to register class %s.",
7389 getIdentifierCString(),
7390 aClass
->getClassName());
7396 /*********************************************************************
7397 *********************************************************************/
7399 OSKext::removeClass(
7400 OSMetaClass
* aClass
)
7402 OSReturn result
= kOSMetaClassNoKModSet
;
7408 if (!metaClasses
->containsObject(aClass
)) {
7410 kOSKextLogWarningLevel
|
7412 "Notice - kext %s asked to unregister unknown class %s.",
7413 getIdentifierCString(),
7414 aClass
->getClassName());
7415 result
= kOSReturnSuccess
;
7420 kOSKextLogDetailLevel
|
7422 "Kext %s unregistering class %s.",
7423 getIdentifierCString(),
7424 aClass
->getClassName());
7426 metaClasses
->removeObject(aClass
);
7428 notifyRemoveClassObservers(this, aClass
, flags
);
7430 result
= kOSReturnSuccess
;
7433 if (result
!= kOSReturnSuccess
) {
7435 kOSKextLogErrorLevel
|
7437 "Failed to unregister kext %s class %s.",
7438 getIdentifierCString(),
7439 aClass
->getClassName());
7444 /*********************************************************************
7445 *********************************************************************/
7447 OSKext::getMetaClasses(void)
7452 /*********************************************************************
7453 *********************************************************************/
7455 OSKext::hasOSMetaClassInstances(void)
7457 bool result
= false;
7458 OSCollectionIterator
* classIterator
= NULL
; // must release
7459 OSMetaClass
* checkClass
= NULL
; // do not release
7465 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7466 if (!classIterator
) {
7467 // xxx - log alloc failure?
7470 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7471 if (checkClass
->getInstanceCount()) {
7479 OSSafeRelease(classIterator
);
7483 /*********************************************************************
7484 *********************************************************************/
7487 OSKext::reportOSMetaClassInstances(
7488 const char * kextIdentifier
,
7489 OSKextLogSpec msgLogSpec
)
7491 OSKext
* theKext
= NULL
; // must release
7493 theKext
= OSKext::lookupKextWithIdentifier(kextIdentifier
);
7498 theKext
->reportOSMetaClassInstances(msgLogSpec
);
7500 OSSafeRelease(theKext
);
7504 /*********************************************************************
7505 *********************************************************************/
7507 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec
)
7509 OSCollectionIterator
* classIterator
= NULL
; // must release
7510 OSMetaClass
* checkClass
= NULL
; // do not release
7516 classIterator
= OSCollectionIterator::withCollection(metaClasses
);
7517 if (!classIterator
) {
7520 while ((checkClass
= (OSMetaClass
*)classIterator
->getNextObject())) {
7521 if (checkClass
->getInstanceCount()) {
7524 " Kext %s class %s has %d instance%s.",
7525 getIdentifierCString(),
7526 checkClass
->getClassName(),
7527 checkClass
->getInstanceCount(),
7528 checkClass
->getInstanceCount() == 1 ? "" : "s");
7533 OSSafeRelease(classIterator
);
7538 #pragma mark User-Space Requests
7540 /*********************************************************************
7541 * XXX - this function is a big ugly mess
7542 *********************************************************************/
7545 OSKext::handleRequest(
7546 host_priv_t hostPriv
,
7547 OSKextLogSpec clientLogFilter
,
7548 char * requestBuffer
,
7549 uint32_t requestLength
,
7550 char ** responseOut
,
7551 uint32_t * responseLengthOut
,
7553 uint32_t * logInfoLengthOut
)
7555 OSReturn result
= kOSReturnError
;
7556 kern_return_t kmem_result
= KERN_FAILURE
;
7558 char * response
= NULL
; // returned by reference
7559 uint32_t responseLength
= 0;
7561 OSObject
* parsedXML
= NULL
; // must release
7562 OSDictionary
* requestDict
= NULL
; // do not release
7563 OSString
* errorString
= NULL
; // must release
7565 OSObject
* responseObject
= NULL
; // must release
7567 OSSerialize
* serializer
= NULL
; // must release
7569 OSArray
* logInfoArray
= NULL
; // must release
7571 OSString
* predicate
= NULL
; // do not release
7572 OSString
* kextIdentifier
= NULL
; // do not release
7573 OSArray
* kextIdentifiers
= NULL
; // do not release
7574 OSKext
* theKext
= NULL
; // do not release
7575 OSBoolean
* boolArg
= NULL
; // do not release
7577 IORecursiveLockLock(sKextLock
);
7580 *responseOut
= NULL
;
7581 *responseLengthOut
= 0;
7585 *logInfoLengthOut
= 0;
7588 OSKext::setUserSpaceLogFilter(clientLogFilter
, logInfoOut
? true : false);
7590 /* XML must be nul-terminated.
7592 if (requestBuffer
[requestLength
- 1] != '\0') {
7593 OSKextLog(/* kext */ NULL
,
7594 kOSKextLogErrorLevel
|
7596 "Invalid request from user space (not nul-terminated).");
7597 result
= kOSKextReturnBadData
;
7600 parsedXML
= OSUnserializeXML((const char *)requestBuffer
, &errorString
);
7602 requestDict
= OSDynamicCast(OSDictionary
, parsedXML
);
7605 const char * errorCString
= "(unknown error)";
7607 if (errorString
&& errorString
->getCStringNoCopy()) {
7608 errorCString
= errorString
->getCStringNoCopy();
7609 } else if (parsedXML
) {
7610 errorCString
= "not a dictionary";
7612 OSKextLog(/* kext */ NULL
,
7613 kOSKextLogErrorLevel
|
7615 "Error unserializing request from user space: %s.",
7617 result
= kOSKextReturnSerialization
;
7621 predicate
= _OSKextGetRequestPredicate(requestDict
);
7623 OSKextLog(/* kext */ NULL
,
7624 kOSKextLogErrorLevel
|
7626 "Recieved kext request from user space with no predicate.");
7627 result
= kOSKextReturnInvalidArgument
;
7631 OSKextLog(/* kext */ NULL
,
7632 kOSKextLogDebugLevel
|
7634 "Received '%s' request from user space.",
7635 predicate
->getCStringNoCopy());
7637 result
= kOSKextReturnNotPrivileged
;
7638 if (hostPriv
== HOST_PRIV_NULL
) {
7639 /* must be root to use these kext requests */
7640 if (predicate
->isEqualTo(kKextRequestPredicateUnload
) ||
7641 predicate
->isEqualTo(kKextRequestPredicateStart
) ||
7642 predicate
->isEqualTo(kKextRequestPredicateStop
) ||
7643 predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
) ||
7644 predicate
->isEqualTo(kKextRequestPredicateSendResource
) ) {
7645 OSKextLog(/* kext */ NULL
,
7646 kOSKextLogErrorLevel
|
7648 "Access Failure - must be root user.");
7653 /* Get common args in anticipation of use.
7655 kextIdentifier
= OSDynamicCast(OSString
, _OSKextGetRequestArgument(
7656 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7657 kextIdentifiers
= OSDynamicCast(OSArray
, _OSKextGetRequestArgument(
7658 requestDict
, kKextRequestArgumentBundleIdentifierKey
));
7659 if (kextIdentifier
) {
7660 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextIdentifier
));
7662 boolArg
= OSDynamicCast(OSBoolean
, _OSKextGetRequestArgument(
7663 requestDict
, kKextRequestArgumentValueKey
));
7665 result
= kOSKextReturnInvalidArgument
;
7667 if (predicate
->isEqualTo(kKextRequestPredicateStart
)) {
7668 if (!kextIdentifier
) {
7669 OSKextLog(/* kext */ NULL
,
7670 kOSKextLogErrorLevel
|
7672 "Invalid arguments to kext start request.");
7673 } else if (!theKext
) {
7674 OSKextLog(/* kext */ NULL
,
7675 kOSKextLogErrorLevel
|
7677 "Kext %s not found for start request.",
7678 kextIdentifier
->getCStringNoCopy());
7679 result
= kOSKextReturnNotFound
;
7681 result
= theKext
->start();
7684 } else if (predicate
->isEqualTo(kKextRequestPredicateStop
)) {
7685 if (!kextIdentifier
) {
7686 OSKextLog(/* kext */ NULL
,
7687 kOSKextLogErrorLevel
|
7689 "Invalid arguments to kext stop request.");
7690 } else if (!theKext
) {
7691 OSKextLog(/* kext */ NULL
,
7692 kOSKextLogErrorLevel
|
7694 "Kext %s not found for stop request.",
7695 kextIdentifier
->getCStringNoCopy());
7696 result
= kOSKextReturnNotFound
;
7698 result
= theKext
->stop();
7701 } else if (predicate
->isEqualTo(kKextRequestPredicateUnload
)) {
7702 if (!kextIdentifier
) {
7703 OSKextLog(/* kext */ NULL
,
7704 kOSKextLogErrorLevel
|
7706 "Invalid arguments to kext unload request.");
7707 } else if (!theKext
) {
7708 OSKextLog(/* kext */ NULL
,
7709 kOSKextLogErrorLevel
|
7711 "Kext %s not found for unload request.",
7712 kextIdentifier
->getCStringNoCopy());
7713 result
= kOSKextReturnNotFound
;
7715 OSBoolean
* terminateFlag
= OSDynamicCast(OSBoolean
,
7716 _OSKextGetRequestArgument(requestDict
,
7717 kKextRequestArgumentTerminateIOServicesKey
));
7718 result
= OSKext::removeKext(theKext
, terminateFlag
== kOSBooleanTrue
);
7721 } else if (predicate
->isEqualTo(kKextRequestPredicateSendResource
)) {
7722 result
= OSKext::dispatchResource(requestDict
);
7724 } else if (predicate
->isEqualTo(kKextRequestPredicateGetLoaded
)) {
7725 OSBoolean
* delayAutounloadBool
= NULL
;
7726 OSObject
* infoKeysRaw
= NULL
;
7727 OSArray
* infoKeys
= NULL
;
7728 uint32_t infoKeysCount
= 0;
7730 delayAutounloadBool
= OSDynamicCast(OSBoolean
,
7731 _OSKextGetRequestArgument(requestDict
,
7732 kKextRequestArgumentDelayAutounloadKey
));
7734 /* If asked to delay autounload, reset the timer if it's currently set.
7735 * (That is, don't schedule an unload if one isn't already pending.
7737 if (delayAutounloadBool
== kOSBooleanTrue
) {
7738 OSKext::considerUnloads(/* rescheduleOnly? */ true);
7741 infoKeysRaw
= _OSKextGetRequestArgument(requestDict
,
7742 kKextRequestArgumentInfoKeysKey
);
7743 infoKeys
= OSDynamicCast(OSArray
, infoKeysRaw
);
7744 if (infoKeysRaw
&& !infoKeys
) {
7745 OSKextLog(/* kext */ NULL
,
7746 kOSKextLogErrorLevel
|
7748 "Invalid arguments to kext info request.");
7753 infoKeysCount
= infoKeys
->getCount();
7754 for (uint32_t i
= 0; i
< infoKeysCount
; i
++) {
7755 if (!OSDynamicCast(OSString
, infoKeys
->getObject(i
))) {
7756 OSKextLog(/* kext */ NULL
,
7757 kOSKextLogErrorLevel
|
7759 "Invalid arguments to kext info request.");
7765 responseObject
= OSKext::copyLoadedKextInfo(kextIdentifiers
, infoKeys
);
7766 if (!responseObject
) {
7767 result
= kOSKextReturnInternalError
;
7769 OSKextLog(/* kext */ NULL
,
7770 kOSKextLogDebugLevel
|
7772 "Returning loaded kext info.");
7773 result
= kOSReturnSuccess
;
7775 } else if (predicate
->isEqualTo(kKextRequestPredicateGetKernelRequests
)) {
7777 /* Hand the current sKernelRequests array to the caller
7778 * (who must release it), and make a new one.
7780 responseObject
= sKernelRequests
;
7781 sKernelRequests
= OSArray::withCapacity(0);
7782 sPostedKextLoadIdentifiers
->flushCollection();
7783 OSKextLog(/* kext */ NULL
,
7784 kOSKextLogDebugLevel
|
7786 "Returning kernel requests.");
7787 result
= kOSReturnSuccess
;
7789 } else if (predicate
->isEqualTo(kKextRequestPredicateGetAllLoadRequests
)) {
7791 /* Return the set of all requested bundle identifiers */
7792 responseObject
= sAllKextLoadIdentifiers
;
7793 responseObject
->retain();
7794 OSKextLog(/* kext */ NULL
,
7795 kOSKextLogDebugLevel
|
7797 "Returning load requests.");
7798 result
= kOSReturnSuccess
;
7801 OSKextLog(/* kext */ NULL
,
7802 kOSKextLogDebugLevel
|
7804 "Received '%s' invalid request from user space.",
7805 predicate
->getCStringNoCopy());
7810 * Now we have handle the request, or not. Gather up the response & logging
7811 * info to ship to user space.
7814 /* Note: Nothing in OSKext is supposed to retain requestDict,
7815 * but you never know....
7817 if (requestDict
->getRetainCount() > 1) {
7818 OSKextLog(/* kext */ NULL
,
7819 kOSKextLogWarningLevel
|
7821 "Request from user space still retained by a kext; "
7822 "probable memory leak.");
7825 if (responseOut
&& responseObject
) {
7826 serializer
= OSSerialize::withCapacity(0);
7828 result
= kOSKextReturnNoMemory
;
7832 if (!responseObject
->serialize(serializer
)) {
7833 OSKextLog(/* kext */ NULL
,
7834 kOSKextLogGeneralFlag
| kOSKextLogErrorLevel
,
7835 "Failed to serialize response to request from user space.");
7836 result
= kOSKextReturnSerialization
;
7840 response
= (char *)serializer
->text();
7841 responseLength
= serializer
->getLength();
7844 if (responseOut
&& response
) {
7847 /* This kmem_alloc sets the return value of the function.
7849 kmem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&buffer
,
7850 round_page(responseLength
), VM_KERN_MEMORY_OSKEXT
);
7851 if (kmem_result
!= KERN_SUCCESS
) {
7852 OSKextLog(/* kext */ NULL
,
7853 kOSKextLogErrorLevel
|
7855 "Failed to copy response to request from user space.");
7856 result
= kmem_result
;
7859 /* 11981737 - clear uninitialized data in last page */
7860 bzero((void *)(buffer
+ responseLength
),
7861 (round_page(responseLength
) - responseLength
));
7862 memcpy(buffer
, response
, responseLength
);
7863 *responseOut
= buffer
;
7864 *responseLengthOut
= responseLength
;
7870 /* Gather up the collected log messages for user space. Any messages
7871 * messages past this call will not make it up as log messages but
7872 * will be in the system log. Note that we ignore the return of the
7873 * serialize; it has no bearing on the operation at hand even if we
7874 * fail to get the log messages.
7876 logInfoArray
= OSKext::clearUserSpaceLogFilter();
7878 if (logInfoArray
&& logInfoOut
&& logInfoLengthOut
) {
7879 (void)OSKext::serializeLogInfo(logInfoArray
,
7880 logInfoOut
, logInfoLengthOut
);
7883 IORecursiveLockUnlock(sKextLock
);
7885 OSSafeRelease(parsedXML
);
7886 OSSafeRelease(errorString
);
7887 OSSafeRelease(responseObject
);
7888 OSSafeRelease(serializer
);
7889 OSSafeRelease(logInfoArray
);
7895 // #include <InstrProfiling.h>
7898 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin
,
7899 const char *DataEnd
,
7900 const char *CountersBegin
,
7901 const char *CountersEnd
,
7902 const char *NamesBegin
,
7903 const char *NamesEnd
);
7904 int __llvm_profile_write_buffer_internal(char *Buffer
,
7905 const char *DataBegin
,
7906 const char *DataEnd
,
7907 const char *CountersBegin
,
7908 const char *CountersEnd
,
7909 const char *NamesBegin
,
7910 const char *NamesEnd
);
7915 void OSKextPgoMetadataPut(char *pBuffer
,
7918 uint32_t *num_pairs
,
7922 size_t strlen_key
= strlen(key
);
7923 size_t strlen_value
= strlen(value
);
7924 size_t len
= strlen(key
) + 1 + strlen(value
) + 1;
7925 char *pos
= pBuffer
+ *position
;
7927 if (pBuffer
&& bufferSize
&& *position
<= bufferSize
) {
7928 memcpy(pos
, key
, strlen_key
); pos
+= strlen_key
;
7930 memcpy(pos
, value
, strlen_value
); pos
+= strlen_value
;
7940 void OSKextPgoMetadataPutMax(size_t *position
, const char *key
, size_t value_max
)
7942 *position
+= strlen(key
) + 1 + value_max
+ 1;
7947 void OSKextPgoMetadataPutAll(OSKext
*kext
,
7948 uuid_t instance_uuid
,
7952 uint32_t *num_pairs
)
7954 assert_static(sizeof(clock_sec_t
) % 2 == 0);
7955 //log_10 2^16 ≈ 4.82
7956 const size_t max_secs_string_size
= 5 * sizeof(clock_sec_t
)/2;
7957 const size_t max_timestamp_string_size
= max_secs_string_size
+ 1 + 6;
7960 OSKextPgoMetadataPutMax(position
, "INSTANCE", 36);
7961 OSKextPgoMetadataPutMax(position
, "UUID", 36);
7962 OSKextPgoMetadataPutMax(position
, "TIMESTAMP", max_timestamp_string_size
);
7964 uuid_string_t instance_uuid_string
;
7965 uuid_unparse(instance_uuid
, instance_uuid_string
);
7966 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
7967 "INSTANCE", instance_uuid_string
);
7971 uuid_string_t uuid_string
;
7972 uuid_data
= kext
->copyUUID();
7974 memcpy(uuid
, uuid_data
->getBytesNoCopy(), sizeof(uuid
));
7975 OSSafeRelease(uuid_data
);
7976 uuid_unparse(uuid
, uuid_string
);
7977 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
7978 "UUID", uuid_string
);
7983 clock_get_calendar_microtime(&secs
, &usecs
);
7984 assert(usecs
< 1000000);
7985 char timestamp
[max_timestamp_string_size
+ 1];
7986 assert_static(sizeof(long) >= sizeof(clock_sec_t
));
7987 snprintf(timestamp
, sizeof(timestamp
), "%lu.%06d", (unsigned long)secs
, (int)usecs
);
7988 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
7989 "TIMESTAMP", timestamp
);
7992 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
7993 "NAME", kext
->getIdentifierCString());
7995 char versionCString
[kOSKextVersionMaxLength
];
7996 OSKextVersionGetString(kext
->getVersion(), versionCString
, kOSKextVersionMaxLength
);
7997 OSKextPgoMetadataPut(pBuffer
, position
, bufferSize
, num_pairs
,
7998 "VERSION", versionCString
);
8003 size_t OSKextPgoMetadataSize(OSKext
*kext
)
8005 size_t position
= 0;
8006 uuid_t fakeuuid
= {};
8007 OSKextPgoMetadataPutAll(kext
, fakeuuid
, NULL
, &position
, 0, NULL
);
8012 int OSKextGrabPgoDataLocked(OSKext
*kext
,
8014 uuid_t instance_uuid
,
8017 uint64_t bufferSize
)
8022 kernel_section_t
*sect_prf_data
= NULL
;
8023 kernel_section_t
*sect_prf_name
= NULL
;
8024 kernel_section_t
*sect_prf_cnts
= NULL
;
8026 size_t metadata_size
= 0;
8028 sect_prf_data
= kext
->lookupSection("__DATA", "__llvm_prf_data");
8029 sect_prf_name
= kext
->lookupSection("__DATA", "__llvm_prf_name");
8030 sect_prf_cnts
= kext
->lookupSection("__DATA", "__llvm_prf_cnts");
8032 if (!sect_prf_data
|| !sect_prf_name
|| !sect_prf_cnts
) {
8037 size
= __llvm_profile_get_size_for_buffer_internal(
8038 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8039 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8040 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8043 metadata_size
= OSKextPgoMetadataSize(kext
);
8044 size
+= metadata_size
;
8045 size
+= sizeof(pgo_metadata_footer
);
8053 if (pBuffer
&& bufferSize
) {
8054 if (bufferSize
< size
) {
8059 err
= __llvm_profile_write_buffer_internal(
8061 (const char*) sect_prf_data
->addr
, (const char*) sect_prf_data
->addr
+ sect_prf_data
->size
,
8062 (const char*) sect_prf_cnts
->addr
, (const char*) sect_prf_cnts
->addr
+ sect_prf_cnts
->size
,
8063 (const char*) sect_prf_name
->addr
, (const char*) sect_prf_name
->addr
+ sect_prf_name
->size
);
8071 char *end_of_buffer
= pBuffer
+ size
;
8072 struct pgo_metadata_footer
*footerp
= (struct pgo_metadata_footer
*) (end_of_buffer
- sizeof(struct pgo_metadata_footer
));
8073 char *metadata_buffer
= end_of_buffer
- (sizeof(struct pgo_metadata_footer
) + metadata_size
);
8075 size_t metadata_position
= 0;
8076 uint32_t num_pairs
= 0;
8077 OSKextPgoMetadataPutAll(kext
, instance_uuid
, metadata_buffer
, &metadata_position
, metadata_size
, &num_pairs
);
8078 while (metadata_position
< metadata_size
) {
8079 metadata_buffer
[metadata_position
++] = 0;
8082 struct pgo_metadata_footer footer
;
8083 footer
.magic
= htonl(0x6d657461);
8084 footer
.number_of_pairs
= htonl( num_pairs
);
8085 footer
.offset_to_pairs
= htonl( sizeof(struct pgo_metadata_footer
) + metadata_size
);
8086 memcpy(footerp
, &footer
, sizeof(footer
));
8097 OSKextGrabPgoData(uuid_t uuid
,
8100 uint64_t bufferSize
,
8101 int wait_for_unload
,
8105 OSKext
*kext
= NULL
;
8108 IORecursiveLockLock(sKextLock
);
8110 kext
= OSKext::lookupKextWithUUID(uuid
);
8116 if (wait_for_unload
) {
8117 OSKextGrabPgoStruct s
;
8119 s
.metadata
= metadata
;
8121 s
.pBuffer
= pBuffer
;
8122 s
.bufferSize
= bufferSize
;
8125 struct list_head
*prev
= &kext
->pendingPgoHead
;
8126 struct list_head
*next
= kext
->pendingPgoHead
.next
;
8128 s
.list_head
.prev
= prev
;
8129 s
.list_head
.next
= next
;
8131 prev
->next
= &s
.list_head
;
8132 next
->prev
= &s
.list_head
;
8137 IORecursiveLockSleep(sKextLock
, &s
, THREAD_ABORTSAFE
);
8139 prev
= s
.list_head
.prev
;
8140 next
= s
.list_head
.next
;
8148 err
= OSKextGrabPgoDataLocked(kext
, metadata
, kext
->instance_uuid
, pSize
, pBuffer
, bufferSize
);
8156 IORecursiveLockUnlock(sKextLock
);
8162 /*********************************************************************
8163 *********************************************************************/
8166 OSKext::copyLoadedKextInfo(
8167 OSArray
* kextIdentifiers
,
8170 OSDictionary
* result
= NULL
;
8171 OSDictionary
* kextInfo
= NULL
; // must release
8173 uint32_t idCount
= 0;
8174 uint32_t idIndex
= 0;
8176 IORecursiveLockLock(sKextLock
);
8179 /* Is the calling process allowed to query kext info? */
8180 if (current_task() != kernel_task
) {
8181 int macCheckResult
= 0;
8182 kauth_cred_t cred
= NULL
;
8184 cred
= kauth_cred_get_with_ref();
8185 macCheckResult
= mac_kext_check_query(cred
);
8186 kauth_cred_unref(&cred
);
8188 if (macCheckResult
!= 0) {
8189 OSKextLog(/* kext */ NULL
,
8190 kOSKextLogErrorLevel
| kOSKextLogLoadFlag
,
8191 "Failed to query kext info (MAC policy error 0x%x).",
8198 /* Empty list of bundle ids is equivalent to no list (get all).
8200 if (kextIdentifiers
&& !kextIdentifiers
->getCount()) {
8201 kextIdentifiers
= NULL
;
8202 } else if (kextIdentifiers
) {
8203 idCount
= kextIdentifiers
->getCount();
8208 if (infoKeys
&& !infoKeys
->getCount()) {
8212 count
= sLoadedKexts
->getCount();
8213 result
= OSDictionary::withCapacity(count
);
8219 OSKextLog(/* kext */ NULL
,
8220 kOSKextLogErrorLevel
|
8221 kOSKextLogGeneralFlag
,
8222 "kaslr: vm_kernel_slide 0x%lx \n",
8224 OSKextLog(/* kext */ NULL
,
8225 kOSKextLogErrorLevel
|
8226 kOSKextLogGeneralFlag
,
8227 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
8228 vm_kernel_stext
, vm_kernel_etext
);
8229 OSKextLog(/* kext */ NULL
,
8230 kOSKextLogErrorLevel
|
8231 kOSKextLogGeneralFlag
,
8232 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
8233 vm_kernel_base
, vm_kernel_top
);
8234 OSKextLog(/* kext */ NULL
,
8235 kOSKextLogErrorLevel
|
8236 kOSKextLogGeneralFlag
,
8237 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
8238 vm_kext_base
, vm_kext_top
);
8239 OSKextLog(/* kext */ NULL
,
8240 kOSKextLogErrorLevel
|
8241 kOSKextLogGeneralFlag
,
8242 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
8243 vm_prelink_stext
, vm_prelink_etext
);
8244 OSKextLog(/* kext */ NULL
,
8245 kOSKextLogErrorLevel
|
8246 kOSKextLogGeneralFlag
,
8247 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
8248 vm_prelink_sinfo
, vm_prelink_einfo
);
8249 OSKextLog(/* kext */ NULL
,
8250 kOSKextLogErrorLevel
|
8251 kOSKextLogGeneralFlag
,
8252 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
8253 vm_slinkedit
, vm_elinkedit
);
8256 for (i
= 0; i
< count
; i
++) {
8257 OSKext
* thisKext
= NULL
; // do not release
8258 Boolean includeThis
= true;
8261 kextInfo
->release();
8264 thisKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
8269 /* Skip current kext if we have a list of bundle IDs and
8270 * it isn't in the list.
8272 if (kextIdentifiers
) {
8273 const OSString
* thisKextID
= thisKext
->getIdentifier();
8275 includeThis
= false;
8277 for (idIndex
= 0; idIndex
< idCount
; idIndex
++) {
8278 const OSString
* thisRequestID
= OSDynamicCast(OSString
,
8279 kextIdentifiers
->getObject(idIndex
));
8280 if (thisKextID
->isEqualTo(thisRequestID
)) {
8291 kextInfo
= thisKext
->copyInfo(infoKeys
);
8293 result
->setObject(thisKext
->getIdentifier(), kextInfo
);
8298 IORecursiveLockUnlock(sKextLock
);
8300 if (kextInfo
) kextInfo
->release();
8305 /*********************************************************************
8306 * Any info that needs to do allocations must goto finish on alloc
8307 * failure. Info that is just a lookup should just not set the object
8308 * if the info does not exist.
8309 *********************************************************************/
8310 #define _OSKextLoadInfoDictCapacity (12)
8313 OSKext::copyInfo(OSArray
* infoKeys
)
8315 OSDictionary
* result
= NULL
;
8316 bool success
= false;
8317 OSData
* headerData
= NULL
; // must release
8318 OSNumber
* cpuTypeNumber
= NULL
; // must release
8319 OSNumber
* cpuSubtypeNumber
= NULL
; // must release
8320 OSString
* versionString
= NULL
; // do not release
8321 uint32_t executablePathCStringSize
= 0;
8322 char * executablePathCString
= NULL
; // must release
8323 OSString
* executablePathString
= NULL
; // must release
8324 OSData
* uuid
= NULL
; // must release
8325 OSNumber
* scratchNumber
= NULL
; // must release
8326 OSArray
* dependencyLoadTags
= NULL
; // must release
8327 OSCollectionIterator
* metaClassIterator
= NULL
; // must release
8328 OSArray
* metaClassInfo
= NULL
; // must release
8329 OSDictionary
* metaClassDict
= NULL
; // must release
8330 OSMetaClass
* thisMetaClass
= NULL
; // do not release
8331 OSString
* metaClassName
= NULL
; // must release
8332 OSString
* superclassName
= NULL
; // must release
8335 result
= OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity
);
8341 /* Empty keys means no keys, but NULL is quicker to check.
8343 if (infoKeys
&& !infoKeys
->getCount()) {
8347 /* Headers, CPU type, and CPU subtype.
8350 _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
) ||
8351 _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
) ||
8352 _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
))
8355 if (linkedExecutable
&& !isInterface()) {
8357 kernel_mach_header_t
*kext_mach_hdr
= (kernel_mach_header_t
*)
8358 linkedExecutable
->getBytesNoCopy();
8361 // do not return macho header info on shipping iOS - 19095897
8362 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleMachOHeadersKey
)) {
8363 kernel_mach_header_t
* temp_kext_mach_hdr
;
8364 struct load_command
* lcp
;
8366 headerData
= OSData::withBytes(kext_mach_hdr
,
8367 (u_int
) (sizeof(*kext_mach_hdr
) + kext_mach_hdr
->sizeofcmds
));
8372 // unslide any vmaddrs we return to userspace - 10726716
8373 temp_kext_mach_hdr
= (kernel_mach_header_t
*)
8374 headerData
->getBytesNoCopy();
8375 if (temp_kext_mach_hdr
== NULL
) {
8379 lcp
= (struct load_command
*) (temp_kext_mach_hdr
+ 1);
8380 for (i
= 0; i
< temp_kext_mach_hdr
->ncmds
; i
++) {
8381 if (lcp
->cmd
== LC_SEGMENT_KERNEL
) {
8382 kernel_segment_command_t
* segp
;
8383 kernel_section_t
* secp
;
8385 segp
= (kernel_segment_command_t
*) lcp
;
8386 // 10543468 - if we jettisoned __LINKEDIT clear size info
8387 if (flags
.jettisonLinkeditSeg
) {
8388 if (strncmp(segp
->segname
, SEG_LINKEDIT
, sizeof(segp
->segname
)) == 0) {
8395 OSKextLog(/* kext */ NULL
,
8396 kOSKextLogErrorLevel
|
8397 kOSKextLogGeneralFlag
,
8398 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
8399 __FUNCTION__
, segp
->segname
, segp
->vmaddr
,
8400 VM_KERNEL_UNSLIDE(segp
->vmaddr
),
8401 segp
->vmsize
, segp
->nsects
);
8402 if ( (VM_KERNEL_IS_SLID(segp
->vmaddr
) == false) &&
8403 (VM_KERNEL_IS_KEXT(segp
->vmaddr
) == false) &&
8404 (VM_KERNEL_IS_PRELINKTEXT(segp
->vmaddr
) == false) &&
8405 (VM_KERNEL_IS_PRELINKINFO(segp
->vmaddr
) == false) &&
8406 (VM_KERNEL_IS_KEXT_LINKEDIT(segp
->vmaddr
) == false) ) {
8407 OSKextLog(/* kext */ NULL
,
8408 kOSKextLogErrorLevel
|
8409 kOSKextLogGeneralFlag
,
8410 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
8411 __FUNCTION__
, segp
->vmaddr
, vm_kext_base
, vm_kext_top
);
8414 segp
->vmaddr
= VM_KERNEL_UNSLIDE(segp
->vmaddr
);
8416 for (secp
= firstsect(segp
); secp
!= NULL
; secp
= nextsect(segp
, secp
)) {
8417 secp
->addr
= VM_KERNEL_UNSLIDE(secp
->addr
);
8420 lcp
= (struct load_command
*)((caddr_t
)lcp
+ lcp
->cmdsize
);
8422 result
->setObject(kOSBundleMachOHeadersKey
, headerData
);
8424 #endif // SECURE_KERNEL
8426 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUTypeKey
)) {
8427 cpuTypeNumber
= OSNumber::withNumber(
8428 (uint64_t) kext_mach_hdr
->cputype
,
8429 8 * sizeof(kext_mach_hdr
->cputype
));
8430 if (!cpuTypeNumber
) {
8433 result
->setObject(kOSBundleCPUTypeKey
, cpuTypeNumber
);
8436 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCPUSubtypeKey
)) {
8437 cpuSubtypeNumber
= OSNumber::withNumber(
8438 (uint64_t) kext_mach_hdr
->cpusubtype
,
8439 8 * sizeof(kext_mach_hdr
->cpusubtype
));
8440 if (!cpuSubtypeNumber
) {
8443 result
->setObject(kOSBundleCPUSubtypeKey
, cpuSubtypeNumber
);
8448 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
8450 result
->setObject(kCFBundleIdentifierKey
, bundleID
);
8454 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kCFBundleVersionKey
)) {
8455 versionString
= OSDynamicCast(OSString
,
8456 getPropertyForHostArch(kCFBundleVersionKey
));
8457 if (versionString
) {
8458 result
->setObject(kCFBundleVersionKey
, versionString
);
8462 /* OSBundleCompatibleVersion.
8464 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleCompatibleVersionKey
)) {
8465 versionString
= OSDynamicCast(OSString
,
8466 getPropertyForHostArch(kOSBundleCompatibleVersionKey
));
8467 if (versionString
) {
8468 result
->setObject(kOSBundleCompatibleVersionKey
, versionString
);
8474 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePathKey
)) {
8476 result
->setObject(kOSBundlePathKey
, path
);
8481 /* OSBundleExecutablePath.
8483 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleExecutablePathKey
)) {
8484 if (path
&& executableRelPath
) {
8486 uint32_t pathLength
= path
->getLength(); // gets incremented below
8488 // +1 for slash, +1 for \0
8489 executablePathCStringSize
= pathLength
+ executableRelPath
->getLength() + 2;
8491 executablePathCString
= (char *)kalloc_tag((executablePathCStringSize
) *
8492 sizeof(char), VM_KERN_MEMORY_OSKEXT
); // +1 for \0
8493 if (!executablePathCString
) {
8496 strlcpy(executablePathCString
, path
->getCStringNoCopy(),
8497 executablePathCStringSize
);
8498 executablePathCString
[pathLength
++] = '/';
8499 executablePathCString
[pathLength
++] = '\0';
8500 strlcat(executablePathCString
, executableRelPath
->getCStringNoCopy(),
8501 executablePathCStringSize
);
8503 executablePathString
= OSString::withCString(executablePathCString
);
8505 if (!executablePathCString
) {
8509 result
->setObject(kOSBundleExecutablePathKey
, executablePathString
);
8513 /* UUID, if the kext has one.
8515 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleUUIDKey
)) {
8518 result
->setObject(kOSBundleUUIDKey
, uuid
);
8523 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
8525 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSKernelResourceKey
)) {
8526 result
->setObject(kOSKernelResourceKey
,
8527 isKernelComponent() ? kOSBooleanTrue
: kOSBooleanFalse
);
8530 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleIsInterfaceKey
)) {
8531 result
->setObject(kOSBundleIsInterfaceKey
,
8532 isInterface() ? kOSBooleanTrue
: kOSBooleanFalse
);
8535 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundlePrelinkedKey
)) {
8536 result
->setObject(kOSBundlePrelinkedKey
,
8537 isPrelinked() ? kOSBooleanTrue
: kOSBooleanFalse
);
8540 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleStartedKey
)) {
8541 result
->setObject(kOSBundleStartedKey
,
8542 isStarted() ? kOSBooleanTrue
: kOSBooleanFalse
);
8547 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadTagKey
)) {
8548 scratchNumber
= OSNumber::withNumber((unsigned long long)loadTag
,
8549 /* numBits */ 8 * sizeof(loadTag
));
8550 if (!scratchNumber
) {
8553 result
->setObject(kOSBundleLoadTagKey
, scratchNumber
);
8554 OSSafeReleaseNULL(scratchNumber
);
8557 /* LoadAddress, LoadSize.
8560 _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
) ||
8561 _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
) ||
8562 _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
))
8564 if (isInterface() || linkedExecutable
) {
8565 /* These go to userspace via serialization, so we don't want any doubts
8568 uint64_t loadAddress
= 0;
8569 uint32_t loadSize
= 0;
8570 uint32_t wiredSize
= 0;
8572 /* Interfaces always report 0 load address & size.
8573 * Just the way they roll.
8575 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
8576 * xxx - shouldn't have one!
8578 if (linkedExecutable
/* && !isInterface() */) {
8579 loadAddress
= (uint64_t)linkedExecutable
->getBytesNoCopy();
8580 loadAddress
= VM_KERNEL_UNSLIDE(loadAddress
);
8581 loadSize
= linkedExecutable
->getLength();
8583 /* If we have a kmod_info struct, calculated the wired size
8584 * from that. Otherwise it's the full load size.
8587 wiredSize
= loadSize
- kmod_info
->hdr_size
;
8589 wiredSize
= loadSize
;
8593 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadAddressKey
)) {
8594 scratchNumber
= OSNumber::withNumber(
8595 (unsigned long long)(loadAddress
),
8596 /* numBits */ 8 * sizeof(loadAddress
));
8597 if (!scratchNumber
) {
8600 result
->setObject(kOSBundleLoadAddressKey
, scratchNumber
);
8601 OSSafeReleaseNULL(scratchNumber
);
8603 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleLoadSizeKey
)) {
8604 scratchNumber
= OSNumber::withNumber(
8605 (unsigned long long)(loadSize
),
8606 /* numBits */ 8 * sizeof(loadSize
));
8607 if (!scratchNumber
) {
8610 result
->setObject(kOSBundleLoadSizeKey
, scratchNumber
);
8611 OSSafeReleaseNULL(scratchNumber
);
8613 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleWiredSizeKey
)) {
8614 scratchNumber
= OSNumber::withNumber(
8615 (unsigned long long)(wiredSize
),
8616 /* numBits */ 8 * sizeof(wiredSize
));
8617 if (!scratchNumber
) {
8620 result
->setObject(kOSBundleWiredSizeKey
, scratchNumber
);
8621 OSSafeReleaseNULL(scratchNumber
);
8626 /* OSBundleDependencies. In descending order for
8627 * easy compatibility with kextstat(8).
8629 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleDependenciesKey
)) {
8630 if ((count
= getNumDependencies())) {
8631 dependencyLoadTags
= OSArray::withCapacity(count
);
8632 result
->setObject(kOSBundleDependenciesKey
, dependencyLoadTags
);
8636 OSKext
* dependency
= OSDynamicCast(OSKext
,
8637 dependencies
->getObject(i
));
8639 OSSafeReleaseNULL(scratchNumber
);
8644 scratchNumber
= OSNumber::withNumber(
8645 (unsigned long long)dependency
->getLoadTag(),
8646 /* numBits*/ 8 * sizeof(loadTag
));
8647 if (!scratchNumber
) {
8650 dependencyLoadTags
->setObject(scratchNumber
);
8655 OSSafeReleaseNULL(scratchNumber
);
8657 /* OSBundleMetaClasses.
8659 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleClassesKey
)) {
8660 if (metaClasses
&& metaClasses
->getCount()) {
8661 metaClassIterator
= OSCollectionIterator::withCollection(metaClasses
);
8662 metaClassInfo
= OSArray::withCapacity(metaClasses
->getCount());
8663 if (!metaClassIterator
|| !metaClassInfo
) {
8666 result
->setObject(kOSBundleClassesKey
, metaClassInfo
);
8668 while ( (thisMetaClass
= OSDynamicCast(OSMetaClass
,
8669 metaClassIterator
->getNextObject())) ) {
8671 OSSafeReleaseNULL(metaClassDict
);
8672 OSSafeReleaseNULL(scratchNumber
);
8673 OSSafeReleaseNULL(metaClassName
);
8674 OSSafeReleaseNULL(superclassName
);
8676 metaClassDict
= OSDictionary::withCapacity(3);
8677 if (!metaClassDict
) {
8681 metaClassName
= OSString::withCString(thisMetaClass
->getClassName());
8682 if (thisMetaClass
->getSuperClass()) {
8683 superclassName
= OSString::withCString(
8684 thisMetaClass
->getSuperClass()->getClassName());
8686 scratchNumber
= OSNumber::withNumber(thisMetaClass
->getInstanceCount(),
8687 8 * sizeof(unsigned int));
8689 /* Bail if any of the essentials is missing. The root class lacks a superclass,
8692 if (!metaClassDict
|| !metaClassName
|| !scratchNumber
) {
8696 metaClassInfo
->setObject(metaClassDict
);
8697 metaClassDict
->setObject(kOSMetaClassNameKey
, metaClassName
);
8698 if (superclassName
) {
8699 metaClassDict
->setObject(kOSMetaClassSuperclassNameKey
, superclassName
);
8701 metaClassDict
->setObject(kOSMetaClassTrackingCountKey
, scratchNumber
);
8706 /* OSBundleRetainCount.
8708 if (!infoKeys
|| _OSArrayContainsCString(infoKeys
, kOSBundleRetainCountKey
)) {
8709 OSSafeReleaseNULL(scratchNumber
);
8711 int kextRetainCount
= getRetainCount() - 1;
8715 scratchNumber
= OSNumber::withNumber(
8716 (int)kextRetainCount
,
8717 /* numBits*/ 8 * sizeof(int));
8718 if (scratchNumber
) {
8719 result
->setObject(kOSBundleRetainCountKey
, scratchNumber
);
8727 OSSafeRelease(headerData
);
8728 OSSafeRelease(cpuTypeNumber
);
8729 OSSafeRelease(cpuSubtypeNumber
);
8730 OSSafeRelease(executablePathString
);
8731 if (executablePathString
) kfree(executablePathCString
, executablePathCStringSize
);
8732 OSSafeRelease(uuid
);
8733 OSSafeRelease(scratchNumber
);
8734 OSSafeRelease(dependencyLoadTags
);
8735 OSSafeRelease(metaClassIterator
);
8736 OSSafeRelease(metaClassInfo
);
8737 OSSafeRelease(metaClassDict
);
8738 OSSafeRelease(metaClassName
);
8739 OSSafeRelease(superclassName
);
8741 OSSafeReleaseNULL(result
);
8746 /*********************************************************************
8747 *********************************************************************/
8750 OSKext::requestResource(
8751 const char * kextIdentifierCString
,
8752 const char * resourceNameCString
,
8753 OSKextRequestResourceCallback callback
,
8755 OSKextRequestTag
* requestTagOut
)
8757 OSReturn result
= kOSReturnError
;
8758 OSKext
* callbackKext
= NULL
; // must release (looked up)
8760 OSKextRequestTag requestTag
= -1;
8761 OSNumber
* requestTagNum
= NULL
; // must release
8763 OSDictionary
* requestDict
= NULL
; // must release
8764 OSString
* kextIdentifier
= NULL
; // must release
8765 OSString
* resourceName
= NULL
; // must release
8767 OSDictionary
* callbackRecord
= NULL
; // must release
8768 OSData
* callbackWrapper
= NULL
; // must release
8770 OSData
* contextWrapper
= NULL
; // must release
8772 IORecursiveLockLock(sKextLock
);
8774 if (requestTagOut
) {
8775 *requestTagOut
= kOSKextRequestTagInvalid
;
8778 /* If requests to user space are disabled, don't go any further */
8779 if (!sKernelRequestsEnabled
) {
8780 OSKextLog(/* kext */ NULL
,
8781 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8782 "Can't request resource %s for %s - requests to user space are disabled.",
8783 resourceNameCString
,
8784 kextIdentifierCString
);
8785 result
= kOSKextReturnDisabled
;
8789 if (!kextIdentifierCString
|| !resourceNameCString
|| !callback
) {
8790 result
= kOSKextReturnInvalidArgument
;
8794 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
8795 if (!callbackKext
) {
8796 OSKextLog(/* kext */ NULL
,
8797 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8798 "Resource request has bad callback address.");
8799 result
= kOSKextReturnInvalidArgument
;
8802 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
8803 OSKextLog(/* kext */ NULL
,
8804 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8805 "Resource request callback is in a kext that is not started.");
8806 result
= kOSKextReturnInvalidArgument
;
8810 /* Do not allow any new requests to be made on a kext that is unloading.
8812 if (callbackKext
->flags
.stopping
) {
8813 result
= kOSKextReturnStopping
;
8817 /* If we're wrapped the next available request tag around to the negative
8818 * numbers, we can't service any more requests.
8820 if (sNextRequestTag
== kOSKextRequestTagInvalid
) {
8821 OSKextLog(/* kext */ NULL
,
8822 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
8823 "No more request tags available; restart required.");
8824 result
= kOSKextReturnNoResources
;
8827 requestTag
= sNextRequestTag
++;
8829 result
= _OSKextCreateRequest(kKextRequestPredicateRequestResource
,
8831 if (result
!= kOSReturnSuccess
) {
8835 kextIdentifier
= OSString::withCString(kextIdentifierCString
);
8836 resourceName
= OSString::withCString(resourceNameCString
);
8837 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
8838 8 * sizeof(requestTag
));
8839 if (!kextIdentifier
||
8842 !_OSKextSetRequestArgument(requestDict
,
8843 kKextRequestArgumentBundleIdentifierKey
, kextIdentifier
) ||
8844 !_OSKextSetRequestArgument(requestDict
,
8845 kKextRequestArgumentNameKey
, resourceName
) ||
8846 !_OSKextSetRequestArgument(requestDict
,
8847 kKextRequestArgumentRequestTagKey
, requestTagNum
)) {
8849 result
= kOSKextReturnNoMemory
;
8853 callbackRecord
= OSDynamicCast(OSDictionary
, requestDict
->copyCollection());
8854 if (!callbackRecord
) {
8855 result
= kOSKextReturnNoMemory
;
8858 // we validate callback address at call time
8859 callbackWrapper
= OSData::withBytes((void *)&callback
, sizeof(void *));
8861 contextWrapper
= OSData::withBytes((void *)&context
, sizeof(void *));
8863 if (!callbackWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
8864 kKextRequestArgumentCallbackKey
, callbackWrapper
)) {
8866 result
= kOSKextReturnNoMemory
;
8871 if (!contextWrapper
|| !_OSKextSetRequestArgument(callbackRecord
,
8872 kKextRequestArgumentContextKey
, contextWrapper
)) {
8874 result
= kOSKextReturnNoMemory
;
8879 /* Only post the requests after all the other potential failure points
8882 if (!sKernelRequests
->setObject(requestDict
) ||
8883 !sRequestCallbackRecords
->setObject(callbackRecord
)) {
8885 result
= kOSKextReturnNoMemory
;
8889 OSKext::pingKextd();
8891 result
= kOSReturnSuccess
;
8892 if (requestTagOut
) {
8893 *requestTagOut
= requestTag
;
8898 /* If we didn't succeed, yank the request & callback
8899 * from their holding arrays.
8901 if (result
!= kOSReturnSuccess
) {
8904 index
= sKernelRequests
->getNextIndexOfObject(requestDict
, 0);
8905 if (index
!= (unsigned int)-1) {
8906 sKernelRequests
->removeObject(index
);
8908 index
= sRequestCallbackRecords
->getNextIndexOfObject(callbackRecord
, 0);
8909 if (index
!= (unsigned int)-1) {
8910 sRequestCallbackRecords
->removeObject(index
);
8914 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8916 IORecursiveLockUnlock(sKextLock
);
8918 if (callbackKext
) callbackKext
->release();
8919 if (requestTagNum
) requestTagNum
->release();
8921 if (requestDict
) requestDict
->release();
8922 if (kextIdentifier
) kextIdentifier
->release();
8923 if (resourceName
) resourceName
->release();
8925 if (callbackRecord
) callbackRecord
->release();
8926 if (callbackWrapper
) callbackWrapper
->release();
8927 if (contextWrapper
) contextWrapper
->release();
8932 /*********************************************************************
8933 * Assumes sKextLock is held.
8934 *********************************************************************/
8937 OSKext::dequeueCallbackForRequestTag(
8938 OSKextRequestTag requestTag
,
8939 OSDictionary
** callbackRecordOut
)
8941 OSReturn result
= kOSReturnError
;
8942 OSNumber
* requestTagNum
= NULL
; // must release
8944 requestTagNum
= OSNumber::withNumber((long long unsigned int)requestTag
,
8945 8 * sizeof(requestTag
));
8946 if (!requestTagNum
) {
8950 result
= OSKext::dequeueCallbackForRequestTag(requestTagNum
,
8954 OSSafeRelease(requestTagNum
);
8959 /*********************************************************************
8960 * Assumes sKextLock is held.
8961 *********************************************************************/
8964 OSKext::dequeueCallbackForRequestTag(
8965 OSNumber
* requestTagNum
,
8966 OSDictionary
** callbackRecordOut
)
8968 OSReturn result
= kOSKextReturnInvalidArgument
;
8969 OSDictionary
* callbackRecord
= NULL
; // retain if matched!
8970 OSNumber
* callbackTagNum
= NULL
; // do not release
8971 unsigned int count
, i
;
8973 result
= kOSReturnError
;
8974 count
= sRequestCallbackRecords
->getCount();
8975 for (i
= 0; i
< count
; i
++) {
8976 callbackRecord
= OSDynamicCast(OSDictionary
,
8977 sRequestCallbackRecords
->getObject(i
));
8978 if (!callbackRecord
) {
8982 /* If we don't find a tag, we basically have a leak here. Maybe
8983 * we should just remove it.
8985 callbackTagNum
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(
8986 callbackRecord
, kKextRequestArgumentRequestTagKey
));
8987 if (!callbackTagNum
) {
8991 /* We could be even more paranoid and check that all the incoming
8992 * args match what's in the callback record.
8994 if (callbackTagNum
->isEqualTo(requestTagNum
)) {
8995 if (callbackRecordOut
) {
8996 *callbackRecordOut
= callbackRecord
;
8997 callbackRecord
->retain();
8999 sRequestCallbackRecords
->removeObject(i
);
9000 result
= kOSReturnSuccess
;
9004 result
= kOSKextReturnNotFound
;
9010 /*********************************************************************
9011 * Assumes sKextLock is held.
9012 *********************************************************************/
9015 OSKext::dispatchResource(OSDictionary
* requestDict
)
9017 OSReturn result
= kOSReturnError
;
9018 OSDictionary
* callbackRecord
= NULL
; // must release
9019 OSNumber
* requestTag
= NULL
; // do not release
9020 OSNumber
* requestResult
= NULL
; // do not release
9021 OSData
* dataObj
= NULL
; // do not release
9022 uint32_t dataLength
= 0;
9023 const void * dataPtr
= NULL
; // do not free
9024 OSData
* callbackWrapper
= NULL
; // do not release
9025 OSKextRequestResourceCallback callback
= NULL
;
9026 OSData
* contextWrapper
= NULL
; // do not release
9027 void * context
= NULL
; // do not free
9028 OSKext
* callbackKext
= NULL
; // must release (looked up)
9030 /* Get the args from the request. Right now we need the tag
9031 * to look up the callback record, and the result for invoking the callback.
9033 requestTag
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9034 kKextRequestArgumentRequestTagKey
));
9035 requestResult
= OSDynamicCast(OSNumber
, _OSKextGetRequestArgument(requestDict
,
9036 kKextRequestArgumentResultKey
));
9037 if (!requestTag
|| !requestResult
) {
9038 result
= kOSKextReturnInvalidArgument
;
9042 /* Look for a callback record matching this request's tag.
9044 result
= dequeueCallbackForRequestTag(requestTag
, &callbackRecord
);
9045 if (result
!= kOSReturnSuccess
) {
9050 * Get the context pointer of the callback record (if there is one).
9052 contextWrapper
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(callbackRecord
,
9053 kKextRequestArgumentContextKey
));
9054 context
= _OSKextExtractPointer(contextWrapper
);
9055 if (contextWrapper
&& !context
) {
9059 callbackWrapper
= OSDynamicCast(OSData
,
9060 _OSKextGetRequestArgument(callbackRecord
,
9061 kKextRequestArgumentCallbackKey
));
9062 callback
= (OSKextRequestResourceCallback
)
9063 _OSKextExtractPointer(callbackWrapper
);
9068 /* Check for a data obj. We might not have one and that's ok, that means
9069 * we didn't find the requested resource, and we still have to tell the
9070 * caller that via the callback.
9072 dataObj
= OSDynamicCast(OSData
, _OSKextGetRequestArgument(requestDict
,
9073 kKextRequestArgumentValueKey
));
9075 dataPtr
= dataObj
->getBytesNoCopy();
9076 dataLength
= dataObj
->getLength();
9079 callbackKext
= OSKext::lookupKextWithAddress((vm_address_t
)callback
);
9080 if (!callbackKext
) {
9081 OSKextLog(/* kext */ NULL
,
9082 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9083 "Can't invoke callback for resource request; ");
9086 if (!callbackKext
->flags
.starting
&& !callbackKext
->flags
.started
) {
9087 OSKextLog(/* kext */ NULL
,
9088 kOSKextLogErrorLevel
| kOSKextLogIPCFlag
,
9089 "Can't invoke kext resource callback; ");
9093 (void)callback(requestTag
->unsigned32BitValue(),
9094 (OSReturn
)requestResult
->unsigned32BitValue(),
9095 dataPtr
, dataLength
, context
);
9097 result
= kOSReturnSuccess
;
9100 if (callbackKext
) callbackKext
->release();
9101 if (callbackRecord
) callbackRecord
->release();
9106 /*********************************************************************
9107 *********************************************************************/
9110 OSKext::invokeRequestCallback(
9111 OSDictionary
* callbackRecord
,
9112 OSReturn callbackResult
)
9114 OSString
* predicate
= _OSKextGetRequestPredicate(callbackRecord
);
9115 OSNumber
* resultNum
= NULL
; // must release
9121 resultNum
= OSNumber::withNumber((long long unsigned int)callbackResult
,
9122 8 * sizeof(callbackResult
));
9127 /* Insert the result into the callback record and dispatch it as if it
9128 * were the reply coming down from user space.
9130 _OSKextSetRequestArgument(callbackRecord
, kKextRequestArgumentResultKey
,
9133 if (predicate
->isEqualTo(kKextRequestPredicateRequestResource
)) {
9134 /* This removes the pending callback record.
9136 OSKext::dispatchResource(callbackRecord
);
9140 if (resultNum
) resultNum
->release();
9144 /*********************************************************************
9145 * Assumes sKextLock is held.
9146 *********************************************************************/
9149 OSKext::cancelRequest(
9150 OSKextRequestTag requestTag
,
9153 OSReturn result
= kOSKextReturnNoMemory
;
9154 OSDictionary
* callbackRecord
= NULL
; // must release
9155 OSData
* contextWrapper
= NULL
; // do not release
9157 IORecursiveLockLock(sKextLock
);
9158 result
= OSKext::dequeueCallbackForRequestTag(requestTag
,
9160 IORecursiveLockUnlock(sKextLock
);
9162 if (result
== kOSReturnSuccess
&& contextOut
) {
9163 contextWrapper
= OSDynamicCast(OSData
,
9164 _OSKextGetRequestArgument(callbackRecord
,
9165 kKextRequestArgumentContextKey
));
9166 *contextOut
= _OSKextExtractPointer(contextWrapper
);
9169 if (callbackRecord
) callbackRecord
->release();
9174 /*********************************************************************
9175 * Assumes sKextLock is held.
9176 *********************************************************************/
9178 OSKext::invokeOrCancelRequestCallbacks(
9179 OSReturn callbackResult
,
9182 unsigned int count
, i
;
9184 count
= sRequestCallbackRecords
->getCount();
9191 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9192 sRequestCallbackRecords
->getObject(i
));
9197 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9198 _OSKextGetRequestArgument(request
,
9199 kKextRequestArgumentCallbackKey
));
9201 if (!callbackWrapper
) {
9202 sRequestCallbackRecords
->removeObject(i
);
9206 vm_address_t callbackAddress
= (vm_address_t
)
9207 _OSKextExtractPointer(callbackWrapper
);
9209 if ((kmod_info
->address
<= callbackAddress
) &&
9210 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9213 /* This removes the callback record.
9215 invokeRequestCallback(request
, callbackResult
);
9217 sRequestCallbackRecords
->removeObject(i
);
9226 /*********************************************************************
9227 * Assumes sKextLock is held.
9228 *********************************************************************/
9230 OSKext::countRequestCallbacks(void)
9232 uint32_t result
= 0;
9233 unsigned int count
, i
;
9235 count
= sRequestCallbackRecords
->getCount();
9242 OSDictionary
* request
= OSDynamicCast(OSDictionary
,
9243 sRequestCallbackRecords
->getObject(i
));
9248 OSData
* callbackWrapper
= OSDynamicCast(OSData
,
9249 _OSKextGetRequestArgument(request
,
9250 kKextRequestArgumentCallbackKey
));
9252 if (!callbackWrapper
) {
9256 vm_address_t callbackAddress
= (vm_address_t
)
9257 _OSKextExtractPointer(callbackWrapper
);
9259 if ((kmod_info
->address
<= callbackAddress
) &&
9260 (callbackAddress
< (kmod_info
->address
+ kmod_info
->size
))) {
9270 /*********************************************************************
9271 *********************************************************************/
9272 static OSReturn
_OSKextCreateRequest(
9273 const char * predicate
,
9274 OSDictionary
** requestP
)
9276 OSReturn result
= kOSKextReturnNoMemory
;
9277 OSDictionary
* request
= NULL
; // must release on error
9279 request
= OSDictionary::withCapacity(2);
9283 result
= _OSDictionarySetCStringValue(request
,
9284 kKextRequestPredicateKey
, predicate
);
9285 if (result
!= kOSReturnSuccess
) {
9288 result
= kOSReturnSuccess
;
9291 if (result
!= kOSReturnSuccess
) {
9292 if (request
) request
->release();
9294 *requestP
= request
;
9300 /*********************************************************************
9301 *********************************************************************/
9302 static OSString
* _OSKextGetRequestPredicate(OSDictionary
* requestDict
)
9304 return OSDynamicCast(OSString
,
9305 requestDict
->getObject(kKextRequestPredicateKey
));
9308 /*********************************************************************
9309 *********************************************************************/
9310 static OSObject
* _OSKextGetRequestArgument(
9311 OSDictionary
* requestDict
,
9312 const char * argName
)
9314 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9315 requestDict
->getObject(kKextRequestArgumentsKey
));
9317 return args
->getObject(argName
);
9322 /*********************************************************************
9323 *********************************************************************/
9324 static bool _OSKextSetRequestArgument(
9325 OSDictionary
* requestDict
,
9326 const char * argName
,
9329 OSDictionary
* args
= OSDynamicCast(OSDictionary
,
9330 requestDict
->getObject(kKextRequestArgumentsKey
));
9332 args
= OSDictionary::withCapacity(2);
9336 requestDict
->setObject(kKextRequestArgumentsKey
, args
);
9340 return args
->setObject(argName
, value
);
9346 /*********************************************************************
9347 *********************************************************************/
9348 static void * _OSKextExtractPointer(OSData
* wrapper
)
9350 void * result
= NULL
;
9351 const void * resultPtr
= NULL
;
9356 resultPtr
= wrapper
->getBytesNoCopy();
9357 result
= *(void **)resultPtr
;
9362 /*********************************************************************
9363 *********************************************************************/
9364 static OSReturn
_OSDictionarySetCStringValue(
9365 OSDictionary
* dict
,
9367 const char * cValue
)
9369 OSReturn result
= kOSKextReturnNoMemory
;
9370 const OSSymbol
* key
= NULL
; // must release
9371 OSString
* value
= NULL
; // must release
9373 key
= OSSymbol::withCString(cKey
);
9374 value
= OSString::withCString(cValue
);
9375 if (!key
|| !value
) {
9378 if (dict
->setObject(key
, value
)) {
9379 result
= kOSReturnSuccess
;
9383 if (key
) key
->release();
9384 if (value
) value
->release();
9389 /*********************************************************************
9390 *********************************************************************/
9391 static bool _OSArrayContainsCString(
9393 const char * cString
)
9395 bool result
= false;
9396 const OSSymbol
* symbol
= NULL
;
9399 if (!array
|| !cString
) {
9403 symbol
= OSSymbol::withCStringNoCopy(cString
);
9408 count
= array
->getCount();
9409 for (i
= 0; i
< count
; i
++) {
9410 OSObject
* thisObject
= array
->getObject(i
);
9411 if (symbol
->isEqualTo(thisObject
)) {
9418 if (symbol
) symbol
->release();
9422 /*********************************************************************
9423 * We really only care about boot / system start up related kexts.
9424 * We return true if we're less than REBUILD_MAX_TIME since start up,
9425 * otherwise return false.
9426 *********************************************************************/
9427 bool _OSKextInPrelinkRebuildWindow(void)
9429 static bool outside_the_window
= false;
9430 AbsoluteTime my_abstime
;
9434 if (outside_the_window
) {
9437 clock_get_uptime(&my_abstime
);
9438 absolutetime_to_nanoseconds(my_abstime
, &my_ns
);
9439 my_secs
= (SInt32
)(my_ns
/ NSEC_PER_SEC
);
9440 if (my_secs
> REBUILD_MAX_TIME
) {
9441 outside_the_window
= true;
9447 /*********************************************************************
9448 *********************************************************************/
9449 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol
* theBundleID
)
9451 int unLoadedCount
, i
;
9452 bool result
= false;
9454 IORecursiveLockLock(sKextLock
);
9456 if (sUnloadedPrelinkedKexts
== NULL
) {
9459 unLoadedCount
= sUnloadedPrelinkedKexts
->getCount();
9460 if (unLoadedCount
== 0) {
9464 for (i
= 0; i
< unLoadedCount
; i
++) {
9465 const OSSymbol
* myBundleID
; // do not release
9467 myBundleID
= OSDynamicCast(OSSymbol
, sUnloadedPrelinkedKexts
->getObject(i
));
9468 if (!myBundleID
) continue;
9469 if (theBundleID
->isEqualTo(myBundleID
->getCStringNoCopy())) {
9475 IORecursiveLockUnlock(sKextLock
);
9480 #pragma mark Personalities (IOKit Drivers)
9482 /*********************************************************************
9483 *********************************************************************/
9486 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag
)
9488 OSArray
* result
= NULL
; // returned
9489 OSCollectionIterator
* kextIterator
= NULL
; // must release
9490 OSArray
* personalities
= NULL
; // must release
9491 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
9493 OSString
* kextID
= NULL
; // do not release
9494 OSKext
* theKext
= NULL
; // do not release
9496 IORecursiveLockLock(sKextLock
);
9498 /* Let's conservatively guess that any given kext has around 3
9499 * personalities for now.
9501 result
= OSArray::withCapacity(sKextsByID
->getCount() * 3);
9506 kextIterator
= OSCollectionIterator::withCollection(sKextsByID
);
9507 if (!kextIterator
) {
9511 while ((kextID
= OSDynamicCast(OSString
, kextIterator
->getNextObject()))) {
9512 if (personalitiesIterator
) {
9513 personalitiesIterator
->release();
9514 personalitiesIterator
= NULL
;
9516 if (personalities
) {
9517 personalities
->release();
9518 personalities
= NULL
;
9521 theKext
= OSDynamicCast(OSKext
, sKextsByID
->getObject(kextID
));
9522 if (!sSafeBoot
|| !filterSafeBootFlag
|| theKext
->isLoadableInSafeBoot()) {
9523 personalities
= theKext
->copyPersonalitiesArray();
9524 if (!personalities
) {
9527 result
->merge(personalities
);
9529 // xxx - check for better place to put this log msg
9531 kOSKextLogWarningLevel
|
9533 "Kext %s is not loadable during safe boot; "
9534 "omitting its personalities.",
9535 theKext
->getIdentifierCString());
9541 IORecursiveLockUnlock(sKextLock
);
9543 if (kextIterator
) kextIterator
->release();
9544 if (personalitiesIterator
) personalitiesIterator
->release();
9545 if (personalities
) personalities
->release();
9550 /*********************************************************************
9551 *********************************************************************/
9554 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching
)
9556 int numPersonalities
= 0;
9558 OSKextLog(/* kext */ NULL
,
9559 kOSKextLogStepLevel
|
9561 "Sending all eligible registered kexts' personalities "
9562 "to the IOCatalogue %s.",
9563 startMatching
? "and starting matching" : "but not starting matching");
9565 OSArray
* personalities
= OSKext::copyAllKextPersonalities(
9566 /* filterSafeBootFlag */ true);
9568 if (personalities
) {
9569 gIOCatalogue
->addDrivers(personalities
, startMatching
);
9570 numPersonalities
= personalities
->getCount();
9571 personalities
->release();
9574 OSKextLog(/* kext */ NULL
,
9575 kOSKextLogStepLevel
|
9577 "%d kext personalit%s sent to the IOCatalogue; %s.",
9578 numPersonalities
, numPersonalities
> 0 ? "ies" : "y",
9579 startMatching
? "matching started" : "matching not started");
9583 /*********************************************************************
9584 * Do not make a deep copy, just convert the IOKitPersonalities dict
9585 * to an array for sending to the IOCatalogue.
9586 *********************************************************************/
9588 OSKext::copyPersonalitiesArray(void)
9590 OSArray
* result
= NULL
;
9591 OSDictionary
* personalities
= NULL
; // do not release
9592 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
9594 OSString
* personalityName
= NULL
; // do not release
9595 OSString
* personalityBundleIdentifier
= NULL
; // do not release
9597 personalities
= OSDynamicCast(OSDictionary
,
9598 getPropertyForHostArch(kIOKitPersonalitiesKey
));
9599 if (!personalities
) {
9603 result
= OSArray::withCapacity(personalities
->getCount());
9608 personalitiesIterator
=
9609 OSCollectionIterator::withCollection(personalities
);
9610 if (!personalitiesIterator
) {
9613 while ((personalityName
= OSDynamicCast(OSString
,
9614 personalitiesIterator
->getNextObject()))) {
9616 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
9617 personalities
->getObject(personalityName
));
9620 * If the personality doesn't have a CFBundleIdentifier, or if it
9621 * differs from the kext's, insert the kext's ID so we can find it.
9622 * The publisher ID is used to remove personalities from bundles
9625 personalityBundleIdentifier
= OSDynamicCast(OSString
,
9626 personality
->getObject(kCFBundleIdentifierKey
));
9628 if (!personalityBundleIdentifier
) {
9629 personality
->setObject(kCFBundleIdentifierKey
, bundleID
);
9630 } else if (!personalityBundleIdentifier
->isEqualTo(bundleID
)) {
9631 personality
->setObject(kIOPersonalityPublisherKey
, bundleID
);
9634 result
->setObject(personality
);
9638 if (personalitiesIterator
) personalitiesIterator
->release();
9643 /*********************************************************************
9644 Might want to change this to a bool return?
9645 *********************************************************************/
9647 OSKext::sendPersonalitiesToCatalog(
9649 OSArray
* personalityNames
)
9651 OSReturn result
= kOSReturnSuccess
;
9652 OSArray
* personalitiesToSend
= NULL
; // must release
9653 OSDictionary
* kextPersonalities
= NULL
; // do not release
9656 if (!sLoadEnabled
) {
9658 kOSKextLogErrorLevel
|
9660 "Kext loading is disabled (attempt to start matching for kext %s).",
9661 getIdentifierCString());
9662 result
= kOSKextReturnDisabled
;
9666 if (sSafeBoot
&& !isLoadableInSafeBoot()) {
9668 kOSKextLogErrorLevel
|
9670 "Kext %s is not loadable during safe boot; "
9671 "not sending personalities to the IOCatalogue.",
9672 getIdentifierCString());
9673 result
= kOSKextReturnNotLoadable
;
9677 if (!personalityNames
|| !personalityNames
->getCount()) {
9678 personalitiesToSend
= copyPersonalitiesArray();
9680 kextPersonalities
= OSDynamicCast(OSDictionary
,
9681 getPropertyForHostArch(kIOKitPersonalitiesKey
));
9682 if (!kextPersonalities
|| !kextPersonalities
->getCount()) {
9686 personalitiesToSend
= OSArray::withCapacity(0);
9687 if (!personalitiesToSend
) {
9688 result
= kOSKextReturnNoMemory
;
9691 count
= personalityNames
->getCount();
9692 for (i
= 0; i
< count
; i
++) {
9693 OSString
* name
= OSDynamicCast(OSString
,
9694 personalityNames
->getObject(i
));
9698 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
9699 kextPersonalities
->getObject(name
));
9701 personalitiesToSend
->setObject(personality
);
9705 if (personalitiesToSend
) {
9706 unsigned numPersonalities
= personalitiesToSend
->getCount();
9708 kOSKextLogStepLevel
|
9710 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
9711 getIdentifierCString(),
9713 numPersonalities
> 1 ? "ies" : "y",
9714 startMatching
? " and starting matching" : " but not starting matching");
9715 gIOCatalogue
->addDrivers(personalitiesToSend
, startMatching
);
9718 if (personalitiesToSend
) {
9719 personalitiesToSend
->release();
9724 /*********************************************************************
9725 * xxx - We should allow removing the kext's declared personalities,
9726 * xxx - even with other bundle identifiers.
9727 *********************************************************************/
9729 OSKext::removePersonalitiesFromCatalog(void)
9731 OSDictionary
* personality
= NULL
; // do not release
9733 personality
= OSDictionary::withCapacity(1);
9737 personality
->setObject(kCFBundleIdentifierKey
, getIdentifier());
9740 kOSKextLogStepLevel
|
9742 "Kext %s removing all personalities naming it from the IOCatalogue.",
9743 getIdentifierCString());
9745 /* Have the IOCatalog remove all personalities matching this kext's
9746 * bundle ID and trigger matching anew.
9748 gIOCatalogue
->removeDrivers(personality
, /* startMatching */ true);
9751 if (personality
) personality
->release();
9758 #pragma mark Logging
9760 /*********************************************************************
9761 * Do not call any function that takes sKextLock here!
9762 *********************************************************************/
9765 OSKext::setUserSpaceLogFilter(
9766 OSKextLogSpec newUserLogFilter
,
9769 OSKextLogSpec result
;
9770 bool allocError
= false;
9772 /* Do not call any function that takes sKextLoggingLock during
9773 * this critical block. That means do logging after.
9775 IOLockLock(sKextLoggingLock
);
9777 result
= sUserSpaceKextLogFilter
;
9778 sUserSpaceKextLogFilter
= newUserLogFilter
;
9780 if (newUserLogFilter
&& captureFlag
&&
9781 !sUserSpaceLogSpecArray
&& !sUserSpaceLogMessageArray
) {
9783 // xxx - do some measurements for a good initial capacity?
9784 sUserSpaceLogSpecArray
= OSArray::withCapacity(0);
9785 sUserSpaceLogMessageArray
= OSArray::withCapacity(0);
9787 if (!sUserSpaceLogSpecArray
|| !sUserSpaceLogMessageArray
) {
9788 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
9789 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
9794 IOLockUnlock(sKextLoggingLock
);
9796 /* If the config flag itself is changing, log the state change
9797 * going both ways, before setting up the user-space log arrays,
9798 * so that this is only logged in the kernel.
9800 if (result
!= newUserLogFilter
) {
9801 OSKextLog(/* kext */ NULL
,
9802 kOSKextLogDebugLevel
|
9803 kOSKextLogGeneralFlag
,
9804 "User-space log flags changed from 0x%x to 0x%x.",
9805 result
, newUserLogFilter
);
9808 OSKextLog(/* kext */ NULL
,
9809 kOSKextLogErrorLevel
|
9810 kOSKextLogGeneralFlag
,
9811 "Failed to allocate user-space log message arrays.");
9817 /*********************************************************************
9818 * Do not call any function that takes sKextLock here!
9819 *********************************************************************/
9822 OSKext::clearUserSpaceLogFilter(void)
9824 OSArray
* result
= NULL
;
9825 OSKextLogSpec oldLogFilter
;
9826 OSKextLogSpec newLogFilter
= kOSKextLogSilentFilter
;
9828 /* Do not call any function that takes sKextLoggingLock during
9829 * this critical block. That means do logging after.
9831 IOLockLock(sKextLoggingLock
);
9833 result
= OSArray::withCapacity(2);
9835 result
->setObject(sUserSpaceLogSpecArray
);
9836 result
->setObject(sUserSpaceLogMessageArray
);
9838 OSSafeReleaseNULL(sUserSpaceLogSpecArray
);
9839 OSSafeReleaseNULL(sUserSpaceLogMessageArray
);
9841 oldLogFilter
= sUserSpaceKextLogFilter
;
9842 sUserSpaceKextLogFilter
= newLogFilter
;
9844 IOLockUnlock(sKextLoggingLock
);
9846 /* If the config flag itself is changing, log the state change
9847 * going both ways, after tearing down the user-space log
9848 * arrays, so this is only logged within the kernel.
9850 if (oldLogFilter
!= newLogFilter
) {
9851 OSKextLog(/* kext */ NULL
,
9852 kOSKextLogDebugLevel
|
9853 kOSKextLogGeneralFlag
,
9854 "User-space log flags changed from 0x%x to 0x%x.",
9855 oldLogFilter
, newLogFilter
);
9862 /*********************************************************************
9863 * Do not call any function that takes sKextLock here!
9864 *********************************************************************/
9867 OSKext::getUserSpaceLogFilter(void)
9869 OSKextLogSpec result
;
9871 IOLockLock(sKextLoggingLock
);
9872 result
= sUserSpaceKextLogFilter
;
9873 IOLockUnlock(sKextLoggingLock
);
9878 /*********************************************************************
9879 * This function is called by OSMetaClass during kernel C++ setup.
9880 * Be careful what you access here; assume only OSKext::initialize()
9883 * Do not call any function that takes sKextLock here!
9884 *********************************************************************/
9885 #define VTRESET "\033[0m"
9887 #define VTBOLD "\033[1m"
9888 #define VTUNDER "\033[4m"
9890 #define VTRED "\033[31m"
9891 #define VTGREEN "\033[32m"
9892 #define VTYELLOW "\033[33m"
9893 #define VTBLUE "\033[34m"
9894 #define VTMAGENTA "\033[35m"
9895 #define VTCYAN "\033[36m"
9897 inline const char * colorForFlags(OSKextLogSpec flags
)
9899 OSKextLogSpec logLevel
= flags
& kOSKextLogLevelMask
;
9902 case kOSKextLogErrorLevel
:
9903 return VTRED VTBOLD
;
9905 case kOSKextLogWarningLevel
:
9908 case kOSKextLogBasicLevel
:
9909 return VTYELLOW VTUNDER
;
9911 case kOSKextLogProgressLevel
:
9914 case kOSKextLogStepLevel
:
9917 case kOSKextLogDetailLevel
:
9920 case kOSKextLogDebugLevel
:
9930 inline bool logSpecMatch(
9931 OSKextLogSpec msgLogSpec
,
9932 OSKextLogSpec logFilter
)
9934 OSKextLogSpec filterKextGlobal
= logFilter
& kOSKextLogKextOrGlobalMask
;
9935 OSKextLogSpec filterLevel
= logFilter
& kOSKextLogLevelMask
;
9936 OSKextLogSpec filterFlags
= logFilter
& kOSKextLogFlagsMask
;
9938 OSKextLogSpec msgKextGlobal
= msgLogSpec
& kOSKextLogKextOrGlobalMask
;
9939 OSKextLogSpec msgLevel
= msgLogSpec
& kOSKextLogLevelMask
;
9940 OSKextLogSpec msgFlags
= msgLogSpec
& kOSKextLogFlagsMask
;
9942 /* Explicit messages always get logged.
9944 if (msgLevel
== kOSKextLogExplicitLevel
) {
9948 /* Warnings and errors are logged regardless of the flags.
9950 if (msgLevel
<= kOSKextLogBasicLevel
&& (msgLevel
<= filterLevel
)) {
9954 /* A verbose message that isn't for a logging-enabled kext and isn't global
9955 * does *not* get logged.
9957 if (!msgKextGlobal
&& !filterKextGlobal
) {
9961 /* Warnings and errors are logged regardless of the flags.
9962 * All other messages must fit the flags and
9963 * have a level at or below the filter.
9966 if ((msgFlags
& filterFlags
) && (msgLevel
<= filterLevel
)) {
9977 OSKextLogSpec msgLogSpec
,
9978 const char * format
, ...)
9982 va_start(argList
, format
);
9983 OSKextVLog(aKext
, msgLogSpec
, format
, argList
);
9990 OSKextLogSpec msgLogSpec
,
9991 const char * format
,
9994 extern int disableConsoleOutput
;
9996 bool logForKernel
= false;
9997 bool logForUser
= false;
9999 char stackBuffer
[120];
10000 uint32_t length
= 0;
10001 char * allocBuffer
= NULL
; // must kfree
10002 OSNumber
* logSpecNum
= NULL
; // must release
10003 OSString
* logString
= NULL
; // must release
10004 char * buffer
= stackBuffer
; // do not free
10006 IOLockLock(sKextLoggingLock
);
10008 /* Set the kext/global bit in the message spec if we have no
10009 * kext or if the kext requests logging.
10011 if (!aKext
|| aKext
->flags
.loggingEnabled
) {
10012 msgLogSpec
= msgLogSpec
| kOSKextLogKextOrGlobalMask
;
10015 logForKernel
= logSpecMatch(msgLogSpec
, sKernelLogFilter
);
10016 if (sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10017 logForUser
= logSpecMatch(msgLogSpec
, sUserSpaceKextLogFilter
);
10020 if (! (logForKernel
|| logForUser
) ) {
10024 /* No goto from here until past va_end()!
10026 va_copy(argList
, srcArgList
);
10027 length
= vsnprintf(stackBuffer
, sizeof(stackBuffer
), format
, argList
);
10030 if (length
+ 1 >= sizeof(stackBuffer
)) {
10031 allocBuffer
= (char *)kalloc_tag((length
+ 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT
);
10032 if (!allocBuffer
) {
10036 /* No goto from here until past va_end()!
10038 va_copy(argList
, srcArgList
);
10039 vsnprintf(allocBuffer
, length
+ 1, format
, argList
);
10042 buffer
= allocBuffer
;
10045 /* If user space wants the log message, queue it up.
10047 if (logForUser
&& sUserSpaceLogSpecArray
&& sUserSpaceLogMessageArray
) {
10048 logSpecNum
= OSNumber::withNumber(msgLogSpec
, 8 * sizeof(msgLogSpec
));
10049 logString
= OSString::withCString(buffer
);
10050 if (logSpecNum
&& logString
) {
10051 sUserSpaceLogSpecArray
->setObject(logSpecNum
);
10052 sUserSpaceLogMessageArray
->setObject(logString
);
10056 /* Always log messages from the kernel according to the kernel's
10059 if (logForKernel
) {
10061 /* If we are in console mode and have a custom log filter,
10062 * colorize the log message.
10064 if (!disableConsoleOutput
&& sBootArgLogFilterFound
) {
10065 const char * color
= ""; // do not free
10066 color
= colorForFlags(msgLogSpec
);
10067 printf("%s%s%s\n", colorForFlags(msgLogSpec
),
10068 buffer
, color
[0] ? VTRESET
: "");
10070 printf("%s\n", buffer
);
10075 IOLockUnlock(sKextLoggingLock
);
10078 kfree(allocBuffer
, (length
+ 1) * sizeof(char));
10080 OSSafeRelease(logString
);
10081 OSSafeRelease(logSpecNum
);
10085 #if KASLR_IOREG_DEBUG
10087 #define IOLOG_INDENT( the_indention ) \
10090 for ( i = 0; i < (the_indention); i++ ) { \
10095 extern vm_offset_t vm_kernel_stext
;
10096 extern vm_offset_t vm_kernel_etext
;
10097 extern mach_vm_offset_t kext_alloc_base
;
10098 extern mach_vm_offset_t kext_alloc_max
;
10100 bool ScanForAddrInObject(OSObject
* theObject
,
10103 bool ScanForAddrInObject(OSObject
* theObject
,
10106 const OSMetaClass
* myTypeID
;
10107 OSCollectionIterator
* myIter
;
10109 OSObject
* myValue
;
10110 bool myResult
= false;
10112 if ( theObject
== NULL
) {
10113 IOLog("%s: theObject is NULL \n",
10118 myTypeID
= OSTypeIDInst(theObject
);
10120 if ( myTypeID
== OSTypeID(OSDictionary
) ) {
10121 OSDictionary
* myDictionary
;
10123 myDictionary
= OSDynamicCast(OSDictionary
, theObject
);
10124 myIter
= OSCollectionIterator::withCollection( myDictionary
);
10125 if ( myIter
== NULL
)
10129 while ( (myKey
= OSDynamicCast(OSSymbol
, myIter
->getNextObject())) ) {
10132 myValue
= myDictionary
->getObject(myKey
);
10133 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10134 if (myTempResult
) {
10135 // if we ever get a true result return true
10137 IOLOG_INDENT(indent
);
10138 IOLog("OSDictionary key \"%s\" \n", myKey
->getCStringNoCopy());
10143 else if ( myTypeID
== OSTypeID(OSArray
) ) {
10146 myArray
= OSDynamicCast(OSArray
, theObject
);
10147 myIter
= OSCollectionIterator::withCollection(myArray
);
10148 if ( myIter
== NULL
)
10152 while ( (myValue
= myIter
->getNextObject()) ) {
10154 myTempResult
= ScanForAddrInObject(myValue
, (indent
+ 4));
10155 if (myTempResult
) {
10156 // if we ever get a true result return true
10158 IOLOG_INDENT(indent
);
10159 IOLog("OSArray: \n");
10164 else if ( myTypeID
== OSTypeID(OSString
) || myTypeID
== OSTypeID(OSSymbol
) ) {
10166 // should we look for addresses in strings?
10168 else if ( myTypeID
== OSTypeID(OSData
) ) {
10171 unsigned int myLen
;
10172 OSData
* myDataObj
;
10174 myDataObj
= OSDynamicCast(OSData
, theObject
);
10175 myPtrPtr
= (void * *) myDataObj
->getBytesNoCopy();
10176 myLen
= myDataObj
->getLength();
10178 if (myPtrPtr
&& myLen
&& myLen
> 7) {
10180 int myPtrCount
= (myLen
/ sizeof(void *));
10182 for (i
= 0; i
< myPtrCount
; i
++) {
10183 UInt64 numberValue
= (UInt64
) *(myPtrPtr
);
10185 if ( kext_alloc_max
!= 0 &&
10186 numberValue
>= kext_alloc_base
&&
10187 numberValue
< kext_alloc_max
) {
10189 OSKext
* myKext
= NULL
; // must release (looked up)
10190 // IOLog("found OSData %p in kext map %p to %p \n",
10192 // (void *) kext_alloc_base,
10193 // (void *) kext_alloc_max);
10195 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) *(myPtrPtr
) );
10197 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
10199 myKext
->getIdentifierCString());
10204 if ( vm_kernel_etext
!= 0 &&
10205 numberValue
>= vm_kernel_stext
&&
10206 numberValue
< vm_kernel_etext
) {
10207 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
10209 (void *) vm_kernel_stext
,
10210 (void *) vm_kernel_etext
);
10217 else if ( myTypeID
== OSTypeID(OSBoolean
) ) {
10219 // do nothing here...
10221 else if ( myTypeID
== OSTypeID(OSNumber
) ) {
10223 OSNumber
* number
= OSDynamicCast(OSNumber
, theObject
);
10225 UInt64 numberValue
= number
->unsigned64BitValue();
10227 if ( kext_alloc_max
!= 0 &&
10228 numberValue
>= kext_alloc_base
&&
10229 numberValue
< kext_alloc_max
) {
10231 OSKext
* myKext
= NULL
; // must release (looked up)
10232 IOLog("found OSNumber in kext map %p to %p \n",
10233 (void *) kext_alloc_base
,
10234 (void *) kext_alloc_max
);
10235 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10237 myKext
= OSKext::lookupKextWithAddress( (vm_address_t
) numberValue
);
10239 IOLog("found in kext \"%s\" \n",
10240 myKext
->getIdentifierCString());
10246 if ( vm_kernel_etext
!= 0 &&
10247 numberValue
>= vm_kernel_stext
&&
10248 numberValue
< vm_kernel_etext
) {
10249 IOLog("found OSNumber in kernel text segment %p to %p \n",
10250 (void *) vm_kernel_stext
,
10251 (void *) vm_kernel_etext
);
10252 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue
, numberValue
);
10258 const OSMetaClass
* myMetaClass
= NULL
;
10260 myMetaClass
= theObject
->getMetaClass();
10261 if ( myMetaClass
) {
10262 IOLog("class %s \n", myMetaClass
->getClassName() );
10265 IOLog("Unknown object \n" );
10272 #endif // KASLR_KEXT_DEBUG
10274 }; /* extern "C" */
10277 #pragma mark Backtrace Dump & kmod_get_info() support
10279 /*********************************************************************
10280 * This function must be safe to call in panic context.
10281 *********************************************************************/
10284 OSKext::printKextsInBacktrace(
10285 vm_offset_t
* addr
,
10287 int (* printf_func
)(const char *fmt
, ...),
10291 addr64_t summary_page
= 0;
10292 addr64_t last_summary_page
= 0;
10293 bool found_kmod
= false;
10297 if (!sKextSummariesLock
) return;
10298 IOLockLock(sKextSummariesLock
);
10301 if (!gLoadedKextSummaries
) {
10302 (*printf_func
)(" can't perform kext scan: no kext summary");
10306 summary_page
= trunc_page((addr64_t
)(uintptr_t)gLoadedKextSummaries
);
10307 last_summary_page
= round_page(summary_page
+ sLoadedKextSummariesAllocSize
);
10308 for (; summary_page
< last_summary_page
; summary_page
+= PAGE_SIZE
) {
10309 if (pmap_find_phys(kernel_pmap
, summary_page
) == 0) {
10310 (*printf_func
)(" can't perform kext scan: "
10311 "missing kext summary page %p", summary_page
);
10316 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10317 OSKextLoadedKextSummary
* summary
;
10319 summary
= gLoadedKextSummaries
->summaries
+ i
;
10320 if (!summary
->address
) {
10324 if (!summaryIsInBacktrace(summary
, addr
, cnt
)) {
10329 (*printf_func
)(" Kernel Extensions in backtrace:\n");
10333 printSummary(summary
, printf_func
, doUnslide
);
10338 IOLockUnlock(sKextSummariesLock
);
10344 /*********************************************************************
10345 * This function must be safe to call in panic context.
10346 *********************************************************************/
10349 OSKext::summaryIsInBacktrace(
10350 OSKextLoadedKextSummary
* summary
,
10351 vm_offset_t
* addr
,
10356 for (i
= 0; i
< cnt
; i
++) {
10357 vm_offset_t kscan_addr
= addr
[i
];
10358 if ((kscan_addr
>= summary
->address
) &&
10359 (kscan_addr
< (summary
->address
+ summary
->size
)))
10368 /*********************************************************************
10369 * scan list of loaded kext summaries looking for a load address match and if
10370 * found return the UUID C string. If not found then set empty string.
10371 *********************************************************************/
10372 static void findSummaryUUID(
10374 uuid_string_t uuid
);
10376 static void findSummaryUUID(
10378 uuid_string_t uuid
)
10382 uuid
[0] = 0x00; // default to no UUID
10384 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
10385 OSKextLoadedKextSummary
* summary
;
10387 summary
= gLoadedKextSummaries
->summaries
+ i
;
10389 if (summary
->loadTag
== tag_ID
) {
10390 (void) uuid_unparse(summary
->uuid
, uuid
);
10397 /*********************************************************************
10398 * This function must be safe to call in panic context.
10399 *********************************************************************/
10400 void OSKext::printSummary(
10401 OSKextLoadedKextSummary
* summary
,
10402 int (* printf_func
)(const char *fmt
, ...),
10405 kmod_reference_t
* kmod_ref
= NULL
;
10406 uuid_string_t uuid
;
10407 char version
[kOSKextVersionMaxLength
];
10410 if (!OSKextVersionGetString(summary
->version
, version
, sizeof(version
))) {
10411 strlcpy(version
, "unknown version", sizeof(version
));
10413 (void) uuid_unparse(summary
->uuid
, uuid
);
10416 tmpAddr
= VM_KERNEL_UNSLIDE(summary
->address
);
10419 tmpAddr
= summary
->address
;
10421 (*printf_func
)(" %s(%s)[%s]@0x%llx->0x%llx\n",
10422 summary
->name
, version
, uuid
,
10423 tmpAddr
, tmpAddr
+ summary
->size
- 1);
10425 /* print dependency info */
10426 for (kmod_ref
= (kmod_reference_t
*) summary
->reference_list
;
10428 kmod_ref
= kmod_ref
->next
) {
10429 kmod_info_t
* rinfo
;
10431 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_ref
)) == 0) {
10432 (*printf_func
)(" kmod dependency scan stopped "
10433 "due to missing dependency page: %p\n", kmod_ref
);
10436 rinfo
= kmod_ref
->info
;
10438 if (pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)rinfo
)) == 0) {
10439 (*printf_func
)(" kmod dependency scan stopped "
10440 "due to missing kmod page: %p\n", rinfo
);
10444 if (!rinfo
->address
) {
10445 continue; // skip fake entries for built-ins
10448 /* locate UUID in gLoadedKextSummaries */
10449 findSummaryUUID(rinfo
->id
, uuid
);
10452 tmpAddr
= VM_KERNEL_UNSLIDE(rinfo
->address
);
10455 tmpAddr
= rinfo
->address
;
10457 (*printf_func
)(" dependency: %s(%s)[%s]@%p\n",
10458 rinfo
->name
, rinfo
->version
, uuid
, tmpAddr
);
10464 /*******************************************************************************
10465 * substitute() looks at an input string (a pointer within a larger buffer)
10466 * for a match to a substring, and on match it writes the marker & substitution
10467 * character to an output string, updating the scan (from) and
10468 * output (to) indexes as appropriate.
10469 *******************************************************************************/
10470 static int substitute(
10471 const char * scan_string
,
10473 uint32_t * to_index
,
10474 uint32_t * from_index
,
10475 const char * substring
,
10477 char substitution
);
10479 /* string_out must be at least KMOD_MAX_NAME bytes.
10483 const char * scan_string
,
10485 uint32_t * to_index
,
10486 uint32_t * from_index
,
10487 const char * substring
,
10491 uint32_t substring_length
= strnlen(substring
, KMOD_MAX_NAME
- 1);
10493 /* On a substring match, append the marker (if there is one) and then
10494 * the substitution character, updating the output (to) index accordingly.
10495 * Then update the input (from) length by the length of the substring
10496 * that got replaced.
10498 if (!strncmp(scan_string
, substring
, substring_length
)) {
10500 string_out
[(*to_index
)++] = marker
;
10502 string_out
[(*to_index
)++] = substitution
;
10503 (*from_index
) += substring_length
;
10509 /*******************************************************************************
10510 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
10511 * KMOD_MAX_NAME characters and performs various substitutions of common
10512 * prefixes & substrings as defined by tables in kext_panic_report.h.
10513 *******************************************************************************/
10514 static void compactIdentifier(
10515 const char * identifier
,
10516 char * identifier_out
,
10517 char ** identifier_out_end
);
10521 const char * identifier
,
10522 char * identifier_out
,
10523 char ** identifier_out_end
)
10525 uint32_t from_index
, to_index
;
10526 uint32_t scan_from_index
= 0;
10527 uint32_t scan_to_index
= 0;
10528 subs_entry_t
* subs_entry
= NULL
;
10531 from_index
= to_index
= 0;
10532 identifier_out
[0] = '\0';
10534 /* Replace certain identifier prefixes with shorter @+character sequences.
10535 * Check the return value of substitute() so we only replace the prefix.
10537 for (subs_entry
= &kext_identifier_prefix_subs
[0];
10538 subs_entry
->substring
&& !did_sub
;
10541 did_sub
= substitute(identifier
, identifier_out
,
10542 &scan_to_index
, &scan_from_index
,
10543 subs_entry
->substring
, /* marker */ '\0', subs_entry
->substitute
);
10547 /* Now scan through the identifier looking for the common substrings
10548 * and replacing them with shorter !+character sequences via substitute().
10550 for (/* see above */;
10551 scan_from_index
< KMOD_MAX_NAME
- 1 && identifier
[scan_from_index
];
10554 const char * scan_string
= &identifier
[scan_from_index
];
10558 if (scan_from_index
) {
10559 for (subs_entry
= &kext_identifier_substring_subs
[0];
10560 subs_entry
->substring
&& !did_sub
;
10563 did_sub
= substitute(scan_string
, identifier_out
,
10564 &scan_to_index
, &scan_from_index
,
10565 subs_entry
->substring
, '!', subs_entry
->substitute
);
10569 /* If we didn't substitute, copy the input character to the output.
10572 identifier_out
[scan_to_index
++] = identifier
[scan_from_index
++];
10576 identifier_out
[scan_to_index
] = '\0';
10577 if (identifier_out_end
) {
10578 *identifier_out_end
= &identifier_out
[scan_to_index
];
10584 /*******************************************************************************
10585 * assemble_identifier_and_version() adds to a string buffer a compacted
10586 * bundle identifier followed by a version string.
10587 *******************************************************************************/
10589 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
10591 static int assemble_identifier_and_version(
10592 kmod_info_t
* kmod_info
,
10593 char * identPlusVers
,
10597 assemble_identifier_and_version(
10598 kmod_info_t
* kmod_info
,
10599 char * identPlusVers
,
10604 compactIdentifier(kmod_info
->name
, identPlusVers
, NULL
);
10605 result
= strnlen(identPlusVers
, KMOD_MAX_NAME
- 1);
10606 identPlusVers
[result
++] = '\t'; // increment for real char
10607 identPlusVers
[result
] = '\0'; // don't increment for nul char
10608 result
= strlcat(identPlusVers
, kmod_info
->version
, bufSize
);
10609 if (result
>= bufSize
) {
10610 identPlusVers
[bufSize
- 1] = '\0';
10611 result
= bufSize
- 1;
10617 /*******************************************************************************
10618 * Assumes sKextLock is held.
10619 *******************************************************************************/
10622 OSKext::saveLoadedKextPanicListTyped(
10623 const char * prefix
,
10627 uint32_t list_size
)
10630 unsigned int count
, i
;
10632 count
= sLoadedKexts
->getCount();
10639 OSObject
* rawKext
= sLoadedKexts
->getObject(i
);
10640 OSKext
* theKext
= OSDynamicCast(OSKext
, rawKext
);
10642 uint32_t identPlusVersLength
;
10644 char identPlusVers
[2*KMOD_MAX_NAME
];
10647 printf("OSKext::saveLoadedKextPanicListTyped - "
10648 "NULL kext in loaded kext list; continuing\n");
10653 printf("OSKext::saveLoadedKextPanicListTyped - "
10654 "Kext type cast failed in loaded kext list; continuing\n");
10658 /* Skip all built-in kexts.
10660 if (theKext
->isKernelComponent()) {
10664 kmod_info_t
* kmod_info
= theKext
->kmod_info
;
10666 /* Filter for kmod name (bundle identifier).
10668 match
= !strncmp(kmod_info
->name
, prefix
, strnlen(prefix
, KMOD_MAX_NAME
));
10669 if ((match
&& invertFlag
) || (!match
&& !invertFlag
)) {
10673 /* Filter for libraries (kexts that have a compatible version).
10675 if ((libsFlag
== 0 && theKext
->getCompatibleVersion() > 1) ||
10676 (libsFlag
== 1 && theKext
->getCompatibleVersion() < 1)) {
10682 !pmap_find_phys(kernel_pmap
, (addr64_t
)((uintptr_t)kmod_info
))) {
10684 printf("kext scan stopped due to missing kmod_info page: %p\n",
10689 identPlusVersLength
= assemble_identifier_and_version(kmod_info
,
10691 sizeof(identPlusVers
));
10692 if (!identPlusVersLength
) {
10693 printf("error saving loaded kext info\n");
10697 /* make sure everything fits and we null terminate.
10699 tempLen
= strlcat(paniclist
, identPlusVers
, list_size
);
10700 if (tempLen
>= list_size
) {
10701 // panic list is full, keep it and null terminate
10702 paniclist
[list_size
- 1] = 0x00;
10706 tempLen
= strlcat(paniclist
, "\n", list_size
);
10707 if (tempLen
>= list_size
) {
10708 // panic list is full, keep it and null terminate
10709 paniclist
[list_size
- 1] = 0x00;
10721 /*********************************************************************
10722 *********************************************************************/
10725 OSKext::saveLoadedKextPanicList(void)
10727 char * newlist
= NULL
;
10728 uint32_t newlist_size
= 0;
10730 newlist_size
= KEXT_PANICLIST_SIZE
;
10731 newlist
= (char *)kalloc_tag(newlist_size
, VM_KERN_MEMORY_OSKEXT
);
10734 OSKextLog(/* kext */ NULL
,
10735 kOSKextLogErrorLevel
| kOSKextLogGeneralFlag
,
10736 "Couldn't allocate kext panic log buffer.");
10742 // non-"com.apple." kexts
10743 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
10744 /* libs? */ -1, newlist
, newlist_size
) != 0) {
10748 // "com.apple." nonlibrary kexts
10749 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10750 /* libs? */ 0, newlist
, newlist_size
) != 0) {
10754 // "com.apple." library kexts
10755 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10756 /* libs? */ 1, newlist
, newlist_size
) != 0) {
10761 if (loaded_kext_paniclist
) {
10762 kfree(loaded_kext_paniclist
, loaded_kext_paniclist_size
);
10764 loaded_kext_paniclist
= newlist
;
10766 loaded_kext_paniclist_size
= newlist_size
;
10770 kfree(newlist
, newlist_size
);
10775 /*********************************************************************
10776 * Assumes sKextLock is held.
10777 *********************************************************************/
10779 OSKext::savePanicString(bool isLoading
)
10784 return; // do not goto finish here b/c of lock
10787 len
= assemble_identifier_and_version( kmod_info
,
10788 (isLoading
) ? last_loaded_str_buf
: last_unloaded_str_buf
,
10789 (isLoading
) ? sizeof(last_loaded_str_buf
) : sizeof(last_unloaded_str_buf
) );
10791 printf("error saving unloaded kext info\n");
10796 last_loaded_strlen
= len
;
10797 last_loaded_address
= (void *)kmod_info
->address
;
10798 last_loaded_size
= kmod_info
->size
;
10799 clock_get_uptime(&last_loaded_timestamp
);
10801 last_unloaded_strlen
= len
;
10802 last_unloaded_address
= (void *)kmod_info
->address
;
10803 last_unloaded_size
= kmod_info
->size
;
10804 clock_get_uptime(&last_unloaded_timestamp
);
10811 /*********************************************************************
10812 *********************************************************************/
10815 OSKext::printKextPanicLists(int (*printf_func
)(const char *fmt
, ...))
10817 if (last_loaded_strlen
) {
10818 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
10819 AbsoluteTime_to_scalar(&last_loaded_timestamp
),
10820 last_loaded_strlen
, last_loaded_str_buf
,
10821 last_loaded_address
, last_loaded_size
);
10824 if (last_unloaded_strlen
) {
10825 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
10826 AbsoluteTime_to_scalar(&last_unloaded_timestamp
),
10827 last_unloaded_strlen
, last_unloaded_str_buf
,
10828 last_unloaded_address
, last_unloaded_size
);
10831 printf_func("loaded kexts:\n");
10832 if (loaded_kext_paniclist
&&
10833 pmap_find_phys(kernel_pmap
, (addr64_t
) (uintptr_t) loaded_kext_paniclist
) &&
10834 loaded_kext_paniclist
[0]) {
10836 printf_func("%.*s",
10837 strnlen(loaded_kext_paniclist
, loaded_kext_paniclist_size
),
10838 loaded_kext_paniclist
);
10840 printf_func("(none)\n");
10845 /*********************************************************************
10846 * Assumes sKextLock is held.
10847 *********************************************************************/
10850 OSKext::updateLoadedKextSummaries(void)
10852 kern_return_t result
= KERN_FAILURE
;
10853 OSKextLoadedKextSummaryHeader
*summaryHeader
= NULL
;
10854 OSKextLoadedKextSummaryHeader
*summaryHeaderAlloc
= NULL
;
10856 vm_map_offset_t start
, end
;
10857 size_t summarySize
= 0;
10862 OSKextActiveAccount
* accountingList
;
10863 OSKextActiveAccount
* prevAccountingList
;
10864 uint32_t idx
, accountingListAlloc
, accountingListCount
, prevAccountingListCount
;
10866 prevAccountingList
= NULL
;
10867 prevAccountingListCount
= 0;
10869 #if DEVELOPMENT || DEBUG
10870 if (IORecursiveLockHaveLock(sKextLock
) == false) {
10871 panic("sKextLock must be held");
10875 IOLockLock(sKextSummariesLock
);
10877 count
= sLoadedKexts
->getCount();
10878 for (i
= 0, maxKexts
= 0; i
< count
; ++i
) {
10879 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10880 maxKexts
+= (aKext
&& aKext
->isExecutable());
10883 if (!maxKexts
) goto finish
;
10884 if (maxKexts
< kOSKextTypicalLoadCount
) maxKexts
= kOSKextTypicalLoadCount
;
10886 /* Calculate the size needed for the new summary headers.
10889 size
= sizeof(*gLoadedKextSummaries
);
10890 size
+= maxKexts
* sizeof(*gLoadedKextSummaries
->summaries
);
10891 size
= round_page(size
);
10893 if (gLoadedKextSummaries
== NULL
|| sLoadedKextSummariesAllocSize
< size
) {
10894 if (gLoadedKextSummaries
) {
10895 kmem_free(kernel_map
,
10896 (vm_offset_t
)gLoadedKextSummaries
,
10897 sLoadedKextSummariesAllocSize
);
10898 gLoadedKextSummaries
= NULL
;
10899 sLoadedKextSummariesAllocSize
= 0;
10901 result
= kmem_alloc(kernel_map
,
10902 (vm_offset_t
*)&summaryHeaderAlloc
,
10903 size
, VM_KERN_MEMORY_OSKEXT
);
10904 if (result
!= KERN_SUCCESS
) goto finish
;
10905 summaryHeader
= summaryHeaderAlloc
;
10906 summarySize
= size
;
10909 summaryHeader
= gLoadedKextSummaries
;
10910 summarySize
= sLoadedKextSummariesAllocSize
;
10912 start
= (vm_map_offset_t
) summaryHeader
;
10913 end
= start
+ summarySize
;
10914 result
= vm_map_protect(kernel_map
,
10919 if (result
!= KERN_SUCCESS
) goto finish
;
10922 /* Populate the summary header.
10925 bzero(summaryHeader
, summarySize
);
10926 summaryHeader
->version
= kOSKextLoadedKextSummaryVersion
;
10927 summaryHeader
->entry_size
= sizeof(OSKextLoadedKextSummary
);
10929 /* Populate each kext summary.
10932 count
= sLoadedKexts
->getCount();
10933 accountingListAlloc
= 0;
10934 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
10935 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10936 if (!aKext
|| !aKext
->isExecutable()) {
10940 aKext
->updateLoadedKextSummary(&summaryHeader
->summaries
[j
++]);
10941 summaryHeader
->numSummaries
++;
10942 accountingListAlloc
++;
10945 accountingList
= IONew(typeof(accountingList
[0]), accountingListAlloc
);
10946 accountingListCount
= 0;
10947 for (i
= 0, j
= 0; i
< count
&& j
< maxKexts
; ++i
) {
10948 aKext
= OSDynamicCast(OSKext
, sLoadedKexts
->getObject(i
));
10949 if (!aKext
|| !aKext
->isExecutable()) {
10953 OSKextActiveAccount activeAccount
;
10954 aKext
->updateActiveAccount(&activeAccount
);
10955 // order by address
10956 for (idx
= 0; idx
< accountingListCount
; idx
++)
10958 if (activeAccount
.address
< accountingList
[idx
].address
) break;
10960 bcopy(&accountingList
[idx
], &accountingList
[idx
+ 1], (accountingListCount
- idx
) * sizeof(accountingList
[0]));
10961 accountingList
[idx
] = activeAccount
;
10962 accountingListCount
++;
10964 assert(accountingListCount
== accountingListAlloc
);
10965 /* Write protect the buffer and move it into place.
10968 start
= (vm_map_offset_t
) summaryHeader
;
10969 end
= start
+ summarySize
;
10971 result
= vm_map_protect(kernel_map
, start
, end
, VM_PROT_READ
, FALSE
);
10972 if (result
!= KERN_SUCCESS
) goto finish
;
10974 gLoadedKextSummaries
= summaryHeader
;
10975 sLoadedKextSummariesAllocSize
= summarySize
;
10976 summaryHeaderAlloc
= NULL
;
10978 /* Call the magic breakpoint function through a static function pointer so
10979 * the compiler can't optimize the function away.
10981 if (sLoadedKextSummariesUpdated
) (*sLoadedKextSummariesUpdated
)();
10983 IOSimpleLockLock(sKextAccountsLock
);
10984 prevAccountingList
= sKextAccounts
;
10985 prevAccountingListCount
= sKextAccountsCount
;
10986 sKextAccounts
= accountingList
;
10987 sKextAccountsCount
= accountingListCount
;
10988 IOSimpleLockUnlock(sKextAccountsLock
);
10991 IOLockUnlock(sKextSummariesLock
);
10993 /* If we had to allocate a new buffer but failed to generate the summaries,
10996 if (summaryHeaderAlloc
) {
10997 kmem_free(kernel_map
, (vm_offset_t
)summaryHeaderAlloc
, summarySize
);
10999 if (prevAccountingList
) {
11000 IODelete(prevAccountingList
, typeof(accountingList
[0]), prevAccountingListCount
);
11006 /*********************************************************************
11007 *********************************************************************/
11009 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary
*summary
)
11013 strlcpy(summary
->name
, getIdentifierCString(),
11014 sizeof(summary
->name
));
11018 memcpy(summary
->uuid
, uuid
->getBytesNoCopy(), sizeof(summary
->uuid
));
11019 OSSafeRelease(uuid
);
11022 summary
->address
= kmod_info
->address
;
11023 summary
->size
= kmod_info
->size
;
11024 summary
->version
= getVersion();
11025 summary
->loadTag
= kmod_info
->id
;
11026 summary
->flags
= 0;
11027 summary
->reference_list
= (uint64_t) kmod_info
->reference_list
;
11032 /*********************************************************************
11033 *********************************************************************/
11036 OSKext::updateActiveAccount(OSKextActiveAccount
*account
)
11038 bzero(account
, sizeof(*account
));
11039 account
->address
= kmod_info
->address
;
11040 if (account
->address
) {
11041 account
->address_end
= kmod_info
->address
+ kmod_info
->size
;
11043 account
->account
= this->account
;
11046 extern "C" const vm_allocation_site_t
*
11047 OSKextGetAllocationSiteForCaller(uintptr_t address
)
11049 OSKextActiveAccount
* active
;
11050 vm_allocation_site_t
* site
;
11054 IOSimpleLockLock(sKextAccountsLock
);
11056 // bsearch sKextAccounts list
11057 for (baseIdx
= 0, lim
= sKextAccountsCount
; lim
; lim
>>= 1)
11059 active
= &sKextAccounts
[baseIdx
+ (lim
>> 1)];
11060 if ((address
>= active
->address
) && (address
< active
->address_end
))
11062 site
= &active
->account
->site
;
11063 if (!site
->tag
) vm_tag_alloc_locked(site
);
11066 else if (address
> active
->address
)
11069 baseIdx
+= (lim
>> 1) + 1;
11074 IOSimpleLockUnlock(sKextAccountsLock
);
11079 extern "C" uint32_t
11080 OSKextGetKmodIDForSite(vm_allocation_site_t
* site
)
11082 OSKextAccount
* account
= (typeof(account
)) site
;
11083 return (account
->loadTag
);
11087 OSKextFreeSite(vm_allocation_site_t
* site
)
11089 OSKextAccount
* freeAccount
= (typeof(freeAccount
)) site
;
11090 IODelete(freeAccount
, OSKextAccount
, 1);
11093 /*********************************************************************
11094 *********************************************************************/
11096 #if CONFIG_KEC_FIPS
11099 #pragma mark Kernel External Components for FIPS compliance
11102 /*********************************************************************
11103 * Kernel External Components for FIPS compliance (KEC_FIPS)
11104 *********************************************************************/
11106 GetAppleTEXTHashForKext(OSKext
* theKext
, OSDictionary
*theInfoDict
)
11108 AppleTEXTHash_t my_ath
= {1, 0, NULL
};
11109 AppleTEXTHash_t
* my_athp
= NULL
; // do not release
11110 OSDictionary
* textHashDict
= NULL
; // do not release
11111 OSData
* segmentHash
= NULL
; // do not release
11113 if (theKext
== NULL
|| theInfoDict
== NULL
) {
11117 textHashDict
= OSDynamicCast(OSDictionary
, theInfoDict
->getObject(kAppleTextHashesKey
));
11118 if (textHashDict
== NULL
) {
11122 segmentHash
= OSDynamicCast(OSData
,
11123 textHashDict
->getObject(ARCHNAME
));
11124 if (segmentHash
== NULL
) {
11128 // KEC_FIPS type kexts never unload so we don't have to clean up our
11130 if (kmem_alloc(kernel_map
, (vm_offset_t
*) &my_athp
,
11131 sizeof(AppleTEXTHash_t
), VM_KERN_MEMORY_OSKEXT
) != KERN_SUCCESS
) {
11135 memcpy(my_athp
, &my_ath
, sizeof(my_ath
));
11136 my_athp
->ath_length
= segmentHash
->getLength();
11137 if (my_athp
->ath_length
> 0) {
11138 my_athp
->ath_hash
= (void *)segmentHash
->getBytesNoCopy();
11143 kOSKextLogErrorLevel
|
11144 kOSKextLogGeneralFlag
,
11145 "Kext %s ath_version %d ath_length %d ath_hash %p",
11146 theKext
->getIdentifierCString(),
11147 my_athp
->ath_version
,
11148 my_athp
->ath_length
,
11149 my_athp
->ath_hash
);
11152 return( (void *) my_athp
);
11155 #endif // CONFIG_KEC_FIPS