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