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