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