]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSKext.cpp
2e15a06e7643401fd500302fc2239866cf89939a
[apple/xnu.git] / libkern / c++ / OSKext.cpp
1 /*
2 * Copyright (c) 2008-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 extern "C" {
30 #include <kern/clock.h>
31 #include <kern/host.h>
32 #include <kern/kext_alloc.h>
33 #include <kextd/kextd_mach.h>
34 #include <libkern/kernel_mach_header.h>
35 #include <libkern/kext_panic_report.h>
36 #include <libkern/kext_request_keys.h>
37 #include <libkern/mkext.h>
38 #include <libkern/prelink.h>
39 #include <libkern/version.h>
40 #include <libkern/zlib.h>
41 #include <mach/host_special_ports.h>
42 #include <mach/mach_vm.h>
43 #include <mach/mach_time.h>
44 #include <sys/sysctl.h>
45 #include <uuid/uuid.h>
46 // 04/18/11 - gab: <rdar://problem/9236163>
47 #include <sys/random.h>
48
49 #if CONFIG_MACF
50 #include <sys/kauth.h>
51 #include <security/mac_framework.h>
52 #endif
53 };
54
55 #include <libkern/OSKextLibPrivate.h>
56 #include <libkern/c++/OSKext.h>
57 #include <libkern/c++/OSLib.h>
58
59 #include <IOKit/IOLib.h>
60 #include <IOKit/IOCatalogue.h>
61 #include <IOKit/IORegistryEntry.h>
62 #include <IOKit/IOService.h>
63
64 #include <IOKit/IOStatisticsPrivate.h>
65
66 #if PRAGMA_MARK
67 #pragma mark External & Internal Function Protos
68 #endif
69 /*********************************************************************
70 *********************************************************************/
71 extern "C" {
72 extern int IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
73 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
74 extern void OSRuntimeUnloadCPPForSegment(kernel_segment_command_t * segment);
75 extern void OSRuntimeUnloadCPP(kmod_info_t * ki, void * data);
76
77 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
78 }
79
80 static OSReturn _OSKextCreateRequest(
81 const char * predicate,
82 OSDictionary ** requestP);
83 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
84 static OSObject * _OSKextGetRequestArgument(
85 OSDictionary * requestDict,
86 const char * argName);
87 static bool _OSKextSetRequestArgument(
88 OSDictionary * requestDict,
89 const char * argName,
90 OSObject * value);
91 static void * _OSKextExtractPointer(OSData * wrapper);
92 static OSReturn _OSDictionarySetCStringValue(
93 OSDictionary * dict,
94 const char * key,
95 const char * value);
96 static bool _OSKextInPrelinkRebuildWindow(void);
97 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
98
99 // We really should add containsObject() & containsCString to OSCollection & subclasses.
100 // So few pad slots, though....
101 static bool _OSArrayContainsCString(OSArray * array, const char * cString);
102
103 #if CONFIG_KEC_FIPS
104 static void * GetAppleTEXTHashForKext(OSKext * theKext, OSDictionary *theInfoDict);
105 #endif // CONFIG_KEC_FIPS
106
107 /* Prelinked arm kexts do not have VM entries because the method we use to
108 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
109 * not work on ARM. To get around that, we must free prelinked kext
110 * executables with ml_static_mfree() instead of kext_free().
111 */
112 #if __i386__ || __x86_64__
113 #define VM_MAPPED_KEXTS 1
114 #define KASLR_KEXT_DEBUG 0
115 #define KASLR_IOREG_DEBUG 0
116 #else
117 #error Unsupported architecture
118 #endif
119
120 #if PRAGMA_MARK
121 #pragma mark Constants & Macros
122 #endif
123 /*********************************************************************
124 * Constants & Macros
125 *********************************************************************/
126
127 /* A typical Snow Leopard system has a bit under 120 kexts loaded.
128 * Use this number to create containers.
129 */
130 #define kOSKextTypicalLoadCount (120)
131
132 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
133 * A loaded kext will no dependents or external retains will have 2 retains.
134 */
135 #define kOSKextMinRetainCount (1)
136 #define kOSKextMinLoadedRetainCount (2)
137
138 /**********
139 * Strings and substrings used in dependency resolution.
140 */
141 #define APPLE_KEXT_PREFIX "com.apple."
142 #define KERNEL_LIB "com.apple.kernel"
143
144 #define PRIVATE_KPI "com.apple.kpi.private"
145
146 /* Version for compatbility pseudokexts (com.apple.kernel.*),
147 * compatible back to v6.0.
148 */
149 #define KERNEL6_LIB "com.apple.kernel.6.0"
150 #define KERNEL6_VERSION "7.9.9"
151
152 #define KERNEL_LIB_PREFIX "com.apple.kernel."
153 #define KPI_LIB_PREFIX "com.apple.kpi."
154
155 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0)
156
157 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
158 #define MINIMUM_WAKEUP_SECONDS (30)
159
160 /*********************************************************************
161 * infoDict keys for internally-stored data. Saves on ivar slots for
162 * objects we don't keep around past boot time or during active load.
163 *********************************************************************/
164
165 /* A usable, uncompressed file is stored under this key.
166 */
167 #define _kOSKextExecutableKey "_OSKextExecutable"
168
169 /* An indirect reference to the executable file from an mkext
170 * is stored under this key.
171 */
172 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference"
173
174 /* If the file is contained in a larger buffer laid down by the booter or
175 * sent from user space, the OSKext stores that OSData under this key so that
176 * references are properly tracked. This is always an mkext, right now.
177 */
178 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
179
180 #if PRAGMA_MARK
181 #pragma mark Typedefs
182 #endif
183 /*********************************************************************
184 * Typedefs
185 *********************************************************************/
186
187 /*********************************************************************
188 * MkextEntryRef describes the contents of an OSData object
189 * referencing a file entry from an mkext so that we can uncompress
190 * (if necessary) and extract it on demand.
191 *
192 * It contains the mkextVersion in case we ever wind up supporting
193 * multiple mkext formats. Mkext format 1 is officially retired as of
194 * Snow Leopard.
195 *********************************************************************/
196 typedef struct MkextEntryRef {
197 mkext_basic_header * mkext; // beginning of whole mkext file
198 void * fileinfo; // mkext2_file_entry or equiv; see mkext.h
199 } MkextEntryRef;
200
201 #if PRAGMA_MARK
202 #pragma mark Global and static Module Variables
203 #endif
204 /*********************************************************************
205 * Global & static variables, used to keep track of kexts.
206 *********************************************************************/
207
208 static bool sPrelinkBoot = false;
209 static bool sSafeBoot = false;
210 static bool sKeepSymbols = false;
211
212 /*********************************************************************
213 * sKextLock is the principal lock for OSKext, and guards all static
214 * and global variables not owned by other locks (declared further
215 * below). It must be taken by any entry-point method or function,
216 * including internal functions called on scheduled threads.
217 *
218 * sKextLock and sKextInnerLock are recursive due to multiple functions
219 * that are called both externally and internally. The other locks are
220 * nonrecursive.
221 *
222 * Which locks are taken depends on what they protect, but if more than
223 * one must be taken, they must always be locked in this order
224 * (and unlocked in reverse order) to prevent deadlocks:
225 *
226 * 1. sKextLock
227 * 2. sKextInnerLock
228 * 3. sKextSummariesLock
229 * 4. sKextLoggingLock
230 */
231 static IORecursiveLock * sKextLock = NULL;
232
233 static OSDictionary * sKextsByID = NULL;
234 static OSDictionary * sExcludeListByID = NULL;
235 static OSArray * sLoadedKexts = NULL;
236 static OSArray * sUnloadedPrelinkedKexts = NULL;
237
238 // Requests to kextd waiting to be picked up.
239 static OSArray * sKernelRequests = NULL;
240 // Identifier of kext load requests in sKernelRequests
241 static OSSet * sPostedKextLoadIdentifiers = NULL;
242 static OSArray * sRequestCallbackRecords = NULL;
243
244 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
245 static OSSet * sAllKextLoadIdentifiers = NULL;
246 static KXLDContext * sKxldContext = NULL;
247 static uint32_t sNextLoadTag = 0;
248 static uint32_t sNextRequestTag = 0;
249
250 static bool sUserLoadsActive = false;
251 static bool sKextdActive = false;
252 static bool sDeferredLoadSucceeded = false;
253 static bool sConsiderUnloadsExecuted = false;
254
255 #if NO_KEXTD
256 static bool sKernelRequestsEnabled = false;
257 #else
258 static bool sKernelRequestsEnabled = true;
259 #endif
260 static bool sLoadEnabled = true;
261 static bool sUnloadEnabled = true;
262
263 /*********************************************************************
264 * Stuff for the OSKext representing the kernel itself.
265 **********/
266 static OSKext * sKernelKext = NULL;
267
268 /* Set up a fake kmod_info struct for the kernel.
269 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
270 * before OSKext is initialized; that call only needs the name
271 * and address to be set correctly.
272 *
273 * We don't do much else with the kerne's kmod_info; we never
274 * put it into the kmod list, never adjust the reference count,
275 * and never have kernel components reference it.
276 * For that matter, we don't do much with kmod_info structs
277 * at all anymore! We just keep them filled in for gdb and
278 * binary compability.
279 */
280 kmod_info_t g_kernel_kmod_info = {
281 /* next */ 0,
282 /* info_version */ KMOD_INFO_VERSION,
283 /* id */ 0, // loadTag: kernel is always 0
284 /* name */ kOSKextKernelIdentifier, // bundle identifier
285 /* version */ "0", // filled in in OSKext::initialize()
286 /* reference_count */ -1, // never adjusted; kernel never unloads
287 /* reference_list */ NULL,
288 /* address */ NULL,
289 /* size */ 0, // filled in in OSKext::initialize()
290 /* hdr_size */ 0,
291 /* start */ 0,
292 /* stop */ 0
293 };
294
295 extern "C" {
296 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
297 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
298 // misc_protos.h, db_low_trace.c, kgmacros
299 // 'kmod' is a holdover from the old kmod system, we can't rename it.
300 kmod_info_t * kmod = NULL;
301
302 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
303
304
305 static char * loaded_kext_paniclist = NULL;
306 static uint32_t loaded_kext_paniclist_size = 0;
307 static uint32_t loaded_kext_paniclist_length = 0;
308
309 AbsoluteTime last_loaded_timestamp;
310 static char last_loaded_str[2*KMOD_MAX_NAME];
311 static u_long last_loaded_strlen = 0;
312 static void * last_loaded_address = NULL;
313 static u_long last_loaded_size = 0;
314
315 AbsoluteTime last_unloaded_timestamp;
316 static char last_unloaded_str[2*KMOD_MAX_NAME];
317 static u_long last_unloaded_strlen = 0;
318 static void * last_unloaded_address = NULL;
319 static u_long last_unloaded_size = 0;
320
321 /*********************************************************************
322 * sKextInnerLock protects against cross-calls with IOService and
323 * IOCatalogue, and owns the variables declared immediately below.
324 *
325 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
326 *
327 * When both sKextLock and sKextInnerLock need to be taken,
328 * always lock sKextLock first and unlock it second. Never take both
329 * locks in an entry point to OSKext; if you need to do so, you must
330 * spawn an independent thread to avoid potential deadlocks for threads
331 * calling into OSKext.
332 **********/
333 static IORecursiveLock * sKextInnerLock = NULL;
334
335 static bool sAutounloadEnabled = true;
336 static bool sConsiderUnloadsCalled = false;
337 static bool sConsiderUnloadsPending = false;
338
339 static unsigned int sConsiderUnloadDelay = 60; // seconds
340 static thread_call_t sUnloadCallout = 0;
341 static thread_call_t sDestroyLinkContextThread = 0; // one-shot, one-at-a-time thread
342 static bool sSystemSleep = false; // true when system going to sleep
343 static AbsoluteTime sLastWakeTime; // last time we woke up
344
345 /*********************************************************************
346 * Backtraces can be printed at various times so we need a tight lock
347 * on data used for that. sKextSummariesLock protects the variables
348 * declared immediately below.
349 *
350 * gLoadedKextSummaries is accessed by other modules, but only during
351 * a panic so the lock isn't needed then.
352 *
353 * gLoadedKextSummaries has the "used" attribute in order to ensure
354 * that it remains visible even when we are performing extremely
355 * aggressive optimizations, as it is needed to allow the debugger
356 * to automatically parse the list of loaded kexts.
357 **********/
358 static IOLock * sKextSummariesLock = NULL;
359
360 void (*sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
361 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
362 static size_t sLoadedKextSummariesAllocSize = 0;
363 OSKextLoadedKextSummaryHeader * sPrevLoadedKextSummaries = NULL;
364 static size_t sPrevLoadedKextSummariesAllocSize = 0;
365 };
366
367 /*********************************************************************
368 * sKextLoggingLock protects the logging variables declared immediately below.
369 **********/
370 static IOLock * sKextLoggingLock = NULL;
371
372 static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel |
373 kOSKextLogVerboseFlagsMask;
374 static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter;
375 static bool sBootArgLogFilterFound = false;
376 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
377 sKernelLogFilter, "kernel kext logging");
378
379 static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter;
380 static OSArray * sUserSpaceLogSpecArray = NULL;
381 static OSArray * sUserSpaceLogMessageArray = NULL;
382
383 /*********
384 * End scope for sKextInnerLock-protected variables.
385 *********************************************************************/
386
387 #if PRAGMA_MARK
388 #pragma mark OSData callbacks (need to move to OSData)
389 #endif
390 /*********************************************************************
391 * C functions used for callbacks.
392 *********************************************************************/
393 extern "C" {
394 void osdata_kmem_free(void * ptr, unsigned int length) {
395 kmem_free(kernel_map, (vm_address_t)ptr, length);
396 return;
397 }
398
399 void osdata_phys_free(void * ptr, unsigned int length) {
400 ml_static_mfree((vm_offset_t)ptr, length);
401 return;
402 }
403
404 void osdata_vm_deallocate(void * ptr, unsigned int length)
405 {
406 (void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
407 return;
408 }
409
410 void osdata_kext_free(void * ptr, unsigned int length)
411 {
412 (void)kext_free((vm_offset_t)ptr, length);
413 }
414
415 };
416
417 #if PRAGMA_MARK
418 #pragma mark KXLD Allocation Callback
419 #endif
420 /*********************************************************************
421 * KXLD Allocation Callback
422 *********************************************************************/
423 kxld_addr_t
424 kern_allocate(
425 u_long size,
426 KXLDAllocateFlags * flags,
427 void * user_data)
428 {
429 vm_address_t result = 0; // returned
430 kern_return_t mach_result = KERN_FAILURE;
431 bool success = false;
432 OSKext * theKext = (OSKext *)user_data;
433 u_long roundSize = round_page(size);
434 OSData * linkBuffer = NULL; // must release
435
436 mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
437 if (mach_result != KERN_SUCCESS) {
438 OSKextLog(theKext,
439 kOSKextLogErrorLevel |
440 kOSKextLogGeneralFlag,
441 "Can't allocate kernel memory to link %s.",
442 theKext->getIdentifierCString());
443 goto finish;
444 }
445
446 /* Create an OSData wrapper for the allocated buffer.
447 */
448 linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
449 if (!linkBuffer) {
450 OSKextLog(theKext,
451 kOSKextLogErrorLevel |
452 kOSKextLogGeneralFlag,
453 "Can't allocate linked executable wrapper for %s.",
454 theKext->getIdentifierCString());
455 goto finish;
456 }
457 linkBuffer->setDeallocFunction(osdata_kext_free);
458 OSKextLog(theKext,
459 kOSKextLogProgressLevel |
460 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
461 "Allocated link buffer for kext %s at %p (%lu bytes).",
462 theKext->getIdentifierCString(),
463 (void *)result, (unsigned long)roundSize);
464
465 theKext->setLinkedExecutable(linkBuffer);
466
467 *flags = kKxldAllocateWritable;
468 success = true;
469
470 finish:
471 if (!success && result) {
472 kext_free(result, roundSize);
473 result = 0;
474 }
475
476 OSSafeRelease(linkBuffer);
477
478 return (kxld_addr_t)result;
479 }
480
481 /*********************************************************************
482 *********************************************************************/
483 void
484 kxld_log_callback(
485 KXLDLogSubsystem subsystem,
486 KXLDLogLevel level,
487 const char * format,
488 va_list argList,
489 void * user_data)
490 {
491 OSKext *theKext = (OSKext *) user_data;
492 OSKextLogSpec logSpec = 0;
493
494 switch (subsystem) {
495 case kKxldLogLinking:
496 logSpec |= kOSKextLogLinkFlag;
497 break;
498 case kKxldLogPatching:
499 logSpec |= kOSKextLogPatchFlag;
500 break;
501 }
502
503 switch (level) {
504 case kKxldLogExplicit:
505 logSpec |= kOSKextLogExplicitLevel;
506 break;
507 case kKxldLogErr:
508 logSpec |= kOSKextLogErrorLevel;
509 break;
510 case kKxldLogWarn:
511 logSpec |= kOSKextLogWarningLevel;
512 break;
513 case kKxldLogBasic:
514 logSpec |= kOSKextLogProgressLevel;
515 break;
516 case kKxldLogDetail:
517 logSpec |= kOSKextLogDetailLevel;
518 break;
519 case kKxldLogDebug:
520 logSpec |= kOSKextLogDebugLevel;
521 break;
522 }
523
524 OSKextVLog(theKext, logSpec, format, argList);
525 }
526
527 #if PRAGMA_MARK
528 #pragma mark IOStatistics defines
529 #endif
530
531 #if IOKITSTATS
532
533 #define notifyKextLoadObservers(kext, kmod_info) \
534 do { \
535 IOStatistics::onKextLoad(kext, kmod_info); \
536 } while (0)
537
538 #define notifyKextUnloadObservers(kext) \
539 do { \
540 IOStatistics::onKextUnload(kext); \
541 } while (0)
542
543 #define notifyAddClassObservers(kext, addedClass, flags) \
544 do { \
545 IOStatistics::onClassAdded(kext, addedClass); \
546 } while (0)
547
548 #define notifyRemoveClassObservers(kext, removedClass, flags) \
549 do { \
550 IOStatistics::onClassRemoved(kext, removedClass); \
551 } while (0)
552
553 #else
554
555 #define notifyKextLoadObservers(kext, kmod_info)
556 #define notifyKextUnloadObservers(kext)
557 #define notifyAddClassObservers(kext, addedClass, flags)
558 #define notifyRemoveClassObservers(kext, removedClass, flags)
559
560 #endif /* IOKITSTATS */
561
562 #if PRAGMA_MARK
563 #pragma mark Module Config (Startup & Shutdown)
564 #endif
565 /*********************************************************************
566 * Module Config (Class Definition & Class Methods)
567 *********************************************************************/
568 #define super OSObject
569 OSDefineMetaClassAndStructors(OSKext, OSObject)
570
571 /*********************************************************************
572 *********************************************************************/
573 /* static */
574 void
575 OSKext::initialize(void)
576 {
577 OSData * kernelExecutable = NULL; // do not release
578 u_char * kernelStart = NULL; // do not free
579 size_t kernelLength = 0;
580 OSString * scratchString = NULL; // must release
581 IORegistryEntry * registryRoot = NULL; // do not release
582 OSNumber * kernelCPUType = NULL; // must release
583 OSNumber * kernelCPUSubtype = NULL; // must release
584 OSKextLogSpec bootLogFilter = kOSKextLogSilentFilter;
585 bool setResult = false;
586 uint64_t * timestamp = 0;
587 char bootArgBuffer[16]; // for PE_parse_boot_argn w/strings
588
589 /* This must be the first thing allocated. Everything else grabs this lock.
590 */
591 sKextLock = IORecursiveLockAlloc();
592 sKextInnerLock = IORecursiveLockAlloc();
593 sKextSummariesLock = IOLockAlloc();
594 sKextLoggingLock = IOLockAlloc();
595 assert(sKextLock);
596 assert(sKextInnerLock);
597 assert(sKextSummariesLock);
598 assert(sKextLoggingLock);
599
600 sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
601 sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
602 sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
603 sKernelRequests = OSArray::withCapacity(0);
604 sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
605 sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
606 sRequestCallbackRecords = OSArray::withCapacity(0);
607 assert(sKextsByID && sLoadedKexts && sKernelRequests &&
608 sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
609 sRequestCallbackRecords && sUnloadedPrelinkedKexts);
610
611 /* Read the log flag boot-args and set the log flags.
612 */
613 if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
614 sBootArgLogFilterFound = true;
615 sKernelLogFilter = bootLogFilter;
616 // log this if any flags are set
617 OSKextLog(/* kext */ NULL,
618 kOSKextLogBasicLevel |
619 kOSKextLogFlagsMask,
620 "Kernel kext log filter 0x%x per kextlog boot arg.",
621 (unsigned)sKernelLogFilter);
622 }
623
624 sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
625 sizeof(bootArgBuffer)) ? true : false;
626
627 if (sSafeBoot) {
628 OSKextLog(/* kext */ NULL,
629 kOSKextLogWarningLevel |
630 kOSKextLogGeneralFlag,
631 "SAFE BOOT DETECTED - "
632 "only valid OSBundleRequired kexts will be loaded.");
633 }
634
635 PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
636
637 /* Set up an OSKext instance to represent the kernel itself.
638 */
639 sKernelKext = new OSKext;
640 assert(sKernelKext);
641
642 kernelStart = (u_char *)&_mh_execute_header;
643 kernelLength = getlastaddr() - (vm_offset_t)kernelStart;
644 kernelExecutable = OSData::withBytesNoCopy(
645 kernelStart, kernelLength);
646 assert(kernelExecutable);
647
648 #if KASLR_KEXT_DEBUG
649 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu \n",
650 (unsigned long)kernelStart,
651 (unsigned long)getlastaddr(),
652 kernelLength);
653 #endif
654
655 sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0
656 sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier);
657
658 sKernelKext->version = OSKextParseVersionString(osrelease);
659 sKernelKext->compatibleVersion = sKernelKext->version;
660 sKernelKext->linkedExecutable = kernelExecutable;
661
662 sKernelKext->flags.hasAllDependencies = 1;
663 sKernelKext->flags.kernelComponent = 1;
664 sKernelKext->flags.prelinked = 0;
665 sKernelKext->flags.loaded = 1;
666 sKernelKext->flags.started = 1;
667 sKernelKext->flags.CPPInitialized = 0;
668 sKernelKext->flags.jettisonLinkeditSeg = 0;
669
670 sKernelKext->kmod_info = &g_kernel_kmod_info;
671 strlcpy(g_kernel_kmod_info.version, osrelease,
672 sizeof(g_kernel_kmod_info.version));
673 g_kernel_kmod_info.size = kernelLength;
674 g_kernel_kmod_info.id = sKernelKext->loadTag;
675
676 /* Cons up an info dict, so we don't have to have special-case
677 * checking all over.
678 */
679 sKernelKext->infoDict = OSDictionary::withCapacity(5);
680 assert(sKernelKext->infoDict);
681 setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey,
682 sKernelKext->bundleID);
683 assert(setResult);
684 setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey,
685 kOSBooleanTrue);
686 assert(setResult);
687
688 scratchString = OSString::withCStringNoCopy(osrelease);
689 assert(scratchString);
690 setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey,
691 scratchString);
692 assert(setResult);
693 OSSafeReleaseNULL(scratchString);
694
695 scratchString = OSString::withCStringNoCopy("mach_kernel");
696 assert(scratchString);
697 setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey,
698 scratchString);
699 assert(setResult);
700 OSSafeReleaseNULL(scratchString);
701
702 /* Add the kernel kext to the bookkeeping dictionaries. Note that
703 * the kernel kext doesn't have a kmod_info struct. copyInfo()
704 * gathers info from other places anyhow.
705 */
706 setResult = sKextsByID->setObject(sKernelKext->bundleID, sKernelKext);
707 assert(setResult);
708 setResult = sLoadedKexts->setObject(sKernelKext);
709 assert(setResult);
710 sKernelKext->release();
711
712 registryRoot = IORegistryEntry::getRegistryRoot();
713 kernelCPUType = OSNumber::withNumber(
714 (long long unsigned int)_mh_execute_header.cputype,
715 8 * sizeof(_mh_execute_header.cputype));
716 kernelCPUSubtype = OSNumber::withNumber(
717 (long long unsigned int)_mh_execute_header.cpusubtype,
718 8 * sizeof(_mh_execute_header.cpusubtype));
719 assert(registryRoot && kernelCPUSubtype && kernelCPUType);
720
721 registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType);
722 registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype);
723
724 OSSafeRelease(kernelCPUType);
725 OSSafeRelease(kernelCPUSubtype);
726
727 timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
728 *timestamp = 0;
729 timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
730 *timestamp = 0;
731 timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
732 *timestamp = 0;
733
734 OSKextLog(/* kext */ NULL,
735 kOSKextLogProgressLevel |
736 kOSKextLogGeneralFlag,
737 "Kext system initialized.");
738
739 notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
740
741 return;
742 }
743
744 /*********************************************************************
745 * This could be in OSKextLib.cpp but we need to hold a lock
746 * while removing all the segments and sKextLock will do.
747 *********************************************************************/
748 /* static */
749 OSReturn
750 OSKext::removeKextBootstrap(void)
751 {
752 OSReturn result = kOSReturnError;
753
754 static bool alreadyDone = false;
755
756 const char * dt_kernel_header_name = "Kernel-__HEADER";
757 const char * dt_kernel_symtab_name = "Kernel-__SYMTAB";
758 kernel_mach_header_t * dt_mach_header = NULL;
759 int dt_mach_header_size = 0;
760 struct symtab_command * dt_symtab = NULL;
761 int dt_symtab_size = 0;
762 int dt_result = 0;
763
764 kernel_segment_command_t * seg_to_remove = NULL;
765
766
767 /* This must be the very first thing done by this function.
768 */
769 IORecursiveLockLock(sKextLock);
770
771 /* If we already did this, it's a success.
772 */
773 if (alreadyDone) {
774 result = kOSReturnSuccess;
775 goto finish;
776 }
777
778 OSKextLog(/* kext */ NULL,
779 kOSKextLogProgressLevel |
780 kOSKextLogGeneralFlag,
781 "Jettisoning kext bootstrap segments.");
782
783 /*****
784 * Dispose of unnecessary stuff that the booter didn't need to load.
785 */
786 dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
787 (void **)&dt_mach_header, &dt_mach_header_size);
788 if (dt_result == 0 && dt_mach_header) {
789 IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
790 round_page_32(dt_mach_header_size));
791 }
792 dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
793 (void **)&dt_symtab, &dt_symtab_size);
794 if (dt_result == 0 && dt_symtab) {
795 IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
796 round_page_32(dt_symtab_size));
797 }
798
799 /*****
800 * KLD bootstrap segment.
801 */
802 // xxx - should rename KLD segment
803 seg_to_remove = getsegbyname("__KLD");
804 if (seg_to_remove) {
805 OSRuntimeUnloadCPPForSegment(seg_to_remove);
806 }
807
808 #if __i386__ || __x86_64__
809 /* On x86, use the mapping data from the segment load command to
810 * unload KLD directly.
811 * This may invalidate any assumptions about "avail_start"
812 * defining the lower bound for valid physical addresses.
813 */
814 if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) {
815 // 04/18/11 - gab: <rdar://problem/9236163>
816 // overwrite memory occupied by KLD segment with random data before
817 // releasing it.
818 read_random((void *) seg_to_remove->vmaddr, seg_to_remove->vmsize);
819 ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize);
820 }
821 #else
822 #error arch
823 #endif
824
825 seg_to_remove = NULL;
826
827 /*****
828 * Prelinked kernel's symtab (if there is one).
829 */
830 kernel_section_t * sect;
831 sect = getsectbyname("__PRELINK", "__symtab");
832 if (sect && sect->addr && sect->size) {
833 ml_static_mfree(sect->addr, sect->size);
834 }
835
836 seg_to_remove = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
837
838 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
839 * pageable, unless keepsyms is set. To do that, we have to copy it from
840 * its booter-allocated memory, free the booter memory, reallocate proper
841 * managed memory, then copy the segment back in.
842 */
843 #if CONFIG_KXLD
844 if (!sKeepSymbols) {
845 kern_return_t mem_result;
846 void *seg_copy = NULL;
847 void *seg_data = NULL;
848 vm_map_offset_t seg_offset = 0;
849 vm_map_offset_t seg_copy_offset = 0;
850 vm_map_size_t seg_length = 0;
851
852 seg_data = (void *) seg_to_remove->vmaddr;
853 seg_offset = (vm_map_offset_t) seg_to_remove->vmaddr;
854 seg_length = (vm_map_size_t) seg_to_remove->vmsize;
855
856 /* Allocate space for the LINKEDIT copy.
857 */
858 mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
859 seg_length);
860 if (mem_result != KERN_SUCCESS) {
861 OSKextLog(/* kext */ NULL,
862 kOSKextLogErrorLevel |
863 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
864 "Can't copy __LINKEDIT segment for VM reassign.");
865 goto finish;
866 }
867 seg_copy_offset = (vm_map_offset_t) seg_copy;
868
869 /* Copy it out.
870 */
871 memcpy(seg_copy, seg_data, seg_length);
872
873 /* Dump the booter memory.
874 */
875 ml_static_mfree(seg_offset, seg_length);
876
877 /* Set up the VM region.
878 */
879 mem_result = vm_map_enter_mem_object(
880 kernel_map,
881 &seg_offset,
882 seg_length, /* mask */ 0,
883 VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
884 (ipc_port_t)NULL,
885 (vm_object_offset_t) 0,
886 /* copy */ FALSE,
887 /* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
888 /* max_protection */ VM_PROT_ALL,
889 /* inheritance */ VM_INHERIT_DEFAULT);
890 if ((mem_result != KERN_SUCCESS) ||
891 (seg_offset != (vm_map_offset_t) seg_data))
892 {
893 OSKextLog(/* kext */ NULL,
894 kOSKextLogErrorLevel |
895 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
896 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
897 seg_data, seg_length, mem_result);
898 goto finish;
899 }
900
901 /* And copy it back.
902 */
903 memcpy(seg_data, seg_copy, seg_length);
904
905 /* Free the copy.
906 */
907 kmem_free(kernel_map, seg_copy_offset, seg_length);
908 }
909 #else /* we are not CONFIG_KXLD */
910 #error CONFIG_KXLD is expected for this arch
911
912 /*****
913 * Dump the LINKEDIT segment, unless keepsyms is set.
914 */
915 if (!sKeepSymbols) {
916 const char *dt_segment_name = "Kernel-__LINKEDIT";
917 if (0 == IODTGetLoaderInfo(dt_segment_name,
918 &segment_paddress, &segment_size)) {
919 #ifdef SECURE_KERNEL
920 vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
921 bzero((void*)vmaddr, segment_size);
922 #endif
923 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
924 (int)segment_size);
925 }
926 } else {
927 OSKextLog(/* kext */ NULL,
928 kOSKextLogBasicLevel |
929 kOSKextLogGeneralFlag,
930 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
931 }
932 #endif /* CONFIG_KXLD */
933
934 seg_to_remove = NULL;
935
936 alreadyDone = true;
937 result = kOSReturnSuccess;
938
939 finish:
940
941 /* This must be the very last thing done before returning.
942 */
943 IORecursiveLockUnlock(sKextLock);
944
945 return result;
946 }
947
948 /*********************************************************************
949 *********************************************************************/
950 void
951 OSKext::flushNonloadedKexts(
952 Boolean flushPrelinkedKexts)
953 {
954 OSSet * prelinkedKexts = NULL; // must release
955 OSCollectionIterator * kextIterator = NULL; // must release
956 OSCollectionIterator * prelinkIterator = NULL; // must release
957 const OSSymbol * thisID = NULL; // do not release
958 OSKext * thisKext = NULL; // do not release
959 uint32_t count, i;
960
961 IORecursiveLockLock(sKextLock);
962
963 OSKextLog(/* kext */ NULL,
964 kOSKextLogProgressLevel |
965 kOSKextLogKextBookkeepingFlag,
966 "Flushing nonloaded kexts and other unused data.");
967
968 OSKext::considerDestroyingLinkContext();
969
970 /* If we aren't flushing unused prelinked kexts, we have to put them
971 * aside while we flush everything else so make a container for them.
972 */
973 if (!flushPrelinkedKexts) {
974 prelinkedKexts = OSSet::withCapacity(0);
975 if (!prelinkedKexts) {
976 goto finish;
977 }
978 }
979
980 /* Set aside prelinked kexts (in-use or not) and break
981 * any lingering inter-kext references for nonloaded kexts
982 * so they have min. retain counts.
983 */
984 kextIterator = OSCollectionIterator::withCollection(sKextsByID);
985 if (!kextIterator) {
986 goto finish;
987 }
988
989 while ((thisID = OSDynamicCast(OSSymbol,
990 kextIterator->getNextObject()))) {
991
992 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
993
994 if (thisKext) {
995 if (prelinkedKexts && thisKext->isPrelinked()) {
996 prelinkedKexts->setObject(thisKext);
997 }
998 thisKext->flushDependencies(/* forceIfLoaded */ false);
999 }
1000 }
1001
1002 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1003 */
1004 sKextsByID->flushCollection();
1005
1006 /* Now put the loaded kexts back into the ID dictionary.
1007 */
1008 count = sLoadedKexts->getCount();
1009 for (i = 0; i < count; i++) {
1010 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
1011 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1012 }
1013
1014 /* Finally, put back the prelinked kexts if we saved any.
1015 */
1016 if (prelinkedKexts) {
1017 prelinkIterator = OSCollectionIterator::withCollection(prelinkedKexts);
1018 if (!prelinkIterator) {
1019 goto finish;
1020 }
1021
1022 while ((thisKext = OSDynamicCast(OSKext,
1023 prelinkIterator->getNextObject()))) {
1024
1025 sKextsByID->setObject(thisKext->getIdentifierCString(),
1026 thisKext);
1027 }
1028 }
1029
1030 finish:
1031 IORecursiveLockUnlock(sKextLock);
1032
1033 OSSafeRelease(prelinkedKexts);
1034 OSSafeRelease(kextIterator);
1035 OSSafeRelease(prelinkIterator);
1036
1037 return;
1038 }
1039
1040 /*********************************************************************
1041 *********************************************************************/
1042 /* static */
1043 void
1044 OSKext::setKextdActive(Boolean active)
1045 {
1046 IORecursiveLockLock(sKextLock);
1047 sKextdActive = active;
1048 if (sKernelRequests->getCount()) {
1049 OSKext::pingKextd();
1050 }
1051 IORecursiveLockUnlock(sKextLock);
1052
1053 return;
1054 }
1055
1056 /*********************************************************************
1057 * OSKextLib.cpp might need access to this someday but for now it's
1058 * private.
1059 *********************************************************************/
1060 extern "C" {
1061 extern void ipc_port_release_send(ipc_port_t);
1062 };
1063
1064 /* static */
1065 OSReturn
1066 OSKext::pingKextd(void)
1067 {
1068 OSReturn result = kOSReturnError;
1069 #if !NO_KEXTD
1070 mach_port_t kextd_port = IPC_PORT_NULL;
1071
1072 if (!sKextdActive) {
1073 result = kOSKextReturnDisabled; // basically unavailable
1074 goto finish;
1075 }
1076
1077 result = host_get_kextd_port(host_priv_self(), &kextd_port);
1078 if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1079 OSKextLog(/* kext */ NULL,
1080 kOSKextLogErrorLevel |
1081 kOSKextLogIPCFlag,
1082 "Can't get kextd port.");
1083 goto finish;
1084 }
1085
1086 result = kextd_ping(kextd_port);
1087 if (result != KERN_SUCCESS) {
1088 OSKextLog(/* kext */ NULL,
1089 kOSKextLogErrorLevel |
1090 kOSKextLogIPCFlag,
1091 "kextd ping failed (0x%x).", (int)result);
1092 goto finish;
1093 }
1094
1095 finish:
1096 if (IPC_PORT_VALID(kextd_port)) {
1097 ipc_port_release_send(kextd_port);
1098 }
1099 #endif
1100
1101 return result;
1102 }
1103
1104 /*********************************************************************
1105 *********************************************************************/
1106 /* static */
1107 void
1108 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1109 {
1110 IORecursiveLockLock(sKextLock);
1111 sDeferredLoadSucceeded = succeeded;
1112 IORecursiveLockUnlock(sKextLock);
1113
1114 return;
1115 }
1116
1117 /*********************************************************************
1118 * Called from IOSystemShutdownNotification.
1119 *********************************************************************/
1120 /* static */
1121 void
1122 OSKext::willShutdown(void)
1123 {
1124 #if !NO_KEXTD
1125 OSReturn checkResult = kOSReturnError;
1126 #endif
1127 OSDictionary * exitRequest = NULL; // must release
1128
1129 IORecursiveLockLock(sKextLock);
1130
1131 OSKext::setLoadEnabled(false);
1132 OSKext::setUnloadEnabled(false);
1133 OSKext::setAutounloadsEnabled(false);
1134 OSKext::setKernelRequestsEnabled(false);
1135
1136 #if !NO_KEXTD
1137 OSKextLog(/* kext */ NULL,
1138 kOSKextLogProgressLevel |
1139 kOSKextLogGeneralFlag,
1140 "System shutdown; requesting immediate kextd exit.");
1141
1142 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit,
1143 &exitRequest);
1144 if (checkResult != kOSReturnSuccess) {
1145 goto finish;
1146 }
1147 if (!sKernelRequests->setObject(exitRequest)) {
1148 goto finish;
1149 }
1150
1151 OSKext::pingKextd();
1152
1153 finish:
1154 #endif
1155
1156 IORecursiveLockUnlock(sKextLock);
1157
1158 OSSafeRelease(exitRequest);
1159 return;
1160 }
1161
1162 /*********************************************************************
1163 *********************************************************************/
1164 /* static */
1165 bool
1166 OSKext::getLoadEnabled(void)
1167 {
1168 bool result;
1169
1170 IORecursiveLockLock(sKextLock);
1171 result = sLoadEnabled;
1172 IORecursiveLockUnlock(sKextLock);
1173 return result;
1174 }
1175
1176 /*********************************************************************
1177 *********************************************************************/
1178 /* static */
1179 bool
1180 OSKext::setLoadEnabled(bool flag)
1181 {
1182 bool result;
1183
1184 IORecursiveLockLock(sKextLock);
1185 result = sLoadEnabled;
1186 sLoadEnabled = (flag ? true : false);
1187
1188 if (sLoadEnabled != result) {
1189 OSKextLog(/* kext */ NULL,
1190 kOSKextLogBasicLevel |
1191 kOSKextLogLoadFlag,
1192 "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1193 }
1194
1195 IORecursiveLockUnlock(sKextLock);
1196
1197 return result;
1198 }
1199
1200 /*********************************************************************
1201 *********************************************************************/
1202 /* static */
1203 bool
1204 OSKext::getUnloadEnabled(void)
1205 {
1206 bool result;
1207
1208 IORecursiveLockLock(sKextLock);
1209 result = sUnloadEnabled;
1210 IORecursiveLockUnlock(sKextLock);
1211 return result;
1212 }
1213
1214 /*********************************************************************
1215 *********************************************************************/
1216 /* static */
1217 bool
1218 OSKext::setUnloadEnabled(bool flag)
1219 {
1220 bool result;
1221
1222 IORecursiveLockLock(sKextLock);
1223 result = sUnloadEnabled;
1224 sUnloadEnabled = (flag ? true : false);
1225 IORecursiveLockUnlock(sKextLock);
1226
1227 if (sUnloadEnabled != result) {
1228 OSKextLog(/* kext */ NULL,
1229 kOSKextLogBasicLevel |
1230 kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1231 "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1232 }
1233
1234 return result;
1235 }
1236
1237 /*********************************************************************
1238 * Do not call any function that takes sKextLock here!
1239 *********************************************************************/
1240 /* static */
1241 bool
1242 OSKext::getAutounloadEnabled(void)
1243 {
1244 bool result;
1245
1246 IORecursiveLockLock(sKextInnerLock);
1247 result = sAutounloadEnabled ? true : false;
1248 IORecursiveLockUnlock(sKextInnerLock);
1249 return result;
1250 }
1251
1252 /*********************************************************************
1253 * Do not call any function that takes sKextLock here!
1254 *********************************************************************/
1255 /* static */
1256 bool
1257 OSKext::setAutounloadsEnabled(bool flag)
1258 {
1259 bool result;
1260
1261 IORecursiveLockLock(sKextInnerLock);
1262
1263 result = sAutounloadEnabled;
1264 sAutounloadEnabled = (flag ? true : false);
1265 if (!sAutounloadEnabled && sUnloadCallout) {
1266 thread_call_cancel(sUnloadCallout);
1267 }
1268
1269 if (sAutounloadEnabled != result) {
1270 OSKextLog(/* kext */ NULL,
1271 kOSKextLogBasicLevel |
1272 kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1273 "Kext autounloading now %sabled.",
1274 sAutounloadEnabled ? "en" : "dis");
1275 }
1276
1277 IORecursiveLockUnlock(sKextInnerLock);
1278
1279 return result;
1280 }
1281
1282 /*********************************************************************
1283 *********************************************************************/
1284 /* instance method operating on OSKext field */
1285 bool
1286 OSKext::setAutounloadEnabled(bool flag)
1287 {
1288 bool result = flags.autounloadEnabled ? true : false;
1289 flags.autounloadEnabled = flag ? 1 : 0;
1290
1291 if (result != (flag ? true : false)) {
1292 OSKextLog(this,
1293 kOSKextLogProgressLevel |
1294 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1295 "Autounloading for kext %s now %sabled.",
1296 getIdentifierCString(),
1297 flags.autounloadEnabled ? "en" : "dis");
1298 }
1299 return result;
1300 }
1301
1302 /*********************************************************************
1303 *********************************************************************/
1304 /* static */
1305 bool
1306 OSKext::setKernelRequestsEnabled(bool flag)
1307 {
1308 bool result;
1309
1310 IORecursiveLockLock(sKextLock);
1311 result = sKernelRequestsEnabled;
1312 sKernelRequestsEnabled = flag ? true : false;
1313
1314 if (sKernelRequestsEnabled != result) {
1315 OSKextLog(/* kext */ NULL,
1316 kOSKextLogBasicLevel |
1317 kOSKextLogGeneralFlag,
1318 "Kernel requests now %sabled.",
1319 sKernelRequestsEnabled ? "en" : "dis");
1320 }
1321 IORecursiveLockUnlock(sKextLock);
1322 return result;
1323 }
1324
1325 /*********************************************************************
1326 *********************************************************************/
1327 /* static */
1328 bool
1329 OSKext::getKernelRequestsEnabled(void)
1330 {
1331 bool result;
1332
1333 IORecursiveLockLock(sKextLock);
1334 result = sKernelRequestsEnabled;
1335 IORecursiveLockUnlock(sKextLock);
1336 return result;
1337 }
1338
1339 #if PRAGMA_MARK
1340 #pragma mark Kext Life Cycle
1341 #endif
1342 /*********************************************************************
1343 *********************************************************************/
1344 OSKext *
1345 OSKext::withPrelinkedInfoDict(
1346 OSDictionary * anInfoDict)
1347 {
1348 OSKext * newKext = new OSKext;
1349
1350 if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict)) {
1351 newKext->release();
1352 return NULL;
1353 }
1354
1355 return newKext;
1356 }
1357
1358 /*********************************************************************
1359 *********************************************************************/
1360 bool
1361 OSKext::initWithPrelinkedInfoDict(
1362 OSDictionary * anInfoDict)
1363 {
1364 bool result = false;
1365 OSString * kextPath = NULL; // do not release
1366 OSNumber * addressNum = NULL; // reused; do not release
1367 OSNumber * lengthNum = NULL; // reused; do not release
1368 void * data = NULL; // do not free
1369 void * srcData = NULL; // do not free
1370 OSData * prelinkedExecutable = NULL; // must release
1371 uint32_t length = 0; // reused
1372
1373 if (!super::init()) {
1374 goto finish;
1375 }
1376
1377 /* Get the path. Don't look for an arch-specific path property.
1378 */
1379 kextPath = OSDynamicCast(OSString,
1380 anInfoDict->getObject(kPrelinkBundlePathKey));
1381
1382 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
1383 goto finish;
1384 }
1385 #if KASLR_KEXT_DEBUG
1386 IOLog("kaslr: kext %s \n", getIdentifierCString());
1387 #endif
1388
1389 /* Also get the executable's bundle-relative path if present.
1390 * Don't look for an arch-specific path property.
1391 */
1392 executableRelPath = OSDynamicCast(OSString,
1393 anInfoDict->getObject(kPrelinkExecutableRelativePathKey));
1394 if (executableRelPath) {
1395 executableRelPath->retain();
1396 }
1397
1398 /* Don't need the paths to be in the info dictionary any more.
1399 */
1400 anInfoDict->removeObject(kPrelinkBundlePathKey);
1401 anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
1402
1403 /* Create an OSData wrapper around the linked executable.
1404 */
1405 addressNum = OSDynamicCast(OSNumber,
1406 anInfoDict->getObject(kPrelinkExecutableLoadKey));
1407 if (addressNum) {
1408 lengthNum = OSDynamicCast(OSNumber,
1409 anInfoDict->getObject(kPrelinkExecutableSizeKey));
1410 if (!lengthNum) {
1411 OSKextLog(this,
1412 kOSKextLogErrorLevel |
1413 kOSKextLogArchiveFlag,
1414 "Kext %s can't find prelinked kext executable size.",
1415 getIdentifierCString());
1416 goto finish;
1417 }
1418
1419 data = (void *) ((intptr_t) (addressNum->unsigned64BitValue()) + vm_kernel_slide);
1420 length = (uint32_t) (lengthNum->unsigned32BitValue());
1421
1422 #if KASLR_KEXT_DEBUG
1423 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1424 (unsigned long)VM_KERNEL_UNSLIDE(data),
1425 (unsigned long)data,
1426 length);
1427 #endif
1428
1429 anInfoDict->removeObject(kPrelinkExecutableLoadKey);
1430 anInfoDict->removeObject(kPrelinkExecutableSizeKey);
1431
1432 /* If the kext's load address differs from its source address, allocate
1433 * space in the kext map at the load address and copy the kext over.
1434 */
1435 addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
1436 if (addressNum) {
1437 srcData = (void *) ((intptr_t) (addressNum->unsigned64BitValue()) + vm_kernel_slide);
1438
1439 #if KASLR_KEXT_DEBUG
1440 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1441 (unsigned long)VM_KERNEL_UNSLIDE(srcData),
1442 (unsigned long)srcData);
1443 #endif
1444
1445 if (data != srcData) {
1446 #if __LP64__
1447 kern_return_t alloc_result;
1448
1449 alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
1450 if (alloc_result != KERN_SUCCESS) {
1451 OSKextLog(this,
1452 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1453 "Failed to allocate space for prelinked kext %s.",
1454 getIdentifierCString());
1455 goto finish;
1456 }
1457 memcpy(data, srcData, length);
1458 #else
1459 OSKextLog(this,
1460 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1461 "Error: prelinked kext %s - source and load addresses "
1462 "differ on ILP32 architecture.",
1463 getIdentifierCString());
1464 goto finish;
1465 #endif /* __LP64__ */
1466 }
1467
1468 anInfoDict->removeObject(kPrelinkExecutableSourceKey);
1469 }
1470
1471 prelinkedExecutable = OSData::withBytesNoCopy(data, length);
1472 if (!prelinkedExecutable) {
1473 OSKextLog(this,
1474 kOSKextLogErrorLevel |
1475 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1476 "Kext %s failed to create executable wrapper.",
1477 getIdentifierCString());
1478 goto finish;
1479 }
1480
1481 #if VM_MAPPED_KEXTS
1482 prelinkedExecutable->setDeallocFunction(osdata_kext_free);
1483 #else
1484 prelinkedExecutable->setDeallocFunction(osdata_phys_free);
1485 #endif
1486 setLinkedExecutable(prelinkedExecutable);
1487 addressNum = OSDynamicCast(OSNumber,
1488 anInfoDict->getObject(kPrelinkKmodInfoKey));
1489 if (!addressNum) {
1490 OSKextLog(this,
1491 kOSKextLogErrorLevel |
1492 kOSKextLogArchiveFlag,
1493 "Kext %s can't find prelinked kext kmod_info address.",
1494 getIdentifierCString());
1495 goto finish;
1496 }
1497
1498 if (addressNum->unsigned64BitValue() != 0) {
1499 kmod_info = (kmod_info_t *) (intptr_t) (addressNum->unsigned64BitValue() + vm_kernel_slide);
1500 kmod_info->address += vm_kernel_slide;
1501 #if KASLR_KEXT_DEBUG
1502 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1503 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info),
1504 (unsigned long)kmod_info);
1505 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1506 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info->address),
1507 (unsigned long)kmod_info->address);
1508 #endif
1509 }
1510
1511 anInfoDict->removeObject(kPrelinkKmodInfoKey);
1512 }
1513
1514 /* If the plist has a UUID for an interface, save that off.
1515 */
1516 if (isInterface()) {
1517 interfaceUUID = OSDynamicCast(OSData,
1518 anInfoDict->getObject(kPrelinkInterfaceUUIDKey));
1519 if (interfaceUUID) {
1520 interfaceUUID->retain();
1521 anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
1522 }
1523 }
1524
1525 flags.prelinked = true;
1526
1527 /* If we created a kext from prelink info,
1528 * we must be booting from a prelinked kernel.
1529 */
1530 sPrelinkBoot = true;
1531
1532 result = registerIdentifier();
1533
1534 finish:
1535 OSSafeRelease(prelinkedExecutable);
1536
1537 return result;
1538 }
1539
1540 /*********************************************************************
1541 *********************************************************************/
1542 OSKext *
1543 OSKext::withBooterData(
1544 OSString * deviceTreeName,
1545 OSData * booterData)
1546 {
1547 OSKext * newKext = new OSKext;
1548
1549 if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
1550 newKext->release();
1551 return NULL;
1552 }
1553
1554 return newKext;
1555 }
1556
1557 /*********************************************************************
1558 *********************************************************************/
1559 typedef struct _BooterKextFileInfo {
1560 uint32_t infoDictPhysAddr;
1561 uint32_t infoDictLength;
1562 uint32_t executablePhysAddr;
1563 uint32_t executableLength;
1564 uint32_t bundlePathPhysAddr;
1565 uint32_t bundlePathLength;
1566 } _BooterKextFileInfo;
1567
1568 bool
1569 OSKext::initWithBooterData(
1570 OSString * deviceTreeName,
1571 OSData * booterData)
1572 {
1573 bool result = false;
1574 _BooterKextFileInfo * kextFileInfo = NULL; // do not free
1575 char * infoDictAddr = NULL; // do not free
1576 void * executableAddr = NULL; // do not free
1577 char * bundlePathAddr = NULL; // do not free
1578
1579 OSObject * parsedXML = NULL; // must release
1580 OSDictionary * theInfoDict = NULL; // do not release
1581 OSString * kextPath = NULL; // must release
1582 OSString * errorString = NULL; // must release
1583 OSData * executable = NULL; // must release
1584
1585 if (!super::init()) {
1586 goto finish;
1587 }
1588
1589 kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
1590 if (!kextFileInfo) {
1591 OSKextLog(this,
1592 kOSKextLogErrorLevel |
1593 kOSKextLogGeneralFlag,
1594 "No booter-provided data for kext device tree entry %s.",
1595 deviceTreeName->getCStringNoCopy());
1596 goto finish;
1597 }
1598
1599 /* The info plist must exist or we can't read the kext.
1600 */
1601 if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
1602 OSKextLog(this,
1603 kOSKextLogErrorLevel |
1604 kOSKextLogGeneralFlag,
1605 "No kext info dictionary for booter device tree entry %s.",
1606 deviceTreeName->getCStringNoCopy());
1607 goto finish;
1608 }
1609
1610 infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
1611 if (!infoDictAddr) {
1612 OSKextLog(this,
1613 kOSKextLogErrorLevel |
1614 kOSKextLogGeneralFlag,
1615 "Can't translate physical address 0x%x of kext info dictionary "
1616 "for device tree entry %s.",
1617 (int)kextFileInfo->infoDictPhysAddr,
1618 deviceTreeName->getCStringNoCopy());
1619 goto finish;
1620 }
1621
1622 parsedXML = OSUnserializeXML(infoDictAddr, &errorString);
1623 if (parsedXML) {
1624 theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
1625 }
1626 if (!theInfoDict) {
1627 const char * errorCString = "(unknown error)";
1628
1629 if (errorString && errorString->getCStringNoCopy()) {
1630 errorCString = errorString->getCStringNoCopy();
1631 } else if (parsedXML) {
1632 errorCString = "not a dictionary";
1633 }
1634 OSKextLog(this,
1635 kOSKextLogErrorLevel |
1636 kOSKextLogGeneralFlag,
1637 "Error unserializing info dictionary for device tree entry %s: %s.",
1638 deviceTreeName->getCStringNoCopy(), errorCString);
1639 goto finish;
1640 }
1641
1642 /* A bundle path is not mandatory.
1643 */
1644 if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
1645 bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
1646 if (!bundlePathAddr) {
1647 OSKextLog(this,
1648 kOSKextLogErrorLevel |
1649 kOSKextLogGeneralFlag,
1650 "Can't translate physical address 0x%x of kext bundle path "
1651 "for device tree entry %s.",
1652 (int)kextFileInfo->bundlePathPhysAddr,
1653 deviceTreeName->getCStringNoCopy());
1654 goto finish;
1655 }
1656 bundlePathAddr[kextFileInfo->bundlePathLength-1] = '\0'; // just in case!
1657
1658 kextPath = OSString::withCString(bundlePathAddr);
1659 if (!kextPath) {
1660 OSKextLog(this,
1661 kOSKextLogErrorLevel |
1662 kOSKextLogGeneralFlag,
1663 "Failed to create wrapper for device tree entry %s kext path %s.",
1664 deviceTreeName->getCStringNoCopy(), bundlePathAddr);
1665 goto finish;
1666 }
1667 }
1668
1669 if (!setInfoDictionaryAndPath(theInfoDict, kextPath)) {
1670 goto finish;
1671 }
1672
1673 /* An executable is not mandatory.
1674 */
1675 if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
1676 executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
1677 if (!executableAddr) {
1678 OSKextLog(this,
1679 kOSKextLogErrorLevel |
1680 kOSKextLogGeneralFlag,
1681 "Can't translate physical address 0x%x of kext executable "
1682 "for device tree entry %s.",
1683 (int)kextFileInfo->executablePhysAddr,
1684 deviceTreeName->getCStringNoCopy());
1685 goto finish;
1686 }
1687
1688 executable = OSData::withBytesNoCopy(executableAddr,
1689 kextFileInfo->executableLength);
1690 if (!executable) {
1691 OSKextLog(this,
1692 kOSKextLogErrorLevel |
1693 kOSKextLogGeneralFlag,
1694 "Failed to create executable wrapper for device tree entry %s.",
1695 deviceTreeName->getCStringNoCopy());
1696 goto finish;
1697 }
1698
1699 /* A kext with an executable needs to retain the whole booterData
1700 * object to keep the executable in memory.
1701 */
1702 if (!setExecutable(executable, booterData)) {
1703 OSKextLog(this,
1704 kOSKextLogErrorLevel |
1705 kOSKextLogGeneralFlag,
1706 "Failed to set kext executable for device tree entry %s.",
1707 deviceTreeName->getCStringNoCopy());
1708 goto finish;
1709 }
1710 }
1711
1712 result = registerIdentifier();
1713
1714 finish:
1715 OSSafeRelease(parsedXML);
1716 OSSafeRelease(kextPath);
1717 OSSafeRelease(errorString);
1718 OSSafeRelease(executable);
1719
1720 return result;
1721 }
1722
1723 /*********************************************************************
1724 *********************************************************************/
1725 bool
1726 OSKext::registerIdentifier(void)
1727 {
1728 bool result = false;
1729 OSKext * existingKext = NULL; // do not release
1730 bool existingIsLoaded = false;
1731 bool existingIsPrelinked = false;
1732 OSKextVersion newVersion = -1;
1733 OSKextVersion existingVersion = -1;
1734 char newVersionCString[kOSKextVersionMaxLength];
1735 char existingVersionCString[kOSKextVersionMaxLength];
1736 OSData * newUUID = NULL; // must release
1737 OSData * existingUUID = NULL; // must release
1738
1739 IORecursiveLockLock(sKextLock);
1740
1741 /* Get the new kext's version for checks & log messages.
1742 */
1743 newVersion = getVersion();
1744 OSKextVersionGetString(newVersion, newVersionCString,
1745 kOSKextVersionMaxLength);
1746
1747 /* If we don't have an existing kext with this identifier,
1748 * just record the new kext and we're done!
1749 */
1750 existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID));
1751 if (!existingKext) {
1752 sKextsByID->setObject(bundleID, this);
1753 result = true;
1754 goto finish;
1755 }
1756
1757 /* Get the existing kext's version for checks & log messages.
1758 */
1759 existingVersion = existingKext->getVersion();
1760 OSKextVersionGetString(existingVersion,
1761 existingVersionCString, kOSKextVersionMaxLength);
1762
1763 existingIsLoaded = existingKext->isLoaded();
1764 existingIsPrelinked = existingKext->isPrelinked();
1765
1766 /* If we have a kext with this identifier that's already loaded/prelinked,
1767 * we can't use the new one, but let's be really thorough and check how
1768 * the two are related for a precise diagnostic log message.
1769 *
1770 * Note that user space can't find out about nonloaded prelinked kexts,
1771 * so in this case we log a message when new & existing are equivalent
1772 * at the step rather than warning level, because we are always going
1773 * be getting a copy of the kext in the user load request mkext.
1774 */
1775 if (existingIsLoaded || existingIsPrelinked) {
1776 bool sameVersion = (newVersion == existingVersion);
1777 bool sameExecutable = true; // assume true unless we have UUIDs
1778
1779 /* Only get the UUID if the existing kext is loaded. Doing so
1780 * might have to uncompress an mkext executable and we shouldn't
1781 * take that hit when neither kext is loaded.
1782 */
1783 newUUID = copyUUID();
1784 existingUUID = existingKext->copyUUID();
1785
1786 /* I'm entirely too paranoid about checking equivalence of executables,
1787 * but I remember nasty problems with it in the past.
1788 *
1789 * - If we have UUIDs for both kexts, compare them.
1790 * - If only one kext has a UUID, they're definitely different.
1791 */
1792 if (newUUID && existingUUID) {
1793 sameExecutable = newUUID->isEqualTo(existingUUID);
1794 } else if (newUUID || existingUUID) {
1795 sameExecutable = false;
1796 }
1797
1798 if (!newUUID && !existingUUID) {
1799
1800 /* If there are no UUIDs, we can't really tell that the executables
1801 * are *different* without a lot of work; the loaded kext's
1802 * unrelocated executable is no longer around (and we never had it
1803 * in-kernel for a prelinked kext). We certainly don't want to do
1804 * a whole fake link for the new kext just to compare, either.
1805 */
1806
1807 OSKextVersionGetString(version, newVersionCString,
1808 sizeof(newVersionCString));
1809 OSKextLog(this,
1810 kOSKextLogWarningLevel |
1811 kOSKextLogKextBookkeepingFlag,
1812 "Notice - new kext %s, v%s matches %s kext "
1813 "but can't determine if executables are the same (no UUIDs).",
1814 getIdentifierCString(),
1815 newVersionCString,
1816 (existingIsLoaded ? "loaded" : "prelinked"));
1817 }
1818
1819 if (sameVersion && sameExecutable) {
1820 OSKextLog(this,
1821 (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
1822 kOSKextLogKextBookkeepingFlag,
1823 "Refusing new kext %s, v%s: a %s copy is already present "
1824 "(same version and executable).",
1825 getIdentifierCString(), newVersionCString,
1826 (existingIsLoaded ? "loaded" : "prelinked"));
1827 } else {
1828 if (!sameVersion) {
1829 /* This condition is significant so log it under warnings.
1830 */
1831 OSKextLog(this,
1832 kOSKextLogWarningLevel |
1833 kOSKextLogKextBookkeepingFlag,
1834 "Refusing new kext %s, v%s: already have %s v%s.",
1835 getIdentifierCString(),
1836 newVersionCString,
1837 (existingIsLoaded ? "loaded" : "prelinked"),
1838 existingVersionCString);
1839 } else {
1840 /* This condition is significant so log it under warnings.
1841 */
1842 OSKextLog(this,
1843 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
1844 "Refusing new kext %s, v%s: a %s copy with a different "
1845 "executable UUID is already present.",
1846 getIdentifierCString(), newVersionCString,
1847 (existingIsLoaded ? "loaded" : "prelinked"));
1848 }
1849 }
1850 goto finish;
1851 } /* if (existingIsLoaded || existingIsPrelinked) */
1852
1853 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
1854 * user loads are happening or if we're still in early boot. User agents are
1855 * supposed to resolve dependencies topside and include only the exact
1856 * kexts needed; so we always accept the new kext (in fact we should never
1857 * see an older unloaded copy hanging around).
1858 */
1859 if (sUserLoadsActive) {
1860 sKextsByID->setObject(bundleID, this);
1861 result = true;
1862
1863 OSKextLog(this,
1864 kOSKextLogStepLevel |
1865 kOSKextLogKextBookkeepingFlag,
1866 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
1867 getIdentifierCString(),
1868 existingVersionCString,
1869 newVersionCString);
1870
1871 goto finish;
1872 }
1873
1874 /* During early boot, the kext with the highest version always wins out.
1875 * Prelinked kernels will never hit this, but mkexts and booter-read
1876 * kexts might have duplicates.
1877 */
1878 if (newVersion > existingVersion) {
1879 sKextsByID->setObject(bundleID, this);
1880 result = true;
1881
1882 OSKextLog(this,
1883 kOSKextLogStepLevel |
1884 kOSKextLogKextBookkeepingFlag,
1885 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
1886 existingVersionCString,
1887 getIdentifierCString(),
1888 newVersionCString);
1889
1890 } else {
1891 OSKextLog(this,
1892 kOSKextLogStepLevel |
1893 kOSKextLogKextBookkeepingFlag,
1894 "Kext %s is already registered with a higher/same version (v%s); "
1895 "dropping newly-added (v%s).",
1896 getIdentifierCString(),
1897 existingVersionCString,
1898 newVersionCString);
1899 }
1900
1901 /* result has been set appropriately by now. */
1902
1903 finish:
1904
1905 IORecursiveLockUnlock(sKextLock);
1906
1907 if (result) {
1908 OSKextLog(this,
1909 kOSKextLogStepLevel |
1910 kOSKextLogKextBookkeepingFlag,
1911 "Kext %s, v%s registered and available for loading.",
1912 getIdentifierCString(), newVersionCString);
1913 }
1914
1915 OSSafeRelease(newUUID);
1916 OSSafeRelease(existingUUID);
1917
1918 return result;
1919 }
1920
1921 /*********************************************************************
1922 * Does the bare minimum validation to look up a kext.
1923 * All other validation is done on the spot as needed.
1924 **********************************************************************/
1925 bool
1926 OSKext::setInfoDictionaryAndPath(
1927 OSDictionary * aDictionary,
1928 OSString * aPath)
1929 {
1930 bool result = false;
1931 OSString * bundleIDString = NULL; // do not release
1932 OSString * versionString = NULL; // do not release
1933 OSString * compatibleVersionString = NULL; // do not release
1934 const char * versionCString = NULL; // do not free
1935 const char * compatibleVersionCString = NULL; // do not free
1936 OSBoolean * scratchBool = NULL; // do not release
1937 OSDictionary * scratchDict = NULL; // do not release
1938
1939 if (infoDict) {
1940 panic("Attempt to set info dictionary on a kext "
1941 "that already has one (%s).",
1942 getIdentifierCString());
1943 }
1944
1945 if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
1946 goto finish;
1947 }
1948
1949 infoDict = aDictionary;
1950 infoDict->retain();
1951
1952 /* Check right away if the info dictionary has any log flags.
1953 */
1954 scratchBool = OSDynamicCast(OSBoolean,
1955 getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
1956 if (scratchBool == kOSBooleanTrue) {
1957 flags.loggingEnabled = 1;
1958 }
1959
1960 /* The very next thing to get is the bundle identifier. Unlike
1961 * in user space, a kext with no bundle identifier gets axed
1962 * immediately.
1963 */
1964 bundleIDString = OSDynamicCast(OSString,
1965 getPropertyForHostArch(kCFBundleIdentifierKey));
1966 if (!bundleIDString) {
1967 OSKextLog(this,
1968 kOSKextLogErrorLevel |
1969 kOSKextLogValidationFlag,
1970 "CFBundleIdentifier missing/invalid type in kext %s.",
1971 aPath ? aPath->getCStringNoCopy() : "(unknown)");
1972 goto finish;
1973 }
1974 bundleID = OSSymbol::withString(bundleIDString);
1975 if (!bundleID) {
1976 OSKextLog(this,
1977 kOSKextLogErrorLevel |
1978 kOSKextLogValidationFlag,
1979 "Can't copy bundle identifier as symbol for kext %s.",
1980 bundleIDString->getCStringNoCopy());
1981 goto finish;
1982 }
1983
1984 /* Save the path if we got one (it should always be available but it's
1985 * just something nice to have for bookkeeping).
1986 */
1987 if (aPath) {
1988 path = aPath;
1989 path->retain();
1990 }
1991
1992 /*****
1993 * Minimal validation to initialize. We'll do other validation on the spot.
1994 */
1995 if (bundleID->getLength() >= KMOD_MAX_NAME) {
1996 OSKextLog(this,
1997 kOSKextLogErrorLevel |
1998 kOSKextLogValidationFlag,
1999 "Kext %s error - CFBundleIdentifier over max length %d.",
2000 getIdentifierCString(), KMOD_MAX_NAME - 1);
2001 goto finish;
2002 }
2003
2004 version = compatibleVersion = -1;
2005
2006 versionString = OSDynamicCast(OSString,
2007 getPropertyForHostArch(kCFBundleVersionKey));
2008 if (!versionString) {
2009 OSKextLog(this,
2010 kOSKextLogErrorLevel |
2011 kOSKextLogValidationFlag,
2012 "Kext %s error - CFBundleVersion missing/invalid type.",
2013 getIdentifierCString());
2014 goto finish;
2015 }
2016 versionCString = versionString->getCStringNoCopy();
2017 version = OSKextParseVersionString(versionCString);
2018 if (version < 0) {
2019 OSKextLog(this,
2020 kOSKextLogErrorLevel |
2021 kOSKextLogValidationFlag,
2022 "Kext %s error - CFBundleVersion bad value '%s'.",
2023 getIdentifierCString(), versionCString);
2024 goto finish;
2025 }
2026
2027 compatibleVersion = -1; // set to illegal value for kexts that don't have
2028
2029 compatibleVersionString = OSDynamicCast(OSString,
2030 getPropertyForHostArch(kOSBundleCompatibleVersionKey));
2031 if (compatibleVersionString) {
2032 compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
2033 compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
2034 if (compatibleVersion < 0) {
2035 OSKextLog(this,
2036 kOSKextLogErrorLevel |
2037 kOSKextLogValidationFlag,
2038 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2039 getIdentifierCString(), compatibleVersionCString);
2040 goto finish;
2041 }
2042
2043 if (compatibleVersion > version) {
2044 OSKextLog(this,
2045 kOSKextLogErrorLevel |
2046 kOSKextLogValidationFlag,
2047 "Kext %s error - %s %s > %s %s (must be <=).",
2048 getIdentifierCString(),
2049 kOSBundleCompatibleVersionKey, compatibleVersionCString,
2050 kCFBundleVersionKey, versionCString);
2051 goto finish;
2052 }
2053 }
2054
2055 /* Check to see if this kext is in exclude list */
2056 if ( isInExcludeList() ) {
2057 OSKextLog(this,
2058 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2059 "Kext %s is in exclude list, not loadable",
2060 getIdentifierCString());
2061 goto finish;
2062 }
2063
2064 /* Set flags for later use if the infoDict gets flushed. We only
2065 * check for true values, not false ones(!)
2066 */
2067 scratchBool = OSDynamicCast(OSBoolean,
2068 getPropertyForHostArch(kOSBundleIsInterfaceKey));
2069 if (scratchBool == kOSBooleanTrue) {
2070 flags.interface = 1;
2071 }
2072
2073 scratchBool = OSDynamicCast(OSBoolean,
2074 getPropertyForHostArch(kOSKernelResourceKey));
2075 if (scratchBool == kOSBooleanTrue) {
2076 flags.kernelComponent = 1;
2077 flags.interface = 1; // xxx - hm. the kernel itself isn't an interface...
2078 flags.started = 1;
2079
2080 /* A kernel component has one implicit dependency on the kernel.
2081 */
2082 flags.hasAllDependencies = 1;
2083 }
2084
2085 /* Make sure common string values in personalities are uniqued to OSSymbols.
2086 */
2087 scratchDict = OSDynamicCast(OSDictionary,
2088 getPropertyForHostArch(kIOKitPersonalitiesKey));
2089 if (scratchDict) {
2090 uniquePersonalityProperties(scratchDict);
2091 }
2092
2093 result = true;
2094
2095 finish:
2096
2097 return result;
2098 }
2099
2100 /*********************************************************************
2101 * Not used for prelinked kernel boot as there is no unrelocated
2102 * executable.
2103 *********************************************************************/
2104 bool
2105 OSKext::setExecutable(
2106 OSData * anExecutable,
2107 OSData * externalData,
2108 bool externalDataIsMkext)
2109 {
2110 bool result = false;
2111 const char * executableKey = NULL; // do not free
2112
2113 if (!anExecutable) {
2114 infoDict->removeObject(_kOSKextExecutableKey);
2115 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
2116 infoDict->removeObject(_kOSKextExecutableExternalDataKey);
2117 result = true;
2118 goto finish;
2119 }
2120
2121 if (infoDict->getObject(_kOSKextExecutableKey) ||
2122 infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
2123
2124 panic("Attempt to set an executable on a kext "
2125 "that already has one (%s).",
2126 getIdentifierCString());
2127 goto finish;
2128 }
2129
2130 if (externalDataIsMkext) {
2131 executableKey = _kOSKextMkextExecutableReferenceKey;
2132 } else {
2133 executableKey = _kOSKextExecutableKey;
2134 }
2135
2136 if (anExecutable) {
2137 infoDict->setObject(executableKey, anExecutable);
2138 if (externalData) {
2139 infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
2140 }
2141 }
2142
2143 result = true;
2144
2145 finish:
2146 return result;
2147 }
2148
2149 /*********************************************************************
2150 *********************************************************************/
2151 static void
2152 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
2153 {
2154 OSString * stringValue = NULL; // do not release
2155 const OSSymbol * symbolValue = NULL; // must release
2156
2157 stringValue = OSDynamicCast(OSString, dict->getObject(key));
2158 if (!stringValue) {
2159 goto finish;
2160 }
2161
2162 symbolValue = OSSymbol::withString(stringValue);
2163 if (!symbolValue) {
2164 goto finish;
2165 }
2166
2167 dict->setObject(key, symbolValue);
2168
2169 finish:
2170 if (symbolValue) symbolValue->release();
2171
2172 return;
2173 }
2174
2175 /*********************************************************************
2176 *********************************************************************/
2177 static void
2178 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
2179 {
2180 OSString * stringValue = NULL; // do not release
2181 const OSSymbol * symbolValue = NULL; // must release
2182
2183 stringValue = OSDynamicCast(OSString, dict->getObject(key));
2184 if (!stringValue) {
2185 goto finish;
2186 }
2187
2188 symbolValue = OSSymbol::withString(stringValue);
2189 if (!symbolValue) {
2190 goto finish;
2191 }
2192
2193 dict->setObject(key, symbolValue);
2194
2195 finish:
2196 if (symbolValue) symbolValue->release();
2197
2198 return;
2199 }
2200
2201 /*********************************************************************
2202 * Replace common personality property values with uniqued instances
2203 * to save on wired memory.
2204 *********************************************************************/
2205 /* static */
2206 void
2207 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
2208 {
2209 /* Properties every personality has.
2210 */
2211 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
2212 uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
2213 uniqueStringPlistProperty(personalityDict, gIOClassKey);
2214
2215 /* Other commonly used properties.
2216 */
2217 uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
2218 uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
2219 uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
2220
2221 uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
2222 uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
2223 uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
2224 uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
2225 uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
2226 uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
2227 uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
2228 uniqueStringPlistProperty(personalityDict, "Vendor");
2229 uniqueStringPlistProperty(personalityDict, "Vendor Identification");
2230 uniqueStringPlistProperty(personalityDict, "Vendor Name");
2231 uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
2232 uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
2233 uniqueStringPlistProperty(personalityDict, "idProduct");
2234
2235 return;
2236 }
2237
2238 /*********************************************************************
2239 *********************************************************************/
2240 void
2241 OSKext::free(void)
2242 {
2243 if (isLoaded()) {
2244 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2245 }
2246
2247 OSSafeRelease(infoDict);
2248 OSSafeRelease(bundleID);
2249 OSSafeRelease(path);
2250 OSSafeRelease(executableRelPath);
2251 OSSafeRelease(dependencies);
2252 OSSafeRelease(linkedExecutable);
2253 OSSafeRelease(metaClasses);
2254 OSSafeRelease(interfaceUUID);
2255
2256 if (isInterface() && kmod_info) {
2257 kfree(kmod_info, sizeof(kmod_info_t));
2258 }
2259
2260 super::free();
2261 return;
2262 }
2263
2264 #if PRAGMA_MARK
2265 #pragma mark Mkext files
2266 #endif
2267 /*********************************************************************
2268 *********************************************************************/
2269 OSReturn
2270 OSKext::readMkextArchive(OSData * mkextData,
2271 uint32_t * checksumPtr)
2272 {
2273 OSReturn result = kOSKextReturnBadData;
2274 uint32_t mkextLength = 0;
2275 mkext_header * mkextHeader = 0; // do not free
2276 uint32_t mkextVersion = 0;
2277
2278 /* Note default return of kOSKextReturnBadData above.
2279 */
2280 mkextLength = mkextData->getLength();
2281 if (mkextLength < sizeof(mkext_basic_header)) {
2282 OSKextLog(/* kext */ NULL,
2283 kOSKextLogErrorLevel |
2284 kOSKextLogArchiveFlag,
2285 "Mkext archive too small to be valid.");
2286 goto finish;
2287 }
2288
2289 mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
2290
2291 if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
2292 MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
2293 OSKextLog(/* kext */ NULL,
2294 kOSKextLogErrorLevel |
2295 kOSKextLogArchiveFlag,
2296 "Mkext archive has invalid magic or signature.");
2297 goto finish;
2298 }
2299
2300 if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
2301 OSKextLog(/* kext */ NULL,
2302 kOSKextLogErrorLevel |
2303 kOSKextLogArchiveFlag,
2304 "Mkext archive recorded length doesn't match actual file length.");
2305 goto finish;
2306 }
2307
2308 mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2309
2310 if (mkextVersion == MKEXT_VERS_2) {
2311 result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
2312 } else if (mkextVersion == MKEXT_VERS_1) {
2313 result = OSKext::readMkext1Archive(mkextData, checksumPtr);
2314 } else {
2315 OSKextLog(/* kext */ NULL,
2316 kOSKextLogErrorLevel |
2317 kOSKextLogArchiveFlag,
2318 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
2319 result = kOSKextReturnUnsupported;
2320 }
2321
2322 finish:
2323 return result;
2324 }
2325
2326 /*********************************************************************
2327 * Assumes magic, signature, version, length have been checked.
2328 *
2329 * Doesn't do as much bounds-checking as it should, but we're dropping
2330 * mkext1 support from the kernel for SnowLeopard soon.
2331 *
2332 * Should keep track of all kexts created so far, and if we hit a
2333 * fatal error halfway through, remove those kexts. If we've dropped
2334 * an older version that had already been read, whoops! Might want to
2335 * add a level of buffering?
2336 *********************************************************************/
2337 /* static */
2338 OSReturn
2339 OSKext::readMkext1Archive(
2340 OSData * mkextData,
2341 uint32_t * checksumPtr)
2342 {
2343 OSReturn result = kOSReturnError;
2344 uint32_t mkextLength;
2345 mkext1_header * mkextHeader = 0; // do not free
2346 void * mkextEnd = 0; // do not free
2347 uint32_t mkextVersion;
2348 uint8_t * crc_address = 0;
2349 uint32_t checksum;
2350 uint32_t numKexts = 0;
2351
2352 OSData * infoDictDataObject = NULL; // must release
2353 OSObject * parsedXML = NULL; // must release
2354 OSDictionary * infoDict = NULL; // do not release
2355 OSString * errorString = NULL; // must release
2356 OSData * mkextExecutableInfo = NULL; // must release
2357 OSKext * theKext = NULL; // must release
2358
2359 mkextLength = mkextData->getLength();
2360 mkextHeader = (mkext1_header *)mkextData->getBytesNoCopy();
2361 mkextEnd = (char *)mkextHeader + mkextLength;
2362 mkextVersion = OSSwapBigToHostInt32(mkextHeader->version);
2363
2364 crc_address = (u_int8_t *)&mkextHeader->version;
2365 checksum = mkext_adler32(crc_address,
2366 (uintptr_t)mkextHeader +
2367 OSSwapBigToHostInt32(mkextHeader->length) - (uintptr_t)crc_address);
2368
2369 if (OSSwapBigToHostInt32(mkextHeader->adler32) != checksum) {
2370 OSKextLog(/* kext */ NULL,
2371 kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2372 "Kext archive has a bad checksum.");
2373 result = kOSKextReturnBadData;
2374 goto finish;
2375 }
2376
2377 if (checksumPtr) {
2378 *checksumPtr = checksum;
2379 }
2380
2381 /* Check that the CPU type & subtype match that of the running kernel. */
2382 if (OSSwapBigToHostInt32(mkextHeader->cputype) != (UInt32)CPU_TYPE_ANY) {
2383 if ((UInt32)_mh_execute_header.cputype !=
2384 OSSwapBigToHostInt32(mkextHeader->cputype)) {
2385
2386 OSKextLog(/* kext */ NULL,
2387 kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2388 "Kext archive doesn't contain software "
2389 "for this computer's CPU type.");
2390 result = kOSKextReturnArchNotFound;
2391 goto finish;
2392 }
2393 }
2394
2395 numKexts = OSSwapBigToHostInt32(mkextHeader->numkexts);
2396
2397 for (uint32_t i = 0; i < numKexts; i++) {
2398
2399 OSSafeReleaseNULL(infoDictDataObject);
2400 OSSafeReleaseNULL(infoDict);
2401 OSSafeReleaseNULL(mkextExecutableInfo);
2402 OSSafeReleaseNULL(errorString);
2403 OSSafeReleaseNULL(theKext);
2404
2405 mkext_kext * kextEntry = &mkextHeader->kext[i];
2406 mkext_file * infoDictPtr = &kextEntry->plist;
2407 mkext_file * executablePtr = &kextEntry->module;
2408 if (kextEntry >= mkextEnd) {
2409 OSKextLog(/* kext */ NULL,
2410 kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2411 "Mkext file overrun.");
2412 result = kOSKextReturnBadData;
2413 goto finish;
2414 }
2415
2416 /* Note that we're pretty tolerant of errors in individual entries.
2417 * As long as we can keep processing, we do.
2418 */
2419 infoDictDataObject = OSKext::extractMkext1Entry(
2420 mkextHeader, infoDictPtr);
2421 if (!infoDictDataObject) {
2422 OSKextLog(/* kext */ NULL,
2423 kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2424 "Can't uncompress info dictionary "
2425 "from mkext archive entry %d.", i);
2426 continue;
2427 }
2428
2429 parsedXML = OSUnserializeXML(
2430 (const char *)infoDictDataObject->getBytesNoCopy(),
2431 &errorString);
2432 if (parsedXML) {
2433 infoDict = OSDynamicCast(OSDictionary, parsedXML);
2434 }
2435 if (!infoDict) {
2436 const char * errorCString = "(unknown error)";
2437
2438 if (errorString && errorString->getCStringNoCopy()) {
2439 errorCString = errorString->getCStringNoCopy();
2440 } else if (parsedXML) {
2441 errorCString = "not a dictionary";
2442 }
2443 OSKextLog(/* kext */ NULL,
2444 kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2445 "Error: Can't read XML property list "
2446 "for mkext archive entry %d: %s.", i, errorCString);
2447 continue;
2448 }
2449
2450 theKext = new OSKext;
2451 if (!theKext) {
2452 OSKextLog(/* kext */ NULL,
2453 kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2454 "Kext allocation failure.");
2455 continue;
2456 }
2457
2458 /*****
2459 * Prepare an entry to hold the mkext entry info for the
2460 * compressed binary module, if there is one. If all four fields
2461 * of the module entry are zero, there isn't one.
2462 */
2463 if ((OSSwapBigToHostInt32(executablePtr->offset) ||
2464 OSSwapBigToHostInt32(executablePtr->compsize) ||
2465 OSSwapBigToHostInt32(executablePtr->realsize) ||
2466 OSSwapBigToHostInt32(executablePtr->modifiedsecs))) {
2467
2468 MkextEntryRef entryRef;
2469
2470 mkextExecutableInfo = OSData::withCapacity(sizeof(entryRef));
2471 if (!mkextExecutableInfo) {
2472 panic("Error: Couldn't allocate data object "
2473 "for mkext archive entry %d.\n", i);
2474 }
2475
2476 entryRef.mkext = (mkext_basic_header *)mkextHeader;
2477 entryRef.fileinfo = (uint8_t *)executablePtr;
2478 if (!mkextExecutableInfo->appendBytes(&entryRef,
2479 sizeof(entryRef))) {
2480
2481 OSKextLog(/* kext */ NULL,
2482 kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2483 "Couldn't record executable info "
2484 "for mkext archive entry %d.", i);
2485 // we might hit a load error later but oh well
2486 // xxx - should probably remove theKext
2487 continue;
2488 }
2489
2490 }
2491
2492 /* Init can fail because of a data/runtime error, or because the
2493 * kext is a dup. Either way, we don't care here.
2494 */
2495 if (!theKext->initWithMkext1Info(infoDict, mkextExecutableInfo,
2496 mkextData)) {
2497
2498 // theKext is released at the top of the loop or in the finish block
2499 continue;
2500 }
2501
2502 /* If we got even one kext out of the mkext archive,
2503 * we have successfully read the archive, in that we
2504 * have data references into its mapped memory.
2505 */
2506 result = kOSReturnSuccess;
2507 }
2508
2509 finish:
2510
2511 OSSafeRelease(infoDictDataObject);
2512 OSSafeRelease(parsedXML);
2513 OSSafeRelease(errorString);
2514 OSSafeRelease(mkextExecutableInfo);
2515 OSSafeRelease(theKext);
2516
2517 return result;
2518 }
2519
2520 /*********************************************************************
2521 *********************************************************************/
2522 bool
2523 OSKext::initWithMkext1Info(
2524 OSDictionary * anInfoDict,
2525 OSData * executableWrapper,
2526 OSData * mkextData)
2527 {
2528 bool result = false;
2529
2530 // mkext1 doesn't allow for path (might stuff in info dict)
2531 if (!setInfoDictionaryAndPath(anInfoDict, /* path */ NULL)) {
2532 goto finish;
2533 }
2534
2535 if (!registerIdentifier()) {
2536 goto finish;
2537 }
2538
2539 if (!setExecutable(executableWrapper, mkextData, true)) {
2540 goto finish;
2541 }
2542
2543 result = true;
2544
2545 finish:
2546
2547 /* If we can't init, remove the kext from the lookup dictionary.
2548 * This is safe to call in init because there's an implicit retain.
2549 */
2550 if (!result) {
2551 OSKext::removeKext(this, /* removePersonalities? */ false);
2552 }
2553
2554 return result;
2555 }
2556
2557 /*********************************************************************
2558 * xxx - this should take the input data length
2559 *********************************************************************/
2560 /* static */
2561 OSData *
2562 OSKext::extractMkext1Entry(
2563 const void * mkextFileBase,
2564 const void * entry)
2565 {
2566 OSData * result = NULL;
2567 OSData * uncompressedData = NULL; // release on error
2568 const char * errmsg = NULL;
2569
2570 mkext_file * fileinfo;
2571 uint8_t * uncompressedDataBuffer = 0; // do not free (panic on alloc. fail)
2572 size_t uncompressed_size = 0;
2573 kern_return_t kern_result;
2574
2575 fileinfo = (mkext_file *)entry;
2576
2577 size_t offset = OSSwapBigToHostInt32(fileinfo->offset);
2578 size_t compressed_size = OSSwapBigToHostInt32(fileinfo->compsize);
2579 size_t expected_size = OSSwapBigToHostInt32(fileinfo->realsize);
2580
2581 // Add 1 for '\0' to terminate XML string (for plists)
2582 // (we really should have the archive format include that).
2583 size_t alloc_size = expected_size + 1;
2584 time_t modifiedsecs = OSSwapBigToHostInt32(fileinfo->modifiedsecs);
2585
2586 /* If these four fields are zero there's no file, but it's up to
2587 * the calling context to decide if that's an error.
2588 */
2589 if (offset == 0 && compressed_size == 0 &&
2590 expected_size == 0 && modifiedsecs == 0) {
2591 goto finish;
2592 }
2593
2594 kern_result = kmem_alloc(kernel_map,
2595 (vm_offset_t *)&uncompressedDataBuffer,
2596 alloc_size);
2597 if (kern_result != KERN_SUCCESS) {
2598 panic(ALLOC_FAIL);
2599 goto finish;
2600 }
2601
2602 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer,
2603 alloc_size);
2604 if (uncompressedData == NULL) {
2605 /* No need to free uncompressedDataBuffer here, either. */
2606 panic(ALLOC_FAIL);
2607 goto finish;
2608 }
2609 uncompressedData->setDeallocFunction(&osdata_kmem_free);
2610
2611 /* Do the decompression if necessary. Note that even if the file isn't
2612 * compressed, we want to make a copy so that we don't have the tie to
2613 * the larger mkext file buffer any more.
2614 * xxx - need to detect decompression overflow too
2615 */
2616 if (compressed_size != 0) {
2617 errmsg = "OSKext::uncompressMkext - "
2618 "uncompressed file shorter than expected";
2619 uncompressed_size = decompress_lzss(uncompressedDataBuffer,
2620 expected_size,
2621 ((uint8_t *)mkextFileBase) + offset,
2622 compressed_size);
2623 if (uncompressed_size != expected_size) {
2624 goto finish;
2625 }
2626 } else {
2627 memcpy(uncompressedDataBuffer,
2628 ((uint8_t *)mkextFileBase) + offset,
2629 expected_size);
2630 }
2631
2632 // Add a terminating nul character in case the data is XML.
2633 // (we really should have the archive format include that).
2634 uncompressedDataBuffer[expected_size] = '\0';
2635
2636 result = uncompressedData;
2637 errmsg = NULL;
2638
2639 finish:
2640 if (!result) {
2641 OSKextLog(/* kext */ NULL,
2642 kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
2643 "%s", errmsg);
2644
2645 if (uncompressedData) {
2646 uncompressedData->release();
2647 }
2648 }
2649 return result;
2650 }
2651
2652 /*********************************************************************
2653 * Assumes magic, signature, version, length have been checked.
2654 * xxx - need to add further bounds checking for each file entry
2655 *
2656 * Should keep track of all kexts created so far, and if we hit a
2657 * fatal error halfway through, remove those kexts. If we've dropped
2658 * an older version that had already been read, whoops! Might want to
2659 * add a level of buffering?
2660 *********************************************************************/
2661 /* static */
2662 OSReturn
2663 OSKext::readMkext2Archive(
2664 OSData * mkextData,
2665 OSDictionary ** mkextPlistOut,
2666 uint32_t * checksumPtr)
2667 {
2668 OSReturn result = kOSReturnError;
2669 uint32_t mkextLength;
2670 mkext2_header * mkextHeader = NULL; // do not free
2671 void * mkextEnd = NULL; // do not free
2672 uint32_t mkextVersion;
2673 uint8_t * crc_address = NULL;
2674 uint32_t checksum;
2675 uint32_t mkextPlistOffset;
2676 uint32_t mkextPlistCompressedSize;
2677 char * mkextPlistEnd = NULL; // do not free
2678 uint32_t mkextPlistFullSize;
2679 OSString * errorString = NULL; // must release
2680 OSData * mkextPlistUncompressedData = NULL; // must release
2681 const char * mkextPlistDataBuffer = NULL; // do not free
2682 OSObject * parsedXML = NULL; // must release
2683 OSDictionary * mkextPlist = NULL; // do not release
2684 OSArray * mkextInfoDictArray = NULL; // do not release
2685 uint32_t count, i;
2686
2687 mkextLength = mkextData->getLength();
2688 mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
2689 mkextEnd = (char *)mkextHeader + mkextLength;
2690 mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2691
2692 crc_address = (u_int8_t *)&mkextHeader->version;
2693 checksum = mkext_adler32(crc_address,
2694 (uintptr_t)mkextHeader +
2695 MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address);
2696
2697 if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
2698 OSKextLog(/* kext */ NULL,
2699 kOSKextLogErrorLevel |
2700 kOSKextLogArchiveFlag,
2701 "Mkext archive has bad checksum.");
2702 result = kOSKextReturnBadData;
2703 goto finish;
2704 }
2705
2706 if (checksumPtr) {
2707 *checksumPtr = checksum;
2708 }
2709
2710 /* Check that the CPU type & subtype match that of the running kernel. */
2711 if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
2712 OSKextLog(/* kext */ NULL,
2713 kOSKextLogErrorLevel |
2714 kOSKextLogArchiveFlag,
2715 "Mkext archive must have a specific CPU type.");
2716 result = kOSKextReturnBadData;
2717 goto finish;
2718 } else {
2719 if ((UInt32)_mh_execute_header.cputype !=
2720 MKEXT_GET_CPUTYPE(mkextHeader)) {
2721
2722 OSKextLog(/* kext */ NULL,
2723 kOSKextLogErrorLevel |
2724 kOSKextLogArchiveFlag,
2725 "Mkext archive does not match the running kernel's CPU type.");
2726 result = kOSKextReturnArchNotFound;
2727 goto finish;
2728 }
2729 }
2730
2731 mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
2732 mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
2733 mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
2734 mkextPlistCompressedSize;
2735 if (mkextPlistEnd > mkextEnd) {
2736 OSKextLog(/* kext */ NULL,
2737 kOSKextLogErrorLevel |
2738 kOSKextLogArchiveFlag,
2739 "Mkext archive file overrun.");
2740 result = kOSKextReturnBadData;
2741 }
2742
2743 mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
2744 if (mkextPlistCompressedSize) {
2745 mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
2746 (UInt8 *)mkextHeader + mkextPlistOffset,
2747 "plist",
2748 mkextPlistCompressedSize, mkextPlistFullSize);
2749 if (!mkextPlistUncompressedData) {
2750 goto finish;
2751 }
2752 mkextPlistDataBuffer = (const char *)
2753 mkextPlistUncompressedData->getBytesNoCopy();
2754 } else {
2755 mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
2756 }
2757
2758 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2759 */
2760 parsedXML = OSUnserializeXML(mkextPlistDataBuffer, &errorString);
2761 if (parsedXML) {
2762 mkextPlist = OSDynamicCast(OSDictionary, parsedXML);
2763 }
2764 if (!mkextPlist) {
2765 const char * errorCString = "(unknown error)";
2766
2767 if (errorString && errorString->getCStringNoCopy()) {
2768 errorCString = errorString->getCStringNoCopy();
2769 } else if (parsedXML) {
2770 errorCString = "not a dictionary";
2771 }
2772 OSKextLog(/* kext */ NULL,
2773 kOSKextLogErrorLevel |
2774 kOSKextLogArchiveFlag,
2775 "Error unserializing mkext plist: %s.", errorCString);
2776 goto finish;
2777 }
2778
2779 /* If the caller needs the plist, hand it back and retain it.
2780 * (This function releases it at the end.)
2781 */
2782 if (mkextPlistOut) {
2783 *mkextPlistOut = mkextPlist;
2784 (*mkextPlistOut)->retain();
2785 }
2786
2787 mkextInfoDictArray = OSDynamicCast(OSArray,
2788 mkextPlist->getObject(kMKEXTInfoDictionariesKey));
2789 if (!mkextInfoDictArray) {
2790 OSKextLog(/* kext */ NULL,
2791 kOSKextLogErrorLevel |
2792 kOSKextLogArchiveFlag,
2793 "Mkext archive contains no kext info dictionaries.");
2794 goto finish;
2795 }
2796
2797 count = mkextInfoDictArray->getCount();
2798 for (i = 0; i < count; i++) {
2799 OSDictionary * infoDict;
2800
2801
2802 infoDict = OSDynamicCast(OSDictionary,
2803 mkextInfoDictArray->getObject(i));
2804
2805 /* Create the kext for the entry, then release it, because the
2806 * kext system keeps them around until explicitly removed.
2807 * Any creation/registration failures are already logged for us.
2808 */
2809 OSKext * newKext = OSKext::withMkext2Info(infoDict, mkextData);
2810 OSSafeRelease(newKext);
2811 }
2812
2813 /* Even if we didn't keep any kexts from the mkext, we may have a load
2814 * request to process, so we are successful (no errors occurred).
2815 */
2816 result = kOSReturnSuccess;
2817
2818 finish:
2819
2820 OSSafeRelease(parsedXML);
2821 OSSafeRelease(mkextPlistUncompressedData);
2822 OSSafeRelease(errorString);
2823
2824 return result;
2825 }
2826
2827 /*********************************************************************
2828 *********************************************************************/
2829 /* static */
2830 OSKext *
2831 OSKext::withMkext2Info(
2832 OSDictionary * anInfoDict,
2833 OSData * mkextData)
2834 {
2835 OSKext * newKext = new OSKext;
2836
2837 if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
2838 newKext->release();
2839 return NULL;
2840 }
2841
2842 return newKext;
2843 }
2844
2845 /*********************************************************************
2846 *********************************************************************/
2847 bool
2848 OSKext::initWithMkext2Info(
2849 OSDictionary * anInfoDict,
2850 OSData * mkextData)
2851 {
2852 bool result = false;
2853 OSString * kextPath = NULL; // do not release
2854 OSNumber * executableOffsetNum = NULL; // do not release
2855 OSCollectionIterator * iterator = NULL; // must release
2856 OSData * executable = NULL; // must release
2857
2858 if (!super::init()) {
2859 goto finish;
2860 }
2861
2862 /* Get the path. Don't look for an arch-specific path property.
2863 */
2864 kextPath = OSDynamicCast(OSString,
2865 anInfoDict->getObject(kMKEXTBundlePathKey));
2866
2867 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2868 goto finish;
2869 }
2870
2871 /* If we have a path to the executable, save it.
2872 */
2873 executableRelPath = OSDynamicCast(OSString,
2874 anInfoDict->getObject(kMKEXTExecutableRelativePathKey));
2875 if (executableRelPath) {
2876 executableRelPath->retain();
2877 }
2878
2879 /* Don't need the paths to be in the info dictionary any more.
2880 */
2881 anInfoDict->removeObject(kMKEXTBundlePathKey);
2882 anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
2883
2884 executableOffsetNum = OSDynamicCast(OSNumber,
2885 infoDict->getObject(kMKEXTExecutableKey));
2886 if (executableOffsetNum) {
2887 executable = createMkext2FileEntry(mkextData,
2888 executableOffsetNum, "executable");
2889 infoDict->removeObject(kMKEXTExecutableKey);
2890 if (!executable) {
2891 goto finish;
2892 }
2893 if (!setExecutable(executable, mkextData, true)) {
2894 goto finish;
2895 }
2896 }
2897
2898 result = registerIdentifier();
2899
2900 finish:
2901
2902 OSSafeRelease(executable);
2903 OSSafeRelease(iterator);
2904 return result;
2905 }
2906
2907 /*********************************************************************
2908 *********************************************************************/
2909 OSData *
2910 OSKext::createMkext2FileEntry(
2911 OSData * mkextData,
2912 OSNumber * offsetNum,
2913 const char * name)
2914 {
2915 OSData * result = NULL;
2916 MkextEntryRef entryRef;
2917 uint8_t * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
2918 uint32_t entryOffset = offsetNum->unsigned32BitValue();
2919
2920 result = OSData::withCapacity(sizeof(entryRef));
2921 if (!result) {
2922 goto finish;
2923 }
2924
2925 entryRef.mkext = (mkext_basic_header *)mkextBuffer;
2926 entryRef.fileinfo = mkextBuffer + entryOffset;
2927 if (!result->appendBytes(&entryRef, sizeof(entryRef))) {
2928 OSSafeReleaseNULL(result);
2929 goto finish;
2930 }
2931
2932 finish:
2933 if (!result) {
2934 OSKextLog(this,
2935 kOSKextLogErrorLevel |
2936 kOSKextLogArchiveFlag,
2937 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2938 name, getIdentifierCString());
2939 }
2940 return result;
2941 }
2942
2943 /*********************************************************************
2944 *********************************************************************/
2945 extern "C" {
2946 static void * z_alloc(void *, u_int items, u_int size);
2947 static void z_free(void *, void *ptr);
2948
2949 typedef struct z_mem {
2950 uint32_t alloc_size;
2951 uint8_t data[0];
2952 } z_mem;
2953
2954 /*
2955 * Space allocation and freeing routines for use by zlib routines.
2956 */
2957 void *
2958 z_alloc(void * notused __unused, u_int num_items, u_int size)
2959 {
2960 void * result = NULL;
2961 z_mem * zmem = NULL;
2962 uint32_t total = num_items * size;
2963 uint32_t allocSize = total + sizeof(zmem);
2964
2965 zmem = (z_mem *)kalloc(allocSize);
2966 if (!zmem) {
2967 goto finish;
2968 }
2969 zmem->alloc_size = allocSize;
2970 result = (void *)&(zmem->data);
2971 finish:
2972 return result;
2973 }
2974
2975 void
2976 z_free(void * notused __unused, void * ptr)
2977 {
2978 uint32_t * skipper = (uint32_t *)ptr - 1;
2979 z_mem * zmem = (z_mem *)skipper;
2980 kfree((void *)zmem, zmem->alloc_size);
2981 return;
2982 }
2983 };
2984
2985 OSData *
2986 OSKext::extractMkext2FileData(
2987 UInt8 * data,
2988 const char * name,
2989 uint32_t compressedSize,
2990 uint32_t fullSize)
2991 {
2992 OSData * result = NULL;
2993
2994 OSData * uncompressedData = NULL; // release on error
2995
2996 uint8_t * uncompressedDataBuffer = 0; // do not free
2997 unsigned long uncompressedSize;
2998 z_stream zstream;
2999 bool zstream_inited = false;
3000 int zlib_result;
3001
3002 /* If the file isn't compressed, we want to make a copy
3003 * so that we don't have the tie to the larger mkext file buffer any more.
3004 */
3005 if (!compressedSize) {
3006 uncompressedData = OSData::withBytes(data, fullSize);
3007 // xxx - no check for failure?
3008 result = uncompressedData;
3009 goto finish;
3010 }
3011
3012 if (KERN_SUCCESS != kmem_alloc(kernel_map,
3013 (vm_offset_t*)&uncompressedDataBuffer, fullSize)) {
3014
3015 /* How's this for cheesy? The kernel is only asked to extract
3016 * kext plists so we tailor the log messages.
3017 */
3018 if (isKernel()) {
3019 OSKextLog(this,
3020 kOSKextLogErrorLevel |
3021 kOSKextLogArchiveFlag,
3022 "Allocation failure extracting %s from mkext.", name);
3023 } else {
3024 OSKextLog(this,
3025 kOSKextLogErrorLevel |
3026 kOSKextLogArchiveFlag,
3027 "Allocation failure extracting %s from mkext for kext %s.",
3028 name, getIdentifierCString());
3029 }
3030
3031 goto finish;
3032 }
3033 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
3034 if (!uncompressedData) {
3035 if (isKernel()) {
3036 OSKextLog(this,
3037 kOSKextLogErrorLevel |
3038 kOSKextLogArchiveFlag,
3039 "Allocation failure extracting %s from mkext.", name);
3040 } else {
3041 OSKextLog(this,
3042 kOSKextLogErrorLevel |
3043 kOSKextLogArchiveFlag,
3044 "Allocation failure extracting %s from mkext for kext %s.",
3045 name, getIdentifierCString());
3046 }
3047 goto finish;
3048 }
3049 uncompressedData->setDeallocFunction(&osdata_kmem_free);
3050
3051 if (isKernel()) {
3052 OSKextLog(this,
3053 kOSKextLogDetailLevel |
3054 kOSKextLogArchiveFlag,
3055 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
3056 name, compressedSize, fullSize);
3057 } else {
3058 OSKextLog(this,
3059 kOSKextLogDetailLevel |
3060 kOSKextLogArchiveFlag,
3061 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
3062 getIdentifierCString(), name, compressedSize, fullSize);
3063 }
3064
3065 bzero(&zstream, sizeof(zstream));
3066 zstream.next_in = (UInt8 *)data;
3067 zstream.avail_in = compressedSize;
3068
3069 zstream.next_out = uncompressedDataBuffer;
3070 zstream.avail_out = fullSize;
3071
3072 zstream.zalloc = z_alloc;
3073 zstream.zfree = z_free;
3074
3075 zlib_result = inflateInit(&zstream);
3076 if (Z_OK != zlib_result) {
3077 if (isKernel()) {
3078 OSKextLog(this,
3079 kOSKextLogErrorLevel |
3080 kOSKextLogArchiveFlag,
3081 "Mkext error; zlib inflateInit failed (%d) for %s.",
3082 zlib_result, name);
3083 } else {
3084 OSKextLog(this,
3085 kOSKextLogErrorLevel |
3086 kOSKextLogArchiveFlag,
3087 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
3088 getIdentifierCString(), zlib_result, name);
3089 }
3090 goto finish;
3091 } else {
3092 zstream_inited = true;
3093 }
3094
3095 zlib_result = inflate(&zstream, Z_FINISH);
3096
3097 if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
3098 uncompressedSize = zstream.total_out;
3099 } else {
3100 if (isKernel()) {
3101 OSKextLog(this,
3102 kOSKextLogErrorLevel |
3103 kOSKextLogArchiveFlag,
3104 "Mkext error; zlib inflate failed (%d) for %s.",
3105 zlib_result, name);
3106 } else {
3107 OSKextLog(this,
3108 kOSKextLogErrorLevel |
3109 kOSKextLogArchiveFlag,
3110 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3111 getIdentifierCString(), zlib_result, name);
3112 }
3113 if (zstream.msg) {
3114 OSKextLog(this,
3115 kOSKextLogErrorLevel |
3116 kOSKextLogArchiveFlag,
3117 "zlib error: %s.", zstream.msg);
3118 }
3119 goto finish;
3120 }
3121
3122 if (uncompressedSize != fullSize) {
3123 if (isKernel()) {
3124 OSKextLog(this,
3125 kOSKextLogErrorLevel |
3126 kOSKextLogArchiveFlag,
3127 "Mkext error; zlib inflate discrepancy for %s, "
3128 "uncompressed size != original size.", name);
3129 } else {
3130 OSKextLog(this,
3131 kOSKextLogErrorLevel |
3132 kOSKextLogArchiveFlag,
3133 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3134 "uncompressed size != original size.",
3135 getIdentifierCString(), name);
3136 }
3137 goto finish;
3138 }
3139
3140 result = uncompressedData;
3141
3142 finish:
3143 /* Don't bother checking return, nothing we can do on fail.
3144 */
3145 if (zstream_inited) inflateEnd(&zstream);
3146
3147 if (!result) {
3148 OSSafeRelease(uncompressedData);
3149 }
3150
3151 return result;
3152 }
3153
3154 /*********************************************************************
3155 *********************************************************************/
3156 /* static */
3157 OSReturn
3158 OSKext::loadFromMkext(
3159 OSKextLogSpec clientLogFilter,
3160 char * mkextBuffer,
3161 uint32_t mkextBufferLength,
3162 char ** logInfoOut,
3163 uint32_t * logInfoLengthOut)
3164 {
3165 OSReturn result = kOSReturnError;
3166 OSReturn tempResult = kOSReturnError;
3167
3168 OSData * mkextData = NULL; // must release
3169 OSDictionary * mkextPlist = NULL; // must release
3170
3171 OSArray * logInfoArray = NULL; // must release
3172 OSSerialize * serializer = NULL; // must release
3173
3174 OSString * predicate = NULL; // do not release
3175 OSDictionary * requestArgs = NULL; // do not release
3176
3177 OSString * kextIdentifier = NULL; // do not release
3178 OSNumber * startKextExcludeNum = NULL; // do not release
3179 OSNumber * startMatchingExcludeNum = NULL; // do not release
3180 OSBoolean * delayAutounloadBool = NULL; // do not release
3181 OSArray * personalityNames = NULL; // do not release
3182
3183 /* Default values for these two options: regular autounload behavior,
3184 * load all kexts, send no personalities.
3185 */
3186 Boolean delayAutounload = false;
3187 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone;
3188 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3189
3190 IORecursiveLockLock(sKextLock);
3191
3192 if (logInfoOut) {
3193 *logInfoOut = NULL;
3194 *logInfoLengthOut = 0;
3195 }
3196
3197 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3198
3199 OSKextLog(/* kext */ NULL,
3200 kOSKextLogDebugLevel |
3201 kOSKextLogIPCFlag,
3202 "Received kext load request from user space.");
3203
3204 /* Regardless of processing, the fact that we have gotten here means some
3205 * user-space program is up and talking to us, so we'll switch our kext
3206 * registration to reflect that.
3207 */
3208 if (!sUserLoadsActive) {
3209 OSKextLog(/* kext */ NULL,
3210 kOSKextLogProgressLevel |
3211 kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3212 "Switching to late startup (user-space) kext loading policy.");
3213
3214 sUserLoadsActive = true;
3215 }
3216
3217 if (!sLoadEnabled) {
3218 OSKextLog(/* kext */ NULL,
3219 kOSKextLogErrorLevel |
3220 kOSKextLogLoadFlag,
3221 "Kext loading is disabled.");
3222 result = kOSKextReturnDisabled;
3223 goto finish;
3224 }
3225
3226 /* Note that we do not set a dealloc function on this OSData
3227 * object! No references to it can remain after the loadFromMkext()
3228 * call since we are in a MIG function, and will vm_deallocate()
3229 * the buffer.
3230 */
3231 mkextData = OSData::withBytesNoCopy(mkextBuffer,
3232 mkextBufferLength);
3233 if (!mkextData) {
3234 OSKextLog(/* kext */ NULL,
3235 kOSKextLogErrorLevel |
3236 kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3237 "Failed to create wrapper for kext load request.");
3238 result = kOSKextReturnNoMemory;
3239 goto finish;
3240 }
3241
3242 result = readMkext2Archive(mkextData, &mkextPlist, NULL);
3243 if (result != kOSReturnSuccess) {
3244 OSKextLog(/* kext */ NULL,
3245 kOSKextLogErrorLevel |
3246 kOSKextLogLoadFlag,
3247 "Failed to read kext load request.");
3248 goto finish;
3249 }
3250
3251 predicate = _OSKextGetRequestPredicate(mkextPlist);
3252 if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3253 OSKextLog(/* kext */ NULL,
3254 kOSKextLogErrorLevel |
3255 kOSKextLogLoadFlag,
3256 "Received kext load request with no predicate; skipping.");
3257 result = kOSKextReturnInvalidArgument;
3258 goto finish;
3259 }
3260
3261 requestArgs = OSDynamicCast(OSDictionary,
3262 mkextPlist->getObject(kKextRequestArgumentsKey));
3263 if (!requestArgs || !requestArgs->getCount()) {
3264 OSKextLog(/* kext */ NULL,
3265 kOSKextLogErrorLevel |
3266 kOSKextLogLoadFlag,
3267 "Received kext load request with no arguments.");
3268 result = kOSKextReturnInvalidArgument;
3269 goto finish;
3270 }
3271
3272 kextIdentifier = OSDynamicCast(OSString,
3273 requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3274 if (!kextIdentifier) {
3275 OSKextLog(/* kext */ NULL,
3276 kOSKextLogErrorLevel |
3277 kOSKextLogLoadFlag,
3278 "Received kext load request with no kext identifier.");
3279 result = kOSKextReturnInvalidArgument;
3280 goto finish;
3281 }
3282
3283 startKextExcludeNum = OSDynamicCast(OSNumber,
3284 requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3285 startMatchingExcludeNum = OSDynamicCast(OSNumber,
3286 requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3287 delayAutounloadBool = OSDynamicCast(OSBoolean,
3288 requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3289 personalityNames = OSDynamicCast(OSArray,
3290 requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3291
3292 if (delayAutounloadBool) {
3293 delayAutounload = delayAutounloadBool->getValue();
3294 }
3295 if (startKextExcludeNum) {
3296 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3297 }
3298 if (startMatchingExcludeNum) {
3299 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3300 }
3301
3302 OSKextLog(/* kext */ NULL,
3303 kOSKextLogProgressLevel |
3304 kOSKextLogIPCFlag,
3305 "Received request from user space to load kext %s.",
3306 kextIdentifier->getCStringNoCopy());
3307
3308 /* Load the kext, with no deferral, since this is a load from outside
3309 * the kernel.
3310 * xxx - Would like a better way to handle the default values for the
3311 * xxx - start/match opt args.
3312 */
3313 result = OSKext::loadKextWithIdentifier(
3314 kextIdentifier,
3315 /* allowDefer */ false,
3316 delayAutounload,
3317 startKextExcludeLevel,
3318 startMatchingExcludeLevel,
3319 personalityNames);
3320 if (result != kOSReturnSuccess) {
3321 goto finish;
3322 }
3323 /* If the load came down from kextd, it will shortly inform IOCatalogue
3324 * for matching via a separate IOKit calldown.
3325 */
3326
3327 finish:
3328
3329 /* Gather up the collected log messages for user space. Any
3330 * error messages past this call will not make it up as log messages
3331 * but will be in the system log.
3332 */
3333 logInfoArray = OSKext::clearUserSpaceLogFilter();
3334
3335 if (logInfoArray && logInfoOut && logInfoLengthOut) {
3336 tempResult = OSKext::serializeLogInfo(logInfoArray,
3337 logInfoOut, logInfoLengthOut);
3338 if (tempResult != kOSReturnSuccess) {
3339 result = tempResult;
3340 }
3341 }
3342
3343 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3344
3345 /* Note: mkextDataObject will have been retained by every kext w/an
3346 * executable in it. That should all have been flushed out at the
3347 * and of the load operation, but you never know....
3348 */
3349 if (mkextData && mkextData->getRetainCount() > 1) {
3350 OSKextLog(/* kext */ NULL,
3351 kOSKextLogErrorLevel |
3352 kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3353 "Kext load request buffer from user space still retained by a kext; "
3354 "probable memory leak.");
3355 }
3356
3357 IORecursiveLockUnlock(sKextLock);
3358
3359 OSSafeRelease(mkextData);
3360 OSSafeRelease(mkextPlist);
3361 OSSafeRelease(serializer);
3362 OSSafeRelease(logInfoArray);
3363
3364 return result;
3365 }
3366
3367 /*********************************************************************
3368 *********************************************************************/
3369 /* static */
3370 OSReturn
3371 OSKext::serializeLogInfo(
3372 OSArray * logInfoArray,
3373 char ** logInfoOut,
3374 uint32_t * logInfoLengthOut)
3375 {
3376 OSReturn result = kOSReturnError;
3377 char * buffer = NULL;
3378 kern_return_t kmem_result = KERN_FAILURE;
3379 OSSerialize * serializer = NULL; // must release; reused
3380 char * logInfo = NULL; // returned by reference
3381 uint32_t logInfoLength = 0;
3382
3383 if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
3384 OSKextLog(/* kext */ NULL,
3385 kOSKextLogErrorLevel |
3386 kOSKextLogIPCFlag,
3387 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3388 /* Bad programmer. */
3389 result = kOSKextReturnInvalidArgument;
3390 goto finish;
3391 }
3392
3393 serializer = OSSerialize::withCapacity(0);
3394 if (!serializer) {
3395 OSKextLog(/* kext */ NULL,
3396 kOSKextLogErrorLevel |
3397 kOSKextLogIPCFlag,
3398 "Failed to create serializer on log info for request from user space.");
3399 /* Incidental error; we're going to (try to) allow the request
3400 * itself to succeed. */
3401 }
3402
3403 if (!logInfoArray->serialize(serializer)) {
3404 OSKextLog(/* kext */ NULL,
3405 kOSKextLogErrorLevel |
3406 kOSKextLogIPCFlag,
3407 "Failed to serialize log info for request from user space.");
3408 /* Incidental error; we're going to (try to) allow the request
3409 * itself to succeed. */
3410 } else {
3411 logInfo = serializer->text();
3412 logInfoLength = serializer->getLength();
3413
3414 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength));
3415 if (kmem_result != KERN_SUCCESS) {
3416 OSKextLog(/* kext */ NULL,
3417 kOSKextLogErrorLevel |
3418 kOSKextLogIPCFlag,
3419 "Failed to copy log info for request from user space.");
3420 /* Incidental error; we're going to (try to) allow the request
3421 * to succeed. */
3422 } else {
3423 /* 11981737 - clear uninitialized data in last page */
3424 bzero((void *)(buffer + logInfoLength),
3425 (round_page(logInfoLength) - logInfoLength));
3426 memcpy(buffer, logInfo, logInfoLength);
3427 *logInfoOut = buffer;
3428 *logInfoLengthOut = logInfoLength;
3429 }
3430 }
3431
3432 result = kOSReturnSuccess;
3433 finish:
3434 OSSafeRelease(serializer);
3435 return result;
3436 }
3437
3438 #if PRAGMA_MARK
3439 #pragma mark Instance Management Methods
3440 #endif
3441 /*********************************************************************
3442 *********************************************************************/
3443 OSKext *
3444 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
3445 {
3446 OSKext * foundKext = NULL;
3447
3448 IORecursiveLockLock(sKextLock);
3449 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
3450 if (foundKext) {
3451 foundKext->retain();
3452 }
3453 IORecursiveLockUnlock(sKextLock);
3454
3455 return foundKext;
3456 }
3457
3458 /*********************************************************************
3459 *********************************************************************/
3460 OSKext *
3461 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
3462 {
3463 return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
3464 }
3465
3466 /*********************************************************************
3467 *********************************************************************/
3468 OSKext *
3469 OSKext::lookupKextWithLoadTag(uint32_t aTag)
3470 {
3471 OSKext * foundKext = NULL; // returned
3472 uint32_t count, i;
3473
3474 IORecursiveLockLock(sKextLock);
3475
3476 count = sLoadedKexts->getCount();
3477 for (i = 0; i < count; i++) {
3478 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3479 if (thisKext->getLoadTag() == aTag) {
3480 foundKext = thisKext;
3481 foundKext->retain();
3482 goto finish;
3483 }
3484 }
3485
3486 finish:
3487 IORecursiveLockUnlock(sKextLock);
3488
3489 return foundKext;
3490 }
3491
3492 /*********************************************************************
3493 *********************************************************************/
3494 OSKext *
3495 OSKext::lookupKextWithAddress(vm_address_t address)
3496 {
3497 OSKext * foundKext = NULL; // returned
3498 uint32_t count, i;
3499
3500 IORecursiveLockLock(sKextLock);
3501
3502 count = sLoadedKexts->getCount();
3503 for (i = 0; i < count; i++) {
3504 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3505 if (thisKext->linkedExecutable) {
3506 vm_address_t kext_start =
3507 (vm_address_t)thisKext->linkedExecutable->getBytesNoCopy();
3508 vm_address_t kext_end = kext_start +
3509 thisKext->linkedExecutable->getLength();
3510
3511 if ((kext_start <= address) && (address < kext_end)) {
3512 foundKext = thisKext;
3513 foundKext->retain();
3514 goto finish;
3515 }
3516 }
3517 }
3518
3519 finish:
3520 IORecursiveLockUnlock(sKextLock);
3521
3522 return foundKext;
3523 }
3524
3525 /*********************************************************************
3526 *********************************************************************/
3527 /* static */
3528 bool OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
3529 {
3530 bool result = false;
3531 OSKext * foundKext = NULL; // returned
3532
3533 IORecursiveLockLock(sKextLock);
3534
3535 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
3536 if (foundKext && foundKext->isLoaded()) {
3537 result = true;
3538 }
3539
3540 IORecursiveLockUnlock(sKextLock);
3541
3542 return result;
3543 }
3544
3545 /*********************************************************************
3546 * xxx - should spawn a separate thread so a kext can safely have
3547 * xxx - itself unloaded.
3548 *********************************************************************/
3549 /* static */
3550 OSReturn
3551 OSKext::removeKext(
3552 OSKext * aKext,
3553 bool terminateServicesAndRemovePersonalitiesFlag)
3554 {
3555 OSReturn result = kOSKextReturnInUse;
3556 OSKext * checkKext = NULL; // do not release
3557 #if CONFIG_MACF
3558 int macCheckResult = 0;
3559 kauth_cred_t cred = NULL;
3560 #endif
3561
3562 IORecursiveLockLock(sKextLock);
3563
3564 /* If the kext has no identifier, it failed to init
3565 * so isn't in sKextsByID and it isn't loaded.
3566 */
3567 if (!aKext->getIdentifier()) {
3568 result = kOSReturnSuccess;
3569 goto finish;
3570 }
3571
3572 checkKext = OSDynamicCast(OSKext,
3573 sKextsByID->getObject(aKext->getIdentifier()));
3574 if (checkKext != aKext) {
3575 result = kOSKextReturnNotFound;
3576 goto finish;
3577 }
3578
3579 if (aKext->isLoaded()) {
3580 #if CONFIG_MACF
3581 if (current_task() != kernel_task) {
3582 cred = kauth_cred_get_with_ref();
3583 macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
3584 kauth_cred_unref(&cred);
3585 }
3586
3587 if (macCheckResult != 0) {
3588 result = kOSReturnError;
3589 OSKextLog(aKext,
3590 kOSKextLogErrorLevel |
3591 kOSKextLogKextBookkeepingFlag,
3592 "Failed to remove kext %s (MAC policy error 0x%x).",
3593 aKext->getIdentifierCString(), macCheckResult);
3594 goto finish;
3595 }
3596 #endif
3597
3598 /* If we are terminating, send the request to the IOCatalogue
3599 * (which will actually call us right back but that's ok we have
3600 * a recursive lock don't you know) but do not ask the IOCatalogue
3601 * to call back with an unload, we'll do that right here.
3602 */
3603 if (terminateServicesAndRemovePersonalitiesFlag) {
3604 result = gIOCatalogue->terminateDriversForModule(
3605 aKext->getIdentifierCString(), /* unload */ false);
3606 if (result != kOSReturnSuccess) {
3607 OSKextLog(aKext,
3608 kOSKextLogErrorLevel |
3609 kOSKextLogKextBookkeepingFlag,
3610 "Can't remove kext %s; services failed to terminate - 0x%x.",
3611 aKext->getIdentifierCString(), result);
3612 goto finish;
3613 }
3614 }
3615
3616 result = aKext->unload();
3617 if (result != kOSReturnSuccess) {
3618 goto finish;
3619 }
3620 }
3621
3622 /* Remove personalities as requested. This is a bit redundant for a loaded
3623 * kext as IOCatalogue::terminateDriversForModule() removes driver
3624 * personalities, but it doesn't restart matching, which we always want
3625 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3626 * that happens.
3627 */
3628 if (terminateServicesAndRemovePersonalitiesFlag) {
3629 aKext->removePersonalitiesFromCatalog();
3630 }
3631
3632 OSKextLog(aKext,
3633 kOSKextLogProgressLevel |
3634 kOSKextLogKextBookkeepingFlag,
3635 "Removing kext %s.",
3636 aKext->getIdentifierCString());
3637
3638 sKextsByID->removeObject(aKext->getIdentifier());
3639 result = kOSReturnSuccess;
3640
3641 finish:
3642 IORecursiveLockUnlock(sKextLock);
3643 return result;
3644 }
3645
3646 /*********************************************************************
3647 *********************************************************************/
3648 /* static */
3649 OSReturn
3650 OSKext::removeKextWithIdentifier(
3651 const char * kextIdentifier,
3652 bool terminateServicesAndRemovePersonalitiesFlag)
3653 {
3654 OSReturn result = kOSReturnError;
3655
3656 IORecursiveLockLock(sKextLock);
3657
3658 OSKext * aKext = OSDynamicCast(OSKext,
3659 sKextsByID->getObject(kextIdentifier));
3660 if (!aKext) {
3661 result = kOSKextReturnNotFound;
3662 OSKextLog(/* kext */ NULL,
3663 kOSKextLogErrorLevel |
3664 kOSKextLogKextBookkeepingFlag,
3665 "Can't remove kext %s - not found.",
3666 kextIdentifier);
3667 goto finish;
3668 }
3669
3670 result = OSKext::removeKext(aKext,
3671 terminateServicesAndRemovePersonalitiesFlag);
3672
3673 finish:
3674 IORecursiveLockUnlock(sKextLock);
3675
3676 return result;
3677 }
3678
3679 /*********************************************************************
3680 *********************************************************************/
3681 /* static */
3682 OSReturn
3683 OSKext::removeKextWithLoadTag(
3684 OSKextLoadTag loadTag,
3685 bool terminateServicesAndRemovePersonalitiesFlag)
3686 {
3687 OSReturn result = kOSReturnError;
3688 OSKext * foundKext = NULL;
3689 uint32_t count, i;
3690
3691 IORecursiveLockLock(sKextLock);
3692
3693 count = sLoadedKexts->getCount();
3694 for (i = 0; i < count; i++) {
3695 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3696 if (thisKext->loadTag == loadTag) {
3697 foundKext = thisKext;
3698 break;
3699 }
3700 }
3701
3702 if (!foundKext) {
3703 result = kOSKextReturnNotFound;
3704 OSKextLog(/* kext */ NULL,
3705 kOSKextLogErrorLevel |
3706 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
3707 "Can't remove kext with load tag %d - not found.",
3708 loadTag);
3709 goto finish;
3710 }
3711
3712 result = OSKext::removeKext(foundKext,
3713 terminateServicesAndRemovePersonalitiesFlag);
3714
3715 finish:
3716 IORecursiveLockUnlock(sKextLock);
3717
3718 return result;
3719 }
3720
3721 /*********************************************************************
3722 *********************************************************************/
3723 OSDictionary *
3724 OSKext::copyKexts(void)
3725 {
3726 OSDictionary * result;
3727
3728 IORecursiveLockLock(sKextLock);
3729 result = OSDynamicCast(OSDictionary, sKextsByID->copyCollection());
3730 IORecursiveLockUnlock(sKextLock);
3731
3732 return result;
3733 }
3734
3735 /*********************************************************************
3736 *********************************************************************/
3737 #define BOOTER_KEXT_PREFIX "Driver-"
3738
3739 typedef struct _DeviceTreeBuffer {
3740 uint32_t paddr;
3741 uint32_t length;
3742 } _DeviceTreeBuffer;
3743
3744 /*********************************************************************
3745 * Create a dictionary of excluded kexts from the given booter data.
3746 *********************************************************************/
3747 /* static */
3748 void
3749 OSKext::createExcludeListFromBooterData(
3750 OSDictionary * theDictionary,
3751 OSCollectionIterator * theIterator )
3752 {
3753 OSString * deviceTreeName = NULL; // do not release
3754 const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not release
3755 char * booterDataPtr = NULL; // do not release
3756 _BooterKextFileInfo * kextFileInfo = NULL; // do not release
3757 char * infoDictAddr = NULL; // do not release
3758 OSObject * parsedXML = NULL; // must release
3759 OSDictionary * theInfoDict = NULL; // do not release
3760
3761 theIterator->reset();
3762
3763 /* look for AppleKextExcludeList.kext */
3764 while ( (deviceTreeName =
3765 OSDynamicCast(OSString, theIterator->getNextObject())) ) {
3766
3767 const char * devTreeNameCString;
3768 OSData * deviceTreeEntry;
3769 OSString * myBundleID; // do not release
3770
3771 OSSafeReleaseNULL(parsedXML);
3772
3773 deviceTreeEntry =
3774 OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
3775 if (!deviceTreeEntry) {
3776 continue;
3777 }
3778
3779 /* Make sure it is a kext */
3780 devTreeNameCString = deviceTreeName->getCStringNoCopy();
3781 if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
3782 (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
3783 OSKextLog(NULL,
3784 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3785 "\"%s\" not a kext",
3786 devTreeNameCString);
3787 continue;
3788 }
3789
3790 deviceTreeBuffer = (const _DeviceTreeBuffer *)
3791 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
3792 if (!deviceTreeBuffer) {
3793 continue;
3794 }
3795
3796 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
3797 if (!booterDataPtr) {
3798 continue;
3799 }
3800
3801 kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
3802 if (!kextFileInfo->infoDictPhysAddr ||
3803 !kextFileInfo->infoDictLength) {
3804 continue;
3805 }
3806
3807 infoDictAddr = (char *)
3808 ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
3809 if (!infoDictAddr) {
3810 continue;
3811 }
3812
3813 parsedXML = OSUnserializeXML(infoDictAddr);
3814 if (!parsedXML) {
3815 continue;
3816 }
3817
3818 theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
3819 if (!theInfoDict) {
3820 continue;
3821 }
3822
3823 myBundleID =
3824 OSDynamicCast(OSString,
3825 theInfoDict->getObject(kCFBundleIdentifierKey));
3826 if ( myBundleID &&
3827 strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3828
3829 /* get copy of exclusion list dictionary */
3830 OSDictionary * myTempDict; // do not free
3831
3832 myTempDict = OSDynamicCast(
3833 OSDictionary,
3834 theInfoDict->getObject("OSKextExcludeList"));
3835 if ( myTempDict ) {
3836 IORecursiveLockLock(sKextLock);
3837
3838 /* get rid of old exclusion list */
3839 if (sExcludeListByID) {
3840 sExcludeListByID->flushCollection();
3841 OSSafeRelease(sExcludeListByID);
3842 }
3843 sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
3844 IORecursiveLockUnlock(sKextLock);
3845 }
3846 break;
3847 }
3848
3849 } // while ( (deviceTreeName = ...) )
3850
3851 OSSafeReleaseNULL(parsedXML);
3852 return;
3853 }
3854
3855 /*********************************************************************
3856 * Create a dictionary of excluded kexts from the given prelink
3857 * info (kernelcache).
3858 *********************************************************************/
3859 /* static */
3860 void
3861 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
3862 {
3863 OSDictionary * myInfoDict = NULL; // do not release
3864 OSString * myBundleID; // do not release
3865 u_int i;
3866
3867 /* Find com.apple.driver.KextExcludeList. */
3868 for (i = 0; i < theInfoArray->getCount(); i++) {
3869 myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
3870 if (!myInfoDict) {
3871 continue;
3872 }
3873 myBundleID =
3874 OSDynamicCast(OSString,
3875 myInfoDict->getObject(kCFBundleIdentifierKey));
3876 if ( myBundleID &&
3877 strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0 ) {
3878 // get copy of exclude list dictionary
3879 OSDictionary * myTempDict; // do not free
3880 myTempDict = OSDynamicCast(OSDictionary,
3881 myInfoDict->getObject("OSKextExcludeList"));
3882 if ( myTempDict ) {
3883 IORecursiveLockLock(sKextLock);
3884 // get rid of old exclude list
3885 if (sExcludeListByID) {
3886 sExcludeListByID->flushCollection();
3887 OSSafeRelease(sExcludeListByID);
3888 }
3889
3890 sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
3891 IORecursiveLockUnlock(sKextLock);
3892 }
3893 break;
3894 }
3895 } // for (i = 0; i < theInfoArray->getCount()...
3896
3897 return;
3898 }
3899
3900 #if PRAGMA_MARK
3901 #pragma mark Accessors
3902 #endif
3903 /*********************************************************************
3904 *********************************************************************/
3905 const OSSymbol *
3906 OSKext::getIdentifier(void)
3907 {
3908 return bundleID;
3909 }
3910
3911 /*********************************************************************
3912 * A kext must have a bundle identifier to even survive initialization;
3913 * this is guaranteed to exist past then.
3914 *********************************************************************/
3915 const char *
3916 OSKext::getIdentifierCString(void)
3917 {
3918 return bundleID->getCStringNoCopy();
3919 }
3920
3921 /*********************************************************************
3922 *********************************************************************/
3923 OSKextVersion
3924 OSKext::getVersion(void)
3925 {
3926 return version;
3927 }
3928
3929 /*********************************************************************
3930 *********************************************************************/
3931 OSKextVersion
3932 OSKext::getCompatibleVersion(void)
3933 {
3934 return compatibleVersion;
3935 }
3936
3937 /*********************************************************************
3938 *********************************************************************/
3939 bool
3940 OSKext::isLibrary(void)
3941 {
3942 return (getCompatibleVersion() > 0);
3943 }
3944
3945 /*********************************************************************
3946 *********************************************************************/
3947 bool
3948 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
3949 {
3950 if ((compatibleVersion > -1 && version > -1) &&
3951 (compatibleVersion <= version && aVersion <= version)) {
3952 return true;
3953 }
3954 return false;
3955 }
3956
3957 /*********************************************************************
3958 *********************************************************************/
3959 bool
3960 OSKext::declaresExecutable(void)
3961 {
3962 return (getPropertyForHostArch(kCFBundleExecutableKey) != NULL);
3963 }
3964
3965 /*********************************************************************
3966 *********************************************************************/
3967 OSData *
3968 OSKext::getExecutable(void)
3969 {
3970 OSData * result = NULL;
3971 OSData * extractedExecutable = NULL; // must release
3972 OSData * mkextExecutableRef = NULL; // do not release
3973
3974 result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
3975 if (result) {
3976 goto finish;
3977 }
3978
3979 mkextExecutableRef = OSDynamicCast(OSData,
3980 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
3981
3982 if (mkextExecutableRef) {
3983
3984 MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
3985 mkextExecutableRef->getBytesNoCopy();
3986 uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
3987 if (mkextVersion == MKEXT_VERS_2) {
3988 mkext2_file_entry * fileinfo =
3989 (mkext2_file_entry *)mkextEntryRef->fileinfo;
3990 uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
3991 uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
3992 extractedExecutable = extractMkext2FileData(
3993 MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
3994 compressedSize, fullSize);
3995 } else if (mkextVersion == MKEXT_VERS_1) {
3996 extractedExecutable = extractMkext1Entry(
3997 mkextEntryRef->mkext, mkextEntryRef->fileinfo);
3998 } else {
3999 OSKextLog(this, kOSKextLogErrorLevel |
4000 kOSKextLogArchiveFlag,
4001 "Kext %s - unknown mkext version 0x%x for executable.",
4002 getIdentifierCString(), mkextVersion);
4003 }
4004
4005 /* Regardless of success, remove the mkext executable,
4006 * and drop one reference on the mkext. (setExecutable() does not
4007 * replace, it removes, or panics if asked to replace.)
4008 */
4009 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4010 infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4011
4012 if (extractedExecutable && extractedExecutable->getLength()) {
4013 if (!setExecutable(extractedExecutable)) {
4014 goto finish;
4015 }
4016 result = extractedExecutable;
4017 } else {
4018 goto finish;
4019 }
4020 }
4021
4022 finish:
4023
4024 OSSafeRelease(extractedExecutable);
4025
4026 return result;
4027 }
4028
4029 /*********************************************************************
4030 *********************************************************************/
4031 bool
4032 OSKext::isInterface(void)
4033 {
4034 return flags.interface;
4035 }
4036
4037 /*********************************************************************
4038 *********************************************************************/
4039 bool
4040 OSKext::isKernel(void)
4041 {
4042 return (this == sKernelKext);
4043 }
4044
4045 /*********************************************************************
4046 *********************************************************************/
4047 bool
4048 OSKext::isKernelComponent(void)
4049 {
4050 return flags.kernelComponent ? true : false;
4051 }
4052
4053 /*********************************************************************
4054 *********************************************************************/
4055 bool
4056 OSKext::isExecutable(void)
4057 {
4058 return (!isKernel() && !isInterface() && declaresExecutable());
4059 }
4060
4061 /*********************************************************************
4062 * We might want to check this recursively for all dependencies,
4063 * since a subtree of dependencies could get loaded before we hit
4064 * a dependency that isn't safe-boot-loadable.
4065 *
4066 * xxx - Might want to return false if OSBundleEnableKextLogging or
4067 * OSBundleDebugLevel
4068 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4069 * the point except it's usually development drivers, which might
4070 * cause panics on startup, that have those properties). Heh; could
4071 * use a "kx" boot-arg!
4072 *********************************************************************/
4073 bool
4074 OSKext::isLoadableInSafeBoot(void)
4075 {
4076 bool result = false;
4077 OSString * required = NULL; // do not release
4078
4079 if (isKernel()) {
4080 result = true;
4081 goto finish;
4082 }
4083
4084 required = OSDynamicCast(OSString,
4085 getPropertyForHostArch(kOSBundleRequiredKey));
4086 if (!required) {
4087 goto finish;
4088 }
4089 if (required->isEqualTo(kOSBundleRequiredRoot) ||
4090 required->isEqualTo(kOSBundleRequiredLocalRoot) ||
4091 required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
4092 required->isEqualTo(kOSBundleRequiredSafeBoot) ||
4093 required->isEqualTo(kOSBundleRequiredConsole)) {
4094
4095 result = true;
4096 }
4097
4098 finish:
4099 return result;
4100 }
4101
4102 /*********************************************************************
4103 *********************************************************************/
4104 bool
4105 OSKext::isPrelinked(void)
4106 {
4107 return flags.prelinked ? true : false;
4108 }
4109
4110 /*********************************************************************
4111 *********************************************************************/
4112 bool OSKext::isLoaded(void)
4113 {
4114 return flags.loaded ? true : false;
4115 }
4116
4117 /*********************************************************************
4118 *********************************************************************/
4119 bool
4120 OSKext::isStarted(void)
4121 {
4122 return flags.started ? true : false;
4123 }
4124
4125 /*********************************************************************
4126 *********************************************************************/
4127 bool
4128 OSKext::isCPPInitialized(void)
4129 {
4130 return flags.CPPInitialized;
4131 }
4132
4133 /*********************************************************************
4134 *********************************************************************/
4135 void
4136 OSKext::setCPPInitialized(bool initialized)
4137 {
4138 flags.CPPInitialized = initialized;
4139 }
4140
4141 /*********************************************************************
4142 *********************************************************************/
4143 uint32_t
4144 OSKext::getLoadTag(void)
4145 {
4146 return loadTag;
4147 }
4148
4149 /*********************************************************************
4150 *********************************************************************/
4151 void OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
4152 {
4153 if (linkedExecutable) {
4154 *loadSize = linkedExecutable->getLength();
4155
4156 /* If we have a kmod_info struct, calculated the wired size
4157 * from that. Otherwise it's the full load size.
4158 */
4159 if (kmod_info) {
4160 *wiredSize = *loadSize - kmod_info->hdr_size;
4161 } else {
4162 *wiredSize = *loadSize;
4163 }
4164 }
4165 else {
4166 *wiredSize = 0;
4167 *loadSize = 0;
4168 }
4169 }
4170
4171 /*********************************************************************
4172 *********************************************************************/
4173 OSData *
4174 OSKext::copyUUID(void)
4175 {
4176 OSData * result = NULL;
4177 OSData * theExecutable = NULL; // do not release
4178 const kernel_mach_header_t * header = NULL;
4179 const struct load_command * load_cmd = NULL;
4180 const struct uuid_command * uuid_cmd = NULL;
4181 uint32_t i;
4182
4183 /* An interface kext doesn't have a linked executable with an LC_UUID,
4184 * we create one when it's linked.
4185 */
4186 if (interfaceUUID) {
4187 result = interfaceUUID;
4188 result->retain();
4189 goto finish;
4190 }
4191
4192 /* For real kexts, try to get the UUID from the linked executable,
4193 * or if is hasn't been linked yet, the unrelocated executable.
4194 */
4195 theExecutable = linkedExecutable;
4196 if (!theExecutable) {
4197 theExecutable = getExecutable();
4198 }
4199 if (!theExecutable) {
4200 goto finish;
4201 }
4202
4203 header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
4204 load_cmd = (const struct load_command *)&header[1];
4205
4206 for (i = 0; i < header->ncmds; i++) {
4207 if (load_cmd->cmd == LC_UUID) {
4208 uuid_cmd = (struct uuid_command *)load_cmd;
4209 result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid));
4210 goto finish;
4211 }
4212 load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
4213 }
4214
4215 finish:
4216 return result;
4217 }
4218
4219 /*********************************************************************
4220 *********************************************************************/
4221
4222 #if defined (__x86_64__)
4223 #define ARCHNAME "x86_64"
4224 #else
4225 #error architecture not supported
4226 #endif
4227
4228 #define ARCH_SEPARATOR_CHAR '_'
4229
4230 static char * makeHostArchKey(const char * key, uint32_t * keySizeOut)
4231 {
4232 char * result = NULL;
4233 uint32_t keyLength = strlen(key);
4234 uint32_t keySize;
4235
4236 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4237 */
4238 keySize = 1 + 1 + strlen(key) + strlen(ARCHNAME);
4239 result = (char *)kalloc(keySize);
4240 if (!result) {
4241 goto finish;
4242 }
4243 strlcpy(result, key, keySize);
4244 result[keyLength++] = ARCH_SEPARATOR_CHAR;
4245 result[keyLength] = '\0';
4246 strlcat(result, ARCHNAME, keySize);
4247 *keySizeOut = keySize;
4248
4249 finish:
4250 return result;
4251 }
4252
4253 /*********************************************************************
4254 *********************************************************************/
4255 OSObject *
4256 OSKext::getPropertyForHostArch(const char * key)
4257 {
4258 OSObject * result = NULL; // do not release
4259 uint32_t hostArchKeySize = 0;
4260 char * hostArchKey = NULL; // must kfree
4261
4262 if (!key || !infoDict) {
4263 goto finish;
4264 }
4265
4266 /* Some properties are not allowed to be arch-variant:
4267 * - Any CFBundle... property.
4268 * - OSBundleIsInterface.
4269 * - OSKernelResource.
4270 */
4271 if (STRING_HAS_PREFIX(key, "OS") ||
4272 STRING_HAS_PREFIX(key, "IO")) {
4273
4274 hostArchKey = makeHostArchKey(key, &hostArchKeySize);
4275 if (!hostArchKey) {
4276 OSKextLog(/* kext (this isn't about a kext) */ NULL,
4277 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4278 "Allocation failure.");
4279 goto finish;
4280 }
4281 result = infoDict->getObject(hostArchKey);
4282 }
4283
4284 if (!result) {
4285 result = infoDict->getObject(key);
4286 }
4287
4288 finish:
4289 if (hostArchKey) kfree(hostArchKey, hostArchKeySize);
4290 return result;
4291 }
4292
4293 #if PRAGMA_MARK
4294 #pragma mark Load/Start/Stop/Unload
4295 #endif
4296
4297 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4298
4299 /*********************************************************************
4300 * sExcludeListByID is a dictionary with keys / values of:
4301 * key = bundleID string of kext we will not allow to load
4302 * value = version string(s) of the kext that is to be denied loading.
4303 * The version strings can be comma delimited. For example if kext
4304 * com.foocompany.fookext has two versions that we want to deny
4305 * loading then the version strings might look like:
4306 * 1.0.0, 1.0.1
4307 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4308 * not load the kext.
4309 *
4310 * Value may also be in the form of "LE 2.0.0" (version numbers
4311 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4312 * number less than 2.0.0 will not load)
4313 *
4314 * NOTE - we cannot use the characters "<=" or "<" because we have code
4315 * that serializes plists and treats '<' as a special character.
4316 *********************************************************************/
4317 bool
4318 OSKext::isInExcludeList(void)
4319 {
4320 OSString * versionString = NULL; // do not release
4321 char * versionCString = NULL; // do not free
4322 size_t i;
4323 boolean_t wantLessThan = false;
4324 boolean_t wantLessThanEqualTo = false;
4325 char myBuffer[32];
4326
4327 if (!sExcludeListByID) {
4328 return(false);
4329 }
4330 /* look up by bundleID in our exclude list and if found get version
4331 * string (or strings) that we will not allow to load
4332 */
4333 versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID));
4334 if (!versionString) {
4335 return(false);
4336 }
4337
4338 /* parse version strings */
4339 versionCString = (char *) versionString->getCStringNoCopy();
4340
4341 /* look for "LT" or "LE" form of version string, must be in first two
4342 * positions.
4343 */
4344 if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
4345 wantLessThan = true;
4346 versionCString +=2;
4347 }
4348 else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
4349 wantLessThanEqualTo = true;
4350 versionCString +=2;
4351 }
4352
4353 for (i = 0; *versionCString != 0x00; versionCString++) {
4354 /* skip whitespace */
4355 if (isWhiteSpace(*versionCString)) {
4356 continue;
4357 }
4358
4359 /* peek ahead for version string separator or null terminator */
4360 if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
4361
4362 /* OK, we have a version string */
4363 myBuffer[i++] = *versionCString;
4364 myBuffer[i] = 0x00;
4365
4366 OSKextVersion excludeVers;
4367 excludeVers = OSKextParseVersionString(myBuffer);
4368
4369 if (wantLessThanEqualTo) {
4370 if (version <= excludeVers) {
4371 return(true);
4372 }
4373 }
4374 else if (wantLessThan) {
4375 if (version < excludeVers) {
4376 return(true);
4377 }
4378 }
4379 else if ( version == excludeVers ) {
4380 return(true);
4381 }
4382
4383 /* reset for the next (if any) version string */
4384 i = 0;
4385 wantLessThan = false;
4386 wantLessThanEqualTo = false;
4387 }
4388 else {
4389 /* save valid version character */
4390 myBuffer[i++] = *versionCString;
4391
4392 /* make sure bogus version string doesn't overrun local buffer */
4393 if ( i >= sizeof(myBuffer) ) {
4394 break;
4395 }
4396 }
4397 }
4398
4399 return(false);
4400 }
4401
4402 /*********************************************************************
4403 *********************************************************************/
4404 /* static */
4405 OSReturn
4406 OSKext::loadKextWithIdentifier(
4407 const char * kextIdentifierCString,
4408 Boolean allowDeferFlag,
4409 Boolean delayAutounloadFlag,
4410 OSKextExcludeLevel startOpt,
4411 OSKextExcludeLevel startMatchingOpt,
4412 OSArray * personalityNames)
4413 {
4414 OSReturn result = kOSReturnError;
4415 OSString * kextIdentifier = NULL; // must release
4416
4417 kextIdentifier = OSString::withCString(kextIdentifierCString);
4418 if (!kextIdentifier) {
4419 result = kOSKextReturnNoMemory;
4420 goto finish;
4421 }
4422 result = OSKext::loadKextWithIdentifier(kextIdentifier,
4423 allowDeferFlag, delayAutounloadFlag,
4424 startOpt, startMatchingOpt, personalityNames);
4425
4426 finish:
4427 OSSafeRelease(kextIdentifier);
4428 return result;
4429 }
4430
4431 /*********************************************************************
4432 *********************************************************************/
4433 OSReturn
4434 OSKext::loadKextWithIdentifier(
4435 OSString * kextIdentifier,
4436 Boolean allowDeferFlag,
4437 Boolean delayAutounloadFlag,
4438 OSKextExcludeLevel startOpt,
4439 OSKextExcludeLevel startMatchingOpt,
4440 OSArray * personalityNames)
4441 {
4442 OSReturn result = kOSReturnError;
4443 OSReturn pingResult = kOSReturnError;
4444 OSKext * theKext = NULL; // do not release
4445 OSDictionary * loadRequest = NULL; // must release
4446 const OSSymbol * kextIdentifierSymbol = NULL; // must release
4447 #if CONFIG_MACF
4448 int macCheckResult = 0;
4449 kauth_cred_t cred = NULL;
4450 #endif
4451
4452 IORecursiveLockLock(sKextLock);
4453
4454 if (!kextIdentifier) {
4455 result = kOSKextReturnInvalidArgument;
4456 goto finish;
4457 }
4458
4459 OSKext::recordIdentifierRequest(kextIdentifier);
4460
4461 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4462 if (!theKext) {
4463 if (!allowDeferFlag) {
4464 OSKextLog(/* kext */ NULL,
4465 kOSKextLogErrorLevel |
4466 kOSKextLogLoadFlag,
4467 "Can't load kext %s - not found.",
4468 kextIdentifier->getCStringNoCopy());
4469 goto finish;
4470 }
4471
4472 if (!sKernelRequestsEnabled) {
4473 OSKextLog(theKext,
4474 kOSKextLogErrorLevel |
4475 kOSKextLogLoadFlag,
4476 "Can't load kext %s - requests to user space are disabled.",
4477 kextIdentifier->getCStringNoCopy());
4478 result = kOSKextReturnDisabled;
4479 goto finish;
4480 }
4481
4482 /* Create a new request unless one is already sitting
4483 * in sKernelRequests for this bundle identifier
4484 */
4485 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
4486 if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
4487 result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
4488 &loadRequest);
4489 if (result != kOSReturnSuccess) {
4490 goto finish;
4491 }
4492 if (!_OSKextSetRequestArgument(loadRequest,
4493 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
4494
4495 result = kOSKextReturnNoMemory;
4496 goto finish;
4497 }
4498 if (!sKernelRequests->setObject(loadRequest)) {
4499 result = kOSKextReturnNoMemory;
4500 goto finish;
4501 }
4502
4503 if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
4504 result = kOSKextReturnNoMemory;
4505 goto finish;
4506 }
4507
4508 OSKextLog(theKext,
4509 kOSKextLogDebugLevel |
4510 kOSKextLogLoadFlag,
4511 "Kext %s not found; queued load request to user space.",
4512 kextIdentifier->getCStringNoCopy());
4513 }
4514
4515 pingResult = OSKext::pingKextd();
4516 if (pingResult == kOSKextReturnDisabled) {
4517 OSKextLog(/* kext */ NULL,
4518 ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
4519 kOSKextLogLoadFlag,
4520 "Kext %s might not load - kextd is currently unavailable.",
4521 kextIdentifier->getCStringNoCopy());
4522 }
4523
4524 result = kOSKextReturnDeferred;
4525 goto finish;
4526 }
4527
4528 #if CONFIG_MACF
4529 if (current_task() != kernel_task) {
4530 cred = kauth_cred_get_with_ref();
4531 macCheckResult = mac_kext_check_load(cred, kextIdentifier->getCStringNoCopy());
4532 kauth_cred_unref(&cred);
4533 }
4534
4535 if (macCheckResult != 0) {
4536 result = kOSReturnError;
4537
4538 OSKextLog(theKext,
4539 kOSKextLogErrorLevel |
4540 kOSKextLogLoadFlag,
4541 "Failed to load kext %s (MAC policy error 0x%x).",
4542 kextIdentifier->getCStringNoCopy(), macCheckResult);
4543
4544 goto finish;
4545 }
4546 #endif
4547
4548 result = theKext->load(startOpt, startMatchingOpt, personalityNames);
4549
4550 if (result != kOSReturnSuccess) {
4551 OSKextLog(theKext,
4552 kOSKextLogErrorLevel |
4553 kOSKextLogLoadFlag,
4554 "Failed to load kext %s (error 0x%x).",
4555 kextIdentifier->getCStringNoCopy(), (int)result);
4556
4557 OSKext::removeKext(theKext,
4558 /* terminateService/removePersonalities */ true);
4559 goto finish;
4560 }
4561
4562 if (delayAutounloadFlag) {
4563 OSKextLog(theKext,
4564 kOSKextLogProgressLevel |
4565 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4566 "Setting delayed autounload for %s.",
4567 kextIdentifier->getCStringNoCopy());
4568 theKext->flags.delayAutounload = 1;
4569 }
4570
4571 finish:
4572 OSSafeRelease(loadRequest);
4573 OSSafeRelease(kextIdentifierSymbol);
4574
4575 IORecursiveLockUnlock(sKextLock);
4576
4577 return result;
4578 }
4579
4580 /*********************************************************************
4581 *********************************************************************/
4582 /* static */
4583 void
4584 OSKext::recordIdentifierRequest(
4585 OSString * kextIdentifier)
4586 {
4587 const OSSymbol * kextIdentifierSymbol = NULL; // must release
4588 bool fail = false;
4589
4590 if (!sAllKextLoadIdentifiers || !kextIdentifier) {
4591 goto finish;
4592 }
4593
4594 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
4595 if (!kextIdentifierSymbol) {
4596 // xxx - this is really a basic alloc failure
4597 fail = true;
4598 goto finish;
4599 }
4600
4601 if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
4602 if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
4603 fail = true;
4604 } else {
4605 // xxx - need to find a way to associate this whole func w/the kext
4606 OSKextLog(/* kext */ NULL,
4607 // xxx - check level
4608 kOSKextLogStepLevel |
4609 kOSKextLogArchiveFlag,
4610 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4611 kextIdentifier->getCStringNoCopy());
4612 }
4613 }
4614 finish:
4615
4616 if (fail) {
4617 OSKextLog(/* kext */ NULL,
4618 kOSKextLogErrorLevel |
4619 kOSKextLogArchiveFlag,
4620 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4621 kextIdentifier->getCStringNoCopy());
4622 }
4623 OSSafeRelease(kextIdentifierSymbol);
4624 return;
4625 }
4626
4627 /*********************************************************************
4628 *********************************************************************/
4629 OSReturn
4630 OSKext::load(
4631 OSKextExcludeLevel startOpt,
4632 OSKextExcludeLevel startMatchingOpt,
4633 OSArray * personalityNames)
4634 {
4635 OSReturn result = kOSReturnError;
4636 kern_return_t kxldResult;
4637 OSKextExcludeLevel dependenciesStartOpt = startOpt;
4638 OSKextExcludeLevel dependenciesStartMatchingOpt = startMatchingOpt;
4639 unsigned int i, count;
4640 Boolean alreadyLoaded = false;
4641 OSKext * lastLoadedKext = NULL;
4642
4643 if (isInExcludeList()) {
4644 OSKextLog(this,
4645 kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
4646 kOSKextLogLoadFlag,
4647 "Kext %s is in exclude list, not loadable",
4648 getIdentifierCString());
4649
4650 result = kOSKextReturnNotLoadable;
4651 goto finish;
4652 }
4653
4654 if (isLoaded()) {
4655 alreadyLoaded = true;
4656 result = kOSReturnSuccess;
4657
4658 OSKextLog(this,
4659 kOSKextLogDebugLevel |
4660 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4661 "Kext %s is already loaded.",
4662 getIdentifierCString());
4663 goto loaded;
4664 }
4665
4666 if (!sLoadEnabled) {
4667 OSKextLog(this,
4668 kOSKextLogErrorLevel |
4669 kOSKextLogLoadFlag,
4670 "Kext loading is disabled (attempt to load kext %s).",
4671 getIdentifierCString());
4672 result = kOSKextReturnDisabled;
4673 goto finish;
4674 }
4675
4676 /* If we've pushed the next available load tag to the invalid value,
4677 * we can't load any more kexts.
4678 */
4679 if (sNextLoadTag == kOSKextInvalidLoadTag) {
4680 OSKextLog(this,
4681 kOSKextLogErrorLevel |
4682 kOSKextLogLoadFlag,
4683 "Can't load kext %s - no more load tags to assign.",
4684 getIdentifierCString());
4685 result = kOSKextReturnNoResources;
4686 goto finish;
4687 }
4688
4689 /* This is a bit of a hack, because we shouldn't be handling
4690 * personalities within the load function.
4691 */
4692 if (!declaresExecutable()) {
4693 result = kOSReturnSuccess;
4694 goto loaded;
4695 }
4696
4697 /* Are we in safe boot?
4698 */
4699 if (sSafeBoot && !isLoadableInSafeBoot()) {
4700 OSKextLog(this,
4701 kOSKextLogErrorLevel |
4702 kOSKextLogLoadFlag,
4703 "Can't load kext %s - not loadable during safe boot.",
4704 getIdentifierCString());
4705 result = kOSKextReturnBootLevel;
4706 goto finish;
4707 }
4708
4709 OSKextLog(this,
4710 kOSKextLogProgressLevel | kOSKextLogLoadFlag,
4711 "Loading kext %s.",
4712 getIdentifierCString());
4713
4714
4715 if (!sKxldContext) {
4716 kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
4717 &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
4718 /* cputype */ 0, /* cpusubtype */ 0);
4719 if (kxldResult) {
4720 OSKextLog(this,
4721 kOSKextLogErrorLevel |
4722 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
4723 "Can't load kext %s - failed to create link context.",
4724 getIdentifierCString());
4725 result = kOSKextReturnNoMemory;
4726 goto finish;
4727 }
4728 }
4729
4730 /* We only need to resolve dependencies once for the whole graph, but
4731 * resolveDependencies will just return if there's no work to do, so it's
4732 * safe to call it more than once.
4733 */
4734 if (!resolveDependencies()) {
4735 // xxx - check resolveDependencies() for log msg
4736 OSKextLog(this,
4737 kOSKextLogErrorLevel |
4738 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4739 "Can't load kext %s - failed to resolve library dependencies.",
4740 getIdentifierCString());
4741 result = kOSKextReturnDependencies;
4742 goto finish;
4743 }
4744
4745 /* If we are excluding just the kext being loaded now (and not its
4746 * dependencies), drop the exclusion level to none so dependencies
4747 * start and/or add their personalities.
4748 */
4749 if (dependenciesStartOpt == kOSKextExcludeKext) {
4750 dependenciesStartOpt = kOSKextExcludeNone;
4751 }
4752
4753 if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
4754 dependenciesStartMatchingOpt = kOSKextExcludeNone;
4755 }
4756
4757 /* Load the dependencies, recursively.
4758 */
4759 count = getNumDependencies();
4760 for (i = 0; i < count; i++) {
4761 OSKext * dependency = OSDynamicCast(OSKext,
4762 dependencies->getObject(i));
4763 if (dependency == NULL) {
4764 OSKextLog(this,
4765 kOSKextLogErrorLevel |
4766 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4767 "Internal error loading kext %s; dependency disappeared.",
4768 getIdentifierCString());
4769 result = kOSKextReturnInternalError;
4770 goto finish;
4771 }
4772
4773 /* Dependencies must be started accorting to the opt,
4774 * but not given the personality names of the main kext.
4775 */
4776 result = dependency->load(dependenciesStartOpt,
4777 dependenciesStartMatchingOpt,
4778 /* personalityNames */ NULL);
4779 if (result != KERN_SUCCESS) {
4780 OSKextLog(this,
4781 kOSKextLogErrorLevel |
4782 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4783 "Dependency %s of kext %s failed to load.",
4784 dependency->getIdentifierCString(),
4785 getIdentifierCString());
4786
4787 OSKext::removeKext(dependency,
4788 /* terminateService/removePersonalities */ true);
4789 result = kOSKextReturnDependencyLoadError;
4790
4791 goto finish;
4792 }
4793 }
4794
4795 result = loadExecutable();
4796 if (result != KERN_SUCCESS) {
4797 goto finish;
4798 }
4799
4800 flags.loaded = true;
4801
4802 /* Add the kext to the list of loaded kexts and update the kmod_info
4803 * struct to point to that of the last loaded kext (which is the way
4804 * it's always been done, though I'd rather do them in order now).
4805 */
4806 lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
4807 sLoadedKexts->setObject(this);
4808
4809 /* Keep the kernel itself out of the kmod list.
4810 */
4811 if (lastLoadedKext->isKernel()) {
4812 lastLoadedKext = NULL;
4813 }
4814
4815 if (lastLoadedKext) {
4816 kmod_info->next = lastLoadedKext->kmod_info;
4817 }
4818
4819 notifyKextLoadObservers(this, kmod_info);
4820
4821 /* Make the global kmod list point at the just-loaded kext. Note that the
4822 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
4823 * although we do report it in kextstat these days by using the newer
4824 * OSArray of loaded kexts, which does contain it.
4825 *
4826 * (The OSKext object representing the kernel doesn't even have a kmod_info
4827 * struct, though I suppose we could stick a pointer to it from the
4828 * static struct in OSRuntime.cpp.)
4829 */
4830 kmod = kmod_info;
4831
4832 /* Save the list of loaded kexts in case we panic.
4833 */
4834 OSKext::saveLoadedKextPanicList();
4835
4836 if (isExecutable()) {
4837 OSKext::updateLoadedKextSummaries();
4838 savePanicString(/* isLoading */ true);
4839
4840 #if CONFIG_DTRACE
4841 registerWithDTrace();
4842 #else
4843 jettisonLinkeditSegment();
4844 #endif /* CONFIG_DTRACE */
4845 }
4846
4847 loaded:
4848 if (isExecutable() && !flags.started) {
4849 if (startOpt == kOSKextExcludeNone) {
4850 result = start();
4851 if (result != kOSReturnSuccess) {
4852 OSKextLog(this,
4853 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
4854 "Kext %s start failed (result 0x%x).",
4855 getIdentifierCString(), result);
4856 result = kOSKextReturnStartStopError;
4857 }
4858 }
4859 }
4860
4861 /* If not excluding matching, send the personalities to the kernel.
4862 * This never affects the result of the load operation.
4863 * This is a bit of a hack, because we shouldn't be handling
4864 * personalities within the load function.
4865 */
4866 if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
4867 result = sendPersonalitiesToCatalog(true, personalityNames);
4868 }
4869
4870 finish:
4871
4872 /* More hack! If the kext doesn't declare an executable, even if we
4873 * "loaded" it, we have to remove any personalities naming it, or we'll
4874 * never see the registry go quiet. Errors here do not count for the
4875 * load operation itself.
4876 *
4877 * Note that in every other regard it's perfectly ok for a kext to
4878 * not declare an executable and serve only as a package for personalities
4879 * naming another kext, so we do have to allow such kexts to be "loaded"
4880 * so that those other personalities get added & matched.
4881 */
4882 if (!declaresExecutable()) {
4883 OSKextLog(this,
4884 kOSKextLogStepLevel | kOSKextLogLoadFlag,
4885 "Kext %s has no executable; removing any personalities naming it.",
4886 getIdentifierCString());
4887 removePersonalitiesFromCatalog();
4888 }
4889
4890 if (result != kOSReturnSuccess) {
4891 OSKextLog(this,
4892 kOSKextLogErrorLevel |
4893 kOSKextLogLoadFlag,
4894 "Kext %s failed to load (0x%x).",
4895 getIdentifierCString(), (int)result);
4896 } else if (!alreadyLoaded) {
4897 OSKextLog(this,
4898 kOSKextLogProgressLevel |
4899 kOSKextLogLoadFlag,
4900 "Kext %s loaded.",
4901 getIdentifierCString());
4902
4903 queueKextNotification(kKextRequestPredicateLoadNotification,
4904 OSDynamicCast(OSString, bundleID));
4905 }
4906 return result;
4907 }
4908
4909 /*********************************************************************
4910 *
4911 *********************************************************************/
4912 static char * strdup(const char * string)
4913 {
4914 char * result = NULL;
4915 size_t size;
4916
4917 if (!string) {
4918 goto finish;
4919 }
4920
4921 size = 1 + strlen(string);
4922 result = (char *)kalloc(size);
4923 if (!result) {
4924 goto finish;
4925 }
4926
4927 memcpy(result, string, size);
4928
4929 finish:
4930 return result;
4931 }
4932
4933 /*********************************************************************
4934 *
4935 *********************************************************************/
4936 OSReturn
4937 OSKext::slidePrelinkedExecutable()
4938 {
4939 OSReturn result = kOSKextReturnBadData;
4940 kernel_mach_header_t * mh = NULL;
4941 kernel_segment_command_t * seg = NULL;
4942 kernel_segment_command_t * linkeditSeg = NULL;
4943 kernel_section_t * sec = NULL;
4944 char * linkeditBase = NULL;
4945 bool haveLinkeditBase = false;
4946 char * relocBase = NULL;
4947 bool haveRelocBase = false;
4948 struct dysymtab_command * dysymtab = NULL;
4949 struct symtab_command * symtab = NULL;
4950 kernel_nlist_t * sym = NULL;
4951 struct relocation_info * reloc = NULL;
4952 uint32_t i = 0;
4953 int reloc_size;
4954 vm_offset_t new_kextsize;
4955
4956 if (linkedExecutable == NULL || vm_kernel_slide == 0) {
4957 result = kOSReturnSuccess;
4958 goto finish;
4959 }
4960
4961 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
4962
4963 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
4964 if (!seg->vmaddr) {
4965 continue;
4966 }
4967 seg->vmaddr += vm_kernel_slide;
4968
4969 #if KASLR_KEXT_DEBUG
4970 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
4971 seg->segname,
4972 (unsigned long)VM_KERNEL_UNSLIDE(seg->vmaddr),
4973 (unsigned long)seg->vmaddr);
4974 #endif
4975
4976 if (!haveRelocBase) {
4977 relocBase = (char *) seg->vmaddr;
4978 haveRelocBase = true;
4979 }
4980 if (!strcmp(seg->segname, "__LINKEDIT")) {
4981 linkeditBase = (char *) seg->vmaddr - seg->fileoff;
4982 haveLinkeditBase = true;
4983 linkeditSeg = seg;
4984 }
4985 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
4986 sec->addr += vm_kernel_slide;
4987
4988 #if KASLR_KEXT_DEBUG
4989 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
4990 sec->sectname,
4991 (unsigned long)VM_KERNEL_UNSLIDE(sec->addr),
4992 (unsigned long)sec->addr);
4993 #endif
4994 }
4995 }
4996
4997 dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
4998
4999 symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
5000
5001 if (symtab != NULL) {
5002 /* Some pseudo-kexts have symbol tables without segments.
5003 * Ignore them. */
5004 if (symtab->nsyms > 0 && haveLinkeditBase) {
5005 sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
5006 for (i = 0; i < symtab->nsyms; i++) {
5007 if (sym[i].n_type & N_STAB) {
5008 continue;
5009 }
5010 sym[i].n_value += vm_kernel_slide;
5011
5012 #if KASLR_KEXT_DEBUG
5013 #define MAX_SYMS_TO_LOG 5
5014 if ( i < MAX_SYMS_TO_LOG ) {
5015 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
5016 (unsigned long)VM_KERNEL_UNSLIDE(sym[i].n_value),
5017 (unsigned long)sym[i].n_value);
5018 }
5019 #endif
5020 }
5021 }
5022 }
5023
5024 if (dysymtab != NULL) {
5025 if (dysymtab->nextrel > 0) {
5026 OSKextLog(this,
5027 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5028 kOSKextLogLinkFlag,
5029 "Sliding kext %s: External relocations found.",
5030 getIdentifierCString());
5031 goto finish;
5032 }
5033
5034 if (dysymtab->nlocrel > 0) {
5035 if (!haveLinkeditBase) {
5036 OSKextLog(this,
5037 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5038 kOSKextLogLinkFlag,
5039 "Sliding kext %s: No linkedit segment.",
5040 getIdentifierCString());
5041 goto finish;
5042 }
5043
5044 if (!haveRelocBase) {
5045 OSKextLog(this,
5046 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5047 kOSKextLogLinkFlag,
5048 #if __x86_64__
5049 "Sliding kext %s: No writable segments.",
5050 #else
5051 "Sliding kext %s: No segments.",
5052 #endif
5053 getIdentifierCString());
5054 goto finish;
5055 }
5056
5057 reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
5058 reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
5059
5060 for (i = 0; i < dysymtab->nlocrel; i++) {
5061 if ( reloc[i].r_extern != 0
5062 || reloc[i].r_type != 0
5063 || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
5064 ) {
5065 OSKextLog(this,
5066 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5067 kOSKextLogLinkFlag,
5068 "Sliding kext %s: Unexpected relocation found.",
5069 getIdentifierCString());
5070 goto finish;
5071 }
5072 if (reloc[i].r_pcrel != 0) {
5073 continue;
5074 }
5075 *((uintptr_t *)(relocBase + reloc[i].r_address)) += vm_kernel_slide;
5076
5077 #if KASLR_KEXT_DEBUG
5078 #define MAX_DYSYMS_TO_LOG 5
5079 if ( i < MAX_DYSYMS_TO_LOG ) {
5080 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
5081 (unsigned long)VM_KERNEL_UNSLIDE(*((uintptr_t *)(relocBase + reloc[i].r_address))),
5082 (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
5083 }
5084 #endif
5085 }
5086
5087 /* We should free these relocations, not just delete the reference to them.
5088 * <rdar://problem/10535549> Free relocations from PIE kexts.
5089 */
5090 new_kextsize = round_page(kmod_info->size - reloc_size);
5091
5092 if ((kmod_info->size - new_kextsize) > PAGE_SIZE) {
5093 vm_offset_t endofkext = kmod_info->address + kmod_info->size;
5094 vm_offset_t new_endofkext = kmod_info->address + new_kextsize;
5095 vm_offset_t endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
5096 int bytes_remaining = endofkext - endofrelocInfo;
5097 OSData * new_osdata = NULL;
5098
5099 /* fix up symbol offsets if they are after the dsymtab local relocs */
5100 if (symtab) {
5101 if (dysymtab->locreloff < symtab->symoff){
5102 symtab->symoff -= reloc_size;
5103 }
5104 if (dysymtab->locreloff < symtab->stroff) {
5105 symtab->stroff -= reloc_size;
5106 }
5107 }
5108 if (dysymtab->locreloff < dysymtab->extreloff) {
5109 dysymtab->extreloff -= reloc_size;
5110 }
5111
5112 /* move data behind reloc info down to new offset */
5113 if (endofrelocInfo < endofkext) {
5114 memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
5115 }
5116
5117 /* Create a new OSData for the smaller kext object and reflect
5118 * new linkedit segment size.
5119 */
5120 linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
5121 linkeditSeg->filesize = linkeditSeg->vmsize;
5122
5123 new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, new_kextsize);
5124 if (new_osdata) {
5125 /* Fix up kmod info and linkedExecutable.
5126 */
5127 kmod_info->size = new_kextsize;
5128 #if VM_MAPPED_KEXTS
5129 new_osdata->setDeallocFunction(osdata_kext_free);
5130 #else
5131 new_osdata->setDeallocFunction(osdata_phys_free);
5132 #endif
5133 linkedExecutable->setDeallocFunction(NULL);
5134 linkedExecutable->release();
5135 linkedExecutable = new_osdata;
5136
5137 #if VM_MAPPED_KEXTS
5138 kext_free(new_endofkext, (endofkext - new_endofkext));
5139 #else
5140 ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
5141 #endif
5142 }
5143 }
5144 dysymtab->nlocrel = 0;
5145 dysymtab->locreloff = 0;
5146 }
5147 }
5148
5149 result = kOSReturnSuccess;
5150 finish:
5151 return result;
5152 }
5153
5154 /*********************************************************************
5155 * called only by load()
5156 *********************************************************************/
5157 OSReturn
5158 OSKext::loadExecutable()
5159 {
5160 OSReturn result = kOSReturnError;
5161 kern_return_t kxldResult;
5162 KXLDDependency * kxlddeps = NULL; // must kfree
5163 uint32_t num_kxlddeps = 0;
5164 OSArray * linkDependencies = NULL; // must release
5165 uint32_t numDirectDependencies = 0;
5166 uint32_t num_kmod_refs = 0;
5167 struct mach_header ** kxldHeaderPtr = NULL; // do not free
5168 struct mach_header * kxld_header = NULL; // xxx - need to free here?
5169 OSData * theExecutable = NULL; // do not release
5170 OSString * versString = NULL; // do not release
5171 const char * versCString = NULL; // do not free
5172 const char * string = NULL; // do not free
5173 unsigned int i;
5174
5175 /* We need the version string for a variety of bits below.
5176 */
5177 versString = OSDynamicCast(OSString,
5178 getPropertyForHostArch(kCFBundleVersionKey));
5179 if (!versString) {
5180 goto finish;
5181 }
5182 versCString = versString->getCStringNoCopy();
5183
5184 if (isKernelComponent()) {
5185 if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
5186
5187 if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
5188 OSKextLog(this,
5189 kOSKextLogErrorLevel |
5190 kOSKextLogLoadFlag,
5191 "Kernel component %s has incorrect version %s; "
5192 "expected %s.",
5193 getIdentifierCString(),
5194 versCString, KERNEL6_VERSION);
5195 result = kOSKextReturnInternalError;
5196 goto finish;
5197 } else if (strcmp(versCString, osrelease)) {
5198 OSKextLog(this,
5199 kOSKextLogErrorLevel |
5200 kOSKextLogLoadFlag,
5201 "Kernel component %s has incorrect version %s; "
5202 "expected %s.",
5203 getIdentifierCString(),
5204 versCString, osrelease);
5205 result = kOSKextReturnInternalError;
5206 goto finish;
5207 }
5208 }
5209 }
5210
5211 if (isPrelinked()) {
5212 result = slidePrelinkedExecutable();
5213 if (result != kOSReturnSuccess) {
5214 goto finish;
5215 }
5216 goto register_kmod;
5217 }
5218
5219 theExecutable = getExecutable();
5220 if (!theExecutable) {
5221 if (declaresExecutable()) {
5222 OSKextLog(this,
5223 kOSKextLogErrorLevel |
5224 kOSKextLogLoadFlag,
5225 "Can't load kext %s - executable is missing.",
5226 getIdentifierCString());
5227 result = kOSKextReturnValidation;
5228 goto finish;
5229 }
5230 goto register_kmod;
5231 }
5232
5233 if (isInterface()) {
5234 OSData *executableCopy = OSData::withData(theExecutable);
5235 setLinkedExecutable(executableCopy);
5236 executableCopy->release();
5237 goto register_kmod;
5238 }
5239
5240 numDirectDependencies = getNumDependencies();
5241
5242 if (flags.hasBleedthrough) {
5243 linkDependencies = dependencies;
5244 linkDependencies->retain();
5245 } else {
5246 linkDependencies = OSArray::withArray(dependencies);
5247 if (!linkDependencies) {
5248 OSKextLog(this,
5249 kOSKextLogErrorLevel |
5250 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5251 "Can't allocate link dependencies to load kext %s.",
5252 getIdentifierCString());
5253 goto finish;
5254 }
5255
5256 for (i = 0; i < numDirectDependencies; ++i) {
5257 OSKext * dependencyKext = OSDynamicCast(OSKext,
5258 dependencies->getObject(i));
5259 dependencyKext->addBleedthroughDependencies(linkDependencies);
5260 }
5261 }
5262
5263 num_kxlddeps = linkDependencies->getCount();
5264 if (!num_kxlddeps) {
5265 OSKextLog(this,
5266 kOSKextLogErrorLevel |
5267 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5268 "Can't load kext %s - it has no library dependencies.",
5269 getIdentifierCString());
5270 goto finish;
5271 }
5272
5273 kxlddeps = (KXLDDependency *)kalloc(num_kxlddeps * sizeof(*kxlddeps));
5274 if (!kxlddeps) {
5275 OSKextLog(this,
5276 kOSKextLogErrorLevel |
5277 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5278 "Can't allocate link context to load kext %s.",
5279 getIdentifierCString());
5280 goto finish;
5281 }
5282 bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
5283
5284 for (i = 0; i < num_kxlddeps; ++i ) {
5285 OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
5286
5287 if (dependency->isInterface()) {
5288 OSKext *interfaceTargetKext = NULL;
5289 OSData * interfaceTarget = NULL;
5290
5291 if (dependency->isKernelComponent()) {
5292 interfaceTargetKext = sKernelKext;
5293 interfaceTarget = sKernelKext->linkedExecutable;
5294 } else {
5295 interfaceTargetKext = OSDynamicCast(OSKext,
5296 dependency->dependencies->getObject(0));
5297
5298 interfaceTarget = interfaceTargetKext->linkedExecutable;
5299 }
5300
5301 if (!interfaceTarget) {
5302 // panic?
5303 goto finish;
5304 }
5305
5306 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5307 * it will be useful to have them in the debugger.
5308 * strdup() failing isn't critical right here so we don't check that.
5309 */
5310 kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
5311 kxlddeps[i].kext_size = interfaceTarget->getLength();
5312 kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
5313
5314 kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
5315 kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
5316 kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
5317 } else {
5318 kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
5319 kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
5320 kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
5321 }
5322
5323 kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
5324 }
5325
5326 kxldHeaderPtr = &kxld_header;
5327
5328 #if DEBUG
5329 OSKextLog(this,
5330 kOSKextLogExplicitLevel |
5331 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5332 "Kext %s - calling kxld_link_file:\n"
5333 " kxld_context: %p\n"
5334 " executable: %p executable_length: %d\n"
5335 " user_data: %p\n"
5336 " kxld_dependencies: %p num_dependencies: %d\n"
5337 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5338 getIdentifierCString(), sKxldContext,
5339 theExecutable->getBytesNoCopy(), theExecutable->getLength(),
5340 this, kxlddeps, num_kxlddeps,
5341 kxldHeaderPtr, &kmod_info);
5342 #endif
5343
5344 /* After this call, the linkedExecutable instance variable
5345 * should exist.
5346 */
5347 kxldResult = kxld_link_file(sKxldContext,
5348 (u_char *)theExecutable->getBytesNoCopy(),
5349 theExecutable->getLength(),
5350 getIdentifierCString(), this, kxlddeps, num_kxlddeps,
5351 (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
5352
5353 if (kxldResult != KERN_SUCCESS) {
5354 // xxx - add kxldResult here?
5355 OSKextLog(this,
5356 kOSKextLogErrorLevel |
5357 kOSKextLogLoadFlag,
5358 "Can't load kext %s - link failed.",
5359 getIdentifierCString());
5360 result = kOSKextReturnLinkError;
5361 goto finish;
5362 }
5363
5364 /* We've written data & instructions into kernel memory, so flush the data
5365 * cache and invalidate the instruction cache.
5366 * I/D caches are coherent on x86
5367 */
5368 #if !defined(__i386__) && !defined(__x86_64__)
5369 flush_dcache(kmod_info->address, kmod_info->size, false);
5370 invalidate_icache(kmod_info->address, kmod_info->size, false);
5371 #endif
5372 register_kmod:
5373
5374 if (isInterface()) {
5375
5376 /* Whip up a fake kmod_info entry for the interface kext.
5377 */
5378 kmod_info = (kmod_info_t *)kalloc(sizeof(kmod_info_t));
5379 if (!kmod_info) {
5380 result = KERN_MEMORY_ERROR;
5381 goto finish;
5382 }
5383
5384 /* A pseudokext has almost nothing in its kmod_info struct.
5385 */
5386 bzero(kmod_info, sizeof(kmod_info_t));
5387
5388 kmod_info->info_version = KMOD_INFO_VERSION;
5389
5390 /* An interface kext doesn't have a linkedExecutable, so save a
5391 * copy of the UUID out of the original executable via copyUUID()
5392 * while we still have the original executable.
5393 */
5394 interfaceUUID = copyUUID();
5395 }
5396
5397 kmod_info->id = loadTag = sNextLoadTag++;
5398 kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid).
5399
5400 /* Stamp the bundle ID and version from the OSKext over anything
5401 * resident inside the kmod_info.
5402 */
5403 string = getIdentifierCString();
5404 strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
5405
5406 string = versCString;
5407 strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
5408
5409 /* Add the dependencies' kmod_info structs as kmod_references.
5410 */
5411 num_kmod_refs = getNumDependencies();
5412 if (num_kmod_refs) {
5413 kmod_info->reference_list = (kmod_reference_t *)kalloc(
5414 num_kmod_refs * sizeof(kmod_reference_t));
5415 if (!kmod_info->reference_list) {
5416 result = KERN_MEMORY_ERROR;
5417 goto finish;
5418 }
5419 bzero(kmod_info->reference_list,
5420 num_kmod_refs * sizeof(kmod_reference_t));
5421 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
5422 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
5423 OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
5424 ref->info = refKext->kmod_info;
5425 ref->info->reference_count++;
5426
5427 if (refIndex + 1 < num_kmod_refs) {
5428 ref->next = kmod_info->reference_list + refIndex + 1;
5429 }
5430 }
5431 }
5432
5433 if (!isInterface() && linkedExecutable) {
5434 OSKextLog(this,
5435 kOSKextLogProgressLevel |
5436 kOSKextLogLoadFlag,
5437 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5438 kmod_info->name,
5439 (unsigned)kmod_info->size / PAGE_SIZE,
5440 (unsigned long)VM_KERNEL_UNSLIDE(kmod_info->address),
5441 (unsigned)kmod_info->id);
5442 }
5443
5444 result = setVMProtections();
5445 if (result != KERN_SUCCESS) {
5446 goto finish;
5447 }
5448
5449 result = kOSReturnSuccess;
5450
5451 finish:
5452 OSSafeRelease(linkDependencies);
5453
5454 /* Clear up locally allocated dependency info.
5455 */
5456 for (i = 0; i < num_kxlddeps; ++i ) {
5457 size_t size;
5458
5459 if (kxlddeps[i].kext_name) {
5460 size = 1 + strlen(kxlddeps[i].kext_name);
5461 kfree(kxlddeps[i].kext_name, size);
5462 }
5463 if (kxlddeps[i].interface_name) {
5464 size = 1 + strlen(kxlddeps[i].interface_name);
5465 kfree(kxlddeps[i].interface_name, size);
5466 }
5467 }
5468 if (kxlddeps) kfree(kxlddeps, (num_kxlddeps * sizeof(*kxlddeps)));
5469
5470 /* We no longer need the unrelocated executable (which the linker
5471 * has altered anyhow).
5472 */
5473 setExecutable(NULL);
5474
5475 if (result != kOSReturnSuccess) {
5476 OSKextLog(this,
5477 kOSKextLogErrorLevel |
5478 kOSKextLogLoadFlag,
5479 "Failed to load executable for kext %s.",
5480 getIdentifierCString());
5481
5482 if (kmod_info && kmod_info->reference_list) {
5483 kfree(kmod_info->reference_list,
5484 num_kmod_refs * sizeof(kmod_reference_t));
5485 }
5486 if (isInterface()) {
5487 kfree(kmod_info, sizeof(kmod_info_t));
5488 }
5489 kmod_info = NULL;
5490 if (linkedExecutable) {
5491 linkedExecutable->release();
5492 linkedExecutable = NULL;
5493 }
5494 }
5495
5496 return result;
5497 }
5498
5499 /*********************************************************************
5500 * The linkedit segment is used by the kext linker for dependency
5501 * resolution, and by dtrace for probe initialization. We can free it
5502 * for non-library kexts, since no kexts depend on non-library kexts
5503 * by definition, once dtrace has been initialized.
5504 *********************************************************************/
5505 void
5506 OSKext::jettisonLinkeditSegment(void)
5507 {
5508 kernel_mach_header_t * machhdr = (kernel_mach_header_t *)kmod_info->address;
5509 kernel_segment_command_t * linkedit = NULL;
5510 vm_offset_t start;
5511 vm_size_t linkeditsize, kextsize;
5512 OSData * data = NULL;
5513
5514 #if NO_KEXTD
5515 /* We can free symbol tables for all embedded kexts because we don't
5516 * support runtime kext linking.
5517 */
5518 if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
5519 #else
5520 if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
5521 #endif
5522 goto finish;
5523 }
5524
5525 /* Find the linkedit segment. If it's not the last segment, then freeing
5526 * it will fragment the kext into multiple VM regions, which OSKext is not
5527 * designed to handle, so we'll have to skip it.
5528 */
5529 linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
5530 if (!linkedit) {
5531 goto finish;
5532 }
5533
5534 if (round_page(kmod_info->address + kmod_info->size) !=
5535 round_page(linkedit->vmaddr + linkedit->vmsize))
5536 {
5537 goto finish;
5538 }
5539
5540 /* Create a new OSData for the smaller kext object.
5541 */
5542 linkeditsize = round_page(linkedit->vmsize);
5543 kextsize = kmod_info->size - linkeditsize;
5544 start = linkedit->vmaddr;
5545
5546 data = OSData::withBytesNoCopy((void *)kmod_info->address, kextsize);
5547 if (!data) {
5548 goto finish;
5549 }
5550
5551 /* Fix the kmod info and linkedExecutable.
5552 */
5553 kmod_info->size = kextsize;
5554
5555 #if VM_MAPPED_KEXTS
5556 data->setDeallocFunction(osdata_kext_free);
5557 #else
5558 data->setDeallocFunction(osdata_phys_free);
5559 #endif
5560 linkedExecutable->setDeallocFunction(NULL);
5561 linkedExecutable->release();
5562 linkedExecutable = data;
5563 flags.jettisonLinkeditSeg = 1;
5564
5565 /* Free the linkedit segment.
5566 */
5567 #if VM_MAPPED_KEXTS
5568 kext_free(start, linkeditsize);
5569 #else
5570 ml_static_mfree(start, linkeditsize);
5571 #endif
5572
5573 finish:
5574 return;
5575 }
5576
5577 /*********************************************************************
5578 *********************************************************************/
5579 void
5580 OSKext::setLinkedExecutable(OSData * anExecutable)
5581 {
5582 if (linkedExecutable) {
5583 panic("Attempt to set linked executable on kext "
5584 "that already has one (%s).\n",
5585 getIdentifierCString());
5586 }
5587 linkedExecutable = anExecutable;
5588 linkedExecutable->retain();
5589 return;
5590 }
5591
5592 #if CONFIG_DTRACE
5593 /*********************************************************************
5594 * Go through all loaded kexts and tell them to register with dtrace.
5595 * The instance method only registers if necessary.
5596 *********************************************************************/
5597 /* static */
5598 void
5599 OSKext::registerKextsWithDTrace(void)
5600 {
5601 uint32_t count = sLoadedKexts->getCount();
5602 uint32_t i;
5603
5604 IORecursiveLockLock(sKextLock);
5605
5606 for (i = 0; i < count; i++) {
5607 OSKext * thisKext = NULL; // do not release
5608
5609 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
5610 if (!thisKext || !thisKext->isExecutable()) {
5611 continue;
5612 }
5613
5614 thisKext->registerWithDTrace();
5615 }
5616
5617 IORecursiveLockUnlock(sKextLock);
5618
5619 return;
5620 }
5621
5622 extern "C" {
5623 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
5624 extern int (*dtrace_modunload)(struct kmod_info *);
5625 };
5626
5627 /*********************************************************************
5628 *********************************************************************/
5629 void
5630 OSKext::registerWithDTrace(void)
5631 {
5632 /* Register kext with dtrace. A dtrace_modload failure should not
5633 * prevent a kext from loading, so we ignore the return code.
5634 */
5635 if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
5636 uint32_t modflag = 0;
5637 OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
5638 if (forceInit == kOSBooleanTrue) {
5639 modflag |= KMOD_DTRACE_FORCE_INIT;
5640 }
5641
5642 (void)(*dtrace_modload)(kmod_info, modflag);
5643 flags.dtraceInitialized = true;
5644 jettisonLinkeditSegment();
5645 }
5646 return;
5647 }
5648 /*********************************************************************
5649 *********************************************************************/
5650 void
5651 OSKext::unregisterWithDTrace(void)
5652 {
5653 /* Unregister kext with dtrace. A dtrace_modunload failure should not
5654 * prevent a kext from loading, so we ignore the return code.
5655 */
5656 if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
5657 (void)(*dtrace_modunload)(kmod_info);
5658 flags.dtraceInitialized = false;
5659 }
5660 return;
5661 }
5662 #endif /* CONFIG_DTRACE */
5663
5664
5665 /*********************************************************************
5666 * called only by loadExecutable()
5667 *********************************************************************/
5668 #if !VM_MAPPED_KEXTS
5669 #error Unrecognized architecture
5670 #else
5671 static inline kern_return_t
5672 OSKext_protect(
5673 vm_map_t map,
5674 vm_map_offset_t start,
5675 vm_map_offset_t end,
5676 vm_prot_t new_prot,
5677 boolean_t set_max)
5678 {
5679 if (start == end) { // 10538581
5680 return(KERN_SUCCESS);
5681 }
5682 return vm_map_protect(map, start, end, new_prot, set_max);
5683 }
5684
5685 static inline kern_return_t
5686 OSKext_wire(
5687 vm_map_t map,
5688 vm_map_offset_t start,
5689 vm_map_offset_t end,
5690 vm_prot_t access_type,
5691 boolean_t user_wire)
5692 {
5693 return vm_map_wire(map, start, end, access_type, user_wire);
5694 }
5695 #endif
5696
5697 OSReturn
5698 OSKext::setVMProtections(void)
5699 {
5700 vm_map_t kext_map = NULL;
5701 kernel_segment_command_t * seg = NULL;
5702 vm_map_offset_t start = 0;
5703 vm_map_offset_t end = 0;
5704 OSReturn result = kOSReturnError;
5705
5706 if (!kmod_info->address && !kmod_info->size) {
5707 result = kOSReturnSuccess;
5708 goto finish;
5709 }
5710
5711 /* Get the kext's vm map */
5712 kext_map = kext_get_vm_map(kmod_info);
5713 if (!kext_map) {
5714 result = KERN_MEMORY_ERROR;
5715 goto finish;
5716 }
5717
5718 /* Protect the headers as read-only; they do not need to be wired */
5719 result = OSKext_protect(kext_map, kmod_info->address,
5720 kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE);
5721 if (result != KERN_SUCCESS) {
5722 goto finish;
5723 }
5724
5725 /* Set the VM protections and wire down each of the segments */
5726 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
5727 while (seg) {
5728 start = round_page(seg->vmaddr);
5729 end = trunc_page(seg->vmaddr + seg->vmsize);
5730
5731 result = OSKext_protect(kext_map, start, end, seg->maxprot, TRUE);
5732 if (result != KERN_SUCCESS) {
5733 OSKextLog(this,
5734 kOSKextLogErrorLevel |
5735 kOSKextLogLoadFlag,
5736 "Kext %s failed to set maximum VM protections "
5737 "for segment %s - 0x%x.",
5738 getIdentifierCString(), seg->segname, (int)result);
5739 goto finish;
5740 }
5741
5742 result = OSKext_protect(kext_map, start, end, seg->initprot, FALSE);
5743 if (result != KERN_SUCCESS) {
5744 OSKextLog(this,
5745 kOSKextLogErrorLevel |
5746 kOSKextLogLoadFlag,
5747 "Kext %s failed to set initial VM protections "
5748 "for segment %s - 0x%x.",
5749 getIdentifierCString(), seg->segname, (int)result);
5750 goto finish;
5751 }
5752
5753 if (segmentShouldBeWired(seg)) {
5754 result = OSKext_wire(kext_map, start, end, seg->initprot, FALSE);
5755 if (result != KERN_SUCCESS) {
5756 goto finish;
5757 }
5758 }
5759
5760 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
5761 }
5762
5763 finish:
5764 return result;
5765 }
5766
5767 /*********************************************************************
5768 *********************************************************************/
5769 boolean_t
5770 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
5771 {
5772 return (sKeepSymbols || strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname)));
5773 }
5774
5775 /*********************************************************************
5776 *********************************************************************/
5777 OSReturn
5778 OSKext::validateKextMapping(bool startFlag)
5779 {
5780 OSReturn result = kOSReturnError;
5781 const char * whichOp = startFlag ? "start" : "stop";
5782 kern_return_t kern_result = 0;
5783 vm_map_t kext_map = NULL;
5784 kernel_segment_command_t * seg = NULL;
5785 mach_vm_address_t address = 0;
5786 mach_vm_size_t size = 0;
5787 uint32_t depth = 0;
5788 mach_msg_type_number_t count;
5789 vm_region_submap_short_info_data_64_t info;
5790
5791 count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
5792 bzero(&info, sizeof(info));
5793
5794 // xxx - do we need a distinct OSReturn value for these or is "bad data"
5795 // xxx - sufficient?
5796
5797 /* Verify that the kmod_info and start/stop pointers are non-NULL.
5798 */
5799 if (!kmod_info) {
5800 OSKextLog(this,
5801 kOSKextLogErrorLevel |
5802 kOSKextLogLoadFlag,
5803 "Kext %s - NULL kmod_info pointer.",
5804 getIdentifierCString());
5805 result = kOSKextReturnBadData;
5806 goto finish;
5807 }
5808
5809 if (startFlag) {
5810 address = (mach_vm_address_t)kmod_info->start;
5811 } else {
5812 address = (mach_vm_address_t)kmod_info->stop;
5813 }
5814
5815 if (!address) {
5816 OSKextLog(this,
5817 kOSKextLogErrorLevel |
5818 kOSKextLogLoadFlag,
5819 "Kext %s - NULL module %s pointer.",
5820 getIdentifierCString(), whichOp);
5821 result = kOSKextReturnBadData;
5822 goto finish;
5823 }
5824
5825 kext_map = kext_get_vm_map(kmod_info);
5826 depth = (kernel_map == kext_map) ? 1 : 2;
5827
5828 /* Verify that the start/stop function lies within the kext's address range.
5829 */
5830 if (address < kmod_info->address + kmod_info->hdr_size ||
5831 kmod_info->address + kmod_info->size <= address)
5832 {
5833 OSKextLog(this,
5834 kOSKextLogErrorLevel |
5835 kOSKextLogLoadFlag,
5836 "Kext %s module %s pointer is outside of kext range "
5837 "(%s %p - kext at %p-%p)..",
5838 getIdentifierCString(),
5839 whichOp,
5840 whichOp,
5841 (void *)VM_KERNEL_UNSLIDE(address),
5842 (void *)VM_KERNEL_UNSLIDE(kmod_info->address),
5843 (void *)(VM_KERNEL_UNSLIDE(kmod_info->address) + kmod_info->size));
5844 result = kOSKextReturnBadData;
5845 goto finish;
5846 }
5847
5848 /* Only do these checks before calling the start function;
5849 * If anything goes wrong with the mapping while the kext is running,
5850 * we'll likely have panicked well before any attempt to stop the kext.
5851 */
5852 if (startFlag) {
5853
5854 /* Verify that the start/stop function is executable.
5855 */
5856 kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
5857 (vm_region_recurse_info_t)&info, &count);
5858 if (kern_result != KERN_SUCCESS) {
5859 OSKextLog(this,
5860 kOSKextLogErrorLevel |
5861 kOSKextLogLoadFlag,
5862 "Kext %s - bad %s pointer %p.",
5863 getIdentifierCString(),
5864 whichOp, (void *)VM_KERNEL_UNSLIDE(address));
5865 result = kOSKextReturnBadData;
5866 goto finish;
5867 }
5868
5869 #if VM_MAPPED_KEXTS
5870 if (!(info.protection & VM_PROT_EXECUTE)) {
5871 OSKextLog(this,
5872 kOSKextLogErrorLevel |
5873 kOSKextLogLoadFlag,
5874 "Kext %s - memory region containing module %s function "
5875 "is not executable.",
5876 getIdentifierCString(), whichOp);
5877 result = kOSKextReturnBadData;
5878 goto finish;
5879 }
5880 #endif
5881
5882 /* Verify that the kext's segments are backed by physical memory.
5883 */
5884 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
5885 while (seg) {
5886 if (!verifySegmentMapping(seg)) {
5887 result = kOSKextReturnBadData;
5888 goto finish;
5889 }
5890
5891 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
5892 }
5893
5894 }
5895
5896 result = kOSReturnSuccess;
5897 finish:
5898 return result;
5899 }
5900
5901 /*********************************************************************
5902 *********************************************************************/
5903 boolean_t
5904 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
5905 {
5906 mach_vm_address_t address = 0;
5907
5908 if (!segmentShouldBeWired(seg)) return true;
5909
5910 for (address = seg->vmaddr;
5911 address < round_page(seg->vmaddr + seg->vmsize);
5912 address += PAGE_SIZE)
5913 {
5914 if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
5915 OSKextLog(this,
5916 kOSKextLogErrorLevel |
5917 kOSKextLogLoadFlag,
5918 "Kext %s - page %p is not backed by physical memory.",
5919 getIdentifierCString(),
5920 (void *)address);
5921 return false;
5922 }
5923 }
5924
5925 return true;
5926 }
5927
5928 /*********************************************************************
5929 *********************************************************************/
5930 OSReturn
5931 OSKext::start(bool startDependenciesFlag)
5932 {
5933 OSReturn result = kOSReturnError;
5934 kern_return_t (* startfunc)(kmod_info_t *, void *);
5935 unsigned int i, count;
5936 void * kmodStartData = NULL;
5937
5938 if (isStarted() || isInterface() || isKernelComponent()) {
5939 result = kOSReturnSuccess;
5940 goto finish;
5941 }
5942
5943 if (!isLoaded()) {
5944 OSKextLog(this,
5945 kOSKextLogErrorLevel |
5946 kOSKextLogLoadFlag,
5947 "Attempt to start nonloaded kext %s.",
5948 getIdentifierCString());
5949 result = kOSKextReturnInvalidArgument;
5950 goto finish;
5951 }
5952
5953 if (!sLoadEnabled) {
5954 OSKextLog(this,
5955 kOSKextLogErrorLevel |
5956 kOSKextLogLoadFlag,
5957 "Kext loading is disabled (attempt to start kext %s).",
5958 getIdentifierCString());
5959 result = kOSKextReturnDisabled;
5960 goto finish;
5961 }
5962
5963 result = validateKextMapping(/* start? */ true);
5964 if (result != kOSReturnSuccess) {
5965 goto finish;
5966 }
5967
5968 startfunc = kmod_info->start;
5969
5970 count = getNumDependencies();
5971 for (i = 0; i < count; i++) {
5972 OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
5973 if (dependency == NULL) {
5974 OSKextLog(this,
5975 kOSKextLogErrorLevel |
5976 kOSKextLogLoadFlag,
5977 "Kext %s start - internal error, dependency disappeared.",
5978 getIdentifierCString());
5979 goto finish;
5980 }
5981 if (!dependency->isStarted()) {
5982 if (startDependenciesFlag) {
5983 OSReturn dependencyResult =
5984 dependency->start(startDependenciesFlag);
5985 if (dependencyResult != KERN_SUCCESS) {
5986 OSKextLog(this,
5987 kOSKextLogErrorLevel |
5988 kOSKextLogLoadFlag,
5989 "Kext %s start - dependency %s failed to start (error 0x%x).",
5990 getIdentifierCString(),
5991 dependency->getIdentifierCString(),
5992 dependencyResult);
5993 goto finish;
5994 }
5995 } else {
5996 OSKextLog(this,
5997 kOSKextLogErrorLevel |
5998 kOSKextLogLoadFlag,
5999 "Not starting %s - dependency %s not started yet.",
6000 getIdentifierCString(),
6001 dependency->getIdentifierCString());
6002 result = kOSKextReturnStartStopError; // xxx - make new return?
6003 goto finish;
6004 }
6005 }
6006 }
6007
6008 OSKextLog(this,
6009 kOSKextLogDetailLevel |
6010 kOSKextLogLoadFlag,
6011 "Kext %s calling module start function.",
6012 getIdentifierCString());
6013
6014 flags.starting = 1;
6015
6016 #if !CONFIG_STATIC_CPPINIT
6017 result = OSRuntimeInitializeCPP(kmod_info, NULL);
6018 if (result == KERN_SUCCESS) {
6019 #endif
6020
6021 #if CONFIG_KEC_FIPS
6022 kmodStartData = GetAppleTEXTHashForKext(this, this->infoDict);
6023
6024 #if 0
6025 if (kmodStartData) {
6026 OSKextLog(this,
6027 kOSKextLogErrorLevel |
6028 kOSKextLogGeneralFlag,
6029 "Kext %s calling module start function. kmodStartData %p. arch %s",
6030 getIdentifierCString(), kmodStartData, ARCHNAME);
6031 }
6032 #endif
6033 #endif // CONFIG_KEC_FIPS
6034
6035 result = startfunc(kmod_info, kmodStartData);
6036
6037 #if !CONFIG_STATIC_CPPINIT
6038 if (result != KERN_SUCCESS) {
6039 (void) OSRuntimeFinalizeCPP(kmod_info, NULL);
6040 }
6041 }
6042 #endif
6043
6044 flags.starting = 0;
6045
6046 /* On success overlap the setting of started/starting. On failure just
6047 * clear starting.
6048 */
6049 if (result == KERN_SUCCESS) {
6050 flags.started = 1;
6051
6052 // xxx - log start error from kernel?
6053 OSKextLog(this,
6054 kOSKextLogProgressLevel |
6055 kOSKextLogLoadFlag,
6056 "Kext %s is now started.",
6057 getIdentifierCString());
6058 } else {
6059 invokeOrCancelRequestCallbacks(
6060 /* result not actually used */ kOSKextReturnStartStopError,
6061 /* invokeFlag */ false);
6062 OSKextLog(this,
6063 kOSKextLogProgressLevel |
6064 kOSKextLogLoadFlag,
6065 "Kext %s did not start (return code 0x%x).",
6066 getIdentifierCString(), result);
6067 }
6068
6069 finish:
6070 return result;
6071 }
6072
6073 /*********************************************************************
6074 *********************************************************************/
6075 /* static */
6076 bool OSKext::canUnloadKextWithIdentifier(
6077 OSString * kextIdentifier,
6078 bool checkClassesFlag)
6079 {
6080 bool result = false;
6081 OSKext * aKext = NULL; // do not release
6082
6083 IORecursiveLockLock(sKextLock);
6084
6085 aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
6086
6087 if (!aKext) {
6088 goto finish; // can't unload what's not loaded
6089 }
6090
6091 if (aKext->isLoaded()) {
6092 if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
6093 goto finish;
6094 }
6095 if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
6096 goto finish;
6097 }
6098 }
6099
6100 result = true;
6101
6102 finish:
6103 IORecursiveLockUnlock(sKextLock);
6104 return result;
6105 }
6106
6107 /*********************************************************************
6108 *********************************************************************/
6109 OSReturn
6110 OSKext::stop(void)
6111 {
6112 OSReturn result = kOSReturnError;
6113 kern_return_t (*stopfunc)(kmod_info_t *, void *);
6114
6115 if (!isStarted() || isInterface()) {
6116 result = kOSReturnSuccess;
6117 goto finish;
6118 }
6119
6120 if (!isLoaded()) {
6121 OSKextLog(this,
6122 kOSKextLogErrorLevel |
6123 kOSKextLogLoadFlag,
6124 "Attempt to stop nonloaded kext %s.",
6125 getIdentifierCString());
6126 result = kOSKextReturnInvalidArgument;
6127 goto finish;
6128 }
6129
6130 /* Refuse to stop if we have clients or instances. It is up to
6131 * the caller to make sure those aren't true.
6132 */
6133 if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6134 OSKextLog(this,
6135 kOSKextLogErrorLevel |
6136 kOSKextLogLoadFlag,
6137 "Kext %s - C++ instances; can't stop.",
6138 getIdentifierCString());
6139 result = kOSKextReturnInUse;
6140 goto finish;
6141 }
6142
6143 if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6144
6145 OSKextLog(this,
6146 kOSKextLogErrorLevel |
6147 kOSKextLogLoadFlag,
6148 "Kext %s - has references (linkage or tracking object); "
6149 "can't stop.",
6150 getIdentifierCString());
6151 result = kOSKextReturnInUse;
6152 goto finish;
6153 }
6154
6155 /* Note: If validateKextMapping fails on the stop & unload path,
6156 * we are in serious trouble and a kernel panic is likely whether
6157 * we stop & unload the kext or not.
6158 */
6159 result = validateKextMapping(/* start? */ false);
6160 if (result != kOSReturnSuccess) {
6161 goto finish;
6162 }
6163
6164 stopfunc = kmod_info->stop;
6165 if (stopfunc) {
6166 OSKextLog(this,
6167 kOSKextLogDetailLevel |
6168 kOSKextLogLoadFlag,
6169 "Kext %s calling module stop function.",
6170 getIdentifierCString());
6171
6172 flags.stopping = 1;
6173
6174 result = stopfunc(kmod_info, /* userData */ NULL);
6175 #if !CONFIG_STATIC_CPPINIT
6176 if (result == KERN_SUCCESS) {
6177 result = OSRuntimeFinalizeCPP(kmod_info, NULL);
6178 }
6179 #endif
6180
6181 flags.stopping = 0;
6182
6183 if (result == KERN_SUCCESS) {
6184 flags.started = 0;
6185
6186 OSKextLog(this,
6187 kOSKextLogDetailLevel |
6188 kOSKextLogLoadFlag,
6189 "Kext %s is now stopped and ready to unload.",
6190 getIdentifierCString());
6191 } else {
6192 OSKextLog(this,
6193 kOSKextLogErrorLevel |
6194 kOSKextLogLoadFlag,
6195 "Kext %s did not stop (return code 0x%x).",
6196 getIdentifierCString(), result);
6197 result = kOSKextReturnStartStopError;
6198 }
6199 }
6200
6201 finish:
6202 return result;
6203 }
6204
6205 /*********************************************************************
6206 *********************************************************************/
6207 OSReturn
6208 OSKext::unload(void)
6209 {
6210 OSReturn result = kOSReturnError;
6211 unsigned int index;
6212 uint32_t num_kmod_refs = 0;
6213
6214 if (!sUnloadEnabled) {
6215 OSKextLog(this,
6216 kOSKextLogErrorLevel |
6217 kOSKextLogLoadFlag,
6218 "Kext unloading is disabled (%s).",
6219 this->getIdentifierCString());
6220
6221 result = kOSKextReturnDisabled;
6222 goto finish;
6223 }
6224
6225 /* Refuse to unload if we have clients or instances. It is up to
6226 * the caller to make sure those aren't true.
6227 */
6228 if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6229 // xxx - Don't log under errors? this is more of an info thing
6230 OSKextLog(this,
6231 kOSKextLogErrorLevel |
6232 kOSKextLogKextBookkeepingFlag,
6233 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6234 getIdentifierCString());
6235 result = kOSKextReturnInUse;
6236 goto finish;
6237 }
6238
6239 if (hasOSMetaClassInstances()) {
6240 OSKextLog(this,
6241 kOSKextLogErrorLevel |
6242 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6243 "Can't unload kext %s; classes have instances:",
6244 getIdentifierCString());
6245 reportOSMetaClassInstances(kOSKextLogErrorLevel |
6246 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
6247 result = kOSKextReturnInUse;
6248 goto finish;
6249 }
6250
6251 if (!isLoaded()) {
6252 result = kOSReturnSuccess;
6253 goto finish;
6254 }
6255
6256 if (isKernelComponent()) {
6257 result = kOSKextReturnInvalidArgument;
6258 goto finish;
6259 }
6260
6261 /* Note that the kext is unloading before running any code that
6262 * might be in the kext (request callbacks, module stop function).
6263 * We will deny certain requests made against a kext in the process
6264 * of unloading.
6265 */
6266 flags.unloading = 1;
6267
6268 /* Update the string describing the last kext to unload in case we panic.
6269 */
6270 savePanicString(/* isLoading */ false);
6271
6272 if (isStarted()) {
6273 result = stop();
6274 if (result != KERN_SUCCESS) {
6275 OSKextLog(this,
6276 kOSKextLogErrorLevel |
6277 kOSKextLogLoadFlag,
6278 "Kext %s can't unload - module stop returned 0x%x.",
6279 getIdentifierCString(), (unsigned)result);
6280 result = kOSKextReturnStartStopError;
6281 goto finish;
6282 }
6283 }
6284
6285 OSKextLog(this,
6286 kOSKextLogProgressLevel |
6287 kOSKextLogLoadFlag,
6288 "Kext %s unloading.",
6289 getIdentifierCString());
6290
6291 /* Even if we don't call the stop function, we want to be sure we
6292 * have no OSMetaClass references before unloading the kext executable
6293 * from memory. OSMetaClasses may have pointers into the kext executable
6294 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6295 */
6296 if (metaClasses) {
6297 metaClasses->flushCollection();
6298 }
6299
6300 /* Remove the kext from the list of loaded kexts, patch the gap
6301 * in the kmod_info_t linked list, and reset "kmod" to point to the
6302 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6303 */
6304 index = sLoadedKexts->getNextIndexOfObject(this, 0);
6305 if (index != (unsigned int)-1) {
6306
6307 sLoadedKexts->removeObject(index);
6308
6309 OSKext * nextKext = OSDynamicCast(OSKext,
6310 sLoadedKexts->getObject(index));
6311
6312 if (nextKext) {
6313 if (index > 0) {
6314 OSKext * gapKext = OSDynamicCast(OSKext,
6315 sLoadedKexts->getObject(index - 1));
6316
6317 nextKext->kmod_info->next = gapKext->kmod_info;
6318
6319 } else /* index == 0 */ {
6320 nextKext->kmod_info->next = NULL;
6321 }
6322 }
6323
6324 OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
6325 if (lastKext && !lastKext->isKernel()) {
6326 kmod = lastKext->kmod_info;
6327 } else {
6328 kmod = NULL; // clear the global kmod variable
6329 }
6330 }
6331
6332 /* Clear out the kmod references that we're keeping for compatibility
6333 * with current panic backtrace code & kgmacros.
6334 * xxx - will want to update those bits sometime and remove this.
6335 */
6336 num_kmod_refs = getNumDependencies();
6337 if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
6338 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
6339 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
6340 ref->info->reference_count--;
6341 }
6342 kfree(kmod_info->reference_list,
6343 num_kmod_refs * sizeof(kmod_reference_t));
6344 }
6345
6346 #if CONFIG_DTRACE
6347 unregisterWithDTrace();
6348 #endif /* CONFIG_DTRACE */
6349
6350 notifyKextUnloadObservers(this);
6351
6352 /* Unwire and free the linked executable.
6353 */
6354 if (linkedExecutable) {
6355 #if VM_MAPPED_KEXTS
6356 if (!isInterface()) {
6357 kernel_segment_command_t *seg = NULL;
6358 vm_map_t kext_map = kext_get_vm_map(kmod_info);
6359
6360 if (!kext_map) {
6361 OSKextLog(this,
6362 kOSKextLogErrorLevel |
6363 kOSKextLogLoadFlag,
6364 "Failed to free kext %s; couldn't find the kext map.",
6365 getIdentifierCString());
6366 result = kOSKextReturnInternalError;
6367 goto finish;
6368 }
6369
6370 OSKextLog(this,
6371 kOSKextLogProgressLevel |
6372 kOSKextLogLoadFlag,
6373 "Kext %s unwiring and unmapping linked executable.",
6374 getIdentifierCString());
6375
6376 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6377 while (seg) {
6378 if (segmentShouldBeWired(seg)) {
6379 result = vm_map_unwire(kext_map, seg->vmaddr,
6380 seg->vmaddr + seg->vmsize, FALSE);
6381 if (result != KERN_SUCCESS) {
6382 OSKextLog(this,
6383 kOSKextLogErrorLevel |
6384 kOSKextLogLoadFlag,
6385 "Failed to unwire kext %s.",
6386 getIdentifierCString());
6387 result = kOSKextReturnInternalError;
6388 goto finish;
6389 }
6390 }
6391
6392 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
6393 }
6394 }
6395 #endif
6396 OSSafeReleaseNULL(linkedExecutable);
6397 }
6398
6399 /* An interface kext has a fake kmod_info that was allocated,
6400 * so we have to free it.
6401 */
6402 if (isInterface()) {
6403 kfree(kmod_info, sizeof(kmod_info_t));
6404 }
6405
6406 kmod_info = NULL;
6407
6408 flags.loaded = false;
6409 flushDependencies();
6410
6411 /* save a copy of the bundle ID for us to check when deciding to
6412 * rebuild the kernel cache file. If a kext was already in the kernel
6413 * cache and unloaded then later loaded we do not need to rebuild the
6414 * kernel cache. 9055303
6415 */
6416 if (isPrelinked()) {
6417 if (!_OSKextInUnloadedPrelinkedKexts(bundleID)) {
6418 IORecursiveLockLock(sKextLock);
6419 if (sUnloadedPrelinkedKexts) {
6420 sUnloadedPrelinkedKexts->setObject(bundleID);
6421 }
6422 IORecursiveLockUnlock(sKextLock);
6423 }
6424 }
6425
6426 OSKextLog(this,
6427 kOSKextLogProgressLevel | kOSKextLogLoadFlag,
6428 "Kext %s unloaded.", getIdentifierCString());
6429
6430 queueKextNotification(kKextRequestPredicateUnloadNotification,
6431 OSDynamicCast(OSString, bundleID));
6432
6433 finish:
6434 OSKext::saveLoadedKextPanicList();
6435 OSKext::updateLoadedKextSummaries();
6436
6437 flags.unloading = 0;
6438 return result;
6439 }
6440
6441 /*********************************************************************
6442 * Assumes sKextLock is held.
6443 *********************************************************************/
6444 /* static */
6445 OSReturn
6446 OSKext::queueKextNotification(
6447 const char * notificationName,
6448 OSString * kextIdentifier)
6449 {
6450 OSReturn result = kOSReturnError;
6451 OSDictionary * loadRequest = NULL; // must release
6452
6453 if (!kextIdentifier) {
6454 result = kOSKextReturnInvalidArgument;
6455 goto finish;
6456 }
6457
6458 /* Create a new request unless one is already sitting
6459 * in sKernelRequests for this bundle identifier
6460 */
6461 result = _OSKextCreateRequest(notificationName, &loadRequest);
6462 if (result != kOSReturnSuccess) {
6463 goto finish;
6464 }
6465 if (!_OSKextSetRequestArgument(loadRequest,
6466 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
6467
6468 result = kOSKextReturnNoMemory;
6469 goto finish;
6470 }
6471 if (!sKernelRequests->setObject(loadRequest)) {
6472 result = kOSKextReturnNoMemory;
6473 goto finish;
6474 }
6475
6476 /* We might want to only queue the notification if kextd is active,
6477 * but that wouldn't work for embedded. Note that we don't care if
6478 * the ping immediately succeeds here so don't do anything with the
6479 * result of this call.
6480 */
6481 OSKext::pingKextd();
6482
6483 result = kOSReturnSuccess;
6484
6485 finish:
6486 OSSafeRelease(loadRequest);
6487
6488 return result;
6489 }
6490
6491 /*********************************************************************
6492 *********************************************************************/
6493 static void
6494 _OSKextConsiderDestroyingLinkContext(
6495 __unused thread_call_param_t p0,
6496 __unused thread_call_param_t p1)
6497 {
6498 /* Take multiple locks in the correct order.
6499 */
6500 IORecursiveLockLock(sKextLock);
6501 IORecursiveLockLock(sKextInnerLock);
6502
6503 /* The first time we destroy the kxldContext is in the first
6504 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
6505 * before calling this function. Thereafter any call to this function
6506 * will actually destroy the context.
6507 */
6508 if (sConsiderUnloadsCalled && sKxldContext) {
6509 kxld_destroy_context(sKxldContext);
6510 sKxldContext = NULL;
6511 }
6512
6513 /* Free the thread_call that was allocated to execute this function.
6514 */
6515 if (sDestroyLinkContextThread) {
6516 if (!thread_call_free(sDestroyLinkContextThread)) {
6517 OSKextLog(/* kext */ NULL,
6518 kOSKextLogErrorLevel |
6519 kOSKextLogGeneralFlag,
6520 "thread_call_free() failed for kext link context.");
6521 }
6522 sDestroyLinkContextThread = 0;
6523 }
6524
6525 IORecursiveLockUnlock(sKextInnerLock);
6526 IORecursiveLockUnlock(sKextLock);
6527
6528 return;
6529 }
6530
6531 /*********************************************************************
6532 * Destroying the kxldContext requires checking variables under both
6533 * sKextInnerLock and sKextLock, so we do it on a separate thread
6534 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
6535 * call relationship.
6536 *
6537 * This function must be invoked with sKextInnerLock held.
6538 * Do not call any function that takes sKextLock here!
6539 *********************************************************************/
6540 /* static */
6541 void
6542 OSKext::considerDestroyingLinkContext(void)
6543 {
6544 IORecursiveLockLock(sKextInnerLock);
6545
6546 /* If we have already queued a thread to destroy the link context,
6547 * don't bother resetting; that thread will take care of it.
6548 */
6549 if (sDestroyLinkContextThread) {
6550 goto finish;
6551 }
6552
6553 /* The function to be invoked in the thread will deallocate
6554 * this thread_call, so don't share it around.
6555 */
6556 sDestroyLinkContextThread = thread_call_allocate(
6557 &_OSKextConsiderDestroyingLinkContext, 0);
6558 if (!sDestroyLinkContextThread) {
6559 OSKextLog(/* kext */ NULL,
6560 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
6561 "Can't create thread to destroy kext link context.");
6562 goto finish;
6563 }
6564
6565 thread_call_enter(sDestroyLinkContextThread);
6566
6567 finish:
6568 IORecursiveLockUnlock(sKextInnerLock);
6569 return;
6570 }
6571
6572 #if PRAGMA_MARK
6573 #pragma mark Autounload
6574 #endif
6575 /*********************************************************************
6576 * This is a static method because the kext will be deallocated if it
6577 * does unload!
6578 *********************************************************************/
6579 /* static */
6580 OSReturn
6581 OSKext::autounloadKext(OSKext * aKext)
6582 {
6583 OSReturn result = kOSKextReturnInUse;
6584
6585 /* Check for external references to this kext (usu. dependents),
6586 * instances of defined classes (or classes derived from them),
6587 * outstanding requests.
6588 */
6589 if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
6590 !aKext->flags.autounloadEnabled ||
6591 aKext->isKernelComponent()) {
6592
6593 goto finish;
6594 }
6595
6596 /* Skip a delay-autounload kext, once.
6597 */
6598 if (aKext->flags.delayAutounload) {
6599 OSKextLog(aKext,
6600 kOSKextLogProgressLevel |
6601 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6602 "Kext %s has delayed autounload set; skipping and clearing flag.",
6603 aKext->getIdentifierCString());
6604 aKext->flags.delayAutounload = 0;
6605 goto finish;
6606 }
6607
6608 if (aKext->hasOSMetaClassInstances() ||
6609 aKext->countRequestCallbacks()) {
6610 goto finish;
6611 }
6612
6613 result = OSKext::removeKext(aKext);
6614
6615 finish:
6616
6617 return result;
6618 }
6619
6620 /*********************************************************************
6621 *********************************************************************/
6622 void
6623 _OSKextConsiderUnloads(
6624 __unused thread_call_param_t p0,
6625 __unused thread_call_param_t p1)
6626 {
6627 bool didUnload = false;
6628 unsigned int count, i;
6629
6630 /* Take multiple locks in the correct order
6631 * (note also sKextSummaries lock further down).
6632 */
6633 IORecursiveLockLock(sKextLock);
6634 IORecursiveLockLock(sKextInnerLock);
6635
6636 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
6637
6638 IOLockLock(sKextSummariesLock);
6639
6640 /* If there is an old kext summary, free that now.
6641 */
6642 if (sPrevLoadedKextSummaries) {
6643 kmem_free(kernel_map, (vm_offset_t)sPrevLoadedKextSummaries,
6644 sPrevLoadedKextSummariesAllocSize);
6645 sPrevLoadedKextSummaries = NULL;
6646 sPrevLoadedKextSummariesAllocSize = 0;
6647 }
6648
6649 IOLockUnlock(sKextSummariesLock);
6650
6651 /* If the system is powering down, don't try to unload anything.
6652 */
6653 if (sSystemSleep) {
6654 goto finish;
6655 }
6656
6657 OSKextLog(/* kext */ NULL,
6658 kOSKextLogProgressLevel |
6659 kOSKextLogLoadFlag,
6660 "Checking for unused kexts to autounload.");
6661
6662 /*****
6663 * Remove any request callbacks marked as stale,
6664 * and mark as stale any currently in flight.
6665 */
6666 count = sRequestCallbackRecords->getCount();
6667 if (count) {
6668 i = count - 1;
6669 do {
6670 OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
6671 sRequestCallbackRecords->getObject(i));
6672 OSBoolean * stale = OSDynamicCast(OSBoolean,
6673 callbackRecord->getObject(kKextRequestStaleKey));
6674
6675 if (stale == kOSBooleanTrue) {
6676 OSKext::invokeRequestCallback(callbackRecord,
6677 kOSKextReturnTimeout);
6678 } else {
6679 callbackRecord->setObject(kKextRequestStaleKey,
6680 kOSBooleanTrue);
6681 }
6682 } while (i--);
6683 }
6684
6685 /*****
6686 * Make multiple passes through the array of loaded kexts until
6687 * we don't unload any. This handles unwinding of dependency
6688 * chains. We have to go *backwards* through the array because
6689 * kexts are removed from it when unloaded, and we cannot make
6690 * a copy or we'll mess up the retain counts we rely on to
6691 * check whether a kext will unload. If only we could have
6692 * nonretaining collections like CF has....
6693 */
6694 do {
6695 didUnload = false;
6696
6697 count = sLoadedKexts->getCount();
6698 if (count) {
6699 i = count - 1;
6700 do {
6701 OSKext * thisKext = OSDynamicCast(OSKext,
6702 sLoadedKexts->getObject(i));
6703 didUnload = (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
6704 } while (i--);
6705 }
6706 } while (didUnload);
6707
6708 finish:
6709 sConsiderUnloadsPending = false;
6710 sConsiderUnloadsExecuted = true;
6711
6712 (void) OSKext::considerRebuildOfPrelinkedKernel();
6713
6714 IORecursiveLockUnlock(sKextInnerLock);
6715 IORecursiveLockUnlock(sKextLock);
6716
6717 return;
6718 }
6719
6720 /*********************************************************************
6721 * Do not call any function that takes sKextLock here!
6722 *********************************************************************/
6723 void OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
6724 {
6725 AbsoluteTime when;
6726
6727 IORecursiveLockLock(sKextInnerLock);
6728
6729 if (!sUnloadCallout) {
6730 sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, 0);
6731 }
6732
6733 /* we only reset delay value for unloading if we already have something
6734 * pending. rescheduleOnlyFlag should not start the count down.
6735 */
6736 if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
6737 goto finish;
6738 }
6739
6740 thread_call_cancel(sUnloadCallout);
6741 if (OSKext::getAutounloadEnabled() && !sSystemSleep) {
6742 clock_interval_to_deadline(sConsiderUnloadDelay,
6743 1000 * 1000 * 1000, &when);
6744
6745 OSKextLog(/* kext */ NULL,
6746 kOSKextLogProgressLevel |
6747 kOSKextLogLoadFlag,
6748 "%scheduling %sscan for unused kexts in %lu seconds.",
6749 sConsiderUnloadsPending ? "Res" : "S",
6750 sConsiderUnloadsCalled ? "" : "initial ",
6751 (unsigned long)sConsiderUnloadDelay);
6752
6753 sConsiderUnloadsPending = true;
6754 thread_call_enter_delayed(sUnloadCallout, when);
6755 }
6756
6757 finish:
6758 /* The kxld context should be reused throughout boot. We mark the end of
6759 * period as the first time considerUnloads() is called, and we destroy
6760 * the first kxld context in that function. Afterwards, it will be
6761 * destroyed in flushNonloadedKexts.
6762 */
6763 if (!sConsiderUnloadsCalled) {
6764 sConsiderUnloadsCalled = true;
6765 OSKext::considerDestroyingLinkContext();
6766 }
6767
6768 IORecursiveLockUnlock(sKextInnerLock);
6769 return;
6770 }
6771
6772 /*********************************************************************
6773 * Do not call any function that takes sKextLock here!
6774 *********************************************************************/
6775 extern "C" {
6776
6777 IOReturn OSKextSystemSleepOrWake(UInt32 messageType)
6778 {
6779 IORecursiveLockLock(sKextInnerLock);
6780
6781 /* If the system is going to sleep, cancel the reaper thread timer,
6782 * and note that we're in a sleep state in case it just fired but hasn't
6783 * taken the lock yet. If we are coming back from sleep, just
6784 * clear the sleep flag; IOService's normal operation will cause
6785 * unloads to be considered soon enough.
6786 */
6787 if (messageType == kIOMessageSystemWillSleep) {
6788 if (sUnloadCallout) {
6789 thread_call_cancel(sUnloadCallout);
6790 }
6791 sSystemSleep = true;
6792 AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
6793 } else if (messageType == kIOMessageSystemHasPoweredOn) {
6794 sSystemSleep = false;
6795 clock_get_uptime(&sLastWakeTime);
6796 }
6797 IORecursiveLockUnlock(sKextInnerLock);
6798
6799 return kIOReturnSuccess;
6800 }
6801
6802 };
6803
6804
6805 #if PRAGMA_MARK
6806 #pragma mark Prelinked Kernel
6807 #endif
6808 /*********************************************************************
6809 * Do not access sConsiderUnloads... variables other than
6810 * sConsiderUnloadsExecuted in this function. They are guarded by a
6811 * different lock.
6812 *********************************************************************/
6813 /* static */
6814 void
6815 OSKext::considerRebuildOfPrelinkedKernel(void)
6816 {
6817 static bool requestedPrelink = false;
6818 OSReturn checkResult = kOSReturnError;
6819 OSDictionary * prelinkRequest = NULL; // must release
6820 OSCollectionIterator * kextIterator = NULL; // must release
6821 const OSSymbol * thisID = NULL; // do not release
6822 bool doRebuild = false;
6823 AbsoluteTime my_abstime;
6824 UInt64 my_ns;
6825 SInt32 delta_secs;
6826
6827 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
6828 if (requestedPrelink || !sPrelinkBoot) {
6829 return;
6830 }
6831
6832 /* no direct return from this point */
6833 IORecursiveLockLock(sKextLock);
6834
6835 /* We need to wait for kextd to get up and running with unloads already done
6836 * and any new startup kexts loaded.
6837 */
6838 if (!sConsiderUnloadsExecuted ||
6839 !sDeferredLoadSucceeded) {
6840 goto finish;
6841 }
6842
6843 /* we really only care about boot / system start up related kexts so bail
6844 * if we're here after REBUILD_MAX_TIME.
6845 */
6846 if (!_OSKextInPrelinkRebuildWindow()) {
6847 OSKextLog(/* kext */ NULL,
6848 kOSKextLogArchiveFlag,
6849 "%s prebuild rebuild has expired",
6850 __FUNCTION__);
6851 requestedPrelink = true;
6852 goto finish;
6853 }
6854
6855 /* we do not want to trigger a rebuild if we get here too close to waking
6856 * up. (see radar 10233768)
6857 */
6858 IORecursiveLockLock(sKextInnerLock);
6859
6860 clock_get_uptime(&my_abstime);
6861 delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
6862 if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
6863 SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
6864 absolutetime_to_nanoseconds(my_abstime, &my_ns);
6865 delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
6866 }
6867 IORecursiveLockUnlock(sKextInnerLock);
6868
6869 if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
6870 /* too close to time of last wake from sleep */
6871 goto finish;
6872 }
6873 requestedPrelink = true;
6874
6875 /* Now it's time to see if we have a reason to rebuild. We may have done
6876 * some loads and unloads but the kernel cache didn't actually change.
6877 * We will rebuild if any kext is not marked prelinked AND is not in our
6878 * list of prelinked kexts that got unloaded. (see radar 9055303)
6879 */
6880 kextIterator = OSCollectionIterator::withCollection(sKextsByID);
6881 if (!kextIterator) {
6882 goto finish;
6883 }
6884
6885 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
6886 OSKext * thisKext; // do not release
6887
6888 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
6889 if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
6890 continue;
6891 }
6892
6893 if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID)) {
6894 continue;
6895 }
6896 /* kext is loaded and was not in current kernel cache so let's rebuild
6897 */
6898 doRebuild = true;
6899 OSKextLog(/* kext */ NULL,
6900 kOSKextLogArchiveFlag,
6901 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
6902 thisKext->bundleID->getCStringNoCopy());
6903 break;
6904 }
6905 sUnloadedPrelinkedKexts->flushCollection();
6906
6907 if (!doRebuild) {
6908 goto finish;
6909 }
6910
6911 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
6912 &prelinkRequest);
6913 if (checkResult != kOSReturnSuccess) {
6914 goto finish;
6915 }
6916
6917 if (!sKernelRequests->setObject(prelinkRequest)) {
6918 goto finish;
6919 }
6920
6921 OSKext::pingKextd();
6922
6923 finish:
6924 IORecursiveLockUnlock(sKextLock);
6925 OSSafeRelease(prelinkRequest);
6926 OSSafeRelease(kextIterator);
6927
6928 return;
6929 }
6930
6931 #if PRAGMA_MARK
6932 #pragma mark Dependencies
6933 #endif
6934 /*********************************************************************
6935 *********************************************************************/
6936 bool
6937 OSKext::resolveDependencies(
6938 OSArray * loopStack)
6939 {
6940 bool result = false;
6941 OSArray * localLoopStack = NULL; // must release
6942 bool addedToLoopStack = false;
6943 OSDictionary * libraries = NULL; // do not release
6944 OSCollectionIterator * libraryIterator = NULL; // must release
6945 OSString * libraryID = NULL; // do not release
6946 OSString * infoString = NULL; // do not release
6947 OSString * readableString = NULL; // do not release
6948 OSKext * libraryKext = NULL; // do not release
6949 bool hasRawKernelDependency = false;
6950 bool hasKernelDependency = false;
6951 bool hasKPIDependency = false;
6952 bool hasPrivateKPIDependency = false;
6953 unsigned int count;
6954
6955 /* A kernel component will automatically have this flag set,
6956 * and a loaded kext should also have it set (as should all its
6957 * loaded dependencies).
6958 */
6959 if (flags.hasAllDependencies) {
6960 result = true;
6961 goto finish;
6962 }
6963
6964 /* Check for loops in the dependency graph.
6965 */
6966 if (loopStack) {
6967 if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
6968 OSKextLog(this,
6969 kOSKextLogErrorLevel |
6970 kOSKextLogDependenciesFlag,
6971 "Kext %s has a dependency loop; can't resolve dependencies.",
6972 getIdentifierCString());
6973 goto finish;
6974 }
6975 } else {
6976 OSKextLog(this,
6977 kOSKextLogStepLevel |
6978 kOSKextLogDependenciesFlag,
6979 "Kext %s resolving dependencies.",
6980 getIdentifierCString());
6981
6982 loopStack = OSArray::withCapacity(6); // any small capacity will do
6983 if (!loopStack) {
6984 OSKextLog(this,
6985 kOSKextLogErrorLevel |
6986 kOSKextLogDependenciesFlag,
6987 "Kext %s can't create bookkeeping stack to resolve dependencies.",
6988 getIdentifierCString());
6989 goto finish;
6990 }
6991 localLoopStack = loopStack;
6992 }
6993 if (!loopStack->setObject(this)) {
6994 OSKextLog(this,
6995 kOSKextLogErrorLevel |
6996 kOSKextLogDependenciesFlag,
6997 "Kext %s - internal error resolving dependencies.",
6998 getIdentifierCString());
6999 goto finish;
7000 }
7001 addedToLoopStack = true;
7002
7003 /* Purge any existing kexts in the dependency list and start over.
7004 */
7005 flushDependencies();
7006 if (dependencies) {
7007 OSKextLog(this,
7008 kOSKextLogErrorLevel |
7009 kOSKextLogDependenciesFlag,
7010 "Kext %s - internal error resolving dependencies.",
7011 getIdentifierCString());
7012 }
7013
7014 libraries = OSDynamicCast(OSDictionary,
7015 getPropertyForHostArch(kOSBundleLibrariesKey));
7016 if (libraries == NULL || libraries->getCount() == 0) {
7017 OSKextLog(this,
7018 kOSKextLogErrorLevel |
7019 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7020 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7021 getIdentifierCString(), kOSBundleLibrariesKey);
7022 goto finish;
7023 }
7024
7025 /* Make a new array to hold the dependencies (flush freed the old one).
7026 */
7027 dependencies = OSArray::withCapacity(libraries->getCount());
7028 if (!dependencies) {
7029 OSKextLog(this,
7030 kOSKextLogErrorLevel |
7031 kOSKextLogDependenciesFlag,
7032 "Kext %s - can't allocate dependencies array.",
7033 getIdentifierCString());
7034 goto finish;
7035 }
7036
7037 // xxx - compat: We used to add an implicit dependency on kernel 6.0
7038 // xxx - compat: if none were declared.
7039
7040 libraryIterator = OSCollectionIterator::withCollection(libraries);
7041 if (!libraryIterator) {
7042 OSKextLog(this,
7043 kOSKextLogErrorLevel |
7044 kOSKextLogDependenciesFlag,
7045 "Kext %s - can't allocate dependencies iterator.",
7046 getIdentifierCString());
7047 goto finish;
7048 }
7049
7050 while ((libraryID = OSDynamicCast(OSString,
7051 libraryIterator->getNextObject()))) {
7052
7053 const char * library_id = libraryID->getCStringNoCopy();
7054
7055 OSString * libraryVersion = OSDynamicCast(OSString,
7056 libraries->getObject(libraryID));
7057 if (libraryVersion == NULL) {
7058 OSKextLog(this,
7059 kOSKextLogErrorLevel |
7060 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7061 "Kext %s - illegal type in OSBundleLibraries.",
7062 getIdentifierCString());
7063 goto finish;
7064 }
7065
7066 OSKextVersion libraryVers =
7067 OSKextParseVersionString(libraryVersion->getCStringNoCopy());
7068 if (libraryVers == -1) {
7069 OSKextLog(this,
7070 kOSKextLogErrorLevel |
7071 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7072 "Kext %s - invalid library version %s.",
7073 getIdentifierCString(),
7074 libraryVersion->getCStringNoCopy());
7075 goto finish;
7076 }
7077
7078 libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
7079 if (libraryKext == NULL) {
7080 OSKextLog(this,
7081 kOSKextLogErrorLevel |
7082 kOSKextLogDependenciesFlag,
7083 "Kext %s - library kext %s not found.",
7084 getIdentifierCString(), library_id);
7085 goto finish;
7086 }
7087
7088 if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
7089 OSKextLog(this,
7090 kOSKextLogErrorLevel |
7091 kOSKextLogDependenciesFlag,
7092 "Kext %s - library kext %s not compatible "
7093 "with requested version %s.",
7094 getIdentifierCString(), library_id,
7095 libraryVersion->getCStringNoCopy());
7096 goto finish;
7097 }
7098
7099 /* If a nonprelinked library somehow got into the mix for a
7100 * prelinked kext, at any point in the chain, we must fail
7101 * because the prelinked relocs for the library will be all wrong.
7102 */
7103 if (this->isPrelinked() &&
7104 libraryKext->declaresExecutable() &&
7105 !libraryKext->isPrelinked()) {
7106
7107 OSKextLog(this,
7108 kOSKextLogErrorLevel |
7109 kOSKextLogDependenciesFlag,
7110 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7111 getIdentifierCString(), library_id,
7112 libraryVersion->getCStringNoCopy());
7113 goto finish;
7114 }
7115
7116 if (!libraryKext->resolveDependencies(loopStack)) {
7117 goto finish;
7118 }
7119
7120 /* Add the library directly only if it has an executable to link.
7121 * Otherwise it's just used to collect other dependencies, so put
7122 * *its* dependencies on the list for this kext.
7123 */
7124 // xxx - We are losing info here; would like to make fake entries or
7125 // xxx - keep these in the dependency graph for loaded kexts.
7126 // xxx - I really want to make kernel components not a special case!
7127 if (libraryKext->declaresExecutable() ||
7128 libraryKext->isInterface()) {
7129
7130 if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
7131 dependencies->setObject(libraryKext);
7132
7133 OSKextLog(this,
7134 kOSKextLogDetailLevel |
7135 kOSKextLogDependenciesFlag,
7136 "Kext %s added dependency %s.",
7137 getIdentifierCString(),
7138 libraryKext->getIdentifierCString());
7139 }
7140 } else {
7141 int numLibDependencies = libraryKext->getNumDependencies();
7142 OSArray * libraryDependencies = libraryKext->getDependencies();
7143 int index;
7144
7145 if (numLibDependencies) {
7146 // xxx - this msg level should be 1 lower than the per-kext one
7147 OSKextLog(this,
7148 kOSKextLogDetailLevel |
7149 kOSKextLogDependenciesFlag,
7150 "Kext %s pulling %d dependencies from codeless library %s.",
7151 getIdentifierCString(),
7152 numLibDependencies,
7153 libraryKext->getIdentifierCString());
7154 }
7155 for (index = 0; index < numLibDependencies; index++) {
7156 OSKext * thisLibDependency = OSDynamicCast(OSKext,
7157 libraryDependencies->getObject(index));
7158 if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
7159 dependencies->setObject(thisLibDependency);
7160 OSKextLog(this,
7161 kOSKextLogDetailLevel |
7162 kOSKextLogDependenciesFlag,
7163 "Kext %s added dependency %s from codeless library %s.",
7164 getIdentifierCString(),
7165 thisLibDependency->getIdentifierCString(),
7166 libraryKext->getIdentifierCString());
7167 }
7168 }
7169 }
7170
7171 if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
7172 0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB)-1)) {
7173
7174 hasRawKernelDependency = true;
7175 } else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
7176 hasKernelDependency = true;
7177 } else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
7178 hasKPIDependency = true;
7179 if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI)-1)) {
7180 hasPrivateKPIDependency = true;
7181 }
7182 }
7183 }
7184
7185 if (hasRawKernelDependency) {
7186 OSKextLog(this,
7187 kOSKextLogErrorLevel |
7188 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7189 "Error - kext %s declares a dependency on %s, which is not permitted.",
7190 getIdentifierCString(), KERNEL_LIB);
7191 goto finish;
7192 }
7193 #if __LP64__
7194 if (hasKernelDependency) {
7195 OSKextLog(this,
7196 kOSKextLogErrorLevel |
7197 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7198 "Error - kext %s declares %s dependencies. "
7199 "Only %s* dependencies are supported for 64-bit kexts.",
7200 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
7201 goto finish;
7202 }
7203 if (!hasKPIDependency) {
7204 OSKextLog(this,
7205 kOSKextLogWarningLevel |
7206 kOSKextLogDependenciesFlag,
7207 "Warning - kext %s declares no %s* dependencies. "
7208 "If it uses any KPIs, the link may fail with undefined symbols.",
7209 getIdentifierCString(), KPI_LIB_PREFIX);
7210 }
7211 #else /* __LP64__ */
7212 // xxx - will change to flatly disallow "kernel" dependencies at some point
7213 // xxx - is it invalid to do both "com.apple.kernel" and any
7214 // xxx - "com.apple.kernel.*"?
7215
7216 if (hasKernelDependency && hasKPIDependency) {
7217 OSKextLog(this,
7218 kOSKextLogWarningLevel |
7219 kOSKextLogDependenciesFlag,
7220 "Warning - kext %s has immediate dependencies on both "
7221 "%s* and %s* components; use only one style.",
7222 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
7223 }
7224
7225 if (!hasKernelDependency && !hasKPIDependency) {
7226 // xxx - do we want to use validation flag for these too?
7227 OSKextLog(this,
7228 kOSKextLogWarningLevel |
7229 kOSKextLogDependenciesFlag,
7230 "Warning - %s declares no kernel dependencies; using %s.",
7231 getIdentifierCString(), KERNEL6_LIB);
7232 OSKext * kernelKext = OSDynamicCast(OSKext,
7233 sKextsByID->getObject(KERNEL6_LIB));
7234 if (kernelKext) {
7235 dependencies->setObject(kernelKext);
7236 } else {
7237 OSKextLog(this,
7238 kOSKextLogErrorLevel |
7239 kOSKextLogDependenciesFlag,
7240 "Error - Library %s not found for %s.",
7241 KERNEL6_LIB, getIdentifierCString());
7242 }
7243 }
7244
7245 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7246 * its indirect dependencies to simulate old-style linking. XXX - Should
7247 * check for duplicates.
7248 */
7249 if (!hasKPIDependency) {
7250 unsigned int i;
7251
7252 flags.hasBleedthrough = true;
7253
7254 count = getNumDependencies();
7255
7256 /* We add to the dependencies array in this loop, but do not iterate
7257 * past its original count.
7258 */
7259 for (i = 0; i < count; i++) {
7260 OSKext * dependencyKext = OSDynamicCast(OSKext,
7261 dependencies->getObject(i));
7262 dependencyKext->addBleedthroughDependencies(dependencies);
7263 }
7264 }
7265 #endif /* __LP64__ */
7266
7267 if (hasPrivateKPIDependency) {
7268 bool hasApplePrefix = false;
7269 bool infoCopyrightIsValid = false;
7270 bool readableCopyrightIsValid = false;
7271
7272 hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
7273 APPLE_KEXT_PREFIX);
7274
7275 infoString = OSDynamicCast(OSString,
7276 getPropertyForHostArch("CFBundleGetInfoString"));
7277 if (infoString) {
7278 infoCopyrightIsValid =
7279 kxld_validate_copyright_string(infoString->getCStringNoCopy());
7280 }
7281
7282 readableString = OSDynamicCast(OSString,
7283 getPropertyForHostArch("NSHumanReadableCopyright"));
7284 if (readableString) {
7285 readableCopyrightIsValid =
7286 kxld_validate_copyright_string(readableString->getCStringNoCopy());
7287 }
7288
7289 if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
7290 OSKextLog(this,
7291 kOSKextLogErrorLevel |
7292 kOSKextLogDependenciesFlag,
7293 "Error - kext %s declares a dependency on %s. "
7294 "Only Apple kexts may declare a dependency on %s.",
7295 getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
7296 goto finish;
7297 }
7298 }
7299
7300 result = true;
7301 flags.hasAllDependencies = 1;
7302
7303 finish:
7304
7305 if (addedToLoopStack) {
7306 count = loopStack->getCount();
7307 if (count > 0 && (this == loopStack->getObject(count - 1))) {
7308 loopStack->removeObject(count - 1);
7309 } else {
7310 OSKextLog(this,
7311 kOSKextLogErrorLevel |
7312 kOSKextLogDependenciesFlag,
7313 "Kext %s - internal error resolving dependencies.",
7314 getIdentifierCString());
7315 }
7316 }
7317
7318 if (result && localLoopStack) {
7319 OSKextLog(this,
7320 kOSKextLogStepLevel |
7321 kOSKextLogDependenciesFlag,
7322 "Kext %s successfully resolved dependencies.",
7323 getIdentifierCString());
7324 }
7325
7326 OSSafeRelease(localLoopStack);
7327 OSSafeRelease(libraryIterator);
7328
7329 return result;
7330 }
7331
7332 /*********************************************************************
7333 *********************************************************************/
7334 bool
7335 OSKext::addBleedthroughDependencies(OSArray * anArray)
7336 {
7337 bool result = false;
7338 unsigned int dependencyIndex, dependencyCount;
7339
7340 dependencyCount = getNumDependencies();
7341
7342 for (dependencyIndex = 0;
7343 dependencyIndex < dependencyCount;
7344 dependencyIndex++) {
7345
7346 OSKext * dependency = OSDynamicCast(OSKext,
7347 dependencies->getObject(dependencyIndex));
7348 if (!dependency) {
7349 OSKextLog(this,
7350 kOSKextLogErrorLevel |
7351 kOSKextLogDependenciesFlag,
7352 "Kext %s - internal error propagating compatibility dependencies.",
7353 getIdentifierCString());
7354 goto finish;
7355 }
7356 if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
7357 anArray->setObject(dependency);
7358 }
7359 dependency->addBleedthroughDependencies(anArray);
7360 }
7361
7362 result = true;
7363
7364 finish:
7365 return result;
7366 }
7367
7368 /*********************************************************************
7369 *********************************************************************/
7370 bool
7371 OSKext::flushDependencies(bool forceFlag)
7372 {
7373 bool result = false;
7374
7375 /* Only clear the dependencies if the kext isn't loaded;
7376 * we need the info for loaded kexts to track references.
7377 */
7378 if (!isLoaded() || forceFlag) {
7379 if (dependencies) {
7380 // xxx - check level
7381 OSKextLog(this,
7382 kOSKextLogProgressLevel |
7383 kOSKextLogDependenciesFlag,
7384 "Kext %s flushing dependencies.",
7385 getIdentifierCString());
7386 OSSafeReleaseNULL(dependencies);
7387
7388 }
7389 if (!isKernelComponent()) {
7390 flags.hasAllDependencies = 0;
7391 }
7392 result = true;
7393 }
7394
7395 return result;
7396 }
7397
7398 /*********************************************************************
7399 *********************************************************************/
7400 uint32_t
7401 OSKext::getNumDependencies(void)
7402 {
7403 if (!dependencies) {
7404 return 0;
7405 }
7406 return dependencies->getCount();
7407 }
7408
7409 /*********************************************************************
7410 *********************************************************************/
7411 OSArray *
7412 OSKext::getDependencies(void)
7413 {
7414 return dependencies;
7415 }
7416
7417 #if PRAGMA_MARK
7418 #pragma mark OSMetaClass Support
7419 #endif
7420 /*********************************************************************
7421 *********************************************************************/
7422 OSReturn
7423 OSKext::addClass(
7424 OSMetaClass * aClass,
7425 uint32_t numClasses)
7426 {
7427 OSReturn result = kOSMetaClassNoInsKModSet;
7428
7429 if (!metaClasses) {
7430 metaClasses = OSSet::withCapacity(numClasses);
7431 if (!metaClasses) {
7432 goto finish;
7433 }
7434 }
7435
7436 if (metaClasses->containsObject(aClass)) {
7437 OSKextLog(this,
7438 kOSKextLogWarningLevel |
7439 kOSKextLogLoadFlag,
7440 "Notice - kext %s has already registered class %s.",
7441 getIdentifierCString(),
7442 aClass->getClassName());
7443 result = kOSReturnSuccess;
7444 goto finish;
7445 }
7446
7447 if (!metaClasses->setObject(aClass)) {
7448 goto finish;
7449 } else {
7450 OSKextLog(this,
7451 kOSKextLogDetailLevel |
7452 kOSKextLogLoadFlag,
7453 "Kext %s registered class %s.",
7454 getIdentifierCString(),
7455 aClass->getClassName());
7456 }
7457
7458 if (!flags.autounloadEnabled) {
7459 const OSMetaClass * metaScan = NULL; // do not release
7460
7461 for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
7462 if (metaScan == OSTypeID(IOService)) {
7463
7464 OSKextLog(this,
7465 kOSKextLogProgressLevel |
7466 kOSKextLogLoadFlag,
7467 "Kext %s has IOService subclass %s; enabling autounload.",
7468 getIdentifierCString(),
7469 aClass->getClassName());
7470
7471 flags.autounloadEnabled = 1;
7472 break;
7473 }
7474 }
7475 }
7476
7477 notifyAddClassObservers(this, aClass, flags);
7478
7479 result = kOSReturnSuccess;
7480
7481 finish:
7482 if (result != kOSReturnSuccess) {
7483 OSKextLog(this,
7484 kOSKextLogErrorLevel |
7485 kOSKextLogLoadFlag,
7486 "Kext %s failed to register class %s.",
7487 getIdentifierCString(),
7488 aClass->getClassName());
7489 }
7490
7491 return result;
7492 }
7493
7494 /*********************************************************************
7495 *********************************************************************/
7496 OSReturn
7497 OSKext::removeClass(
7498 OSMetaClass * aClass)
7499 {
7500 OSReturn result = kOSMetaClassNoKModSet;
7501
7502 if (!metaClasses) {
7503 goto finish;
7504 }
7505
7506 if (!metaClasses->containsObject(aClass)) {
7507 OSKextLog(this,
7508 kOSKextLogWarningLevel |
7509 kOSKextLogLoadFlag,
7510 "Notice - kext %s asked to unregister unknown class %s.",
7511 getIdentifierCString(),
7512 aClass->getClassName());
7513 result = kOSReturnSuccess;
7514 goto finish;
7515 }
7516
7517 OSKextLog(this,
7518 kOSKextLogDetailLevel |
7519 kOSKextLogLoadFlag,
7520 "Kext %s unregistering class %s.",
7521 getIdentifierCString(),
7522 aClass->getClassName());
7523
7524 metaClasses->removeObject(aClass);
7525
7526 notifyRemoveClassObservers(this, aClass, flags);
7527
7528 result = kOSReturnSuccess;
7529
7530 finish:
7531 if (result != kOSReturnSuccess) {
7532 OSKextLog(this,
7533 kOSKextLogErrorLevel |
7534 kOSKextLogLoadFlag,
7535 "Failed to unregister kext %s class %s.",
7536 getIdentifierCString(),
7537 aClass->getClassName());
7538 }
7539 return result;
7540 }
7541
7542 /*********************************************************************
7543 *********************************************************************/
7544 OSSet *
7545 OSKext::getMetaClasses(void)
7546 {
7547 return metaClasses;
7548 }
7549
7550 /*********************************************************************
7551 *********************************************************************/
7552 bool
7553 OSKext::hasOSMetaClassInstances(void)
7554 {
7555 bool result = false;
7556 OSCollectionIterator * classIterator = NULL; // must release
7557 OSMetaClass * checkClass = NULL; // do not release
7558
7559 if (!metaClasses) {
7560 goto finish;
7561 }
7562
7563 classIterator = OSCollectionIterator::withCollection(metaClasses);
7564 if (!classIterator) {
7565 // xxx - log alloc failure?
7566 goto finish;
7567 }
7568 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
7569 if (checkClass->getInstanceCount()) {
7570 result = true;
7571 goto finish;
7572 }
7573 }
7574
7575 finish:
7576
7577 OSSafeRelease(classIterator);
7578 return result;
7579 }
7580
7581 /*********************************************************************
7582 *********************************************************************/
7583 /* static */
7584 void
7585 OSKext::reportOSMetaClassInstances(
7586 const char * kextIdentifier,
7587 OSKextLogSpec msgLogSpec)
7588 {
7589 OSKext * theKext = NULL; // must release
7590
7591 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
7592 if (!theKext) {
7593 goto finish;
7594 }
7595
7596 theKext->reportOSMetaClassInstances(msgLogSpec);
7597 finish:
7598 OSSafeRelease(theKext);
7599 return;
7600 }
7601
7602 /*********************************************************************
7603 *********************************************************************/
7604 void
7605 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
7606 {
7607 OSCollectionIterator * classIterator = NULL; // must release
7608 OSMetaClass * checkClass = NULL; // do not release
7609
7610 if (!metaClasses) {
7611 goto finish;
7612 }
7613
7614 classIterator = OSCollectionIterator::withCollection(metaClasses);
7615 if (!classIterator) {
7616 goto finish;
7617 }
7618 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
7619 if (checkClass->getInstanceCount()) {
7620 OSKextLog(this,
7621 msgLogSpec,
7622 " Kext %s class %s has %d instance%s.",
7623 getIdentifierCString(),
7624 checkClass->getClassName(),
7625 checkClass->getInstanceCount(),
7626 checkClass->getInstanceCount() == 1 ? "" : "s");
7627 }
7628 }
7629
7630 finish:
7631 OSSafeRelease(classIterator);
7632 return;
7633 }
7634
7635 #if PRAGMA_MARK
7636 #pragma mark User-Space Requests
7637 #endif
7638 /*********************************************************************
7639 * XXX - this function is a big ugly mess
7640 *********************************************************************/
7641 /* static */
7642 OSReturn
7643 OSKext::handleRequest(
7644 host_priv_t hostPriv,
7645 OSKextLogSpec clientLogFilter,
7646 char * requestBuffer,
7647 uint32_t requestLength,
7648 char ** responseOut,
7649 uint32_t * responseLengthOut,
7650 char ** logInfoOut,
7651 uint32_t * logInfoLengthOut)
7652 {
7653 OSReturn result = kOSReturnError;
7654 kern_return_t kmem_result = KERN_FAILURE;
7655
7656 char * response = NULL; // returned by reference
7657 uint32_t responseLength = 0;
7658
7659 OSObject * parsedXML = NULL; // must release
7660 OSDictionary * requestDict = NULL; // do not release
7661 OSString * errorString = NULL; // must release
7662
7663 OSData * responseData = NULL; // must release
7664 OSObject * responseObject = NULL; // must release
7665
7666 OSSerialize * serializer = NULL; // must release
7667
7668 OSArray * logInfoArray = NULL; // must release
7669
7670 OSString * predicate = NULL; // do not release
7671 OSString * kextIdentifier = NULL; // do not release
7672 OSArray * kextIdentifiers = NULL; // do not release
7673 OSKext * theKext = NULL; // do not release
7674 OSBoolean * boolArg = NULL; // do not release
7675
7676 bool hideTheSlide = false;
7677
7678 IORecursiveLockLock(sKextLock);
7679
7680 if (responseOut) {
7681 *responseOut = NULL;
7682 *responseLengthOut = 0;
7683 }
7684 if (logInfoOut) {
7685 *logInfoOut = NULL;
7686 *logInfoLengthOut = 0;
7687 }
7688
7689 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
7690
7691 /* XML must be nul-terminated.
7692 */
7693 if (requestBuffer[requestLength - 1] != '\0') {
7694 OSKextLog(/* kext */ NULL,
7695 kOSKextLogErrorLevel |
7696 kOSKextLogIPCFlag,
7697 "Invalid request from user space (not nul-terminated).");
7698 result = kOSKextReturnBadData;
7699 goto finish;
7700 }
7701 parsedXML = OSUnserializeXML((const char *)requestBuffer, &errorString);
7702 if (parsedXML) {
7703 requestDict = OSDynamicCast(OSDictionary, parsedXML);
7704 }
7705 if (!requestDict) {
7706 const char * errorCString = "(unknown error)";
7707
7708 if (errorString && errorString->getCStringNoCopy()) {
7709 errorCString = errorString->getCStringNoCopy();
7710 } else if (parsedXML) {
7711 errorCString = "not a dictionary";
7712 }
7713 OSKextLog(/* kext */ NULL,
7714 kOSKextLogErrorLevel |
7715 kOSKextLogIPCFlag,
7716 "Error unserializing request from user space: %s.",
7717 errorCString);
7718 result = kOSKextReturnSerialization;
7719 goto finish;
7720 }
7721
7722 predicate = _OSKextGetRequestPredicate(requestDict);
7723 if (!predicate) {
7724 OSKextLog(/* kext */ NULL,
7725 kOSKextLogErrorLevel |
7726 kOSKextLogIPCFlag,
7727 "Recieved kext request from user space with no predicate.");
7728 result = kOSKextReturnInvalidArgument;
7729 goto finish;
7730 }
7731
7732 OSKextLog(/* kext */ NULL,
7733 kOSKextLogDebugLevel |
7734 kOSKextLogIPCFlag,
7735 "Received '%s' request from user space.",
7736 predicate->getCStringNoCopy());
7737
7738 result = kOSKextReturnNotPrivileged;
7739 if (hostPriv == HOST_PRIV_NULL) {
7740 if (sPrelinkBoot) {
7741 hideTheSlide = true;
7742 /* must be root to use these kext requests */
7743 if (predicate->isEqualTo(kKextRequestPredicateGetKernelLoadAddress) ||
7744 predicate->isEqualTo(kKextRequestPredicateUnload) ||
7745 predicate->isEqualTo(kKextRequestPredicateStart) ||
7746 predicate->isEqualTo(kKextRequestPredicateStop) ) {
7747 OSKextLog(/* kext */ NULL,
7748 kOSKextLogErrorLevel |
7749 kOSKextLogIPCFlag,
7750 "Access Failure - must be root user.");
7751 goto finish;
7752 }
7753 }
7754 }
7755
7756 /* Get common args in anticipation of use.
7757 */
7758 kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
7759 requestDict, kKextRequestArgumentBundleIdentifierKey));
7760 kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
7761 requestDict, kKextRequestArgumentBundleIdentifierKey));
7762 if (kextIdentifier) {
7763 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
7764 }
7765 boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
7766 requestDict, kKextRequestArgumentValueKey));
7767
7768 result = kOSKextReturnInvalidArgument;
7769
7770 if (predicate->isEqualTo(kKextRequestPredicateStart)) {
7771 if (!kextIdentifier) {
7772 OSKextLog(/* kext */ NULL,
7773 kOSKextLogErrorLevel |
7774 kOSKextLogIPCFlag,
7775 "Invalid arguments to kext start request.");
7776 } else if (!theKext) {
7777 OSKextLog(/* kext */ NULL,
7778 kOSKextLogErrorLevel |
7779 kOSKextLogIPCFlag,
7780 "Kext %s not found for start request.",
7781 kextIdentifier->getCStringNoCopy());
7782 result = kOSKextReturnNotFound;
7783 } else {
7784 result = theKext->start();
7785 }
7786
7787 } else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
7788 if (!kextIdentifier) {
7789 OSKextLog(/* kext */ NULL,
7790 kOSKextLogErrorLevel |
7791 kOSKextLogIPCFlag,
7792 "Invalid arguments to kext stop request.");
7793 } else if (!theKext) {
7794 OSKextLog(/* kext */ NULL,
7795 kOSKextLogErrorLevel |
7796 kOSKextLogIPCFlag,
7797 "Kext %s not found for stop request.",
7798 kextIdentifier->getCStringNoCopy());
7799 result = kOSKextReturnNotFound;
7800 } else {
7801 result = theKext->stop();
7802 }
7803
7804 } else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
7805 if (!kextIdentifier) {
7806 OSKextLog(/* kext */ NULL,
7807 kOSKextLogErrorLevel |
7808 kOSKextLogIPCFlag,
7809 "Invalid arguments to kext unload request.");
7810 } else if (!theKext) {
7811 OSKextLog(/* kext */ NULL,
7812 kOSKextLogErrorLevel |
7813 kOSKextLogIPCFlag,
7814 "Kext %s not found for unload request.",
7815 kextIdentifier->getCStringNoCopy());
7816 result = kOSKextReturnNotFound;
7817 } else {
7818 OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
7819 _OSKextGetRequestArgument(requestDict,
7820 kKextRequestArgumentTerminateIOServicesKey));
7821 result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
7822 }
7823
7824 } else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
7825 result = OSKext::dispatchResource(requestDict);
7826
7827 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
7828 OSBoolean * delayAutounloadBool = NULL;
7829 OSObject * infoKeysRaw = NULL;
7830 OSArray * infoKeys = NULL;
7831 uint32_t infoKeysCount = 0;
7832
7833 delayAutounloadBool = OSDynamicCast(OSBoolean,
7834 _OSKextGetRequestArgument(requestDict,
7835 kKextRequestArgumentDelayAutounloadKey));
7836
7837 /* If asked to delay autounload, reset the timer if it's currently set.
7838 * (That is, don't schedule an unload if one isn't already pending.
7839 */
7840 if (delayAutounloadBool == kOSBooleanTrue) {
7841 OSKext::considerUnloads(/* rescheduleOnly? */ true);
7842 }
7843
7844 infoKeysRaw = _OSKextGetRequestArgument(requestDict,
7845 kKextRequestArgumentInfoKeysKey);
7846 infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
7847 if (infoKeysRaw && !infoKeys) {
7848 OSKextLog(/* kext */ NULL,
7849 kOSKextLogErrorLevel |
7850 kOSKextLogIPCFlag,
7851 "Invalid arguments to kext info request.");
7852 goto finish;
7853 }
7854
7855 if (infoKeys) {
7856 infoKeysCount = infoKeys->getCount();
7857 for (uint32_t i = 0; i < infoKeysCount; i++) {
7858 if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
7859 OSKextLog(/* kext */ NULL,
7860 kOSKextLogErrorLevel |
7861 kOSKextLogIPCFlag,
7862 "Invalid arguments to kext info request.");
7863 goto finish;
7864 }
7865 }
7866 }
7867
7868 responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
7869 if (!responseObject) {
7870 result = kOSKextReturnInternalError;
7871 } else {
7872 OSKextLog(/* kext */ NULL,
7873 kOSKextLogDebugLevel |
7874 kOSKextLogIPCFlag,
7875 "Returning loaded kext info.");
7876 result = kOSReturnSuccess;
7877 }
7878 #if !SECURE_KERNEL
7879 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelLoadAddress)) {
7880 OSNumber * addressNum = NULL; // released as responseObject
7881 unsigned long long unslid_addr = 0;
7882 kernel_segment_command_t * textseg = getsegbyname("__TEXT");
7883
7884 if (!textseg) {
7885 OSKextLog(/* kext */ NULL,
7886 kOSKextLogErrorLevel |
7887 kOSKextLogGeneralFlag | kOSKextLogIPCFlag,
7888 "Can't find text segment for kernel load address.");
7889 result = kOSReturnError;
7890 goto finish;
7891 }
7892
7893 unslid_addr = VM_KERNEL_UNSLIDE(textseg->vmaddr);
7894
7895 OSKextLog(/* kext */ NULL,
7896 kOSKextLogDebugLevel |
7897 kOSKextLogIPCFlag,
7898 "Returning kernel load address 0x%llx.",
7899 (unsigned long long) unslid_addr);
7900
7901 addressNum = OSNumber::withNumber((long long unsigned int) unslid_addr,
7902 8 * sizeof(long long unsigned int));
7903 responseObject = addressNum;
7904 result = kOSReturnSuccess;
7905 #endif
7906 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
7907
7908 /* Hand the current sKernelRequests array to the caller
7909 * (who must release it), and make a new one.
7910 */
7911 responseObject = sKernelRequests;
7912 sKernelRequests = OSArray::withCapacity(0);
7913 sPostedKextLoadIdentifiers->flushCollection();
7914 OSKextLog(/* kext */ NULL,
7915 kOSKextLogDebugLevel |
7916 kOSKextLogIPCFlag,
7917 "Returning kernel requests.");
7918 result = kOSReturnSuccess;
7919
7920 } else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
7921
7922 /* Return the set of all requested bundle identifiers */
7923 responseObject = sAllKextLoadIdentifiers;
7924 responseObject->retain();
7925 OSKextLog(/* kext */ NULL,
7926 kOSKextLogDebugLevel |
7927 kOSKextLogIPCFlag,
7928 "Returning load requests.");
7929 result = kOSReturnSuccess;
7930 }
7931 else {
7932 OSKextLog(/* kext */ NULL,
7933 kOSKextLogDebugLevel |
7934 kOSKextLogIPCFlag,
7935 "Received '%s' invalid request from user space.",
7936 predicate->getCStringNoCopy());
7937 goto finish;
7938 }
7939
7940 /**********
7941 * Now we have handle the request, or not. Gather up the response & logging
7942 * info to ship to user space.
7943 *********/
7944
7945 /* Note: Nothing in OSKext is supposed to retain requestDict,
7946 * but you never know....
7947 */
7948 if (requestDict->getRetainCount() > 1) {
7949 OSKextLog(/* kext */ NULL,
7950 kOSKextLogWarningLevel |
7951 kOSKextLogIPCFlag,
7952 "Request from user space still retained by a kext; "
7953 "probable memory leak.");
7954 }
7955
7956 if (responseData && responseObject) {
7957 OSKextLog(/* kext */ NULL,
7958 kOSKextLogErrorLevel |
7959 kOSKextLogIPCFlag,
7960 "Mistakenly generated both data & plist responses to user request "
7961 "(returning only data).");
7962 }
7963
7964 if (responseData && responseData->getLength() && responseOut) {
7965
7966 response = (char *)responseData->getBytesNoCopy();
7967 responseLength = responseData->getLength();
7968 } else if (responseOut && responseObject) {
7969 serializer = OSSerialize::withCapacity(0);
7970 if (!serializer) {
7971 result = kOSKextReturnNoMemory;
7972 goto finish;
7973 }
7974
7975 if (!responseObject->serialize(serializer)) {
7976 OSKextLog(/* kext */ NULL,
7977 kOSKextLogErrorLevel |
7978 kOSKextLogIPCFlag,
7979 "Failed to serialize response to request from user space.");
7980 result = kOSKextReturnSerialization;
7981 goto finish;
7982 }
7983
7984 response = (char *)serializer->text();
7985 responseLength = serializer->getLength();
7986 }
7987
7988 if (responseOut && response) {
7989 char * buffer;
7990
7991 /* This kmem_alloc sets the return value of the function.
7992 */
7993 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
7994 round_page(responseLength));
7995 if (kmem_result != KERN_SUCCESS) {
7996 OSKextLog(/* kext */ NULL,
7997 kOSKextLogErrorLevel |
7998 kOSKextLogIPCFlag,
7999 "Failed to copy response to request from user space.");
8000 result = kmem_result;
8001 goto finish;
8002 } else {
8003 /* 11981737 - clear uninitialized data in last page */
8004 bzero((void *)(buffer + responseLength),
8005 (round_page(responseLength) - responseLength));
8006 memcpy(buffer, response, responseLength);
8007 *responseOut = buffer;
8008 *responseLengthOut = responseLength;
8009 }
8010 }
8011
8012 finish:
8013
8014 /* Gather up the collected log messages for user space. Any messages
8015 * messages past this call will not make it up as log messages but
8016 * will be in the system log. Note that we ignore the return of the
8017 * serialize; it has no bearing on the operation at hand even if we
8018 * fail to get the log messages.
8019 */
8020 logInfoArray = OSKext::clearUserSpaceLogFilter();
8021
8022 if (logInfoArray && logInfoOut && logInfoLengthOut) {
8023 (void)OSKext::serializeLogInfo(logInfoArray,
8024 logInfoOut, logInfoLengthOut);
8025 }
8026
8027 IORecursiveLockUnlock(sKextLock);
8028
8029 OSSafeRelease(parsedXML);
8030 OSSafeRelease(errorString);
8031 OSSafeRelease(responseData);
8032 OSSafeRelease(responseObject);
8033 OSSafeRelease(serializer);
8034 OSSafeRelease(logInfoArray);
8035
8036 return result;
8037 }
8038
8039 /*********************************************************************
8040 *********************************************************************/
8041 /* static */
8042 OSDictionary *
8043 OSKext::copyLoadedKextInfo(
8044 OSArray * kextIdentifiers,
8045 OSArray * infoKeys)
8046 {
8047 OSDictionary * result = NULL;
8048 OSDictionary * kextInfo = NULL; // must release
8049 uint32_t count, i;
8050 uint32_t idCount = 0;
8051 uint32_t idIndex = 0;
8052
8053 IORecursiveLockLock(sKextLock);
8054
8055 /* Empty list of bundle ids is equivalent to no list (get all).
8056 */
8057 if (kextIdentifiers && !kextIdentifiers->getCount()) {
8058 kextIdentifiers = NULL;
8059 } else if (kextIdentifiers) {
8060 idCount = kextIdentifiers->getCount();
8061 }
8062
8063 /* Same for keys.
8064 */
8065 if (infoKeys && !infoKeys->getCount()) {
8066 infoKeys = NULL;
8067 }
8068
8069 count = sLoadedKexts->getCount();
8070 result = OSDictionary::withCapacity(count);
8071 if (!result) {
8072 goto finish;
8073 }
8074 for (i = 0; i < count; i++) {
8075 OSKext * thisKext = NULL; // do not release
8076 Boolean includeThis = true;
8077
8078 if (kextInfo) {
8079 kextInfo->release();
8080 kextInfo = NULL;
8081 }
8082 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
8083 if (!thisKext) {
8084 continue;
8085 }
8086
8087 /* Skip current kext if we have a list of bundle IDs and
8088 * it isn't in the list.
8089 */
8090 if (kextIdentifiers) {
8091 const OSString * thisKextID = thisKext->getIdentifier();
8092
8093 includeThis = false;
8094
8095 for (idIndex = 0; idIndex < idCount; idIndex++) {
8096 const OSString * thisRequestID = OSDynamicCast(OSString,
8097 kextIdentifiers->getObject(idIndex));
8098 if (thisKextID->isEqualTo(thisRequestID)) {
8099 includeThis = true;
8100 break;
8101 }
8102 }
8103 }
8104
8105 if (!includeThis) {
8106 continue;
8107 }
8108
8109 kextInfo = thisKext->copyInfo(infoKeys);
8110 if (kextInfo) {
8111 result->setObject(thisKext->getIdentifier(), kextInfo);
8112 }
8113 }
8114
8115 finish:
8116 IORecursiveLockUnlock(sKextLock);
8117
8118 if (kextInfo) kextInfo->release();
8119
8120 return result;
8121 }
8122
8123 /*********************************************************************
8124 * Any info that needs to do allocations must goto finish on alloc
8125 * failure. Info that is just a lookup should just not set the object
8126 * if the info does not exist.
8127 *********************************************************************/
8128 #define _OSKextLoadInfoDictCapacity (12)
8129
8130 OSDictionary *
8131 OSKext::copyInfo(OSArray * infoKeys)
8132 {
8133 OSDictionary * result = NULL;
8134 bool success = false;
8135 OSData * headerData = NULL; // must release
8136 OSNumber * cpuTypeNumber = NULL; // must release
8137 OSNumber * cpuSubtypeNumber = NULL; // must release
8138 OSString * versionString = NULL; // do not release
8139 uint32_t executablePathCStringSize = 0;
8140 char * executablePathCString = NULL; // must release
8141 OSString * executablePathString = NULL; // must release
8142 OSData * uuid = NULL; // must release
8143 OSNumber * scratchNumber = NULL; // must release
8144 OSArray * dependencyLoadTags = NULL; // must release
8145 OSCollectionIterator * metaClassIterator = NULL; // must release
8146 OSArray * metaClassInfo = NULL; // must release
8147 OSDictionary * metaClassDict = NULL; // must release
8148 OSMetaClass * thisMetaClass = NULL; // do not release
8149 OSString * metaClassName = NULL; // must release
8150 OSString * superclassName = NULL; // must release
8151 uint32_t count, i;
8152
8153 result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
8154 if (!result) {
8155 goto finish;
8156 }
8157
8158
8159 /* Empty keys means no keys, but NULL is quicker to check.
8160 */
8161 if (infoKeys && !infoKeys->getCount()) {
8162 infoKeys = NULL;
8163 }
8164
8165 /* Headers, CPU type, and CPU subtype.
8166 */
8167 if (!infoKeys ||
8168 _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
8169 _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
8170 _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey))
8171 {
8172
8173 if (linkedExecutable && !isInterface()) {
8174
8175 kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
8176 linkedExecutable->getBytesNoCopy();
8177
8178 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
8179 kernel_mach_header_t * temp_kext_mach_hdr;
8180 struct load_command * lcp;
8181
8182 headerData = OSData::withBytes(kext_mach_hdr,
8183 (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
8184 if (!headerData) {
8185 goto finish;
8186 }
8187
8188 // unslide any vmaddrs we return to userspace - 10726716
8189 temp_kext_mach_hdr = (kernel_mach_header_t *)
8190 headerData->getBytesNoCopy();
8191 if (temp_kext_mach_hdr == NULL) {
8192 goto finish;
8193 }
8194
8195 lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
8196 for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) {
8197 if (lcp->cmd == LC_SEGMENT_KERNEL) {
8198 kernel_segment_command_t * segp;
8199 kernel_section_t * secp;
8200
8201 segp = (kernel_segment_command_t *) lcp;
8202 // 10543468 - if we jettisoned __LINKEDIT clear size info
8203 if (flags.jettisonLinkeditSeg) {
8204 if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
8205 segp->vmsize = 0;
8206 segp->fileoff = 0;
8207 segp->filesize = 0;
8208 }
8209 }
8210 #if 0
8211 OSKextLog(/* kext */ NULL,
8212 kOSKextLogErrorLevel |
8213 kOSKextLogGeneralFlag,
8214 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
8215 __FUNCTION__, segp->segname, segp->vmaddr,
8216 VM_KERNEL_UNSLIDE(segp->vmaddr),
8217 segp->vmsize, segp->nsects);
8218 #endif
8219 segp->vmaddr = VM_KERNEL_UNSLIDE(segp->vmaddr);
8220
8221 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
8222 secp->addr = VM_KERNEL_UNSLIDE(secp->addr);
8223 }
8224 }
8225 lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
8226 }
8227 result->setObject(kOSBundleMachOHeadersKey, headerData);
8228 }
8229
8230 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
8231 cpuTypeNumber = OSNumber::withNumber(
8232 (uint64_t) kext_mach_hdr->cputype,
8233 8 * sizeof(kext_mach_hdr->cputype));
8234 if (!cpuTypeNumber) {
8235 goto finish;
8236 }
8237 result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber);
8238 }
8239
8240 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
8241 cpuSubtypeNumber = OSNumber::withNumber(
8242 (uint64_t) kext_mach_hdr->cpusubtype,
8243 8 * sizeof(kext_mach_hdr->cpusubtype));
8244 if (!cpuSubtypeNumber) {
8245 goto finish;
8246 }
8247 result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber);
8248 }
8249 }
8250 }
8251
8252 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
8253 */
8254 result->setObject(kCFBundleIdentifierKey, bundleID);
8255
8256 /* CFBundleVersion.
8257 */
8258 if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
8259 versionString = OSDynamicCast(OSString,
8260 getPropertyForHostArch(kCFBundleVersionKey));
8261 if (versionString) {
8262 result->setObject(kCFBundleVersionKey, versionString);
8263 }
8264 }
8265
8266 /* OSBundleCompatibleVersion.
8267 */
8268 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
8269 versionString = OSDynamicCast(OSString,
8270 getPropertyForHostArch(kOSBundleCompatibleVersionKey));
8271 if (versionString) {
8272 result->setObject(kOSBundleCompatibleVersionKey, versionString);
8273 }
8274 }
8275
8276 /* Path.
8277 */
8278 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
8279 if (path) {
8280 result->setObject(kOSBundlePathKey, path);
8281 }
8282 }
8283
8284
8285 /* OSBundleExecutablePath.
8286 */
8287 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
8288 if (path && executableRelPath) {
8289
8290 uint32_t pathLength = path->getLength(); // gets incremented below
8291
8292 // +1 for slash, +1 for \0
8293 executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
8294
8295 executablePathCString = (char *)kalloc((executablePathCStringSize) *
8296 sizeof(char)); // +1 for \0
8297 if (!executablePathCString) {
8298 goto finish;
8299 }
8300 strlcpy(executablePathCString, path->getCStringNoCopy(),
8301 executablePathCStringSize);
8302 executablePathCString[pathLength++] = '/';
8303 executablePathCString[pathLength++] = '\0';
8304 strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
8305 executablePathCStringSize);
8306
8307 executablePathString = OSString::withCString(executablePathCString);
8308
8309 if (!executablePathCString) {
8310 goto finish;
8311 }
8312
8313 result->setObject(kOSBundleExecutablePathKey, executablePathString);
8314 }
8315 }
8316
8317 /* UUID, if the kext has one.
8318 */
8319 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
8320 uuid = copyUUID();
8321 if (uuid) {
8322 result->setObject(kOSBundleUUIDKey, uuid);
8323 }
8324 }
8325
8326 /*****
8327 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
8328 */
8329 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
8330 result->setObject(kOSKernelResourceKey,
8331 isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
8332 }
8333
8334 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
8335 result->setObject(kOSBundleIsInterfaceKey,
8336 isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
8337 }
8338
8339 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
8340 result->setObject(kOSBundlePrelinkedKey,
8341 isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
8342 }
8343
8344 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
8345 result->setObject(kOSBundleStartedKey,
8346 isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
8347 }
8348
8349 /* LoadTag (Index).
8350 */
8351 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
8352 scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
8353 /* numBits */ 8 * sizeof(loadTag));
8354 if (!scratchNumber) {
8355 goto finish;
8356 }
8357 result->setObject(kOSBundleLoadTagKey, scratchNumber);
8358 OSSafeReleaseNULL(scratchNumber);
8359 }
8360
8361 /* LoadAddress, LoadSize.
8362 */
8363 if (!infoKeys ||
8364 _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
8365 _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
8366 _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey))
8367 {
8368 if (isInterface() || linkedExecutable) {
8369 /* These go to userspace via serialization, so we don't want any doubts
8370 * about their size.
8371 */
8372 uint64_t loadAddress = 0;
8373 uint32_t loadSize = 0;
8374 uint32_t wiredSize = 0;
8375
8376 /* Interfaces always report 0 load address & size.
8377 * Just the way they roll.
8378 *
8379 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
8380 * xxx - shouldn't have one!
8381 */
8382 if (linkedExecutable /* && !isInterface() */) {
8383 loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
8384 loadAddress = VM_KERNEL_UNSLIDE(loadAddress);
8385 loadSize = linkedExecutable->getLength();
8386
8387 /* If we have a kmod_info struct, calculated the wired size
8388 * from that. Otherwise it's the full load size.
8389 */
8390 if (kmod_info) {
8391 wiredSize = loadSize - kmod_info->hdr_size;
8392 } else {
8393 wiredSize = loadSize;
8394 }
8395 }
8396
8397 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
8398 scratchNumber = OSNumber::withNumber(
8399 (unsigned long long)(loadAddress),
8400 /* numBits */ 8 * sizeof(loadAddress));
8401 if (!scratchNumber) {
8402 goto finish;
8403 }
8404 result->setObject(kOSBundleLoadAddressKey, scratchNumber);
8405 OSSafeReleaseNULL(scratchNumber);
8406 }
8407 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
8408 scratchNumber = OSNumber::withNumber(
8409 (unsigned long long)(loadSize),
8410 /* numBits */ 8 * sizeof(loadSize));
8411 if (!scratchNumber) {
8412 goto finish;
8413 }
8414 result->setObject(kOSBundleLoadSizeKey, scratchNumber);
8415 OSSafeReleaseNULL(scratchNumber);
8416 }
8417 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
8418 scratchNumber = OSNumber::withNumber(
8419 (unsigned long long)(wiredSize),
8420 /* numBits */ 8 * sizeof(wiredSize));
8421 if (!scratchNumber) {
8422 goto finish;
8423 }
8424 result->setObject(kOSBundleWiredSizeKey, scratchNumber);
8425 OSSafeReleaseNULL(scratchNumber);
8426 }
8427 }
8428 }
8429
8430 /* OSBundleDependencies. In descending order for
8431 * easy compatibility with kextstat(8).
8432 */
8433 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
8434 if ((count = getNumDependencies())) {
8435 dependencyLoadTags = OSArray::withCapacity(count);
8436 result->setObject(kOSBundleDependenciesKey, dependencyLoadTags);
8437
8438 i = count - 1;
8439 do {
8440 OSKext * dependency = OSDynamicCast(OSKext,
8441 dependencies->getObject(i));
8442
8443 OSSafeReleaseNULL(scratchNumber);
8444
8445 if (!dependency) {
8446 continue;
8447 }
8448 scratchNumber = OSNumber::withNumber(
8449 (unsigned long long)dependency->getLoadTag(),
8450 /* numBits*/ 8 * sizeof(loadTag));
8451 if (!scratchNumber) {
8452 goto finish;
8453 }
8454 dependencyLoadTags->setObject(scratchNumber);
8455 } while (i--);
8456 }
8457 }
8458
8459 OSSafeReleaseNULL(scratchNumber);
8460
8461 /* OSBundleMetaClasses.
8462 */
8463 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
8464 if (metaClasses && metaClasses->getCount()) {
8465 metaClassIterator = OSCollectionIterator::withCollection(metaClasses);
8466 metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
8467 if (!metaClassIterator || !metaClassInfo) {
8468 goto finish;
8469 }
8470 result->setObject(kOSBundleClassesKey, metaClassInfo);
8471
8472 while ( (thisMetaClass = OSDynamicCast(OSMetaClass,
8473 metaClassIterator->getNextObject())) ) {
8474
8475 OSSafeReleaseNULL(metaClassDict);
8476 OSSafeReleaseNULL(scratchNumber);
8477 OSSafeReleaseNULL(metaClassName);
8478 OSSafeReleaseNULL(superclassName);
8479
8480 metaClassDict = OSDictionary::withCapacity(3);
8481 if (!metaClassDict) {
8482 goto finish;
8483 }
8484
8485 metaClassName = OSString::withCString(thisMetaClass->getClassName());
8486 if (thisMetaClass->getSuperClass()) {
8487 superclassName = OSString::withCString(
8488 thisMetaClass->getSuperClass()->getClassName());
8489 }
8490 scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
8491 8 * sizeof(unsigned int));
8492
8493 /* Bail if any of the essentials is missing. The root class lacks a superclass,
8494 * of course.
8495 */
8496 if (!metaClassDict || !metaClassName || !scratchNumber) {
8497 goto finish;
8498 }
8499
8500 metaClassInfo->setObject(metaClassDict);
8501 metaClassDict->setObject(kOSMetaClassNameKey, metaClassName);
8502 if (superclassName) {
8503 metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName);
8504 }
8505 metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber);
8506 }
8507 }
8508 }
8509
8510 /* OSBundleRetainCount.
8511 */
8512 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
8513 OSSafeReleaseNULL(scratchNumber);
8514 {
8515 int kextRetainCount = getRetainCount() - 1;
8516 if (isLoaded()) {
8517 kextRetainCount--;
8518 }
8519 scratchNumber = OSNumber::withNumber(
8520 (int)kextRetainCount,
8521 /* numBits*/ 8 * sizeof(int));
8522 if (scratchNumber) {
8523 result->setObject(kOSBundleRetainCountKey, scratchNumber);
8524 }
8525 }
8526 }
8527
8528 success = true;
8529
8530 finish:
8531 OSSafeRelease(headerData);
8532 OSSafeRelease(cpuTypeNumber);
8533 OSSafeRelease(cpuSubtypeNumber);
8534 OSSafeRelease(executablePathString);
8535 if (executablePathString) kfree(executablePathCString, executablePathCStringSize);
8536 OSSafeRelease(uuid);
8537 OSSafeRelease(scratchNumber);
8538 OSSafeRelease(dependencyLoadTags);
8539 OSSafeRelease(metaClassIterator);
8540 OSSafeRelease(metaClassInfo);
8541 OSSafeRelease(metaClassDict);
8542 OSSafeRelease(metaClassName);
8543 OSSafeRelease(superclassName);
8544 if (!success) {
8545 OSSafeReleaseNULL(result);
8546 }
8547 return result;
8548 }
8549
8550 /*********************************************************************
8551 *********************************************************************/
8552 /* static */
8553 OSReturn
8554 OSKext::requestResource(
8555 const char * kextIdentifierCString,
8556 const char * resourceNameCString,
8557 OSKextRequestResourceCallback callback,
8558 void * context,
8559 OSKextRequestTag * requestTagOut)
8560 {
8561 OSReturn result = kOSReturnError;
8562 OSKext * callbackKext = NULL; // must release (looked up)
8563
8564 OSKextRequestTag requestTag = -1;
8565 OSNumber * requestTagNum = NULL; // must release
8566
8567 OSDictionary * requestDict = NULL; // must release
8568 OSString * kextIdentifier = NULL; // must release
8569 OSString * resourceName = NULL; // must release
8570
8571 OSDictionary * callbackRecord = NULL; // must release
8572 OSData * callbackWrapper = NULL; // must release
8573
8574 OSData * contextWrapper = NULL; // must release
8575
8576 IORecursiveLockLock(sKextLock);
8577
8578 if (requestTagOut) {
8579 *requestTagOut = kOSKextRequestTagInvalid;
8580 }
8581
8582 /* If requests to user space are disabled, don't go any further */
8583 if (!sKernelRequestsEnabled) {
8584 OSKextLog(/* kext */ NULL,
8585 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8586 "Can't request resource %s for %s - requests to user space are disabled.",
8587 resourceNameCString,
8588 kextIdentifierCString);
8589 result = kOSKextReturnDisabled;
8590 goto finish;
8591 }
8592
8593 if (!kextIdentifierCString || !resourceNameCString || !callback) {
8594 result = kOSKextReturnInvalidArgument;
8595 goto finish;
8596 }
8597
8598 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
8599 if (!callbackKext) {
8600 OSKextLog(/* kext */ NULL,
8601 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8602 "Resource request has bad callback address.");
8603 result = kOSKextReturnInvalidArgument;
8604 goto finish;
8605 }
8606 if (!callbackKext->flags.starting && !callbackKext->flags.started) {
8607 OSKextLog(/* kext */ NULL,
8608 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8609 "Resource request callback is in a kext that is not started.");
8610 result = kOSKextReturnInvalidArgument;
8611 goto finish;
8612 }
8613
8614 /* Do not allow any new requests to be made on a kext that is unloading.
8615 */
8616 if (callbackKext->flags.stopping) {
8617 result = kOSKextReturnStopping;
8618 goto finish;
8619 }
8620
8621 /* If we're wrapped the next available request tag around to the negative
8622 * numbers, we can't service any more requests.
8623 */
8624 if (sNextRequestTag == kOSKextRequestTagInvalid) {
8625 OSKextLog(/* kext */ NULL,
8626 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8627 "No more request tags available; restart required.");
8628 result = kOSKextReturnNoResources;
8629 goto finish;
8630 }
8631 requestTag = sNextRequestTag++;
8632
8633 result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
8634 &requestDict);
8635 if (result != kOSReturnSuccess) {
8636 goto finish;
8637 }
8638
8639 kextIdentifier = OSString::withCString(kextIdentifierCString);
8640 resourceName = OSString::withCString(resourceNameCString);
8641 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag,
8642 8 * sizeof(requestTag));
8643 if (!kextIdentifier ||
8644 !resourceName ||
8645 !requestTagNum ||
8646 !_OSKextSetRequestArgument(requestDict,
8647 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
8648 !_OSKextSetRequestArgument(requestDict,
8649 kKextRequestArgumentNameKey, resourceName) ||
8650 !_OSKextSetRequestArgument(requestDict,
8651 kKextRequestArgumentRequestTagKey, requestTagNum)) {
8652
8653 result = kOSKextReturnNoMemory;
8654 goto finish;
8655 }
8656
8657 callbackRecord = OSDynamicCast(OSDictionary, requestDict->copyCollection());
8658 if (!callbackRecord) {
8659 result = kOSKextReturnNoMemory;
8660 goto finish;
8661 }
8662 // we validate callback address at call time
8663 callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *));
8664 if (context) {
8665 contextWrapper = OSData::withBytes((void *)&context, sizeof(void *));
8666 }
8667 if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord,
8668 kKextRequestArgumentCallbackKey, callbackWrapper)) {
8669
8670 result = kOSKextReturnNoMemory;
8671 goto finish;
8672 }
8673
8674 if (context) {
8675 if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord,
8676 kKextRequestArgumentContextKey, contextWrapper)) {
8677
8678 result = kOSKextReturnNoMemory;
8679 goto finish;
8680 }
8681 }
8682
8683 /* Only post the requests after all the other potential failure points
8684 * have been passed.
8685 */
8686 if (!sKernelRequests->setObject(requestDict) ||
8687 !sRequestCallbackRecords->setObject(callbackRecord)) {
8688
8689 result = kOSKextReturnNoMemory;
8690 goto finish;
8691 }
8692
8693 OSKext::pingKextd();
8694
8695 result = kOSReturnSuccess;
8696 if (requestTagOut) {
8697 *requestTagOut = requestTag;
8698 }
8699
8700 finish:
8701
8702 /* If we didn't succeed, yank the request & callback
8703 * from their holding arrays.
8704 */
8705 if (result != kOSReturnSuccess) {
8706 unsigned int index;
8707
8708 index = sKernelRequests->getNextIndexOfObject(requestDict, 0);
8709 if (index != (unsigned int)-1) {
8710 sKernelRequests->removeObject(index);
8711 }
8712 index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord, 0);
8713 if (index != (unsigned int)-1) {
8714 sRequestCallbackRecords->removeObject(index);
8715 }
8716 }
8717
8718 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8719
8720 IORecursiveLockUnlock(sKextLock);
8721
8722 if (callbackKext) callbackKext->release();
8723 if (requestTagNum) requestTagNum->release();
8724
8725 if (requestDict) requestDict->release();
8726 if (kextIdentifier) kextIdentifier->release();
8727 if (resourceName) resourceName->release();
8728
8729 if (callbackRecord) callbackRecord->release();
8730 if (callbackWrapper) callbackWrapper->release();
8731 if (contextWrapper) contextWrapper->release();
8732
8733 return result;
8734 }
8735
8736 /*********************************************************************
8737 * Assumes sKextLock is held.
8738 *********************************************************************/
8739 /* static */
8740 OSReturn
8741 OSKext::dequeueCallbackForRequestTag(
8742 OSKextRequestTag requestTag,
8743 OSDictionary ** callbackRecordOut)
8744 {
8745 OSReturn result = kOSReturnError;
8746 OSNumber * requestTagNum = NULL; // must release
8747
8748 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag,
8749 8 * sizeof(requestTag));
8750 if (!requestTagNum) {
8751 goto finish;
8752 }
8753
8754 result = OSKext::dequeueCallbackForRequestTag(requestTagNum,
8755 callbackRecordOut);
8756
8757 finish:
8758 OSSafeRelease(requestTagNum);
8759
8760 return result;
8761 }
8762
8763 /*********************************************************************
8764 * Assumes sKextLock is held.
8765 *********************************************************************/
8766 /* static */
8767 OSReturn
8768 OSKext::dequeueCallbackForRequestTag(
8769 OSNumber * requestTagNum,
8770 OSDictionary ** callbackRecordOut)
8771 {
8772 OSReturn result = kOSKextReturnInvalidArgument;
8773 OSDictionary * callbackRecord = NULL; // retain if matched!
8774 OSNumber * callbackTagNum = NULL; // do not release
8775 unsigned int count, i;
8776
8777 result = kOSReturnError;
8778 count = sRequestCallbackRecords->getCount();
8779 for (i = 0; i < count; i++) {
8780 callbackRecord = OSDynamicCast(OSDictionary,
8781 sRequestCallbackRecords->getObject(i));
8782 if (!callbackRecord) {
8783 goto finish;
8784 }
8785
8786 /* If we don't find a tag, we basically have a leak here. Maybe
8787 * we should just remove it.
8788 */
8789 callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
8790 callbackRecord, kKextRequestArgumentRequestTagKey));
8791 if (!callbackTagNum) {
8792 goto finish;
8793 }
8794
8795 /* We could be even more paranoid and check that all the incoming
8796 * args match what's in the callback record.
8797 */
8798 if (callbackTagNum->isEqualTo(requestTagNum)) {
8799 if (callbackRecordOut) {
8800 *callbackRecordOut = callbackRecord;
8801 callbackRecord->retain();
8802 }
8803 sRequestCallbackRecords->removeObject(i);
8804 result = kOSReturnSuccess;
8805 goto finish;
8806 }
8807 }
8808 result = kOSKextReturnNotFound;
8809
8810 finish:
8811 return result;
8812 }
8813
8814 /*********************************************************************
8815 * Assumes sKextLock is held.
8816 *********************************************************************/
8817 /* static */
8818 OSReturn
8819 OSKext::dispatchResource(OSDictionary * requestDict)
8820 {
8821 OSReturn result = kOSReturnError;
8822 OSDictionary * callbackRecord = NULL; // must release
8823 OSNumber * requestTag = NULL; // do not release
8824 OSNumber * requestResult = NULL; // do not release
8825 OSData * dataObj = NULL; // do not release
8826 uint32_t dataLength = 0;
8827 const void * dataPtr = NULL; // do not free
8828 OSData * callbackWrapper = NULL; // do not release
8829 OSKextRequestResourceCallback callback = NULL;
8830 OSData * contextWrapper = NULL; // do not release
8831 void * context = NULL; // do not free
8832 OSKext * callbackKext = NULL; // must release (looked up)
8833
8834 /* Get the args from the request. Right now we need the tag
8835 * to look up the callback record, and the result for invoking the callback.
8836 */
8837 requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
8838 kKextRequestArgumentRequestTagKey));
8839 requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
8840 kKextRequestArgumentResultKey));
8841 if (!requestTag || !requestResult) {
8842 result = kOSKextReturnInvalidArgument;
8843 goto finish;
8844 }
8845
8846 /* Look for a callback record matching this request's tag.
8847 */
8848 result = dequeueCallbackForRequestTag(requestTag, &callbackRecord);
8849 if (result != kOSReturnSuccess) {
8850 goto finish;
8851 }
8852
8853 /*****
8854 * Get the context pointer of the callback record (if there is one).
8855 */
8856 contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord,
8857 kKextRequestArgumentContextKey));
8858 context = _OSKextExtractPointer(contextWrapper);
8859 if (contextWrapper && !context) {
8860 goto finish;
8861 }
8862
8863 callbackWrapper = OSDynamicCast(OSData,
8864 _OSKextGetRequestArgument(callbackRecord,
8865 kKextRequestArgumentCallbackKey));
8866 callback = (OSKextRequestResourceCallback)
8867 _OSKextExtractPointer(callbackWrapper);
8868 if (!callback) {
8869 goto finish;
8870 }
8871
8872 /* Check for a data obj. We might not have one and that's ok, that means
8873 * we didn't find the requested resource, and we still have to tell the
8874 * caller that via the callback.
8875 */
8876 dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
8877 kKextRequestArgumentValueKey));
8878 if (dataObj) {
8879 dataPtr = dataObj->getBytesNoCopy();
8880 dataLength = dataObj->getLength();
8881 }
8882
8883 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
8884 if (!callbackKext) {
8885 OSKextLog(/* kext */ NULL,
8886 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8887 "Can't invoke callback for resource request; ");
8888 goto finish;
8889 }
8890 if (!callbackKext->flags.starting && !callbackKext->flags.started) {
8891 OSKextLog(/* kext */ NULL,
8892 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
8893 "Can't invoke kext resource callback; ");
8894 goto finish;
8895 }
8896
8897 (void)callback(requestTag->unsigned32BitValue(),
8898 (OSReturn)requestResult->unsigned32BitValue(),
8899 dataPtr, dataLength, context);
8900
8901 result = kOSReturnSuccess;
8902
8903 finish:
8904 if (callbackKext) callbackKext->release();
8905 if (callbackRecord) callbackRecord->release();
8906
8907 return result;
8908 }
8909
8910 /*********************************************************************
8911 *********************************************************************/
8912 /* static */
8913 void
8914 OSKext::invokeRequestCallback(
8915 OSDictionary * callbackRecord,
8916 OSReturn callbackResult)
8917 {
8918 OSString * predicate = _OSKextGetRequestPredicate(callbackRecord);
8919 OSNumber * resultNum = NULL; // must release
8920
8921 if (!predicate) {
8922 goto finish;
8923 }
8924
8925 resultNum = OSNumber::withNumber((long long unsigned int)callbackResult,
8926 8 * sizeof(callbackResult));
8927 if (!resultNum) {
8928 goto finish;
8929 }
8930
8931 /* Insert the result into the callback record and dispatch it as if it
8932 * were the reply coming down from user space.
8933 */
8934 _OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
8935 resultNum);
8936
8937 if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
8938 /* This removes the pending callback record.
8939 */
8940 OSKext::dispatchResource(callbackRecord);
8941 }
8942
8943 finish:
8944 if (resultNum) resultNum->release();
8945 return;
8946 }
8947
8948 /*********************************************************************
8949 * Assumes sKextLock is held.
8950 *********************************************************************/
8951 /* static */
8952 OSReturn
8953 OSKext::cancelRequest(
8954 OSKextRequestTag requestTag,
8955 void ** contextOut)
8956 {
8957 OSReturn result = kOSKextReturnNoMemory;
8958 OSDictionary * callbackRecord = NULL; // must release
8959 OSData * contextWrapper = NULL; // do not release
8960
8961 IORecursiveLockLock(sKextLock);
8962 result = OSKext::dequeueCallbackForRequestTag(requestTag,
8963 &callbackRecord);
8964 IORecursiveLockUnlock(sKextLock);
8965
8966 if (result == kOSReturnSuccess && contextOut) {
8967 contextWrapper = OSDynamicCast(OSData,
8968 _OSKextGetRequestArgument(callbackRecord,
8969 kKextRequestArgumentContextKey));
8970 *contextOut = _OSKextExtractPointer(contextWrapper);
8971 }
8972
8973 if (callbackRecord) callbackRecord->release();
8974
8975 return result;
8976 }
8977
8978 /*********************************************************************
8979 * Assumes sKextLock is held.
8980 *********************************************************************/
8981 void
8982 OSKext::invokeOrCancelRequestCallbacks(
8983 OSReturn callbackResult,
8984 bool invokeFlag)
8985 {
8986 unsigned int count, i;
8987
8988 count = sRequestCallbackRecords->getCount();
8989 if (!count) {
8990 goto finish;
8991 }
8992
8993 i = count - 1;
8994 do {
8995 OSDictionary * request = OSDynamicCast(OSDictionary,
8996 sRequestCallbackRecords->getObject(i));
8997
8998 if (!request) {
8999 continue;
9000 }
9001 OSData * callbackWrapper = OSDynamicCast(OSData,
9002 _OSKextGetRequestArgument(request,
9003 kKextRequestArgumentCallbackKey));
9004
9005 if (!callbackWrapper) {
9006 sRequestCallbackRecords->removeObject(i);
9007 continue;
9008 }
9009
9010 vm_address_t callbackAddress = (vm_address_t)
9011 _OSKextExtractPointer(callbackWrapper);
9012
9013 if ((kmod_info->address <= callbackAddress) &&
9014 (callbackAddress < (kmod_info->address + kmod_info->size))) {
9015
9016 if (invokeFlag) {
9017 /* This removes the callback record.
9018 */
9019 invokeRequestCallback(request, callbackResult);
9020 } else {
9021 sRequestCallbackRecords->removeObject(i);
9022 }
9023 }
9024 } while (i--);
9025
9026 finish:
9027 return;
9028 }
9029
9030 /*********************************************************************
9031 * Assumes sKextLock is held.
9032 *********************************************************************/
9033 uint32_t
9034 OSKext::countRequestCallbacks(void)
9035 {
9036 uint32_t result = 0;
9037 unsigned int count, i;
9038
9039 count = sRequestCallbackRecords->getCount();
9040 if (!count) {
9041 goto finish;
9042 }
9043
9044 i = count - 1;
9045 do {
9046 OSDictionary * request = OSDynamicCast(OSDictionary,
9047 sRequestCallbackRecords->getObject(i));
9048
9049 if (!request) {
9050 continue;
9051 }
9052 OSData * callbackWrapper = OSDynamicCast(OSData,
9053 _OSKextGetRequestArgument(request,
9054 kKextRequestArgumentCallbackKey));
9055
9056 if (!callbackWrapper) {
9057 continue;
9058 }
9059
9060 vm_address_t callbackAddress = (vm_address_t)
9061 _OSKextExtractPointer(callbackWrapper);
9062
9063 if ((kmod_info->address <= callbackAddress) &&
9064 (callbackAddress < (kmod_info->address + kmod_info->size))) {
9065
9066 result++;
9067 }
9068 } while (i--);
9069
9070 finish:
9071 return result;
9072 }
9073
9074 /*********************************************************************
9075 *********************************************************************/
9076 static OSReturn _OSKextCreateRequest(
9077 const char * predicate,
9078 OSDictionary ** requestP)
9079 {
9080 OSReturn result = kOSKextReturnNoMemory;
9081 OSDictionary * request = NULL; // must release on error
9082 OSDictionary * args = NULL; // must release
9083
9084 request = OSDictionary::withCapacity(2);
9085 if (!request) {
9086 goto finish;
9087 }
9088 result = _OSDictionarySetCStringValue(request,
9089 kKextRequestPredicateKey, predicate);
9090 if (result != kOSReturnSuccess) {
9091 goto finish;
9092 }
9093 result = kOSReturnSuccess;
9094
9095 finish:
9096 if (result != kOSReturnSuccess) {
9097 if (request) request->release();
9098 } else {
9099 *requestP = request;
9100 }
9101 if (args) args->release();
9102
9103 return result;
9104 }
9105
9106 /*********************************************************************
9107 *********************************************************************/
9108 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict)
9109 {
9110 return OSDynamicCast(OSString,
9111 requestDict->getObject(kKextRequestPredicateKey));
9112 }
9113
9114 /*********************************************************************
9115 *********************************************************************/
9116 static OSObject * _OSKextGetRequestArgument(
9117 OSDictionary * requestDict,
9118 const char * argName)
9119 {
9120 OSDictionary * args = OSDynamicCast(OSDictionary,
9121 requestDict->getObject(kKextRequestArgumentsKey));
9122 if (args) {
9123 return args->getObject(argName);
9124 }
9125 return NULL;
9126 }
9127
9128 /*********************************************************************
9129 *********************************************************************/
9130 static bool _OSKextSetRequestArgument(
9131 OSDictionary * requestDict,
9132 const char * argName,
9133 OSObject * value)
9134 {
9135 OSDictionary * args = OSDynamicCast(OSDictionary,
9136 requestDict->getObject(kKextRequestArgumentsKey));
9137 if (!args) {
9138 args = OSDictionary::withCapacity(2);
9139 if (!args) {
9140 goto finish;
9141 }
9142 requestDict->setObject(kKextRequestArgumentsKey, args);
9143 args->release();
9144 }
9145 if (args) {
9146 return args->setObject(argName, value);
9147 }
9148 finish:
9149 return false;
9150 }
9151
9152 /*********************************************************************
9153 *********************************************************************/
9154 static void * _OSKextExtractPointer(OSData * wrapper)
9155 {
9156 void * result = NULL;
9157 const void * resultPtr = NULL;
9158
9159 if (!wrapper) {
9160 goto finish;
9161 }
9162 resultPtr = wrapper->getBytesNoCopy();
9163 result = *(void **)resultPtr;
9164 finish:
9165 return result;
9166 }
9167
9168 /*********************************************************************
9169 *********************************************************************/
9170 static OSReturn _OSDictionarySetCStringValue(
9171 OSDictionary * dict,
9172 const char * cKey,
9173 const char * cValue)
9174 {
9175 OSReturn result = kOSKextReturnNoMemory;
9176 const OSSymbol * key = NULL; // must release
9177 OSString * value = NULL; // must release
9178
9179 key = OSSymbol::withCString(cKey);
9180 value = OSString::withCString(cValue);
9181 if (!key || !value) {
9182 goto finish;
9183 }
9184 if (dict->setObject(key, value)) {
9185 result = kOSReturnSuccess;
9186 }
9187
9188 finish:
9189 if (key) key->release();
9190 if (value) value->release();
9191
9192 return result;
9193 }
9194
9195 /*********************************************************************
9196 *********************************************************************/
9197 static bool _OSArrayContainsCString(
9198 OSArray * array,
9199 const char * cString)
9200 {
9201 bool result = false;
9202 const OSSymbol * symbol = NULL;
9203 uint32_t count, i;
9204
9205 if (!array || !cString) {
9206 goto finish;
9207 }
9208
9209 symbol = OSSymbol::withCStringNoCopy(cString);
9210 if (!symbol) {
9211 goto finish;
9212 }
9213
9214 count = array->getCount();
9215 for (i = 0; i < count; i++) {
9216 OSObject * thisObject = array->getObject(i);
9217 if (symbol->isEqualTo(thisObject)) {
9218 result = true;
9219 goto finish;
9220 }
9221 }
9222
9223 finish:
9224 if (symbol) symbol->release();
9225 return result;
9226 }
9227
9228 /*********************************************************************
9229 * We really only care about boot / system start up related kexts.
9230 * We return true if we're less than REBUILD_MAX_TIME since start up,
9231 * otherwise return false.
9232 *********************************************************************/
9233 bool _OSKextInPrelinkRebuildWindow(void)
9234 {
9235 static bool outside_the_window = false;
9236 AbsoluteTime my_abstime;
9237 UInt64 my_ns;
9238 SInt32 my_secs;
9239
9240 if (outside_the_window) {
9241 return(false);
9242 }
9243 clock_get_uptime(&my_abstime);
9244 absolutetime_to_nanoseconds(my_abstime, &my_ns);
9245 my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
9246 if (my_secs > REBUILD_MAX_TIME) {
9247 outside_the_window = true;
9248 return(false);
9249 }
9250 return(true);
9251 }
9252
9253 /*********************************************************************
9254 *********************************************************************/
9255 bool _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
9256 {
9257 int unLoadedCount, i;
9258 bool result = false;
9259
9260 IORecursiveLockLock(sKextLock);
9261
9262 if (sUnloadedPrelinkedKexts == NULL) {
9263 goto finish;
9264 }
9265 unLoadedCount = sUnloadedPrelinkedKexts->getCount();
9266 if (unLoadedCount == 0) {
9267 goto finish;
9268 }
9269
9270 for (i = 0; i < unLoadedCount; i++) {
9271 const OSSymbol * myBundleID; // do not release
9272
9273 myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
9274 if (!myBundleID) continue;
9275 if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
9276 result = true;
9277 break;
9278 }
9279 }
9280 finish:
9281 IORecursiveLockUnlock(sKextLock);
9282 return(result);
9283 }
9284
9285 #if PRAGMA_MARK
9286 #pragma mark Personalities (IOKit Drivers)
9287 #endif
9288 /*********************************************************************
9289 *********************************************************************/
9290 /* static */
9291 OSArray *
9292 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
9293 {
9294 OSArray * result = NULL; // returned
9295 OSCollectionIterator * kextIterator = NULL; // must release
9296 OSArray * personalities = NULL; // must release
9297 OSCollectionIterator * personalitiesIterator = NULL; // must release
9298
9299 OSString * kextID = NULL; // do not release
9300 OSKext * theKext = NULL; // do not release
9301
9302 IORecursiveLockLock(sKextLock);
9303
9304 /* Let's conservatively guess that any given kext has around 3
9305 * personalities for now.
9306 */
9307 result = OSArray::withCapacity(sKextsByID->getCount() * 3);
9308 if (!result) {
9309 goto finish;
9310 }
9311
9312 kextIterator = OSCollectionIterator::withCollection(sKextsByID);
9313 if (!kextIterator) {
9314 goto finish;
9315 }
9316
9317 while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
9318 if (personalitiesIterator) {
9319 personalitiesIterator->release();
9320 personalitiesIterator = NULL;
9321 }
9322 if (personalities) {
9323 personalities->release();
9324 personalities = NULL;
9325 }
9326
9327 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
9328 if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
9329 personalities = theKext->copyPersonalitiesArray();
9330 if (!personalities) {
9331 continue;
9332 }
9333 result->merge(personalities);
9334 } else {
9335 // xxx - check for better place to put this log msg
9336 OSKextLog(theKext,
9337 kOSKextLogWarningLevel |
9338 kOSKextLogLoadFlag,
9339 "Kext %s is not loadable during safe boot; "
9340 "omitting its personalities.",
9341 theKext->getIdentifierCString());
9342 }
9343
9344 }
9345
9346 finish:
9347 IORecursiveLockUnlock(sKextLock);
9348
9349 if (kextIterator) kextIterator->release();
9350 if (personalitiesIterator) personalitiesIterator->release();
9351 if (personalities) personalities->release();
9352
9353 return result;
9354 }
9355
9356 /*********************************************************************
9357 *********************************************************************/
9358 /* static */
9359 void
9360 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
9361 {
9362 int numPersonalities = 0;
9363
9364 OSKextLog(/* kext */ NULL,
9365 kOSKextLogStepLevel |
9366 kOSKextLogLoadFlag,
9367 "Sending all eligible registered kexts' personalities "
9368 "to the IOCatalogue %s.",
9369 startMatching ? "and starting matching" : "but not starting matching");
9370
9371 OSArray * personalities = OSKext::copyAllKextPersonalities(
9372 /* filterSafeBootFlag */ true);
9373
9374 if (personalities) {
9375 gIOCatalogue->addDrivers(personalities, startMatching);
9376 numPersonalities = personalities->getCount();
9377 personalities->release();
9378 }
9379
9380 OSKextLog(/* kext */ NULL,
9381 kOSKextLogStepLevel |
9382 kOSKextLogLoadFlag,
9383 "%d kext personalit%s sent to the IOCatalogue; %s.",
9384 numPersonalities, numPersonalities > 0 ? "ies" : "y",
9385 startMatching ? "matching started" : "matching not started");
9386 return;
9387 }
9388
9389 /*********************************************************************
9390 * Do not make a deep copy, just convert the IOKitPersonalities dict
9391 * to an array for sending to the IOCatalogue.
9392 *********************************************************************/
9393 OSArray *
9394 OSKext::copyPersonalitiesArray(void)
9395 {
9396 OSArray * result = NULL;
9397 OSDictionary * personalities = NULL; // do not release
9398 OSCollectionIterator * personalitiesIterator = NULL; // must release
9399
9400 OSString * personalityName = NULL; // do not release
9401 OSString * personalityBundleIdentifier = NULL; // do not release
9402
9403 personalities = OSDynamicCast(OSDictionary,
9404 getPropertyForHostArch(kIOKitPersonalitiesKey));
9405 if (!personalities) {
9406 goto finish;
9407 }
9408
9409 result = OSArray::withCapacity(personalities->getCount());
9410 if (!result) {
9411 goto finish;
9412 }
9413
9414 personalitiesIterator =
9415 OSCollectionIterator::withCollection(personalities);
9416 if (!personalitiesIterator) {
9417 goto finish;
9418 }
9419 while ((personalityName = OSDynamicCast(OSString,
9420 personalitiesIterator->getNextObject()))) {
9421
9422 OSDictionary * personality = OSDynamicCast(OSDictionary,
9423 personalities->getObject(personalityName));
9424
9425 /******
9426 * If the personality doesn't have a CFBundleIdentifier, or if it
9427 * differs from the kext's, insert the kext's ID so we can find it.
9428 * The publisher ID is used to remove personalities from bundles
9429 * correctly.
9430 */
9431 personalityBundleIdentifier = OSDynamicCast(OSString,
9432 personality->getObject(kCFBundleIdentifierKey));
9433
9434 if (!personalityBundleIdentifier) {
9435 personality->setObject(kCFBundleIdentifierKey, bundleID);
9436 } else if (!personalityBundleIdentifier->isEqualTo(bundleID)) {
9437 personality->setObject(kIOPersonalityPublisherKey, bundleID);
9438 }
9439
9440 result->setObject(personality);
9441 }
9442
9443 finish:
9444 if (personalitiesIterator) personalitiesIterator->release();
9445
9446 return result;
9447 }
9448
9449 /*********************************************************************
9450 Might want to change this to a bool return?
9451 *********************************************************************/
9452 OSReturn
9453 OSKext::sendPersonalitiesToCatalog(
9454 bool startMatching,
9455 OSArray * personalityNames)
9456 {
9457 OSReturn result = kOSReturnSuccess;
9458 OSArray * personalitiesToSend = NULL; // must release
9459 OSDictionary * kextPersonalities = NULL; // do not release
9460 int count, i;
9461
9462 if (!sLoadEnabled) {
9463 OSKextLog(this,
9464 kOSKextLogErrorLevel |
9465 kOSKextLogLoadFlag,
9466 "Kext loading is disabled (attempt to start matching for kext %s).",
9467 getIdentifierCString());
9468 result = kOSKextReturnDisabled;
9469 goto finish;
9470 }
9471
9472 if (sSafeBoot && !isLoadableInSafeBoot()) {
9473 OSKextLog(this,
9474 kOSKextLogErrorLevel |
9475 kOSKextLogLoadFlag,
9476 "Kext %s is not loadable during safe boot; "
9477 "not sending personalities to the IOCatalogue.",
9478 getIdentifierCString());
9479 result = kOSKextReturnNotLoadable;
9480 goto finish;
9481 }
9482
9483 if (!personalityNames || !personalityNames->getCount()) {
9484 personalitiesToSend = copyPersonalitiesArray();
9485 } else {
9486 kextPersonalities = OSDynamicCast(OSDictionary,
9487 getPropertyForHostArch(kIOKitPersonalitiesKey));
9488 if (!kextPersonalities || !kextPersonalities->getCount()) {
9489 // not an error
9490 goto finish;
9491 }
9492 personalitiesToSend = OSArray::withCapacity(0);
9493 if (!personalitiesToSend) {
9494 result = kOSKextReturnNoMemory;
9495 goto finish;
9496 }
9497 count = personalityNames->getCount();
9498 for (i = 0; i < count; i++) {
9499 OSString * name = OSDynamicCast(OSString,
9500 personalityNames->getObject(i));
9501 if (!name) {
9502 continue;
9503 }
9504 OSDictionary * personality = OSDynamicCast(OSDictionary,
9505 kextPersonalities->getObject(name));
9506 if (personality) {
9507 personalitiesToSend->setObject(personality);
9508 }
9509 }
9510 }
9511 if (personalitiesToSend) {
9512 unsigned numPersonalities = personalitiesToSend->getCount();
9513 OSKextLog(this,
9514 kOSKextLogStepLevel |
9515 kOSKextLogLoadFlag,
9516 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
9517 getIdentifierCString(),
9518 numPersonalities,
9519 numPersonalities > 1 ? "ies" : "y",
9520 startMatching ? " and starting matching" : " but not starting matching");
9521 gIOCatalogue->addDrivers(personalitiesToSend, startMatching);
9522 }
9523 finish:
9524 if (personalitiesToSend) {
9525 personalitiesToSend->release();
9526 }
9527 return result;
9528 }
9529
9530 /*********************************************************************
9531 * xxx - We should allow removing the kext's declared personalities,
9532 * xxx - even with other bundle identifiers.
9533 *********************************************************************/
9534 void
9535 OSKext::removePersonalitiesFromCatalog(void)
9536 {
9537 OSDictionary * personality = NULL; // do not release
9538
9539 personality = OSDictionary::withCapacity(1);
9540 if (!personality) {
9541 goto finish;
9542 }
9543 personality->setObject(kCFBundleIdentifierKey, getIdentifier());
9544
9545 OSKextLog(this,
9546 kOSKextLogStepLevel |
9547 kOSKextLogLoadFlag,
9548 "Kext %s removing all personalities naming it from the IOCatalogue.",
9549 getIdentifierCString());
9550
9551 /* Have the IOCatalog remove all personalities matching this kext's
9552 * bundle ID and trigger matching anew.
9553 */
9554 gIOCatalogue->removeDrivers(personality, /* startMatching */ true);
9555
9556 finish:
9557 if (personality) personality->release();
9558
9559 return;
9560 }
9561
9562
9563 #if PRAGMA_MARK
9564 #pragma mark Logging
9565 #endif
9566 /*********************************************************************
9567 * Do not call any function that takes sKextLock here!
9568 *********************************************************************/
9569 /* static */
9570 OSKextLogSpec
9571 OSKext::setUserSpaceLogFilter(
9572 OSKextLogSpec newUserLogFilter,
9573 bool captureFlag)
9574 {
9575 OSKextLogSpec result;
9576 bool allocError = false;
9577
9578 /* Do not call any function that takes sKextLoggingLock during
9579 * this critical block. That means do logging after.
9580 */
9581 IOLockLock(sKextLoggingLock);
9582
9583 result = sUserSpaceKextLogFilter;
9584 sUserSpaceKextLogFilter = newUserLogFilter;
9585
9586 if (newUserLogFilter && captureFlag &&
9587 !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
9588
9589 // xxx - do some measurements for a good initial capacity?
9590 sUserSpaceLogSpecArray = OSArray::withCapacity(0);
9591 sUserSpaceLogMessageArray = OSArray::withCapacity(0);
9592
9593 if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
9594 OSSafeReleaseNULL(sUserSpaceLogSpecArray);
9595 OSSafeReleaseNULL(sUserSpaceLogMessageArray);
9596 allocError = true;
9597 }
9598 }
9599
9600 IOLockUnlock(sKextLoggingLock);
9601
9602 /* If the config flag itself is changing, log the state change
9603 * going both ways, before setting up the user-space log arrays,
9604 * so that this is only logged in the kernel.
9605 */
9606 if (result != newUserLogFilter) {
9607 OSKextLog(/* kext */ NULL,
9608 kOSKextLogDebugLevel |
9609 kOSKextLogGeneralFlag,
9610 "User-space log flags changed from 0x%x to 0x%x.",
9611 result, newUserLogFilter);
9612 }
9613 if (allocError) {
9614 OSKextLog(/* kext */ NULL,
9615 kOSKextLogErrorLevel |
9616 kOSKextLogGeneralFlag,
9617 "Failed to allocate user-space log message arrays.");
9618 }
9619
9620 return result;
9621 }
9622
9623 /*********************************************************************
9624 * Do not call any function that takes sKextLock here!
9625 *********************************************************************/
9626 /* static */
9627 OSArray *
9628 OSKext::clearUserSpaceLogFilter(void)
9629 {
9630 OSArray * result = NULL;
9631 OSKextLogSpec oldLogFilter;
9632 OSKextLogSpec newLogFilter = kOSKextLogSilentFilter;
9633
9634 /* Do not call any function that takes sKextLoggingLock during
9635 * this critical block. That means do logging after.
9636 */
9637 IOLockLock(sKextLoggingLock);
9638
9639 result = OSArray::withCapacity(2);
9640 if (result) {
9641 result->setObject(sUserSpaceLogSpecArray);
9642 result->setObject(sUserSpaceLogMessageArray);
9643 }
9644 OSSafeReleaseNULL(sUserSpaceLogSpecArray);
9645 OSSafeReleaseNULL(sUserSpaceLogMessageArray);
9646
9647 oldLogFilter = sUserSpaceKextLogFilter;
9648 sUserSpaceKextLogFilter = newLogFilter;
9649
9650 IOLockUnlock(sKextLoggingLock);
9651
9652 /* If the config flag itself is changing, log the state change
9653 * going both ways, after tearing down the user-space log
9654 * arrays, so this is only logged within the kernel.
9655 */
9656 if (oldLogFilter != newLogFilter) {
9657 OSKextLog(/* kext */ NULL,
9658 kOSKextLogDebugLevel |
9659 kOSKextLogGeneralFlag,
9660 "User-space log flags changed from 0x%x to 0x%x.",
9661 oldLogFilter, newLogFilter);
9662 }
9663
9664 return result;
9665 }
9666
9667
9668 /*********************************************************************
9669 * Do not call any function that takes sKextLock here!
9670 *********************************************************************/
9671 /* static */
9672 OSKextLogSpec
9673 OSKext::getUserSpaceLogFilter(void)
9674 {
9675 OSKextLogSpec result;
9676
9677 IOLockLock(sKextLoggingLock);
9678 result = sUserSpaceKextLogFilter;
9679 IOLockUnlock(sKextLoggingLock);
9680
9681 return result;
9682 }
9683
9684 /*********************************************************************
9685 * This function is called by OSMetaClass during kernel C++ setup.
9686 * Be careful what you access here; assume only OSKext::initialize()
9687 * has been called.
9688 *
9689 * Do not call any function that takes sKextLock here!
9690 *********************************************************************/
9691 #define VTRESET "\033[0m"
9692
9693 #define VTBOLD "\033[1m"
9694 #define VTUNDER "\033[4m"
9695
9696 #define VTRED "\033[31m"
9697 #define VTGREEN "\033[32m"
9698 #define VTYELLOW "\033[33m"
9699 #define VTBLUE "\033[34m"
9700 #define VTMAGENTA "\033[35m"
9701 #define VTCYAN "\033[36m"
9702
9703 inline const char * colorForFlags(OSKextLogSpec flags)
9704 {
9705 OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
9706
9707 switch (logLevel) {
9708 case kOSKextLogErrorLevel:
9709 return VTRED VTBOLD;
9710 break;
9711 case kOSKextLogWarningLevel:
9712 return VTRED;
9713 break;
9714 case kOSKextLogBasicLevel:
9715 return VTYELLOW VTUNDER;
9716 break;
9717 case kOSKextLogProgressLevel:
9718 return VTYELLOW;
9719 break;
9720 case kOSKextLogStepLevel:
9721 return VTGREEN;
9722 break;
9723 case kOSKextLogDetailLevel:
9724 return VTCYAN;
9725 break;
9726 case kOSKextLogDebugLevel:
9727 return VTMAGENTA;
9728 break;
9729 default:
9730 return ""; // white
9731 break;
9732 }
9733 return "";
9734 }
9735
9736 inline bool logSpecMatch(
9737 OSKextLogSpec msgLogSpec,
9738 OSKextLogSpec logFilter)
9739 {
9740 OSKextLogSpec filterKextGlobal = logFilter & kOSKextLogKextOrGlobalMask;
9741 OSKextLogSpec filterLevel = logFilter & kOSKextLogLevelMask;
9742 OSKextLogSpec filterFlags = logFilter & kOSKextLogFlagsMask;
9743
9744 OSKextLogSpec msgKextGlobal = msgLogSpec & kOSKextLogKextOrGlobalMask;
9745 OSKextLogSpec msgLevel = msgLogSpec & kOSKextLogLevelMask;
9746 OSKextLogSpec msgFlags = msgLogSpec & kOSKextLogFlagsMask;
9747
9748 /* Explicit messages always get logged.
9749 */
9750 if (msgLevel == kOSKextLogExplicitLevel) {
9751 return true;
9752 }
9753
9754 /* Warnings and errors are logged regardless of the flags.
9755 */
9756 if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
9757 return true;
9758 }
9759
9760 /* A verbose message that isn't for a logging-enabled kext and isn't global
9761 * does *not* get logged.
9762 */
9763 if (!msgKextGlobal && !filterKextGlobal) {
9764 return false;
9765 }
9766
9767 /* Warnings and errors are logged regardless of the flags.
9768 * All other messages must fit the flags and
9769 * have a level at or below the filter.
9770 *
9771 */
9772 if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
9773 return true;
9774 }
9775 return false;
9776 }
9777
9778 extern "C" {
9779
9780 void
9781 OSKextLog(
9782 OSKext * aKext,
9783 OSKextLogSpec msgLogSpec,
9784 const char * format, ...)
9785 {
9786 va_list argList;
9787
9788 va_start(argList, format);
9789 OSKextVLog(aKext, msgLogSpec, format, argList);
9790 va_end(argList);
9791 }
9792
9793 void
9794 OSKextVLog(
9795 OSKext * aKext,
9796 OSKextLogSpec msgLogSpec,
9797 const char * format,
9798 va_list srcArgList)
9799 {
9800 extern int disableConsoleOutput;
9801
9802 bool logForKernel = false;
9803 bool logForUser = false;
9804 va_list argList;
9805 char stackBuffer[120];
9806 uint32_t length = 0;
9807 char * allocBuffer = NULL; // must kfree
9808 OSNumber * logSpecNum = NULL; // must release
9809 OSString * logString = NULL; // must release
9810 char * buffer = stackBuffer; // do not free
9811
9812 IOLockLock(sKextLoggingLock);
9813
9814 /* Set the kext/global bit in the message spec if we have no
9815 * kext or if the kext requests logging.
9816 */
9817 if (!aKext || aKext->flags.loggingEnabled) {
9818 msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
9819 }
9820
9821 logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
9822 if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
9823 logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
9824 }
9825
9826 if (! (logForKernel || logForUser) ) {
9827 goto finish;
9828 }
9829
9830 /* No goto from here until past va_end()!
9831 */
9832 va_copy(argList, srcArgList);
9833 length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
9834 va_end(argList);
9835
9836 if (length + 1 >= sizeof(stackBuffer)) {
9837 allocBuffer = (char *)kalloc((length + 1) * sizeof(char));
9838 if (!allocBuffer) {
9839 goto finish;
9840 }
9841
9842 /* No goto from here until past va_end()!
9843 */
9844 va_copy(argList, srcArgList);
9845 vsnprintf(allocBuffer, length + 1, format, argList);
9846 va_end(argList);
9847
9848 buffer = allocBuffer;
9849 }
9850
9851 /* If user space wants the log message, queue it up.
9852 */
9853 if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
9854 logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
9855 logString = OSString::withCString(buffer);
9856 if (logSpecNum && logString) {
9857 sUserSpaceLogSpecArray->setObject(logSpecNum);
9858 sUserSpaceLogMessageArray->setObject(logString);
9859 }
9860 }
9861
9862 /* Always log messages from the kernel according to the kernel's
9863 * log flags.
9864 */
9865 if (logForKernel) {
9866
9867 /* If we are in console mode and have a custom log filter,
9868 * colorize the log message.
9869 */
9870 if (!disableConsoleOutput && sBootArgLogFilterFound) {
9871 const char * color = ""; // do not free
9872 color = colorForFlags(msgLogSpec);
9873 printf("%s%s%s\n", colorForFlags(msgLogSpec),
9874 buffer, color[0] ? VTRESET : "");
9875 } else {
9876 printf("%s\n", buffer);
9877 }
9878 }
9879
9880 finish:
9881 IOLockUnlock(sKextLoggingLock);
9882
9883 if (allocBuffer) {
9884 kfree(allocBuffer, (length + 1) * sizeof(char));
9885 }
9886 OSSafeRelease(logString);
9887 OSSafeRelease(logSpecNum);
9888 return;
9889 }
9890
9891 #if KASLR_IOREG_DEBUG
9892
9893 #define IOLOG_INDENT( the_indention ) \
9894 { \
9895 int i; \
9896 for ( i = 0; i < (the_indention); i++ ) { \
9897 IOLog(" "); \
9898 } \
9899 }
9900
9901 extern vm_offset_t vm_kernel_stext;
9902 extern vm_offset_t vm_kernel_etext;
9903 extern mach_vm_offset_t kext_alloc_base;
9904 extern mach_vm_offset_t kext_alloc_max;
9905
9906 bool ScanForAddrInObject(OSObject * theObject,
9907 int indent );
9908
9909 bool ScanForAddrInObject(OSObject * theObject,
9910 int indent)
9911 {
9912 const OSMetaClass * myTypeID;
9913 OSCollectionIterator * myIter;
9914 OSSymbol * myKey;
9915 OSObject * myValue;
9916 bool myResult = false;
9917
9918 if ( theObject == NULL ) {
9919 IOLog("%s: theObject is NULL \n",
9920 __FUNCTION__);
9921 return myResult;
9922 }
9923
9924 myTypeID = OSTypeIDInst(theObject);
9925
9926 if ( myTypeID == OSTypeID(OSDictionary) ) {
9927 OSDictionary * myDictionary;
9928
9929 myDictionary = OSDynamicCast(OSDictionary, theObject);
9930 myIter = OSCollectionIterator::withCollection( myDictionary );
9931 if ( myIter == NULL )
9932 return myResult;
9933 myIter->reset();
9934
9935 while ( (myKey = OSDynamicCast(OSSymbol, myIter->getNextObject())) ) {
9936 bool myTempResult;
9937
9938 myValue = myDictionary->getObject(myKey);
9939 myTempResult = ScanForAddrInObject(myValue, (indent + 4));
9940 if (myTempResult) {
9941 // if we ever get a true result return true
9942 myResult = true;
9943 IOLOG_INDENT(indent);
9944 IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
9945 }
9946 }
9947 myIter->release();
9948 }
9949 else if ( myTypeID == OSTypeID(OSArray) ) {
9950 OSArray * myArray;
9951
9952 myArray = OSDynamicCast(OSArray, theObject);
9953 myIter = OSCollectionIterator::withCollection(myArray);
9954 if ( myIter == NULL )
9955 return myResult;
9956 myIter->reset();
9957
9958 while ( (myValue = myIter->getNextObject()) ) {
9959 bool myTempResult;
9960 myTempResult = ScanForAddrInObject(myValue, (indent + 4));
9961 if (myTempResult) {
9962 // if we ever get a true result return true
9963 myResult = true;
9964 IOLOG_INDENT(indent);
9965 IOLog("OSArray: \n");
9966 }
9967 }
9968 myIter->release();
9969 }
9970 else if ( myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol) ) {
9971
9972 // should we look for addresses in strings?
9973 }
9974 else if ( myTypeID == OSTypeID(OSData) ) {
9975
9976 void * * myPtrPtr;
9977 unsigned int myLen;
9978 OSData * myDataObj;
9979
9980 myDataObj = OSDynamicCast(OSData, theObject);
9981 myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
9982 myLen = myDataObj->getLength();
9983
9984 if (myPtrPtr && myLen && myLen > 7) {
9985 int i;
9986 int myPtrCount = (myLen / sizeof(void *));
9987
9988 for (i = 0; i < myPtrCount; i++) {
9989 UInt64 numberValue = (UInt64) *(myPtrPtr);
9990
9991 if ( kext_alloc_max != 0 &&
9992 numberValue >= kext_alloc_base &&
9993 numberValue < kext_alloc_max ) {
9994
9995 OSKext * myKext = NULL; // must release (looked up)
9996 // IOLog("found OSData %p in kext map %p to %p \n",
9997 // *(myPtrPtr),
9998 // (void *) kext_alloc_base,
9999 // (void *) kext_alloc_max);
10000
10001 myKext = OSKext::lookupKextWithAddress( (vm_address_t) *(myPtrPtr) );
10002 if (myKext) {
10003 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
10004 *(myPtrPtr),
10005 myKext->getIdentifierCString());
10006 myKext->release();
10007 }
10008 myResult = true;
10009 }
10010 if ( vm_kernel_etext != 0 &&
10011 numberValue >= vm_kernel_stext &&
10012 numberValue < vm_kernel_etext ) {
10013 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
10014 *(myPtrPtr),
10015 (void *) vm_kernel_stext,
10016 (void *) vm_kernel_etext);
10017 myResult = true;
10018 }
10019 myPtrPtr++;
10020 }
10021 }
10022 }
10023 else if ( myTypeID == OSTypeID(OSBoolean) ) {
10024
10025 // do nothing here...
10026 }
10027 else if ( myTypeID == OSTypeID(OSNumber) ) {
10028
10029 OSNumber * number = OSDynamicCast(OSNumber, theObject);
10030
10031 UInt64 numberValue = number->unsigned64BitValue();
10032
10033 if ( kext_alloc_max != 0 &&
10034 numberValue >= kext_alloc_base &&
10035 numberValue < kext_alloc_max ) {
10036
10037 OSKext * myKext = NULL; // must release (looked up)
10038 IOLog("found OSNumber in kext map %p to %p \n",
10039 (void *) kext_alloc_base,
10040 (void *) kext_alloc_max);
10041 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
10042
10043 myKext = OSKext::lookupKextWithAddress( (vm_address_t) numberValue );
10044 if (myKext) {
10045 IOLog("found in kext \"%s\" \n",
10046 myKext->getIdentifierCString());
10047 myKext->release();
10048 }
10049
10050 myResult = true;
10051 }
10052 if ( vm_kernel_etext != 0 &&
10053 numberValue >= vm_kernel_stext &&
10054 numberValue < vm_kernel_etext ) {
10055 IOLog("found OSNumber in kernel text segment %p to %p \n",
10056 (void *) vm_kernel_stext,
10057 (void *) vm_kernel_etext);
10058 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
10059 myResult = true;
10060 }
10061 }
10062 #if 0
10063 else {
10064 const OSMetaClass* myMetaClass = NULL;
10065
10066 myMetaClass = theObject->getMetaClass();
10067 if ( myMetaClass ) {
10068 IOLog("class %s \n", myMetaClass->getClassName() );
10069 }
10070 else {
10071 IOLog("Unknown object \n" );
10072 }
10073 }
10074 #endif
10075
10076 return myResult;
10077 }
10078 #endif // KASLR_KEXT_DEBUG
10079
10080 }; /* extern "C" */
10081
10082 #if PRAGMA_MARK
10083 #pragma mark Backtrace Dump & kmod_get_info() support
10084 #endif
10085 /*********************************************************************
10086 * This function must be safe to call in panic context.
10087 *********************************************************************/
10088 /* static */
10089 void
10090 OSKext::printKextsInBacktrace(
10091 vm_offset_t * addr,
10092 unsigned int cnt,
10093 int (* printf_func)(const char *fmt, ...),
10094 bool lockFlag)
10095 {
10096 addr64_t summary_page = 0;
10097 addr64_t last_summary_page = 0;
10098 bool found_kmod = false;
10099 u_int i = 0;
10100
10101 if (lockFlag) {
10102 IOLockLock(sKextSummariesLock);
10103 }
10104
10105 if (!gLoadedKextSummaries) {
10106 (*printf_func)(" can't perform kext scan: no kext summary");
10107 goto finish;
10108 }
10109
10110 summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
10111 last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
10112 for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
10113 if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
10114 (*printf_func)(" can't perform kext scan: "
10115 "missing kext summary page %p", summary_page);
10116 goto finish;
10117 }
10118 }
10119
10120 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
10121 OSKextLoadedKextSummary * summary;
10122
10123 summary = gLoadedKextSummaries->summaries + i;
10124 if (!summary->address) {
10125 continue;
10126 }
10127
10128 if (!summaryIsInBacktrace(summary, addr, cnt)) {
10129 continue;
10130 }
10131
10132 if (!found_kmod) {
10133 (*printf_func)(" Kernel Extensions in backtrace:\n");
10134 found_kmod = true;
10135 }
10136
10137 printSummary(summary, printf_func);
10138 }
10139
10140 finish:
10141 if (lockFlag) {
10142 IOLockUnlock(sKextSummariesLock);
10143 }
10144
10145 return;
10146 }
10147
10148 /*********************************************************************
10149 * This function must be safe to call in panic context.
10150 *********************************************************************/
10151 /* static */
10152 boolean_t
10153 OSKext::summaryIsInBacktrace(
10154 OSKextLoadedKextSummary * summary,
10155 vm_offset_t * addr,
10156 unsigned int cnt)
10157 {
10158 u_int i = 0;
10159
10160 for (i = 0; i < cnt; i++) {
10161 vm_offset_t kscan_addr = addr[i];
10162 if ((kscan_addr >= summary->address) &&
10163 (kscan_addr < (summary->address + summary->size)))
10164 {
10165 return TRUE;
10166 }
10167 }
10168
10169 return FALSE;
10170 }
10171
10172 /*********************************************************************
10173 * scan list of loaded kext summaries looking for a load address match and if
10174 * found return the UUID C string. If not found then set empty string.
10175 *********************************************************************/
10176 static void findSummaryUUID(
10177 uint32_t tag_ID,
10178 uuid_string_t uuid);
10179
10180 static void findSummaryUUID(
10181 uint32_t tag_ID,
10182 uuid_string_t uuid)
10183 {
10184 u_int i;
10185
10186 uuid[0] = 0x00; // default to no UUID
10187
10188 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
10189 OSKextLoadedKextSummary * summary;
10190
10191 summary = gLoadedKextSummaries->summaries + i;
10192
10193 if (summary->loadTag == tag_ID) {
10194 (void) uuid_unparse(summary->uuid, uuid);
10195 break;
10196 }
10197 }
10198 return;
10199 }
10200
10201 /*********************************************************************
10202 * This function must be safe to call in panic context.
10203 *********************************************************************/
10204 void OSKext::printSummary(
10205 OSKextLoadedKextSummary * summary,
10206 int (* printf_func)(const char *fmt, ...))
10207 {
10208 kmod_reference_t * kmod_ref = NULL;
10209 uuid_string_t uuid;
10210 char version[kOSKextVersionMaxLength];
10211
10212 if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
10213 strlcpy(version, "unknown version", sizeof(version));
10214 }
10215 (void) uuid_unparse(summary->uuid, uuid);
10216
10217 (*printf_func)(" %s(%s)[%s]@0x%llx->0x%llx\n",
10218 summary->name, version, uuid,
10219 summary->address, summary->address + summary->size - 1);
10220
10221 /* print dependency info */
10222 for (kmod_ref = (kmod_reference_t *) summary->reference_list;
10223 kmod_ref;
10224 kmod_ref = kmod_ref->next) {
10225 kmod_info_t * rinfo;
10226
10227 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
10228 (*printf_func)(" kmod dependency scan stopped "
10229 "due to missing dependency page: %p\n", kmod_ref);
10230 break;
10231 }
10232 rinfo = kmod_ref->info;
10233
10234 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
10235 (*printf_func)(" kmod dependency scan stopped "
10236 "due to missing kmod page: %p\n", rinfo);
10237 break;
10238 }
10239
10240 if (!rinfo->address) {
10241 continue; // skip fake entries for built-ins
10242 }
10243
10244 /* locate UUID in gLoadedKextSummaries */
10245 findSummaryUUID(rinfo->id, uuid);
10246
10247 (*printf_func)(" dependency: %s(%s)[%s]@%p\n",
10248 rinfo->name, rinfo->version, uuid, rinfo->address);
10249 }
10250 return;
10251 }
10252
10253
10254 /*******************************************************************************
10255 * substitute() looks at an input string (a pointer within a larger buffer)
10256 * for a match to a substring, and on match it writes the marker & substitution
10257 * character to an output string, updating the scan (from) and
10258 * output (to) indexes as appropriate.
10259 *******************************************************************************/
10260 static int substitute(
10261 const char * scan_string,
10262 char * string_out,
10263 uint32_t * to_index,
10264 uint32_t * from_index,
10265 const char * substring,
10266 char marker,
10267 char substitution);
10268
10269 /* string_out must be at least KMOD_MAX_NAME bytes.
10270 */
10271 static int
10272 substitute(
10273 const char * scan_string,
10274 char * string_out,
10275 uint32_t * to_index,
10276 uint32_t * from_index,
10277 const char * substring,
10278 char marker,
10279 char substitution)
10280 {
10281 uint32_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
10282
10283 /* On a substring match, append the marker (if there is one) and then
10284 * the substitution character, updating the output (to) index accordingly.
10285 * Then update the input (from) length by the length of the substring
10286 * that got replaced.
10287 */
10288 if (!strncmp(scan_string, substring, substring_length)) {
10289 if (marker) {
10290 string_out[(*to_index)++] = marker;
10291 }
10292 string_out[(*to_index)++] = substitution;
10293 (*from_index) += substring_length;
10294 return 1;
10295 }
10296 return 0;
10297 }
10298
10299 /*******************************************************************************
10300 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
10301 * KMOD_MAX_NAME characters and performs various substitutions of common
10302 * prefixes & substrings as defined by tables in kext_panic_report.h.
10303 *******************************************************************************/
10304 static void compactIdentifier(
10305 const char * identifier,
10306 char * identifier_out,
10307 char ** identifier_out_end);
10308
10309 static void
10310 compactIdentifier(
10311 const char * identifier,
10312 char * identifier_out,
10313 char ** identifier_out_end)
10314 {
10315 uint32_t from_index, to_index;
10316 uint32_t scan_from_index = 0;
10317 uint32_t scan_to_index = 0;
10318 subs_entry_t * subs_entry = NULL;
10319 int did_sub = 0;
10320
10321 from_index = to_index = 0;
10322 identifier_out[0] = '\0';
10323
10324 /* Replace certain identifier prefixes with shorter @+character sequences.
10325 * Check the return value of substitute() so we only replace the prefix.
10326 */
10327 for (subs_entry = &kext_identifier_prefix_subs[0];
10328 subs_entry->substring && !did_sub;
10329 subs_entry++) {
10330
10331 did_sub = substitute(identifier, identifier_out,
10332 &scan_to_index, &scan_from_index,
10333 subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
10334 }
10335 did_sub = 0;
10336
10337 /* Now scan through the identifier looking for the common substrings
10338 * and replacing them with shorter !+character sequences via substitute().
10339 */
10340 for (/* see above */;
10341 scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
10342 /* see loop */) {
10343
10344 const char * scan_string = &identifier[scan_from_index];
10345
10346 did_sub = 0;
10347
10348 if (scan_from_index) {
10349 for (subs_entry = &kext_identifier_substring_subs[0];
10350 subs_entry->substring && !did_sub;
10351 subs_entry++) {
10352
10353 did_sub = substitute(scan_string, identifier_out,
10354 &scan_to_index, &scan_from_index,
10355 subs_entry->substring, '!', subs_entry->substitute);
10356 }
10357 }
10358
10359 /* If we didn't substitute, copy the input character to the output.
10360 */
10361 if (!did_sub) {
10362 identifier_out[scan_to_index++] = identifier[scan_from_index++];
10363 }
10364 }
10365
10366 identifier_out[scan_to_index] = '\0';
10367 if (identifier_out_end) {
10368 *identifier_out_end = &identifier_out[scan_to_index];
10369 }
10370
10371 return;
10372 }
10373
10374 /*******************************************************************************
10375 * assemble_identifier_and_version() adds to a string buffer a compacted
10376 * bundle identifier followed by a version string.
10377 *******************************************************************************/
10378
10379 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
10380 */
10381 static int assemble_identifier_and_version(
10382 kmod_info_t * kmod_info,
10383 char * identPlusVers);
10384 static int
10385 assemble_identifier_and_version(
10386 kmod_info_t * kmod_info,
10387 char * identPlusVers)
10388 {
10389 int result = 0;
10390
10391 compactIdentifier(kmod_info->name, identPlusVers, NULL);
10392 result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
10393 identPlusVers[result++] = '\t'; // increment for real char
10394 identPlusVers[result] = '\0'; // don't increment for nul char
10395 result = strlcat(identPlusVers, kmod_info->version, KMOD_MAX_NAME);
10396
10397 return result;
10398 }
10399
10400 /*******************************************************************************
10401 * Assumes sKextLock is held.
10402 *******************************************************************************/
10403 /* static */
10404 uint32_t
10405 OSKext::saveLoadedKextPanicListTyped(
10406 const char * prefix,
10407 int invertFlag,
10408 int libsFlag,
10409 char * paniclist,
10410 uint32_t list_size,
10411 uint32_t * list_length_ptr)
10412 {
10413 uint32_t result = 0;
10414 int error = 0;
10415 unsigned int count, i;
10416
10417 count = sLoadedKexts->getCount();
10418 if (!count) {
10419 goto finish;
10420 }
10421
10422 i = count - 1;
10423 do {
10424 OSObject * rawKext = sLoadedKexts->getObject(i);
10425 OSKext * theKext = OSDynamicCast(OSKext, rawKext);
10426 int match;
10427 char identPlusVers[2*KMOD_MAX_NAME];
10428 uint32_t identPlusVersLength;
10429
10430 if (!rawKext) {
10431 printf("OSKext::saveLoadedKextPanicListTyped - "
10432 "NULL kext in loaded kext list; continuing\n");
10433 continue;
10434 }
10435
10436 if (!theKext) {
10437 printf("OSKext::saveLoadedKextPanicListTyped - "
10438 "Kext type cast failed in loaded kext list; continuing\n");
10439 continue;
10440 }
10441
10442 /* Skip all built-in kexts.
10443 */
10444 if (theKext->isKernelComponent()) {
10445 continue;
10446 }
10447
10448 kmod_info_t * kmod_info = theKext->kmod_info;
10449
10450 /* Filter for kmod name (bundle identifier).
10451 */
10452 match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
10453 if ((match && invertFlag) || (!match && !invertFlag)) {
10454 continue;
10455 }
10456
10457 /* Filter for libraries (kexts that have a compatible version).
10458 */
10459 if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
10460 (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
10461
10462 continue;
10463 }
10464
10465 if (!kmod_info ||
10466 !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
10467
10468 printf("kext scan stopped due to missing kmod_info page: %p\n",
10469 kmod_info);
10470 error = 1;
10471 goto finish;
10472 }
10473
10474 identPlusVersLength = assemble_identifier_and_version(kmod_info,
10475 identPlusVers);
10476 if (!identPlusVersLength) {
10477 printf("error saving loaded kext info\n");
10478 goto finish;
10479 }
10480
10481 /* Adding 1 for the newline.
10482 */
10483 if (*list_length_ptr + identPlusVersLength + 1 >= list_size) {
10484 goto finish;
10485 }
10486
10487 *list_length_ptr = strlcat(paniclist, identPlusVers, list_size);
10488 *list_length_ptr = strlcat(paniclist, "\n", list_size);
10489
10490 } while (i--);
10491
10492 finish:
10493 if (!error) {
10494 if (*list_length_ptr + 1 <= list_size) {
10495 result = list_size - (*list_length_ptr + 1);
10496 }
10497 }
10498
10499 return result;
10500 }
10501
10502 /*********************************************************************
10503 *********************************************************************/
10504 /* static */
10505 void
10506 OSKext::saveLoadedKextPanicList(void)
10507 {
10508 char * newlist = NULL;
10509 uint32_t newlist_size = 0;
10510 uint32_t newlist_length = 0;
10511
10512 newlist_length = 0;
10513 newlist_size = KEXT_PANICLIST_SIZE;
10514 newlist = (char *)kalloc(newlist_size);
10515
10516 if (!newlist) {
10517 OSKextLog(/* kext */ NULL,
10518 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
10519 "Couldn't allocate kext panic log buffer.");
10520 goto finish;
10521 }
10522
10523 newlist[0] = '\0';
10524
10525 // non-"com.apple." kexts
10526 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
10527 /* libs? */ -1, newlist, newlist_size, &newlist_length)) {
10528
10529 goto finish;
10530 }
10531 // "com.apple." nonlibrary kexts
10532 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10533 /* libs? */ 0, newlist, newlist_size, &newlist_length)) {
10534
10535 goto finish;
10536 }
10537 // "com.apple." library kexts
10538 if (!OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
10539 /* libs? */ 1, newlist, newlist_size, &newlist_length)) {
10540
10541 goto finish;
10542 }
10543
10544 if (loaded_kext_paniclist) {
10545 kfree(loaded_kext_paniclist, loaded_kext_paniclist_size);
10546 }
10547 loaded_kext_paniclist = newlist;
10548 loaded_kext_paniclist_size = newlist_size;
10549 loaded_kext_paniclist_length = newlist_length;
10550
10551 finish:
10552 return;
10553 }
10554
10555 /*********************************************************************
10556 * Assumes sKextLock is held.
10557 *********************************************************************/
10558 void
10559 OSKext::savePanicString(bool isLoading)
10560 {
10561 u_long len;
10562
10563 if (!kmod_info) {
10564 return; // do not goto finish here b/c of lock
10565 }
10566
10567 len = assemble_identifier_and_version(kmod_info,
10568 (isLoading) ? last_loaded_str : last_unloaded_str);
10569 if (!len) {
10570 printf("error saving unloaded kext info\n");
10571 goto finish;
10572 }
10573
10574 if (isLoading) {
10575 last_loaded_strlen = len;
10576 last_loaded_address = (void *)kmod_info->address;
10577 last_loaded_size = kmod_info->size;
10578 clock_get_uptime(&last_loaded_timestamp);
10579 } else {
10580 last_unloaded_strlen = len;
10581 last_unloaded_address = (void *)kmod_info->address;
10582 last_unloaded_size = kmod_info->size;
10583 clock_get_uptime(&last_unloaded_timestamp);
10584 }
10585
10586 finish:
10587 return;
10588 }
10589
10590 /*********************************************************************
10591 *********************************************************************/
10592 /* static */
10593 void
10594 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
10595 {
10596 if (last_loaded_strlen) {
10597 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
10598 AbsoluteTime_to_scalar(&last_loaded_timestamp),
10599 last_loaded_strlen, last_loaded_str,
10600 last_loaded_address, last_loaded_size);
10601 }
10602
10603 if (last_unloaded_strlen) {
10604 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
10605 AbsoluteTime_to_scalar(&last_unloaded_timestamp),
10606 last_unloaded_strlen, last_unloaded_str,
10607 last_unloaded_address, last_unloaded_size);
10608 }
10609
10610 printf_func("loaded kexts:\n");
10611 if (loaded_kext_paniclist &&
10612 pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
10613 loaded_kext_paniclist[0]) {
10614
10615 printf_func("%.*s", loaded_kext_paniclist_length, loaded_kext_paniclist);
10616 } else {
10617 printf_func("(none)\n");
10618 }
10619 return;
10620 }
10621
10622 /*********************************************************************
10623 * Assumes sKextLock is held.
10624 *********************************************************************/
10625 /* static */
10626 void
10627 OSKext::updateLoadedKextSummaries(void)
10628 {
10629 kern_return_t result = KERN_FAILURE;
10630 OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
10631 OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
10632 OSKext *aKext;
10633 vm_map_offset_t start, end;
10634 size_t summarySize = 0;
10635 size_t size;
10636 u_int count;
10637 u_int numKexts;
10638 u_int i, j;
10639
10640 IOLockLock(sKextSummariesLock);
10641
10642 count = sLoadedKexts->getCount();
10643 for (i = 0, numKexts = 0; i < count; ++i) {
10644 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
10645 numKexts += (aKext && aKext->isExecutable());
10646 }
10647
10648 if (!numKexts) goto finish;
10649
10650 /* Calculate the size needed for the new summary headers.
10651 */
10652
10653 size = sizeof(*gLoadedKextSummaries);
10654 size += numKexts * sizeof(*gLoadedKextSummaries->summaries);
10655 size = round_page(size);
10656
10657 /* If the previous summary is large enough, use it (and be sure to make
10658 * it writable). If it's too small, free it and allocate a new buffer.
10659 */
10660
10661 if (sPrevLoadedKextSummariesAllocSize < size) {
10662 if (sPrevLoadedKextSummaries) {
10663 kmem_free(kernel_map, (vm_offset_t)sPrevLoadedKextSummaries,
10664 sPrevLoadedKextSummariesAllocSize);
10665 sPrevLoadedKextSummaries = NULL;
10666 sPrevLoadedKextSummariesAllocSize = 0;
10667 }
10668
10669 result = kmem_alloc(kernel_map,
10670 (vm_offset_t*)&summaryHeaderAlloc, size);
10671 if (result != KERN_SUCCESS) goto finish;
10672
10673 summaryHeader = summaryHeaderAlloc;
10674 summarySize = size;
10675 } else {
10676 summaryHeader = sPrevLoadedKextSummaries;
10677 summarySize = sPrevLoadedKextSummariesAllocSize;
10678
10679 start = (vm_map_offset_t) summaryHeader;
10680 end = start + summarySize;
10681 result = vm_map_protect(kernel_map, start, end, VM_PROT_DEFAULT, FALSE);
10682 if (result != KERN_SUCCESS) goto finish;
10683 }
10684
10685 /* Populate the summary header.
10686 */
10687
10688 bzero(summaryHeader, summarySize);
10689 summaryHeader->version = kOSKextLoadedKextSummaryVersion;
10690 summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
10691 summaryHeader->numSummaries = numKexts;
10692
10693 /* Populate each kext summary.
10694 */
10695
10696 count = sLoadedKexts->getCount();
10697 for (i = 0, j = 0; i < count; ++i) {
10698 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
10699 if (!aKext || !aKext->isExecutable()) continue;
10700
10701 aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
10702 }
10703
10704 /* Write protect the buffer and move it into place.
10705 */
10706
10707 start = (vm_map_offset_t) summaryHeader;
10708 end = start + summarySize;
10709 result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
10710 if (result != KERN_SUCCESS) goto finish;
10711
10712 sPrevLoadedKextSummaries = gLoadedKextSummaries;
10713 sPrevLoadedKextSummariesAllocSize = sLoadedKextSummariesAllocSize;
10714
10715 gLoadedKextSummaries = summaryHeader;
10716 sLoadedKextSummariesAllocSize = summarySize;
10717
10718 summaryHeaderAlloc = NULL;
10719
10720 /* Call the magic breakpoint function through a static function pointer so
10721 * the compiler can't optimize the function away.
10722 */
10723 if (sLoadedKextSummariesUpdated) (*sLoadedKextSummariesUpdated)();
10724
10725 finish:
10726 IOLockUnlock(sKextSummariesLock);
10727
10728 /* If we had to allocate a new buffer but failed to generate the summaries,
10729 * free that now.
10730 */
10731 if (summaryHeaderAlloc) {
10732 kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
10733 }
10734
10735 return;
10736 }
10737
10738 /*********************************************************************
10739 *********************************************************************/
10740 void
10741 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
10742 {
10743 OSData *uuid;
10744
10745 strlcpy(summary->name, getIdentifierCString(),
10746 sizeof(summary->name));
10747
10748 uuid = copyUUID();
10749 if (uuid) {
10750 memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
10751 OSSafeRelease(uuid);
10752 }
10753
10754 summary->address = kmod_info->address;
10755 summary->size = kmod_info->size;
10756 summary->version = getVersion();
10757 summary->loadTag = kmod_info->id;
10758 summary->flags = 0;
10759 summary->reference_list = (uint64_t) kmod_info->reference_list;
10760
10761 return;
10762 }
10763
10764 /*********************************************************************
10765 *********************************************************************/
10766
10767 #if CONFIG_KEC_FIPS
10768
10769 #if PRAGMA_MARK
10770 #pragma mark Kernel External Components for FIPS compliance
10771 #endif
10772
10773 /*********************************************************************
10774 * Kernel External Components for FIPS compliance (KEC_FIPS)
10775 *********************************************************************/
10776 static void *
10777 GetAppleTEXTHashForKext(OSKext * theKext, OSDictionary *theInfoDict)
10778 {
10779 AppleTEXTHash_t my_ath = {1, 0, NULL};
10780 AppleTEXTHash_t * my_athp = NULL; // do not release
10781 OSDictionary * textHashDict = NULL; // do not release
10782 OSData * segmentHash = NULL; // do not release
10783
10784 if (theKext == NULL || theInfoDict == NULL) {
10785 return(NULL);
10786 }
10787
10788 textHashDict = OSDynamicCast(OSDictionary, theInfoDict->getObject(kAppleTextHashesKey));
10789 if (textHashDict == NULL) {
10790 return(NULL);
10791 }
10792
10793 segmentHash = OSDynamicCast(OSData,
10794 textHashDict->getObject(ARCHNAME));
10795 if (segmentHash == NULL) {
10796 return(NULL);
10797 }
10798
10799 // KEC_FIPS type kexts never unload so we don't have to clean up our
10800 // AppleTEXTHash_t
10801 if (kmem_alloc(kernel_map, (vm_offset_t *) &my_athp,
10802 sizeof(AppleTEXTHash_t)) != KERN_SUCCESS) {
10803 return(NULL);
10804 }
10805
10806 memcpy(my_athp, &my_ath, sizeof(my_ath));
10807 my_athp->ath_length = segmentHash->getLength();
10808 if (my_athp->ath_length > 0) {
10809 my_athp->ath_hash = (void *)segmentHash->getBytesNoCopy();
10810 }
10811
10812 #if 0
10813 OSKextLog(theKext,
10814 kOSKextLogErrorLevel |
10815 kOSKextLogGeneralFlag,
10816 "Kext %s ath_version %d ath_length %d ath_hash %p",
10817 theKext->getIdentifierCString(),
10818 my_athp->ath_version,
10819 my_athp->ath_length,
10820 my_athp->ath_hash);
10821 #endif
10822
10823 return( (void *) my_athp );
10824 }
10825
10826 #endif // CONFIG_KEC_FIPS
10827