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