]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSKext.cpp
xnu-6153.141.1.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 #include <sys/random.h>
52
53 #include <sys/pgo.h>
54
55 #if CONFIG_MACF
56 #include <sys/kauth.h>
57 #include <security/mac_framework.h>
58 #endif
59 };
60
61 #include <libkern/OSKextLibPrivate.h>
62 #include <libkern/c++/OSKext.h>
63 #include <libkern/c++/OSLib.h>
64
65 #include <IOKit/IOLib.h>
66 #include <IOKit/IOCatalogue.h>
67 #include <IOKit/IORegistryEntry.h>
68 #include <IOKit/IOService.h>
69
70 #include <IOKit/IOStatisticsPrivate.h>
71 #include <IOKit/IOBSD.h>
72
73 #include <san/kasan.h>
74
75 #if PRAGMA_MARK
76 #pragma mark External & Internal Function Protos
77 #endif
78 /*********************************************************************
79 *********************************************************************/
80 extern "C" {
81 extern int IODTGetLoaderInfo(const char * key, void ** infoAddr, int * infoSize);
82 extern void IODTFreeLoaderInfo(const char * key, void * infoAddr, int infoSize);
83
84 extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); /* osfmk/machine/pmap.h */
85 extern int dtrace_keep_kernel_symbols(void);
86 }
87
88 extern unsigned long gVirtBase;
89 extern unsigned long gPhysBase;
90 #if CONFIG_EMBEDDED
91 extern vm_offset_t segLOWESTTEXT;
92 #endif /* CONFIG_EMBEDDED */
93
94 static OSReturn _OSKextCreateRequest(
95 const char * predicate,
96 OSDictionary ** requestP);
97 static OSString * _OSKextGetRequestPredicate(OSDictionary * requestDict);
98 static OSObject * _OSKextGetRequestArgument(
99 OSDictionary * requestDict,
100 const char * argName);
101 static bool _OSKextSetRequestArgument(
102 OSDictionary * requestDict,
103 const char * argName,
104 OSObject * value);
105 static void * _OSKextExtractPointer(OSData * wrapper);
106 static OSReturn _OSDictionarySetCStringValue(
107 OSDictionary * dict,
108 const char * key,
109 const char * value);
110 static bool _OSKextInPrelinkRebuildWindow(void);
111 static bool _OSKextInUnloadedPrelinkedKexts(const OSSymbol * theBundleID);
112
113 // We really should add containsObject() & containsCString to OSCollection & subclasses.
114 // So few pad slots, though....
115 static bool _OSArrayContainsCString(OSArray * array, const char * cString);
116 static void OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code);
117
118 /* Prelinked arm kexts do not have VM entries because the method we use to
119 * fake an entry (see libsa/bootstrap.cpp:readPrelinkedExtensions()) does
120 * not work on ARM. To get around that, we must free prelinked kext
121 * executables with ml_static_mfree() instead of kext_free().
122 */
123 #if __i386__ || __x86_64__
124 #define VM_MAPPED_KEXTS 1
125 #define KASLR_KEXT_DEBUG 0
126 #define KASLR_IOREG_DEBUG 0
127 #elif __arm__ || __arm64__
128 #define VM_MAPPED_KEXTS 0
129 #define KASLR_KEXT_DEBUG 0
130 #else
131 #error Unsupported architecture
132 #endif
133
134 #if PRAGMA_MARK
135 #pragma mark Constants & Macros
136 #endif
137 /*********************************************************************
138 * Constants & Macros
139 *********************************************************************/
140
141 /* Use this number to create containers.
142 */
143 #define kOSKextTypicalLoadCount (150)
144
145 /* Any kext will have at least 1 retain for the internal lookup-by-ID dict.
146 * A loaded kext will no dependents or external retains will have 2 retains.
147 */
148 #define kOSKextMinRetainCount (1)
149 #define kOSKextMinLoadedRetainCount (2)
150
151 /**********
152 * Strings and substrings used in dependency resolution.
153 */
154 #define APPLE_KEXT_PREFIX "com.apple."
155 #define KERNEL_LIB "com.apple.kernel"
156
157 #define PRIVATE_KPI "com.apple.kpi.private"
158
159 /* Version for compatbility pseudokexts (com.apple.kernel.*),
160 * compatible back to v6.0.
161 */
162 #define KERNEL6_LIB "com.apple.kernel.6.0"
163 #define KERNEL6_VERSION "7.9.9"
164
165 #define KERNEL_LIB_PREFIX "com.apple.kernel."
166 #define KPI_LIB_PREFIX "com.apple.kpi."
167
168 #define STRING_HAS_PREFIX(s, p) (strncmp((s), (p), strlen(p)) == 0)
169
170 #define REBUILD_MAX_TIME (60 * 5) // 5 minutes
171 #define MINIMUM_WAKEUP_SECONDS (30)
172
173 /*********************************************************************
174 * infoDict keys for internally-stored data. Saves on ivar slots for
175 * objects we don't keep around past boot time or during active load.
176 *********************************************************************/
177
178 /* A usable, uncompressed file is stored under this key.
179 */
180 #define _kOSKextExecutableKey "_OSKextExecutable"
181
182 /* An indirect reference to the executable file from an mkext
183 * is stored under this key.
184 */
185 #define _kOSKextMkextExecutableReferenceKey "_OSKextMkextExecutableReference"
186
187 /* If the file is contained in a larger buffer laid down by the booter or
188 * sent from user space, the OSKext stores that OSData under this key so that
189 * references are properly tracked. This is always an mkext, right now.
190 */
191 #define _kOSKextExecutableExternalDataKey "_OSKextExecutableExternalData"
192
193 #define OS_LOG_HDR_VERSION 1
194 #define NUM_OS_LOG_SECTIONS 2
195
196 #define OS_LOG_SECT_IDX 0
197 #define CSTRING_SECT_IDX 1
198
199 #if PRAGMA_MARK
200 #pragma mark Typedefs
201 #endif
202 /*********************************************************************
203 * Typedefs
204 *********************************************************************/
205
206 /*********************************************************************
207 * osLogDataHeaderRef describes the header information of an OSData
208 * object that is returned when querying for kOSBundleLogStringsKey.
209 * We currently return information regarding 2 sections - os_log and
210 * cstring. In the case that the os_log section doesn't exist, we just
211 * return an offset and length of 0 for that section.
212 *********************************************************************/
213 typedef struct osLogDataHeader {
214 uint32_t version;
215 uint32_t sect_count;
216 struct {
217 uint32_t sect_offset;
218 uint32_t sect_size;
219 } sections[0];
220 } osLogDataHeaderRef;
221
222 /*********************************************************************
223 * MkextEntryRef describes the contents of an OSData object
224 * referencing a file entry from an mkext so that we can uncompress
225 * (if necessary) and extract it on demand.
226 *
227 * It contains the mkextVersion in case we ever wind up supporting
228 * multiple mkext formats. Mkext format 1 is officially retired as of
229 * Snow Leopard.
230 *********************************************************************/
231 typedef struct MkextEntryRef {
232 mkext_basic_header * mkext; // beginning of whole mkext file
233 void * fileinfo;// mkext2_file_entry or equiv; see mkext.h
234 } MkextEntryRef;
235
236 #if PRAGMA_MARK
237 #pragma mark Global and static Module Variables
238 #endif
239 /*********************************************************************
240 * Global & static variables, used to keep track of kexts.
241 *********************************************************************/
242
243 static bool sPrelinkBoot = false;
244 static bool sSafeBoot = false;
245 static bool sKeepSymbols = false;
246
247 /*********************************************************************
248 * sKextLock is the principal lock for OSKext, and guards all static
249 * and global variables not owned by other locks (declared further
250 * below). It must be taken by any entry-point method or function,
251 * including internal functions called on scheduled threads.
252 *
253 * sKextLock and sKextInnerLock are recursive due to multiple functions
254 * that are called both externally and internally. The other locks are
255 * nonrecursive.
256 *
257 * Which locks are taken depends on what they protect, but if more than
258 * one must be taken, they must always be locked in this order
259 * (and unlocked in reverse order) to prevent deadlocks:
260 *
261 * 1. sKextLock
262 * 2. sKextInnerLock
263 * 3. sKextSummariesLock
264 * 4. sKextLoggingLock
265 */
266 static IORecursiveLock * sKextLock = NULL;
267
268 static OSDictionary * sKextsByID = NULL;
269 static OSDictionary * sExcludeListByID = NULL;
270 static OSKextVersion sExcludeListVersion = 0;
271 static OSArray * sLoadedKexts = NULL;
272 static OSArray * sUnloadedPrelinkedKexts = NULL;
273 static OSArray * sLoadedDriverKitKexts = NULL;
274
275 // Requests to kextd waiting to be picked up.
276 static OSArray * sKernelRequests = NULL;
277 // Identifier of kext load requests in sKernelRequests
278 static OSSet * sPostedKextLoadIdentifiers = NULL;
279 static OSArray * sRequestCallbackRecords = NULL;
280
281 // Identifiers of all kexts ever requested in kernel; used for prelinked kernel
282 static OSSet * sAllKextLoadIdentifiers = NULL;
283 static KXLDContext * sKxldContext = NULL;
284 static uint32_t sNextLoadTag = 0;
285 static uint32_t sNextRequestTag = 0;
286
287 static bool sUserLoadsActive = false;
288 static bool sKextdActive = false;
289 static bool sDeferredLoadSucceeded = false;
290 static bool sConsiderUnloadsExecuted = false;
291
292 #if NO_KEXTD
293 static bool sKernelRequestsEnabled = false;
294 #else
295 static bool sKernelRequestsEnabled = true;
296 #endif
297 static bool sLoadEnabled = true;
298 static bool sUnloadEnabled = true;
299
300 /*********************************************************************
301 * Stuff for the OSKext representing the kernel itself.
302 **********/
303 static OSKext * sKernelKext = NULL;
304
305 /* Set up a fake kmod_info struct for the kernel.
306 * It's used in OSRuntime.cpp to call OSRuntimeInitializeCPP()
307 * before OSKext is initialized; that call only needs the name
308 * and address to be set correctly.
309 *
310 * We don't do much else with the kerne's kmod_info; we never
311 * put it into the kmod list, never adjust the reference count,
312 * and never have kernel components reference it.
313 * For that matter, we don't do much with kmod_info structs
314 * at all anymore! We just keep them filled in for gdb and
315 * binary compability.
316 */
317 kmod_info_t g_kernel_kmod_info = {
318 .next = NULL,
319 .info_version = KMOD_INFO_VERSION,
320 .id = 0, // loadTag: kernel is always 0
321 .name = kOSKextKernelIdentifier,// bundle identifier
322 .version = "0", // filled in in OSKext::initialize()
323 .reference_count = -1, // never adjusted; kernel never unloads
324 .reference_list = NULL,
325 .address = 0,
326 .size = 0, // filled in in OSKext::initialize()
327 .hdr_size = 0,
328 .start = NULL,
329 .stop = NULL
330 };
331
332 /* Set up a fake kmod_info struct for statically linked kexts that don't have one. */
333
334 kmod_info_t invalid_kmod_info = {
335 .next = NULL,
336 .info_version = KMOD_INFO_VERSION,
337 .id = UINT32_MAX,
338 .name = "invalid",
339 .version = "0",
340 .reference_count = -1,
341 .reference_list = NULL,
342 .address = 0,
343 .size = 0,
344 .hdr_size = 0,
345 .start = NULL,
346 .stop = NULL
347 };
348
349 extern "C" {
350 // symbol 'kmod' referenced in: model_dep.c, db_trace.c, symbols.c, db_low_trace.c,
351 // dtrace.c, dtrace_glue.h, OSKext.cpp, locore.s, lowmem_vectors.s,
352 // misc_protos.h, db_low_trace.c, kgmacros
353 // 'kmod' is a holdover from the old kmod system, we can't rename it.
354 kmod_info_t * kmod = NULL;
355
356 #define KEXT_PANICLIST_SIZE (2 * PAGE_SIZE)
357
358
359 static char * loaded_kext_paniclist = NULL;
360 static uint32_t loaded_kext_paniclist_size = 0;
361
362 AbsoluteTime last_loaded_timestamp;
363 static char last_loaded_str_buf[2 * KMOD_MAX_NAME];
364 static u_long last_loaded_strlen = 0;
365 static void * last_loaded_address = NULL;
366 static u_long last_loaded_size = 0;
367
368 AbsoluteTime last_unloaded_timestamp;
369 static char last_unloaded_str_buf[2 * KMOD_MAX_NAME];
370 static u_long last_unloaded_strlen = 0;
371 static void * last_unloaded_address = NULL;
372 static u_long last_unloaded_size = 0;
373
374 // Statically linked kmods described by several mach-o sections:
375 //
376 // kPrelinkInfoSegment:kBuiltinInfoSection
377 // Array of pointers to kmod_info_t structs.
378 //
379 // kPrelinkInfoSegment:kBuiltinInfoSection
380 // Array of pointers to an embedded mach-o header.
381 //
382 // __DATA:kBuiltinInitSection, kBuiltinTermSection
383 // Structors for all kmods. Has to be filtered by proc address.
384 //
385
386 static uint32_t gBuiltinKmodsCount;
387 static kernel_section_t * gBuiltinKmodsSectionInfo;
388 static kernel_section_t * gBuiltinKmodsSectionStart;
389
390 static const OSSymbol * gIOSurfaceIdentifier;
391 vm_tag_t gIOSurfaceTag;
392
393 /*********************************************************************
394 * sKextInnerLock protects against cross-calls with IOService and
395 * IOCatalogue, and owns the variables declared immediately below.
396 *
397 * Note that sConsiderUnloadsExecuted above belongs to sKextLock!
398 *
399 * When both sKextLock and sKextInnerLock need to be taken,
400 * always lock sKextLock first and unlock it second. Never take both
401 * locks in an entry point to OSKext; if you need to do so, you must
402 * spawn an independent thread to avoid potential deadlocks for threads
403 * calling into OSKext.
404 **********/
405 static IORecursiveLock * sKextInnerLock = NULL;
406
407 static bool sAutounloadEnabled = true;
408 static bool sConsiderUnloadsCalled = false;
409 static bool sConsiderUnloadsPending = false;
410
411 static unsigned int sConsiderUnloadDelay = 60; // seconds
412 static thread_call_t sUnloadCallout = NULL;
413 static thread_call_t sDestroyLinkContextThread = NULL; // one-shot, one-at-a-time thread
414 static bool sSystemSleep = false; // true when system going to sleep
415 static AbsoluteTime sLastWakeTime; // last time we woke up
416
417 /*********************************************************************
418 * Backtraces can be printed at various times so we need a tight lock
419 * on data used for that. sKextSummariesLock protects the variables
420 * declared immediately below.
421 *
422 * gLoadedKextSummaries is accessed by other modules, but only during
423 * a panic so the lock isn't needed then.
424 *
425 * gLoadedKextSummaries has the "used" attribute in order to ensure
426 * that it remains visible even when we are performing extremely
427 * aggressive optimizations, as it is needed to allow the debugger
428 * to automatically parse the list of loaded kexts.
429 **********/
430 static IOLock * sKextSummariesLock = NULL;
431 extern "C" lck_spin_t vm_allocation_sites_lock;
432 static IOSimpleLock * sKextAccountsLock = &vm_allocation_sites_lock;
433
434 void(*const sLoadedKextSummariesUpdated)(void) = OSKextLoadedKextSummariesUpdated;
435 OSKextLoadedKextSummaryHeader * gLoadedKextSummaries __attribute__((used)) = NULL;
436 uint64_t gLoadedKextSummariesTimestamp __attribute__((used)) = 0;
437 static size_t sLoadedKextSummariesAllocSize = 0;
438
439 static OSKextActiveAccount * sKextAccounts;
440 static uint32_t sKextAccountsCount;
441 };
442
443 /*********************************************************************
444 * sKextLoggingLock protects the logging variables declared immediately below.
445 **********/
446 static IOLock * sKextLoggingLock = NULL;
447
448 static const OSKextLogSpec kDefaultKernelLogFilter = kOSKextLogBasicLevel |
449 kOSKextLogVerboseFlagsMask;
450 static OSKextLogSpec sKernelLogFilter = kDefaultKernelLogFilter;
451 static bool sBootArgLogFilterFound = false;
452 SYSCTL_UINT(_debug, OID_AUTO, kextlog, CTLFLAG_RW | CTLFLAG_LOCKED, &sKernelLogFilter,
453 0, "kernel kext logging");
454
455 static OSKextLogSpec sUserSpaceKextLogFilter = kOSKextLogSilentFilter;
456 static OSArray * sUserSpaceLogSpecArray = NULL;
457 static OSArray * sUserSpaceLogMessageArray = NULL;
458
459 /*********
460 * End scope for sKextInnerLock-protected variables.
461 *********************************************************************/
462
463
464 /*********************************************************************
465 * helper function used for collecting PGO data upon unload of a kext
466 */
467
468 static int OSKextGrabPgoDataLocked(OSKext *kext,
469 bool metadata,
470 uuid_t instance_uuid,
471 uint64_t *pSize,
472 char *pBuffer,
473 uint64_t bufferSize);
474
475 /**********************************************************************/
476
477
478
479 #if PRAGMA_MARK
480 #pragma mark OSData callbacks (need to move to OSData)
481 #endif
482 /*********************************************************************
483 * C functions used for callbacks.
484 *********************************************************************/
485 extern "C" {
486 void
487 osdata_kmem_free(void * ptr, unsigned int length)
488 {
489 kmem_free(kernel_map, (vm_address_t)ptr, length);
490 return;
491 }
492
493 void
494 osdata_phys_free(void * ptr, unsigned int length)
495 {
496 ml_static_mfree((vm_offset_t)ptr, length);
497 return;
498 }
499
500 void
501 osdata_vm_deallocate(void * ptr, unsigned int length)
502 {
503 (void)vm_deallocate(kernel_map, (vm_offset_t)ptr, length);
504 return;
505 }
506
507 void
508 osdata_kext_free(void * ptr, unsigned int length)
509 {
510 (void)kext_free((vm_offset_t)ptr, length);
511 }
512 };
513
514 #if PRAGMA_MARK
515 #pragma mark KXLD Allocation Callback
516 #endif
517 /*********************************************************************
518 * KXLD Allocation Callback
519 *********************************************************************/
520 kxld_addr_t
521 kern_allocate(
522 u_long size,
523 KXLDAllocateFlags * flags,
524 void * user_data)
525 {
526 vm_address_t result = 0; // returned
527 kern_return_t mach_result = KERN_FAILURE;
528 bool success = false;
529 OSKext * theKext = (OSKext *)user_data;
530 u_long roundSize = round_page(size);
531 OSData * linkBuffer = NULL;// must release
532
533 mach_result = kext_alloc(&result, roundSize, /* fixed */ FALSE);
534 if (mach_result != KERN_SUCCESS) {
535 OSKextLog(theKext,
536 kOSKextLogErrorLevel |
537 kOSKextLogGeneralFlag,
538 "Can't allocate kernel memory to link %s.",
539 theKext->getIdentifierCString());
540 goto finish;
541 }
542
543 /* Create an OSData wrapper for the allocated buffer.
544 */
545 linkBuffer = OSData::withBytesNoCopy((void *)result, roundSize);
546 if (!linkBuffer) {
547 OSKextLog(theKext,
548 kOSKextLogErrorLevel |
549 kOSKextLogGeneralFlag,
550 "Can't allocate linked executable wrapper for %s.",
551 theKext->getIdentifierCString());
552 goto finish;
553 }
554 linkBuffer->setDeallocFunction(osdata_kext_free);
555 OSKextLog(theKext,
556 kOSKextLogProgressLevel |
557 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
558 "Allocated link buffer for kext %s at %p (%lu bytes).",
559 theKext->getIdentifierCString(),
560 (void *)result, (unsigned long)roundSize);
561
562 theKext->setLinkedExecutable(linkBuffer);
563
564 *flags = kKxldAllocateWritable;
565 success = true;
566
567 finish:
568 if (!success && result) {
569 kext_free(result, roundSize);
570 result = 0;
571 }
572
573 OSSafeReleaseNULL(linkBuffer);
574
575 return (kxld_addr_t)result;
576 }
577
578 /*********************************************************************
579 *********************************************************************/
580 void
581 kxld_log_callback(
582 KXLDLogSubsystem subsystem,
583 KXLDLogLevel level,
584 const char * format,
585 va_list argList,
586 void * user_data)
587 {
588 OSKext *theKext = (OSKext *) user_data;
589 OSKextLogSpec logSpec = 0;
590
591 switch (subsystem) {
592 case kKxldLogLinking:
593 logSpec |= kOSKextLogLinkFlag;
594 break;
595 case kKxldLogPatching:
596 logSpec |= kOSKextLogPatchFlag;
597 break;
598 }
599
600 switch (level) {
601 case kKxldLogExplicit:
602 logSpec |= kOSKextLogExplicitLevel;
603 break;
604 case kKxldLogErr:
605 logSpec |= kOSKextLogErrorLevel;
606 break;
607 case kKxldLogWarn:
608 logSpec |= kOSKextLogWarningLevel;
609 break;
610 case kKxldLogBasic:
611 logSpec |= kOSKextLogProgressLevel;
612 break;
613 case kKxldLogDetail:
614 logSpec |= kOSKextLogDetailLevel;
615 break;
616 case kKxldLogDebug:
617 logSpec |= kOSKextLogDebugLevel;
618 break;
619 }
620
621 OSKextVLog(theKext, logSpec, format, argList);
622 }
623
624 #if PRAGMA_MARK
625 #pragma mark IOStatistics defines
626 #endif
627
628 #if IOKITSTATS
629
630 #define notifyKextLoadObservers(kext, kmod_info) \
631 do { \
632 IOStatistics::onKextLoad(kext, kmod_info); \
633 } while (0)
634
635 #define notifyKextUnloadObservers(kext) \
636 do { \
637 IOStatistics::onKextUnload(kext); \
638 } while (0)
639
640 #define notifyAddClassObservers(kext, addedClass, flags) \
641 do { \
642 IOStatistics::onClassAdded(kext, addedClass); \
643 } while (0)
644
645 #define notifyRemoveClassObservers(kext, removedClass, flags) \
646 do { \
647 IOStatistics::onClassRemoved(kext, removedClass); \
648 } while (0)
649
650 #else
651
652 #define notifyKextLoadObservers(kext, kmod_info)
653 #define notifyKextUnloadObservers(kext)
654 #define notifyAddClassObservers(kext, addedClass, flags)
655 #define notifyRemoveClassObservers(kext, removedClass, flags)
656
657 #endif /* IOKITSTATS */
658
659 #if PRAGMA_MARK
660 #pragma mark Module Config (Startup & Shutdown)
661 #endif
662 /*********************************************************************
663 * Module Config (Class Definition & Class Methods)
664 *********************************************************************/
665 #define super OSObject
666 OSDefineMetaClassAndStructors(OSKext, OSObject)
667
668 /*********************************************************************
669 *********************************************************************/
670 /* static */
671 void
672 OSKext::initialize(void)
673 {
674 OSData * kernelExecutable = NULL;// do not release
675 u_char * kernelStart = NULL;// do not free
676 size_t kernelLength = 0;
677 OSString * scratchString = NULL;// must release
678 IORegistryEntry * registryRoot = NULL;// do not release
679 OSNumber * kernelCPUType = NULL;// must release
680 OSNumber * kernelCPUSubtype = NULL;// must release
681 OSKextLogSpec bootLogFilter = kOSKextLogSilentFilter;
682 bool setResult = false;
683 uint64_t * timestamp = NULL;
684 char bootArgBuffer[16];// for PE_parse_boot_argn w/strings
685
686 /* This must be the first thing allocated. Everything else grabs this lock.
687 */
688 sKextLock = IORecursiveLockAlloc();
689 sKextInnerLock = IORecursiveLockAlloc();
690 sKextSummariesLock = IOLockAlloc();
691 sKextLoggingLock = IOLockAlloc();
692 assert(sKextLock);
693 assert(sKextInnerLock);
694 assert(sKextSummariesLock);
695 assert(sKextLoggingLock);
696
697 sKextsByID = OSDictionary::withCapacity(kOSKextTypicalLoadCount);
698 sLoadedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
699 sLoadedDriverKitKexts = OSArray::withCapacity(kOSKextTypicalLoadCount);
700 sUnloadedPrelinkedKexts = OSArray::withCapacity(kOSKextTypicalLoadCount / 10);
701 sKernelRequests = OSArray::withCapacity(0);
702 sPostedKextLoadIdentifiers = OSSet::withCapacity(0);
703 sAllKextLoadIdentifiers = OSSet::withCapacity(kOSKextTypicalLoadCount);
704 sRequestCallbackRecords = OSArray::withCapacity(0);
705 assert(sKextsByID && sLoadedKexts && sLoadedDriverKitKexts && sKernelRequests &&
706 sPostedKextLoadIdentifiers && sAllKextLoadIdentifiers &&
707 sRequestCallbackRecords && sUnloadedPrelinkedKexts);
708
709 /* Read the log flag boot-args and set the log flags.
710 */
711 if (PE_parse_boot_argn("kextlog", &bootLogFilter, sizeof(bootLogFilter))) {
712 sBootArgLogFilterFound = true;
713 sKernelLogFilter = bootLogFilter;
714 // log this if any flags are set
715 OSKextLog(/* kext */ NULL,
716 kOSKextLogBasicLevel |
717 kOSKextLogFlagsMask,
718 "Kernel kext log filter 0x%x per kextlog boot arg.",
719 (unsigned)sKernelLogFilter);
720 }
721
722 sSafeBoot = PE_parse_boot_argn("-x", bootArgBuffer,
723 sizeof(bootArgBuffer)) ? true : false;
724
725 if (sSafeBoot) {
726 OSKextLog(/* kext */ NULL,
727 kOSKextLogWarningLevel |
728 kOSKextLogGeneralFlag,
729 "SAFE BOOT DETECTED - "
730 "only valid OSBundleRequired kexts will be loaded.");
731 }
732
733 PE_parse_boot_argn("keepsyms", &sKeepSymbols, sizeof(sKeepSymbols));
734 #if CONFIG_DTRACE
735 if (dtrace_keep_kernel_symbols()) {
736 sKeepSymbols = true;
737 }
738 #endif /* CONFIG_DTRACE */
739 #if KASAN_DYNAMIC_BLACKLIST
740 /* needed for function lookup */
741 sKeepSymbols = true;
742 #endif
743
744 /* Set up an OSKext instance to represent the kernel itself.
745 */
746 sKernelKext = new OSKext;
747 assert(sKernelKext);
748
749 kernelStart = (u_char *)&_mh_execute_header;
750 kernelLength = getlastaddr() - (vm_offset_t)kernelStart;
751 kernelExecutable = OSData::withBytesNoCopy(
752 kernelStart, kernelLength);
753 assert(kernelExecutable);
754
755 #if KASLR_KEXT_DEBUG
756 IOLog("kaslr: kernel start 0x%lx end 0x%lx length %lu vm_kernel_slide %lu (0x%016lx) \n",
757 (unsigned long)kernelStart,
758 (unsigned long)getlastaddr(),
759 kernelLength,
760 (unsigned long)vm_kernel_slide,
761 (unsigned long)vm_kernel_slide);
762 #endif
763
764 sKernelKext->loadTag = sNextLoadTag++; // the kernel is load tag 0
765 sKernelKext->bundleID = OSSymbol::withCString(kOSKextKernelIdentifier);
766
767 sKernelKext->version = OSKextParseVersionString(osrelease);
768 sKernelKext->compatibleVersion = sKernelKext->version;
769 sKernelKext->linkedExecutable = kernelExecutable;
770 sKernelKext->interfaceUUID = sKernelKext->copyUUID();
771
772 sKernelKext->flags.hasAllDependencies = 1;
773 sKernelKext->flags.kernelComponent = 1;
774 sKernelKext->flags.prelinked = 0;
775 sKernelKext->flags.loaded = 1;
776 sKernelKext->flags.started = 1;
777 sKernelKext->flags.CPPInitialized = 0;
778 sKernelKext->flags.jettisonLinkeditSeg = 0;
779
780 sKernelKext->kmod_info = &g_kernel_kmod_info;
781 strlcpy(g_kernel_kmod_info.version, osrelease,
782 sizeof(g_kernel_kmod_info.version));
783 g_kernel_kmod_info.size = kernelLength;
784 g_kernel_kmod_info.id = sKernelKext->loadTag;
785
786 /* Cons up an info dict, so we don't have to have special-case
787 * checking all over.
788 */
789 sKernelKext->infoDict = OSDictionary::withCapacity(5);
790 assert(sKernelKext->infoDict);
791 setResult = sKernelKext->infoDict->setObject(kCFBundleIdentifierKey,
792 sKernelKext->bundleID);
793 assert(setResult);
794 setResult = sKernelKext->infoDict->setObject(kOSKernelResourceKey,
795 kOSBooleanTrue);
796 assert(setResult);
797
798 scratchString = OSString::withCStringNoCopy(osrelease);
799 assert(scratchString);
800 setResult = sKernelKext->infoDict->setObject(kCFBundleVersionKey,
801 scratchString);
802 assert(setResult);
803 OSSafeReleaseNULL(scratchString);
804
805 scratchString = OSString::withCStringNoCopy("mach_kernel");
806 assert(scratchString);
807 setResult = sKernelKext->infoDict->setObject(kCFBundleNameKey,
808 scratchString);
809 assert(setResult);
810 OSSafeReleaseNULL(scratchString);
811
812 /* Add the kernel kext to the bookkeeping dictionaries. Note that
813 * the kernel kext doesn't have a kmod_info struct. copyInfo()
814 * gathers info from other places anyhow.
815 */
816 setResult = sKextsByID->setObject(sKernelKext->bundleID, sKernelKext);
817 assert(setResult);
818 setResult = sLoadedKexts->setObject(sKernelKext);
819 assert(setResult);
820 sKernelKext->release();
821
822 registryRoot = IORegistryEntry::getRegistryRoot();
823 kernelCPUType = OSNumber::withNumber(
824 (long long unsigned int)_mh_execute_header.cputype,
825 8 * sizeof(_mh_execute_header.cputype));
826 kernelCPUSubtype = OSNumber::withNumber(
827 (long long unsigned int)_mh_execute_header.cpusubtype,
828 8 * sizeof(_mh_execute_header.cpusubtype));
829 assert(registryRoot && kernelCPUSubtype && kernelCPUType);
830
831 registryRoot->setProperty(kOSKernelCPUTypeKey, kernelCPUType);
832 registryRoot->setProperty(kOSKernelCPUSubtypeKey, kernelCPUSubtype);
833
834 OSSafeReleaseNULL(kernelCPUType);
835 OSSafeReleaseNULL(kernelCPUSubtype);
836
837 gBuiltinKmodsSectionInfo = getsectbyname(kPrelinkInfoSegment, kBuiltinInfoSection);
838 if (gBuiltinKmodsSectionInfo) {
839 uint32_t count;
840
841 assert(gBuiltinKmodsSectionInfo->addr);
842 assert(gBuiltinKmodsSectionInfo->size);
843 gBuiltinKmodsCount = (gBuiltinKmodsSectionInfo->size / sizeof(kmod_info_t *));
844
845 gBuiltinKmodsSectionStart = getsectbyname(kPrelinkInfoSegment, kBuiltinStartSection);
846 assert(gBuiltinKmodsSectionStart);
847 assert(gBuiltinKmodsSectionStart->addr);
848 assert(gBuiltinKmodsSectionStart->size);
849 count = (gBuiltinKmodsSectionStart->size / sizeof(uintptr_t));
850 // one extra pointer for the end of last kmod
851 assert(count == (gBuiltinKmodsCount + 1));
852
853 vm_kernel_builtinkmod_text = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[0];
854 vm_kernel_builtinkmod_text_end = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[count - 1];
855 }
856 gIOSurfaceIdentifier = OSSymbol::withCStringNoCopy("com.apple.iokit.IOSurface");
857
858 timestamp = __OSAbsoluteTimePtr(&last_loaded_timestamp);
859 *timestamp = 0;
860 timestamp = __OSAbsoluteTimePtr(&last_unloaded_timestamp);
861 *timestamp = 0;
862 timestamp = __OSAbsoluteTimePtr(&sLastWakeTime);
863 *timestamp = 0;
864
865 OSKextLog(/* kext */ NULL,
866 kOSKextLogProgressLevel |
867 kOSKextLogGeneralFlag,
868 "Kext system initialized.");
869
870 notifyKextLoadObservers(sKernelKext, sKernelKext->kmod_info);
871
872 return;
873 }
874
875 /*********************************************************************
876 * This is expected to be called exactly once, from exactly one thread
877 * context, during kernel bootstrap.
878 *********************************************************************/
879 /* static */
880 OSReturn
881 OSKext::removeKextBootstrap(void)
882 {
883 OSReturn result = kOSReturnError;
884
885 const char * dt_kernel_header_name = "Kernel-__HEADER";
886 const char * dt_kernel_symtab_name = "Kernel-__SYMTAB";
887 kernel_mach_header_t * dt_mach_header = NULL;
888 int dt_mach_header_size = 0;
889 struct symtab_command * dt_symtab = NULL;
890 int dt_symtab_size = 0;
891 int dt_result = 0;
892
893 kernel_segment_command_t * seg_to_remove = NULL;
894
895 #if __arm__ || __arm64__
896 const char * dt_segment_name = NULL;
897 void * segment_paddress = NULL;
898 int segment_size = 0;
899 #endif
900
901 OSKextLog(/* kext */ NULL,
902 kOSKextLogProgressLevel |
903 kOSKextLogGeneralFlag,
904 "Jettisoning kext bootstrap segments.");
905
906 /*****
907 * Dispose of unnecessary stuff that the booter didn't need to load.
908 */
909 dt_result = IODTGetLoaderInfo(dt_kernel_header_name,
910 (void **)&dt_mach_header, &dt_mach_header_size);
911 if (dt_result == 0 && dt_mach_header) {
912 IODTFreeLoaderInfo(dt_kernel_header_name, (void *)dt_mach_header,
913 round_page_32(dt_mach_header_size));
914 }
915 dt_result = IODTGetLoaderInfo(dt_kernel_symtab_name,
916 (void **)&dt_symtab, &dt_symtab_size);
917 if (dt_result == 0 && dt_symtab) {
918 IODTFreeLoaderInfo(dt_kernel_symtab_name, (void *)dt_symtab,
919 round_page_32(dt_symtab_size));
920 }
921
922 /*****
923 * KLD bootstrap segment.
924 */
925 // xxx - should rename KLD segment
926 seg_to_remove = getsegbyname("__KLD");
927 if (seg_to_remove) {
928 OSRuntimeUnloadCPPForSegment(seg_to_remove);
929 }
930
931 #if __arm__ || __arm64__
932 /* Free the memory that was set up by bootx.
933 */
934 dt_segment_name = "Kernel-__KLD";
935 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
936 /* We cannot free this with KTRR enabled, as we cannot
937 * update the permissions on the KLD range this late
938 * in the boot process.
939 */
940 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
941 (int)segment_size);
942 }
943 #elif __i386__ || __x86_64__
944 /* On x86, use the mapping data from the segment load command to
945 * unload KLD directly.
946 * This may invalidate any assumptions about "avail_start"
947 * defining the lower bound for valid physical addresses.
948 */
949 if (seg_to_remove && seg_to_remove->vmaddr && seg_to_remove->vmsize) {
950 // 04/18/11 - gab: <rdar://problem/9236163>
951 // overwrite memory occupied by KLD segment with random data before
952 // releasing it.
953 read_frandom((void *) seg_to_remove->vmaddr, seg_to_remove->vmsize);
954 ml_static_mfree(seg_to_remove->vmaddr, seg_to_remove->vmsize);
955 }
956 #else
957 #error arch
958 #endif
959
960 seg_to_remove = NULL;
961
962 /*****
963 * Prelinked kernel's symtab (if there is one).
964 */
965 kernel_section_t * sect;
966 sect = getsectbyname("__PRELINK", "__symtab");
967 if (sect && sect->addr && sect->size) {
968 ml_static_mfree(sect->addr, sect->size);
969 }
970
971 seg_to_remove = (kernel_segment_command_t *)getsegbyname("__LINKEDIT");
972
973 /* kxld always needs the kernel's __LINKEDIT segment, but we can make it
974 * pageable, unless keepsyms is set. To do that, we have to copy it from
975 * its booter-allocated memory, free the booter memory, reallocate proper
976 * managed memory, then copy the segment back in.
977 */
978 #if CONFIG_KXLD
979 #if (__arm__ || __arm64__)
980 #error CONFIG_KXLD not expected for this arch
981 #endif
982 if (!sKeepSymbols) {
983 kern_return_t mem_result;
984 void *seg_copy = NULL;
985 void *seg_data = NULL;
986 vm_map_offset_t seg_offset = 0;
987 vm_map_offset_t seg_copy_offset = 0;
988 vm_map_size_t seg_length = 0;
989
990 seg_data = (void *) seg_to_remove->vmaddr;
991 seg_offset = (vm_map_offset_t) seg_to_remove->vmaddr;
992 seg_length = (vm_map_size_t) seg_to_remove->vmsize;
993
994 /* Allocate space for the LINKEDIT copy.
995 */
996 mem_result = kmem_alloc(kernel_map, (vm_offset_t *) &seg_copy,
997 seg_length, VM_KERN_MEMORY_KEXT);
998 if (mem_result != KERN_SUCCESS) {
999 OSKextLog(/* kext */ NULL,
1000 kOSKextLogErrorLevel |
1001 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1002 "Can't copy __LINKEDIT segment for VM reassign.");
1003 return result;
1004 }
1005 seg_copy_offset = (vm_map_offset_t) seg_copy;
1006
1007 /* Copy it out.
1008 */
1009 memcpy(seg_copy, seg_data, seg_length);
1010
1011 /* Dump the booter memory.
1012 */
1013 ml_static_mfree(seg_offset, seg_length);
1014
1015 /* Set up the VM region.
1016 */
1017 mem_result = vm_map_enter_mem_object(
1018 kernel_map,
1019 &seg_offset,
1020 seg_length, /* mask */ 0,
1021 VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
1022 VM_MAP_KERNEL_FLAGS_NONE,
1023 VM_KERN_MEMORY_NONE,
1024 (ipc_port_t)NULL,
1025 (vm_object_offset_t) 0,
1026 /* copy */ FALSE,
1027 /* cur_protection */ VM_PROT_READ | VM_PROT_WRITE,
1028 /* max_protection */ VM_PROT_ALL,
1029 /* inheritance */ VM_INHERIT_DEFAULT);
1030 if ((mem_result != KERN_SUCCESS) ||
1031 (seg_offset != (vm_map_offset_t) seg_data)) {
1032 OSKextLog(/* kext */ NULL,
1033 kOSKextLogErrorLevel |
1034 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1035 "Can't create __LINKEDIT VM entry at %p, length 0x%llx (error 0x%x).",
1036 seg_data, seg_length, mem_result);
1037 return result;
1038 }
1039
1040 /* And copy it back.
1041 */
1042 memcpy(seg_data, seg_copy, seg_length);
1043
1044 /* Free the copy.
1045 */
1046 kmem_free(kernel_map, seg_copy_offset, seg_length);
1047 }
1048 #else /* we are not CONFIG_KXLD */
1049 #if !(__arm__ || __arm64__)
1050 #error CONFIG_KXLD is expected for this arch
1051 #endif
1052
1053 /*****
1054 * Dump the LINKEDIT segment, unless keepsyms is set.
1055 */
1056 if (!sKeepSymbols) {
1057 dt_segment_name = "Kernel-__LINKEDIT";
1058 if (0 == IODTGetLoaderInfo(dt_segment_name,
1059 &segment_paddress, &segment_size)) {
1060 #ifdef SECURE_KERNEL
1061 vm_offset_t vmaddr = ml_static_ptovirt((vm_offset_t)segment_paddress);
1062 bzero((void*)vmaddr, segment_size);
1063 #endif
1064 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1065 (int)segment_size);
1066 }
1067 } else {
1068 OSKextLog(/* kext */ NULL,
1069 kOSKextLogBasicLevel |
1070 kOSKextLogGeneralFlag,
1071 "keepsyms boot arg specified; keeping linkedit segment for symbols.");
1072 }
1073 #endif /* CONFIG_KXLD */
1074
1075 seg_to_remove = NULL;
1076
1077 result = kOSReturnSuccess;
1078
1079 return result;
1080 }
1081
1082 /*********************************************************************
1083 *********************************************************************/
1084 void
1085 OSKext::flushNonloadedKexts(
1086 Boolean flushPrelinkedKexts)
1087 {
1088 OSSet * keepKexts = NULL;// must release
1089
1090 IORecursiveLockLock(sKextLock);
1091
1092 OSKextLog(/* kext */ NULL,
1093 kOSKextLogProgressLevel |
1094 kOSKextLogKextBookkeepingFlag,
1095 "Flushing nonloaded kexts and other unused data.");
1096
1097 OSKext::considerDestroyingLinkContext();
1098
1099 /* If we aren't flushing unused prelinked kexts, we have to put them
1100 * aside while we flush everything else so make a container for them.
1101 */
1102 keepKexts = OSSet::withCapacity(16);
1103 if (!keepKexts) {
1104 goto finish;
1105 }
1106
1107 /* Set aside prelinked kexts (in-use or not) and break
1108 * any lingering inter-kext references for nonloaded kexts
1109 * so they have min. retain counts.
1110 */
1111 sKextsByID->iterateObjects(^bool (const OSSymbol * thisID __unused, OSObject * obj) {
1112 OSKext * thisKext = OSDynamicCast(OSKext, obj);
1113 if (!thisKext) {
1114 return false;
1115 }
1116 if (!flushPrelinkedKexts && thisKext->isPrelinked()) {
1117 keepKexts->setObject(thisKext);
1118 }
1119 if (!thisKext->declaresExecutable()) {
1120 /*
1121 * Don't unload codeless kexts, because they never appear in the loadedKexts array.
1122 * Requesting one from kextd will load it and then immediately remove it by calling
1123 * flushNonloadedKexts().
1124 * And adding one to loadedKexts breaks code assuming they have kmod_info etc.
1125 */
1126 keepKexts->setObject(thisKext);
1127 }
1128
1129 thisKext->flushDependencies(/* forceIfLoaded */ false);
1130 return false;
1131 });
1132
1133 /* Dump all the kexts in the ID dictionary; we'll repopulate it shortly.
1134 */
1135 sKextsByID->flushCollection();
1136
1137 /* Now put the loaded kexts back into the ID dictionary.
1138 */
1139 sLoadedKexts->iterateObjects(^bool (OSObject * obj) {
1140 OSKext * thisKext = OSDynamicCast(OSKext, obj);
1141 if (!thisKext) {
1142 return false;
1143 }
1144 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1145 return false;
1146 });
1147
1148 /* Finally, put back the kept kexts if we saved any.
1149 */
1150 keepKexts->iterateObjects(^bool (OSObject * obj) {
1151 OSKext * thisKext = OSDynamicCast(OSKext, obj);
1152 if (!thisKext) {
1153 return false;
1154 }
1155 sKextsByID->setObject(thisKext->getIdentifierCString(), thisKext);
1156 return false;
1157 });
1158
1159 finish:
1160 IORecursiveLockUnlock(sKextLock);
1161
1162 OSSafeReleaseNULL(keepKexts);
1163
1164 return;
1165 }
1166
1167 /*********************************************************************
1168 *********************************************************************/
1169 /* static */
1170 void
1171 OSKext::setKextdActive(Boolean active)
1172 {
1173 IORecursiveLockLock(sKextLock);
1174 sKextdActive = active;
1175 if (sKernelRequests->getCount()) {
1176 OSKext::pingKextd();
1177 }
1178 IORecursiveLockUnlock(sKextLock);
1179
1180 return;
1181 }
1182
1183 /*********************************************************************
1184 * OSKextLib.cpp might need access to this someday but for now it's
1185 * private.
1186 *********************************************************************/
1187 extern "C" {
1188 extern void ipc_port_release_send(ipc_port_t);
1189 };
1190
1191 /* static */
1192 OSReturn
1193 OSKext::pingKextd(void)
1194 {
1195 OSReturn result = kOSReturnError;
1196 #if !NO_KEXTD
1197 mach_port_t kextd_port = IPC_PORT_NULL;
1198
1199 if (!sKextdActive) {
1200 result = kOSKextReturnDisabled; // basically unavailable
1201 goto finish;
1202 }
1203
1204 result = host_get_kextd_port(host_priv_self(), &kextd_port);
1205 if (result != KERN_SUCCESS || !IPC_PORT_VALID(kextd_port)) {
1206 OSKextLog(/* kext */ NULL,
1207 kOSKextLogErrorLevel |
1208 kOSKextLogIPCFlag,
1209 "Can't get kextd port.");
1210 goto finish;
1211 }
1212
1213 result = kextd_ping(kextd_port);
1214 if (result != KERN_SUCCESS) {
1215 OSKextLog(/* kext */ NULL,
1216 kOSKextLogErrorLevel |
1217 kOSKextLogIPCFlag,
1218 "kextd ping failed (0x%x).", (int)result);
1219 goto finish;
1220 }
1221
1222 finish:
1223 if (IPC_PORT_VALID(kextd_port)) {
1224 ipc_port_release_send(kextd_port);
1225 }
1226 #endif
1227
1228 return result;
1229 }
1230
1231 /*********************************************************************
1232 *********************************************************************/
1233 /* static */
1234 void
1235 OSKext::setDeferredLoadSucceeded(Boolean succeeded)
1236 {
1237 IORecursiveLockLock(sKextLock);
1238 sDeferredLoadSucceeded = succeeded;
1239 IORecursiveLockUnlock(sKextLock);
1240
1241 return;
1242 }
1243
1244 /*********************************************************************
1245 * Called from IOSystemShutdownNotification.
1246 *********************************************************************/
1247 /* static */
1248 void
1249 OSKext::willShutdown(void)
1250 {
1251 #if !NO_KEXTD
1252 OSReturn checkResult = kOSReturnError;
1253 #endif
1254 OSDictionary * exitRequest = NULL; // must release
1255
1256 IORecursiveLockLock(sKextLock);
1257
1258 OSKext::setLoadEnabled(false);
1259 OSKext::setUnloadEnabled(false);
1260 OSKext::setAutounloadsEnabled(false);
1261 OSKext::setKernelRequestsEnabled(false);
1262
1263 #if !NO_KEXTD
1264 OSKextLog(/* kext */ NULL,
1265 kOSKextLogProgressLevel |
1266 kOSKextLogGeneralFlag,
1267 "System shutdown; requesting immediate kextd exit.");
1268
1269 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestKextdExit,
1270 &exitRequest);
1271 if (checkResult != kOSReturnSuccess) {
1272 goto finish;
1273 }
1274 if (!sKernelRequests->setObject(exitRequest)) {
1275 goto finish;
1276 }
1277
1278 OSKext::pingKextd();
1279
1280 finish:
1281 #endif
1282
1283 IORecursiveLockUnlock(sKextLock);
1284
1285 OSSafeReleaseNULL(exitRequest);
1286 return;
1287 }
1288
1289 /*********************************************************************
1290 *********************************************************************/
1291 /* static */
1292 bool
1293 OSKext::getLoadEnabled(void)
1294 {
1295 bool result;
1296
1297 IORecursiveLockLock(sKextLock);
1298 result = sLoadEnabled;
1299 IORecursiveLockUnlock(sKextLock);
1300 return result;
1301 }
1302
1303 /*********************************************************************
1304 *********************************************************************/
1305 /* static */
1306 bool
1307 OSKext::setLoadEnabled(bool flag)
1308 {
1309 bool result;
1310
1311 IORecursiveLockLock(sKextLock);
1312 result = sLoadEnabled;
1313 sLoadEnabled = (flag ? true : false);
1314
1315 if (sLoadEnabled != result) {
1316 OSKextLog(/* kext */ NULL,
1317 kOSKextLogBasicLevel |
1318 kOSKextLogLoadFlag,
1319 "Kext loading now %sabled.", sLoadEnabled ? "en" : "dis");
1320 }
1321
1322 IORecursiveLockUnlock(sKextLock);
1323
1324 return result;
1325 }
1326
1327 /*********************************************************************
1328 *********************************************************************/
1329 /* static */
1330 bool
1331 OSKext::getUnloadEnabled(void)
1332 {
1333 bool result;
1334
1335 IORecursiveLockLock(sKextLock);
1336 result = sUnloadEnabled;
1337 IORecursiveLockUnlock(sKextLock);
1338 return result;
1339 }
1340
1341 /*********************************************************************
1342 *********************************************************************/
1343 /* static */
1344 bool
1345 OSKext::setUnloadEnabled(bool flag)
1346 {
1347 bool result;
1348
1349 IORecursiveLockLock(sKextLock);
1350 result = sUnloadEnabled;
1351 sUnloadEnabled = (flag ? true : false);
1352 IORecursiveLockUnlock(sKextLock);
1353
1354 if (sUnloadEnabled != result) {
1355 OSKextLog(/* kext */ NULL,
1356 kOSKextLogBasicLevel |
1357 kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1358 "Kext unloading now %sabled.", sUnloadEnabled ? "en" : "dis");
1359 }
1360
1361 return result;
1362 }
1363
1364 /*********************************************************************
1365 * Do not call any function that takes sKextLock here!
1366 *********************************************************************/
1367 /* static */
1368 bool
1369 OSKext::getAutounloadEnabled(void)
1370 {
1371 bool result;
1372
1373 IORecursiveLockLock(sKextInnerLock);
1374 result = sAutounloadEnabled ? true : false;
1375 IORecursiveLockUnlock(sKextInnerLock);
1376 return result;
1377 }
1378
1379 /*********************************************************************
1380 * Do not call any function that takes sKextLock here!
1381 *********************************************************************/
1382 /* static */
1383 bool
1384 OSKext::setAutounloadsEnabled(bool flag)
1385 {
1386 bool result;
1387
1388 IORecursiveLockLock(sKextInnerLock);
1389
1390 result = sAutounloadEnabled;
1391 sAutounloadEnabled = (flag ? true : false);
1392 if (!sAutounloadEnabled && sUnloadCallout) {
1393 thread_call_cancel(sUnloadCallout);
1394 }
1395
1396 if (sAutounloadEnabled != result) {
1397 OSKextLog(/* kext */ NULL,
1398 kOSKextLogBasicLevel |
1399 kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
1400 "Kext autounloading now %sabled.",
1401 sAutounloadEnabled ? "en" : "dis");
1402 }
1403
1404 IORecursiveLockUnlock(sKextInnerLock);
1405
1406 return result;
1407 }
1408
1409 /*********************************************************************
1410 *********************************************************************/
1411 /* instance method operating on OSKext field */
1412 bool
1413 OSKext::setAutounloadEnabled(bool flag)
1414 {
1415 bool result = flags.autounloadEnabled ? true : false;
1416 flags.autounloadEnabled = flag ? 1 : 0;
1417
1418 if (result != (flag ? true : false)) {
1419 OSKextLog(this,
1420 kOSKextLogProgressLevel |
1421 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
1422 "Autounloading for kext %s now %sabled.",
1423 getIdentifierCString(),
1424 flags.autounloadEnabled ? "en" : "dis");
1425 }
1426 return result;
1427 }
1428
1429 /*********************************************************************
1430 *********************************************************************/
1431 /* static */
1432 bool
1433 OSKext::setKernelRequestsEnabled(bool flag)
1434 {
1435 bool result;
1436
1437 IORecursiveLockLock(sKextLock);
1438 result = sKernelRequestsEnabled;
1439 sKernelRequestsEnabled = flag ? true : false;
1440
1441 if (sKernelRequestsEnabled != result) {
1442 OSKextLog(/* kext */ NULL,
1443 kOSKextLogBasicLevel |
1444 kOSKextLogGeneralFlag,
1445 "Kernel requests now %sabled.",
1446 sKernelRequestsEnabled ? "en" : "dis");
1447 }
1448 IORecursiveLockUnlock(sKextLock);
1449 return result;
1450 }
1451
1452 /*********************************************************************
1453 *********************************************************************/
1454 /* static */
1455 bool
1456 OSKext::getKernelRequestsEnabled(void)
1457 {
1458 bool result;
1459
1460 IORecursiveLockLock(sKextLock);
1461 result = sKernelRequestsEnabled;
1462 IORecursiveLockUnlock(sKextLock);
1463 return result;
1464 }
1465
1466 #if PRAGMA_MARK
1467 #pragma mark Kext Life Cycle
1468 #endif
1469 /*********************************************************************
1470 *********************************************************************/
1471 OSKext *
1472 OSKext::withPrelinkedInfoDict(
1473 OSDictionary * anInfoDict,
1474 bool doCoalesedSlides)
1475 {
1476 OSKext * newKext = new OSKext;
1477
1478 if (newKext && !newKext->initWithPrelinkedInfoDict(anInfoDict, doCoalesedSlides)) {
1479 newKext->release();
1480 return NULL;
1481 }
1482
1483 return newKext;
1484 }
1485
1486 /*********************************************************************
1487 *********************************************************************/
1488 bool
1489 OSKext::initWithPrelinkedInfoDict(
1490 OSDictionary * anInfoDict,
1491 bool doCoalesedSlides)
1492 {
1493 bool result = false;
1494 OSString * kextPath = NULL;// do not release
1495 OSNumber * addressNum = NULL;// reused; do not release
1496 OSNumber * lengthNum = NULL;// reused; do not release
1497 void * data = NULL;// do not free
1498 void * srcData = NULL;// do not free
1499 OSData * prelinkedExecutable = NULL;// must release
1500 uint32_t length = 0; // reused
1501
1502 if (!super::init()) {
1503 goto finish;
1504 }
1505
1506 /* Get the path. Don't look for an arch-specific path property.
1507 */
1508 kextPath = OSDynamicCast(OSString,
1509 anInfoDict->getObject(kPrelinkBundlePathKey));
1510
1511 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
1512 goto finish;
1513 }
1514 #if KASLR_KEXT_DEBUG
1515 IOLog("kaslr: doCoalesedSlides %d kext %s \n", doCoalesedSlides, getIdentifierCString());
1516 #endif
1517
1518 /* Also get the executable's bundle-relative path if present.
1519 * Don't look for an arch-specific path property.
1520 */
1521 executableRelPath = OSDynamicCast(OSString,
1522 anInfoDict->getObject(kPrelinkExecutableRelativePathKey));
1523 if (executableRelPath) {
1524 executableRelPath->retain();
1525 }
1526
1527 userExecutableRelPath = OSDynamicCast(OSString,
1528 anInfoDict->getObject("CFBundleUEXTExecutable"));
1529 if (userExecutableRelPath) {
1530 userExecutableRelPath->retain();
1531 }
1532
1533 /* Don't need the paths to be in the info dictionary any more.
1534 */
1535 anInfoDict->removeObject(kPrelinkBundlePathKey);
1536 anInfoDict->removeObject(kPrelinkExecutableRelativePathKey);
1537
1538 /* Create an OSData wrapper around the linked executable.
1539 */
1540 addressNum = OSDynamicCast(OSNumber,
1541 anInfoDict->getObject(kPrelinkExecutableLoadKey));
1542 if (addressNum) {
1543 lengthNum = OSDynamicCast(OSNumber,
1544 anInfoDict->getObject(kPrelinkExecutableSizeKey));
1545 if (!lengthNum) {
1546 OSKextLog(this,
1547 kOSKextLogErrorLevel |
1548 kOSKextLogArchiveFlag,
1549 "Kext %s can't find prelinked kext executable size.",
1550 getIdentifierCString());
1551 goto finish;
1552 }
1553
1554 data = (void *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
1555 length = (uint32_t) (lengthNum->unsigned32BitValue());
1556
1557 #if KASLR_KEXT_DEBUG
1558 IOLog("kaslr: unslid 0x%lx slid 0x%lx length %u - prelink executable \n",
1559 (unsigned long)ml_static_unslide((vm_offset_t)data),
1560 (unsigned long)data,
1561 length);
1562 #endif
1563
1564 anInfoDict->removeObject(kPrelinkExecutableLoadKey);
1565 anInfoDict->removeObject(kPrelinkExecutableSizeKey);
1566
1567 /* If the kext's load address differs from its source address, allocate
1568 * space in the kext map at the load address and copy the kext over.
1569 */
1570 addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject(kPrelinkExecutableSourceKey));
1571 if (addressNum) {
1572 srcData = (void *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
1573
1574 #if KASLR_KEXT_DEBUG
1575 IOLog("kaslr: unslid 0x%lx slid 0x%lx - prelink executable source \n",
1576 (unsigned long)ml_static_unslide((vm_offset_t)srcData),
1577 (unsigned long)srcData);
1578 #endif
1579
1580 if (data != srcData) {
1581 #if __LP64__
1582 kern_return_t alloc_result;
1583
1584 alloc_result = kext_alloc((vm_offset_t *)&data, length, /* fixed */ TRUE);
1585 if (alloc_result != KERN_SUCCESS) {
1586 OSKextLog(this,
1587 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1588 "Failed to allocate space for prelinked kext %s.",
1589 getIdentifierCString());
1590 goto finish;
1591 }
1592 memcpy(data, srcData, length);
1593 #else
1594 OSKextLog(this,
1595 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
1596 "Error: prelinked kext %s - source and load addresses "
1597 "differ on ILP32 architecture.",
1598 getIdentifierCString());
1599 goto finish;
1600 #endif /* __LP64__ */
1601 }
1602
1603 anInfoDict->removeObject(kPrelinkExecutableSourceKey);
1604 }
1605
1606 prelinkedExecutable = OSData::withBytesNoCopy(data, length);
1607 if (!prelinkedExecutable) {
1608 OSKextLog(this,
1609 kOSKextLogErrorLevel |
1610 kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
1611 "Kext %s failed to create executable wrapper.",
1612 getIdentifierCString());
1613 goto finish;
1614 }
1615
1616 #if VM_MAPPED_KEXTS
1617 prelinkedExecutable->setDeallocFunction(osdata_kext_free);
1618 #else
1619 prelinkedExecutable->setDeallocFunction(osdata_phys_free);
1620 #endif
1621 setLinkedExecutable(prelinkedExecutable);
1622 addressNum = OSDynamicCast(OSNumber,
1623 anInfoDict->getObject(kPrelinkKmodInfoKey));
1624 if (!addressNum) {
1625 OSKextLog(this,
1626 kOSKextLogErrorLevel |
1627 kOSKextLogArchiveFlag,
1628 "Kext %s can't find prelinked kext kmod_info address.",
1629 getIdentifierCString());
1630 goto finish;
1631 }
1632
1633 if (addressNum->unsigned64BitValue() != 0) {
1634 kmod_info = (kmod_info_t *) ml_static_slide((intptr_t) (addressNum->unsigned64BitValue()));
1635 kmod_info->address = ml_static_slide(kmod_info->address);
1636 #if KASLR_KEXT_DEBUG
1637 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info \n",
1638 (unsigned long)ml_static_unslide((vm_offset_t)kmod_info),
1639 (unsigned long)kmod_info);
1640 IOLog("kaslr: unslid 0x%lx slid 0x%lx - kmod_info->address \n",
1641 (unsigned long)ml_static_unslide(kmod_info->address),
1642 (unsigned long)kmod_info->address);
1643 #endif
1644 }
1645
1646 anInfoDict->removeObject(kPrelinkKmodInfoKey);
1647 }
1648
1649 if ((addressNum = OSDynamicCast(OSNumber, anInfoDict->getObject("ModuleIndex")))) {
1650 uintptr_t builtinTextStart;
1651 uintptr_t builtinTextEnd;
1652
1653 flags.builtin = true;
1654 builtinKmodIdx = addressNum->unsigned32BitValue();
1655 assert(builtinKmodIdx < gBuiltinKmodsCount);
1656
1657 builtinTextStart = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx];
1658 builtinTextEnd = ((uintptr_t *)gBuiltinKmodsSectionStart->addr)[builtinKmodIdx + 1];
1659
1660 kmod_info = ((kmod_info_t **)gBuiltinKmodsSectionInfo->addr)[builtinKmodIdx];
1661 kmod_info->address = builtinTextStart;
1662 kmod_info->size = builtinTextEnd - builtinTextStart;
1663 }
1664
1665 /* If the plist has a UUID for an interface, save that off.
1666 */
1667 if (isInterface()) {
1668 interfaceUUID = OSDynamicCast(OSData,
1669 anInfoDict->getObject(kPrelinkInterfaceUUIDKey));
1670 if (interfaceUUID) {
1671 interfaceUUID->retain();
1672 anInfoDict->removeObject(kPrelinkInterfaceUUIDKey);
1673 }
1674 }
1675
1676 result = slidePrelinkedExecutable(doCoalesedSlides);
1677 if (result != kOSReturnSuccess) {
1678 goto finish;
1679 }
1680
1681 if (doCoalesedSlides == false) {
1682 /* set VM protections now, wire later at kext load */
1683 result = setVMAttributes(true, false);
1684 if (result != KERN_SUCCESS) {
1685 goto finish;
1686 }
1687 }
1688
1689 flags.prelinked = true;
1690
1691 /* If we created a kext from prelink info,
1692 * we must be booting from a prelinked kernel.
1693 */
1694 sPrelinkBoot = true;
1695
1696 result = registerIdentifier();
1697
1698 finish:
1699 OSSafeReleaseNULL(prelinkedExecutable);
1700
1701 return result;
1702 }
1703
1704 /*********************************************************************
1705 *********************************************************************/
1706 /* static */
1707 void
1708 OSKext::setAllVMAttributes(void)
1709 {
1710 OSCollectionIterator * kextIterator = NULL;// must release
1711 const OSSymbol * thisID = NULL;// do not release
1712
1713 IORecursiveLockLock(sKextLock);
1714
1715 kextIterator = OSCollectionIterator::withCollection(sKextsByID);
1716 if (!kextIterator) {
1717 goto finish;
1718 }
1719
1720 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
1721 OSKext * thisKext;// do not release
1722
1723 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
1724 if (!thisKext || thisKext->isInterface() || !thisKext->declaresExecutable()) {
1725 continue;
1726 }
1727
1728 /* set VM protections now, wire later at kext load */
1729 thisKext->setVMAttributes(true, false);
1730 }
1731
1732 finish:
1733 IORecursiveLockUnlock(sKextLock);
1734 OSSafeReleaseNULL(kextIterator);
1735
1736 return;
1737 }
1738
1739 /*********************************************************************
1740 *********************************************************************/
1741 OSKext *
1742 OSKext::withBooterData(
1743 OSString * deviceTreeName,
1744 OSData * booterData)
1745 {
1746 OSKext * newKext = new OSKext;
1747
1748 if (newKext && !newKext->initWithBooterData(deviceTreeName, booterData)) {
1749 newKext->release();
1750 return NULL;
1751 }
1752
1753 return newKext;
1754 }
1755
1756 /*********************************************************************
1757 *********************************************************************/
1758 typedef struct _BooterKextFileInfo {
1759 uint32_t infoDictPhysAddr;
1760 uint32_t infoDictLength;
1761 uint32_t executablePhysAddr;
1762 uint32_t executableLength;
1763 uint32_t bundlePathPhysAddr;
1764 uint32_t bundlePathLength;
1765 } _BooterKextFileInfo;
1766
1767 bool
1768 OSKext::initWithBooterData(
1769 OSString * deviceTreeName,
1770 OSData * booterData)
1771 {
1772 bool result = false;
1773 _BooterKextFileInfo * kextFileInfo = NULL;// do not free
1774 char * infoDictAddr = NULL;// do not free
1775 void * executableAddr = NULL;// do not free
1776 char * bundlePathAddr = NULL;// do not free
1777
1778 OSObject * parsedXML = NULL;// must release
1779 OSDictionary * theInfoDict = NULL;// do not release
1780 OSString * kextPath = NULL;// must release
1781 OSString * errorString = NULL;// must release
1782 OSData * executable = NULL;// must release
1783
1784 if (!super::init()) {
1785 goto finish;
1786 }
1787
1788 kextFileInfo = (_BooterKextFileInfo *)booterData->getBytesNoCopy();
1789 if (!kextFileInfo) {
1790 OSKextLog(this,
1791 kOSKextLogErrorLevel |
1792 kOSKextLogGeneralFlag,
1793 "No booter-provided data for kext device tree entry %s.",
1794 deviceTreeName->getCStringNoCopy());
1795 goto finish;
1796 }
1797
1798 /* The info plist must exist or we can't read the kext.
1799 */
1800 if (!kextFileInfo->infoDictPhysAddr || !kextFileInfo->infoDictLength) {
1801 OSKextLog(this,
1802 kOSKextLogErrorLevel |
1803 kOSKextLogGeneralFlag,
1804 "No kext info dictionary for booter device tree entry %s.",
1805 deviceTreeName->getCStringNoCopy());
1806 goto finish;
1807 }
1808
1809 infoDictAddr = (char *)ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
1810 if (!infoDictAddr) {
1811 OSKextLog(this,
1812 kOSKextLogErrorLevel |
1813 kOSKextLogGeneralFlag,
1814 "Can't translate physical address 0x%x of kext info dictionary "
1815 "for device tree entry %s.",
1816 (int)kextFileInfo->infoDictPhysAddr,
1817 deviceTreeName->getCStringNoCopy());
1818 goto finish;
1819 }
1820
1821 parsedXML = OSUnserializeXML(infoDictAddr, &errorString);
1822 if (parsedXML) {
1823 theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
1824 }
1825 if (!theInfoDict) {
1826 const char * errorCString = "(unknown error)";
1827
1828 if (errorString && errorString->getCStringNoCopy()) {
1829 errorCString = errorString->getCStringNoCopy();
1830 } else if (parsedXML) {
1831 errorCString = "not a dictionary";
1832 }
1833 OSKextLog(this,
1834 kOSKextLogErrorLevel |
1835 kOSKextLogGeneralFlag,
1836 "Error unserializing info dictionary for device tree entry %s: %s.",
1837 deviceTreeName->getCStringNoCopy(), errorCString);
1838 goto finish;
1839 }
1840
1841 /* A bundle path is not mandatory.
1842 */
1843 if (kextFileInfo->bundlePathPhysAddr && kextFileInfo->bundlePathLength) {
1844 bundlePathAddr = (char *)ml_static_ptovirt(kextFileInfo->bundlePathPhysAddr);
1845 if (!bundlePathAddr) {
1846 OSKextLog(this,
1847 kOSKextLogErrorLevel |
1848 kOSKextLogGeneralFlag,
1849 "Can't translate physical address 0x%x of kext bundle path "
1850 "for device tree entry %s.",
1851 (int)kextFileInfo->bundlePathPhysAddr,
1852 deviceTreeName->getCStringNoCopy());
1853 goto finish;
1854 }
1855 bundlePathAddr[kextFileInfo->bundlePathLength - 1] = '\0'; // just in case!
1856
1857 kextPath = OSString::withCString(bundlePathAddr);
1858 if (!kextPath) {
1859 OSKextLog(this,
1860 kOSKextLogErrorLevel |
1861 kOSKextLogGeneralFlag,
1862 "Failed to create wrapper for device tree entry %s kext path %s.",
1863 deviceTreeName->getCStringNoCopy(), bundlePathAddr);
1864 goto finish;
1865 }
1866 }
1867
1868 if (!setInfoDictionaryAndPath(theInfoDict, kextPath)) {
1869 goto finish;
1870 }
1871
1872 /* An executable is not mandatory.
1873 */
1874 if (kextFileInfo->executablePhysAddr && kextFileInfo->executableLength) {
1875 executableAddr = (void *)ml_static_ptovirt(kextFileInfo->executablePhysAddr);
1876 if (!executableAddr) {
1877 OSKextLog(this,
1878 kOSKextLogErrorLevel |
1879 kOSKextLogGeneralFlag,
1880 "Can't translate physical address 0x%x of kext executable "
1881 "for device tree entry %s.",
1882 (int)kextFileInfo->executablePhysAddr,
1883 deviceTreeName->getCStringNoCopy());
1884 goto finish;
1885 }
1886
1887 executable = OSData::withBytesNoCopy(executableAddr,
1888 kextFileInfo->executableLength);
1889 if (!executable) {
1890 OSKextLog(this,
1891 kOSKextLogErrorLevel |
1892 kOSKextLogGeneralFlag,
1893 "Failed to create executable wrapper for device tree entry %s.",
1894 deviceTreeName->getCStringNoCopy());
1895 goto finish;
1896 }
1897
1898 /* A kext with an executable needs to retain the whole booterData
1899 * object to keep the executable in memory.
1900 */
1901 if (!setExecutable(executable, booterData)) {
1902 OSKextLog(this,
1903 kOSKextLogErrorLevel |
1904 kOSKextLogGeneralFlag,
1905 "Failed to set kext executable for device tree entry %s.",
1906 deviceTreeName->getCStringNoCopy());
1907 goto finish;
1908 }
1909 }
1910
1911 result = registerIdentifier();
1912
1913 finish:
1914 OSSafeReleaseNULL(parsedXML);
1915 OSSafeReleaseNULL(kextPath);
1916 OSSafeReleaseNULL(errorString);
1917 OSSafeReleaseNULL(executable);
1918
1919 return result;
1920 }
1921
1922 /*********************************************************************
1923 *********************************************************************/
1924 bool
1925 OSKext::registerIdentifier(void)
1926 {
1927 bool result = false;
1928 OSKext * existingKext = NULL;// do not release
1929 bool existingIsLoaded = false;
1930 bool existingIsPrelinked = false;
1931 OSKextVersion newVersion = -1;
1932 OSKextVersion existingVersion = -1;
1933 char newVersionCString[kOSKextVersionMaxLength];
1934 char existingVersionCString[kOSKextVersionMaxLength];
1935 OSData * newUUID = NULL;// must release
1936 OSData * existingUUID = NULL;// must release
1937
1938 IORecursiveLockLock(sKextLock);
1939
1940 /* Get the new kext's version for checks & log messages.
1941 */
1942 newVersion = getVersion();
1943 OSKextVersionGetString(newVersion, newVersionCString,
1944 kOSKextVersionMaxLength);
1945
1946 /* If we don't have an existing kext with this identifier,
1947 * just record the new kext and we're done!
1948 */
1949 existingKext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID));
1950 if (!existingKext) {
1951 sKextsByID->setObject(bundleID, this);
1952 result = true;
1953 goto finish;
1954 }
1955
1956 /* Get the existing kext's version for checks & log messages.
1957 */
1958 existingVersion = existingKext->getVersion();
1959 OSKextVersionGetString(existingVersion,
1960 existingVersionCString, kOSKextVersionMaxLength);
1961
1962 existingIsLoaded = existingKext->isLoaded();
1963 existingIsPrelinked = existingKext->isPrelinked();
1964
1965 /* If we have a kext with this identifier that's already loaded/prelinked,
1966 * we can't use the new one, but let's be really thorough and check how
1967 * the two are related for a precise diagnostic log message.
1968 *
1969 * Note that user space can't find out about nonloaded prelinked kexts,
1970 * so in this case we log a message when new & existing are equivalent
1971 * at the step rather than warning level, because we are always going
1972 * be getting a copy of the kext in the user load request mkext.
1973 */
1974 if (existingIsLoaded || existingIsPrelinked) {
1975 bool sameVersion = (newVersion == existingVersion);
1976 bool sameExecutable = true; // assume true unless we have UUIDs
1977
1978 /* Only get the UUID if the existing kext is loaded. Doing so
1979 * might have to uncompress an mkext executable and we shouldn't
1980 * take that hit when neither kext is loaded.
1981 */
1982 newUUID = copyUUID();
1983 existingUUID = existingKext->copyUUID();
1984
1985 /* I'm entirely too paranoid about checking equivalence of executables,
1986 * but I remember nasty problems with it in the past.
1987 *
1988 * - If we have UUIDs for both kexts, compare them.
1989 * - If only one kext has a UUID, they're definitely different.
1990 */
1991 if (newUUID && existingUUID) {
1992 sameExecutable = newUUID->isEqualTo(existingUUID);
1993 } else if (newUUID || existingUUID) {
1994 sameExecutable = false;
1995 }
1996
1997 if (!newUUID && !existingUUID) {
1998 /* If there are no UUIDs, we can't really tell that the executables
1999 * are *different* without a lot of work; the loaded kext's
2000 * unrelocated executable is no longer around (and we never had it
2001 * in-kernel for a prelinked kext). We certainly don't want to do
2002 * a whole fake link for the new kext just to compare, either.
2003 */
2004
2005 OSKextVersionGetString(version, newVersionCString,
2006 sizeof(newVersionCString));
2007 OSKextLog(this,
2008 kOSKextLogWarningLevel |
2009 kOSKextLogKextBookkeepingFlag,
2010 "Notice - new kext %s, v%s matches %s kext "
2011 "but can't determine if executables are the same (no UUIDs).",
2012 getIdentifierCString(),
2013 newVersionCString,
2014 (existingIsLoaded ? "loaded" : "prelinked"));
2015 }
2016
2017 if (sameVersion && sameExecutable) {
2018 OSKextLog(this,
2019 (existingIsLoaded ? kOSKextLogWarningLevel : kOSKextLogStepLevel) |
2020 kOSKextLogKextBookkeepingFlag,
2021 "Refusing new kext %s, v%s: a %s copy is already present "
2022 "(same version and executable).",
2023 getIdentifierCString(), newVersionCString,
2024 (existingIsLoaded ? "loaded" : "prelinked"));
2025 } else {
2026 if (!sameVersion) {
2027 /* This condition is significant so log it under warnings.
2028 */
2029 OSKextLog(this,
2030 kOSKextLogWarningLevel |
2031 kOSKextLogKextBookkeepingFlag,
2032 "Refusing new kext %s, v%s: already have %s v%s.",
2033 getIdentifierCString(),
2034 newVersionCString,
2035 (existingIsLoaded ? "loaded" : "prelinked"),
2036 existingVersionCString);
2037 } else {
2038 /* This condition is significant so log it under warnings.
2039 */
2040 OSKextLog(this,
2041 kOSKextLogWarningLevel | kOSKextLogKextBookkeepingFlag,
2042 "Refusing new kext %s, v%s: a %s copy with a different "
2043 "executable UUID is already present.",
2044 getIdentifierCString(), newVersionCString,
2045 (existingIsLoaded ? "loaded" : "prelinked"));
2046 }
2047 }
2048 goto finish;
2049 } /* if (existingIsLoaded || existingIsPrelinked) */
2050
2051 /* We have two nonloaded/nonprelinked kexts, so our decision depends on whether
2052 * user loads are happening or if we're still in early boot. User agents are
2053 * supposed to resolve dependencies topside and include only the exact
2054 * kexts needed; so we always accept the new kext (in fact we should never
2055 * see an older unloaded copy hanging around).
2056 */
2057 if (sUserLoadsActive) {
2058 sKextsByID->setObject(bundleID, this);
2059 result = true;
2060
2061 OSKextLog(this,
2062 kOSKextLogStepLevel |
2063 kOSKextLogKextBookkeepingFlag,
2064 "Dropping old copy of kext %s (v%s) for newly-added (v%s).",
2065 getIdentifierCString(),
2066 existingVersionCString,
2067 newVersionCString);
2068
2069 goto finish;
2070 }
2071
2072 /* During early boot, the kext with the highest version always wins out.
2073 * Prelinked kernels will never hit this, but mkexts and booter-read
2074 * kexts might have duplicates.
2075 */
2076 if (newVersion > existingVersion) {
2077 sKextsByID->setObject(bundleID, this);
2078 result = true;
2079
2080 OSKextLog(this,
2081 kOSKextLogStepLevel |
2082 kOSKextLogKextBookkeepingFlag,
2083 "Dropping lower version (v%s) of registered kext %s for higher (v%s).",
2084 existingVersionCString,
2085 getIdentifierCString(),
2086 newVersionCString);
2087 } else {
2088 OSKextLog(this,
2089 kOSKextLogStepLevel |
2090 kOSKextLogKextBookkeepingFlag,
2091 "Kext %s is already registered with a higher/same version (v%s); "
2092 "dropping newly-added (v%s).",
2093 getIdentifierCString(),
2094 existingVersionCString,
2095 newVersionCString);
2096 }
2097
2098 /* result has been set appropriately by now. */
2099
2100 finish:
2101
2102 IORecursiveLockUnlock(sKextLock);
2103
2104 if (result) {
2105 OSKextLog(this,
2106 kOSKextLogStepLevel |
2107 kOSKextLogKextBookkeepingFlag,
2108 "Kext %s, v%s registered and available for loading.",
2109 getIdentifierCString(), newVersionCString);
2110 }
2111
2112 OSSafeReleaseNULL(newUUID);
2113 OSSafeReleaseNULL(existingUUID);
2114
2115 return result;
2116 }
2117
2118 /*********************************************************************
2119 * Does the bare minimum validation to look up a kext.
2120 * All other validation is done on the spot as needed.
2121 **********************************************************************/
2122 bool
2123 OSKext::setInfoDictionaryAndPath(
2124 OSDictionary * aDictionary,
2125 OSString * aPath)
2126 {
2127 bool result = false;
2128 OSString * bundleIDString = NULL;// do not release
2129 OSString * versionString = NULL;// do not release
2130 OSString * compatibleVersionString = NULL;// do not release
2131 const char * versionCString = NULL;// do not free
2132 const char * compatibleVersionCString = NULL;// do not free
2133 OSBoolean * scratchBool = NULL;// do not release
2134 OSDictionary * scratchDict = NULL;// do not release
2135
2136 if (infoDict) {
2137 panic("Attempt to set info dictionary on a kext "
2138 "that already has one (%s).",
2139 getIdentifierCString());
2140 }
2141
2142 if (!aDictionary || !OSDynamicCast(OSDictionary, aDictionary)) {
2143 goto finish;
2144 }
2145
2146 infoDict = aDictionary;
2147 infoDict->retain();
2148
2149 /* Check right away if the info dictionary has any log flags.
2150 */
2151 scratchBool = OSDynamicCast(OSBoolean,
2152 getPropertyForHostArch(kOSBundleEnableKextLoggingKey));
2153 if (scratchBool == kOSBooleanTrue) {
2154 flags.loggingEnabled = 1;
2155 }
2156
2157 /* The very next thing to get is the bundle identifier. Unlike
2158 * in user space, a kext with no bundle identifier gets axed
2159 * immediately.
2160 */
2161 bundleIDString = OSDynamicCast(OSString,
2162 getPropertyForHostArch(kCFBundleIdentifierKey));
2163 if (!bundleIDString) {
2164 OSKextLog(this,
2165 kOSKextLogErrorLevel |
2166 kOSKextLogValidationFlag,
2167 "CFBundleIdentifier missing/invalid type in kext %s.",
2168 aPath ? aPath->getCStringNoCopy() : "(unknown)");
2169 goto finish;
2170 }
2171 bundleID = OSSymbol::withString(bundleIDString);
2172 if (!bundleID) {
2173 OSKextLog(this,
2174 kOSKextLogErrorLevel |
2175 kOSKextLogValidationFlag,
2176 "Can't copy bundle identifier as symbol for kext %s.",
2177 bundleIDString->getCStringNoCopy());
2178 goto finish;
2179 }
2180
2181 /* Save the path if we got one (it should always be available but it's
2182 * just something nice to have for bookkeeping).
2183 */
2184 if (aPath) {
2185 path = aPath;
2186 path->retain();
2187 }
2188
2189 /*****
2190 * Minimal validation to initialize. We'll do other validation on the spot.
2191 */
2192 if (bundleID->getLength() >= KMOD_MAX_NAME) {
2193 OSKextLog(this,
2194 kOSKextLogErrorLevel |
2195 kOSKextLogValidationFlag,
2196 "Kext %s error - CFBundleIdentifier over max length %d.",
2197 getIdentifierCString(), KMOD_MAX_NAME - 1);
2198 goto finish;
2199 }
2200
2201 version = compatibleVersion = -1;
2202
2203 versionString = OSDynamicCast(OSString,
2204 getPropertyForHostArch(kCFBundleVersionKey));
2205 if (!versionString) {
2206 OSKextLog(this,
2207 kOSKextLogErrorLevel |
2208 kOSKextLogValidationFlag,
2209 "Kext %s error - CFBundleVersion missing/invalid type.",
2210 getIdentifierCString());
2211 goto finish;
2212 }
2213 versionCString = versionString->getCStringNoCopy();
2214 version = OSKextParseVersionString(versionCString);
2215 if (version < 0) {
2216 OSKextLog(this,
2217 kOSKextLogErrorLevel |
2218 kOSKextLogValidationFlag,
2219 "Kext %s error - CFBundleVersion bad value '%s'.",
2220 getIdentifierCString(), versionCString);
2221 goto finish;
2222 }
2223
2224 compatibleVersion = -1; // set to illegal value for kexts that don't have
2225
2226 compatibleVersionString = OSDynamicCast(OSString,
2227 getPropertyForHostArch(kOSBundleCompatibleVersionKey));
2228 if (compatibleVersionString) {
2229 compatibleVersionCString = compatibleVersionString->getCStringNoCopy();
2230 compatibleVersion = OSKextParseVersionString(compatibleVersionCString);
2231 if (compatibleVersion < 0) {
2232 OSKextLog(this,
2233 kOSKextLogErrorLevel |
2234 kOSKextLogValidationFlag,
2235 "Kext %s error - OSBundleCompatibleVersion bad value '%s'.",
2236 getIdentifierCString(), compatibleVersionCString);
2237 goto finish;
2238 }
2239
2240 if (compatibleVersion > version) {
2241 OSKextLog(this,
2242 kOSKextLogErrorLevel |
2243 kOSKextLogValidationFlag,
2244 "Kext %s error - %s %s > %s %s (must be <=).",
2245 getIdentifierCString(),
2246 kOSBundleCompatibleVersionKey, compatibleVersionCString,
2247 kCFBundleVersionKey, versionCString);
2248 goto finish;
2249 }
2250 }
2251
2252 /* Check to see if this kext is in exclude list */
2253 if (isInExcludeList()) {
2254 OSKextLog(this,
2255 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
2256 "Kext %s is in exclude list, not loadable",
2257 getIdentifierCString());
2258 goto finish;
2259 }
2260
2261 /* Set flags for later use if the infoDict gets flushed. We only
2262 * check for true values, not false ones(!)
2263 */
2264 scratchBool = OSDynamicCast(OSBoolean,
2265 getPropertyForHostArch(kOSBundleIsInterfaceKey));
2266 if (scratchBool == kOSBooleanTrue) {
2267 flags.interface = 1;
2268 }
2269
2270 scratchBool = OSDynamicCast(OSBoolean,
2271 getPropertyForHostArch(kOSKernelResourceKey));
2272 if (scratchBool == kOSBooleanTrue) {
2273 flags.kernelComponent = 1;
2274 flags.interface = 1; // xxx - hm. the kernel itself isn't an interface...
2275 flags.started = 1;
2276
2277 /* A kernel component has one implicit dependency on the kernel.
2278 */
2279 flags.hasAllDependencies = 1;
2280 }
2281
2282 /* Make sure common string values in personalities are uniqued to OSSymbols.
2283 */
2284 scratchDict = OSDynamicCast(OSDictionary,
2285 getPropertyForHostArch(kIOKitPersonalitiesKey));
2286 if (scratchDict) {
2287 uniquePersonalityProperties(scratchDict);
2288 }
2289
2290 result = true;
2291
2292 finish:
2293
2294 return result;
2295 }
2296
2297 /*********************************************************************
2298 * Not used for prelinked kernel boot as there is no unrelocated
2299 * executable.
2300 *********************************************************************/
2301 bool
2302 OSKext::setExecutable(
2303 OSData * anExecutable,
2304 OSData * externalData,
2305 bool externalDataIsMkext)
2306 {
2307 bool result = false;
2308 const char * executableKey = NULL; // do not free
2309
2310 if (!anExecutable) {
2311 infoDict->removeObject(_kOSKextExecutableKey);
2312 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
2313 infoDict->removeObject(_kOSKextExecutableExternalDataKey);
2314 result = true;
2315 goto finish;
2316 }
2317
2318 if (infoDict->getObject(_kOSKextExecutableKey) ||
2319 infoDict->getObject(_kOSKextMkextExecutableReferenceKey)) {
2320 panic("Attempt to set an executable on a kext "
2321 "that already has one (%s).",
2322 getIdentifierCString());
2323 goto finish;
2324 }
2325
2326 if (externalDataIsMkext) {
2327 executableKey = _kOSKextMkextExecutableReferenceKey;
2328 } else {
2329 executableKey = _kOSKextExecutableKey;
2330 }
2331
2332 if (anExecutable) {
2333 infoDict->setObject(executableKey, anExecutable);
2334 if (externalData) {
2335 infoDict->setObject(_kOSKextExecutableExternalDataKey, externalData);
2336 }
2337 }
2338
2339 result = true;
2340
2341 finish:
2342 return result;
2343 }
2344
2345 /*********************************************************************
2346 *********************************************************************/
2347 static void
2348 uniqueStringPlistProperty(OSDictionary * dict, const char * key)
2349 {
2350 OSString * stringValue = NULL;// do not release
2351 const OSSymbol * symbolValue = NULL; // must release
2352
2353 stringValue = OSDynamicCast(OSString, dict->getObject(key));
2354 if (!stringValue) {
2355 goto finish;
2356 }
2357
2358 symbolValue = OSSymbol::withString(stringValue);
2359 if (!symbolValue) {
2360 goto finish;
2361 }
2362
2363 dict->setObject(key, symbolValue);
2364
2365 finish:
2366 if (symbolValue) {
2367 symbolValue->release();
2368 }
2369
2370 return;
2371 }
2372
2373 /*********************************************************************
2374 *********************************************************************/
2375 static void
2376 uniqueStringPlistProperty(OSDictionary * dict, const OSString * key)
2377 {
2378 OSString * stringValue = NULL;// do not release
2379 const OSSymbol * symbolValue = NULL; // must release
2380
2381 stringValue = OSDynamicCast(OSString, dict->getObject(key));
2382 if (!stringValue) {
2383 goto finish;
2384 }
2385
2386 symbolValue = OSSymbol::withString(stringValue);
2387 if (!symbolValue) {
2388 goto finish;
2389 }
2390
2391 dict->setObject(key, symbolValue);
2392
2393 finish:
2394 if (symbolValue) {
2395 symbolValue->release();
2396 }
2397
2398 return;
2399 }
2400
2401 /*********************************************************************
2402 * Replace common personality property values with uniqued instances
2403 * to save on wired memory.
2404 *********************************************************************/
2405 /* static */
2406 void
2407 OSKext::uniquePersonalityProperties(OSDictionary * personalityDict)
2408 {
2409 /* Properties every personality has.
2410 */
2411 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKey);
2412 uniqueStringPlistProperty(personalityDict, kIOProviderClassKey);
2413 uniqueStringPlistProperty(personalityDict, gIOClassKey);
2414 if (personalityDict->getObject(kCFBundleIdentifierKernelKey)) {
2415 uniqueStringPlistProperty(personalityDict, kCFBundleIdentifierKernelKey);
2416 } else {
2417 personalityDict->setObject(kCFBundleIdentifierKernelKey, personalityDict->getObject(kCFBundleIdentifierKey));
2418 }
2419
2420 /* Other commonly used properties.
2421 */
2422 uniqueStringPlistProperty(personalityDict, gIOMatchCategoryKey);
2423 uniqueStringPlistProperty(personalityDict, gIOResourceMatchKey);
2424 uniqueStringPlistProperty(personalityDict, gIOUserClientClassKey);
2425
2426 uniqueStringPlistProperty(personalityDict, "HIDDefaultBehavior");
2427 uniqueStringPlistProperty(personalityDict, "HIDPointerAccelerationType");
2428 uniqueStringPlistProperty(personalityDict, "HIDRemoteControlType");
2429 uniqueStringPlistProperty(personalityDict, "HIDScrollAccelerationType");
2430 uniqueStringPlistProperty(personalityDict, "IOPersonalityPublisher");
2431 uniqueStringPlistProperty(personalityDict, "Physical Interconnect");
2432 uniqueStringPlistProperty(personalityDict, "Physical Interconnect Location");
2433 uniqueStringPlistProperty(personalityDict, "Vendor");
2434 uniqueStringPlistProperty(personalityDict, "Vendor Identification");
2435 uniqueStringPlistProperty(personalityDict, "Vendor Name");
2436 uniqueStringPlistProperty(personalityDict, "bConfigurationValue");
2437 uniqueStringPlistProperty(personalityDict, "bInterfaceNumber");
2438 uniqueStringPlistProperty(personalityDict, "idProduct");
2439
2440 return;
2441 }
2442
2443 /*********************************************************************
2444 *********************************************************************/
2445 void
2446 OSKext::free(void)
2447 {
2448 if (isLoaded()) {
2449 panic("Attempt to free loaded kext %s.", getIdentifierCString());
2450 }
2451
2452 OSSafeReleaseNULL(infoDict);
2453 OSSafeReleaseNULL(bundleID);
2454 OSSafeReleaseNULL(path);
2455 OSSafeReleaseNULL(executableRelPath);
2456 OSSafeReleaseNULL(userExecutableRelPath);
2457 OSSafeReleaseNULL(dependencies);
2458 OSSafeReleaseNULL(linkedExecutable);
2459 OSSafeReleaseNULL(metaClasses);
2460 OSSafeReleaseNULL(interfaceUUID);
2461 OSSafeReleaseNULL(driverKitUUID);
2462
2463 if (isInterface() && kmod_info) {
2464 kfree(kmod_info, sizeof(kmod_info_t));
2465 }
2466
2467 super::free();
2468 return;
2469 }
2470
2471 #if PRAGMA_MARK
2472 #pragma mark Mkext files
2473 #endif
2474 /*********************************************************************
2475 *********************************************************************/
2476 OSReturn
2477 OSKext::readMkextArchive(OSData * mkextData,
2478 uint32_t * checksumPtr)
2479 {
2480 OSReturn result = kOSKextReturnBadData;
2481 uint32_t mkextLength = 0;
2482 mkext_header * mkextHeader = NULL;// do not free
2483 uint32_t mkextVersion = 0;
2484
2485 /* Note default return of kOSKextReturnBadData above.
2486 */
2487 mkextLength = mkextData->getLength();
2488 if (mkextLength < sizeof(mkext_basic_header)) {
2489 OSKextLog(/* kext */ NULL,
2490 kOSKextLogErrorLevel |
2491 kOSKextLogArchiveFlag,
2492 "Mkext archive too small to be valid.");
2493 goto finish;
2494 }
2495
2496 mkextHeader = (mkext_header *)mkextData->getBytesNoCopy();
2497
2498 if (MKEXT_GET_MAGIC(mkextHeader) != MKEXT_MAGIC ||
2499 MKEXT_GET_SIGNATURE(mkextHeader) != MKEXT_SIGN) {
2500 OSKextLog(/* kext */ NULL,
2501 kOSKextLogErrorLevel |
2502 kOSKextLogArchiveFlag,
2503 "Mkext archive has invalid magic or signature.");
2504 goto finish;
2505 }
2506
2507 if (MKEXT_GET_LENGTH(mkextHeader) != mkextLength) {
2508 OSKextLog(/* kext */ NULL,
2509 kOSKextLogErrorLevel |
2510 kOSKextLogArchiveFlag,
2511 "Mkext archive recorded length doesn't match actual file length.");
2512 goto finish;
2513 }
2514
2515 mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2516
2517 if (mkextVersion == MKEXT_VERS_2) {
2518 result = OSKext::readMkext2Archive(mkextData, NULL, checksumPtr);
2519 } else {
2520 OSKextLog(/* kext */ NULL,
2521 kOSKextLogErrorLevel |
2522 kOSKextLogArchiveFlag,
2523 "Mkext archive of unsupported mkext version 0x%x.", mkextVersion);
2524 result = kOSKextReturnUnsupported;
2525 }
2526
2527 finish:
2528 return result;
2529 }
2530
2531 /*********************************************************************
2532 * Assumes magic, signature, version, length have been checked.
2533 * xxx - need to add further bounds checking for each file entry
2534 *
2535 * Should keep track of all kexts created so far, and if we hit a
2536 * fatal error halfway through, remove those kexts. If we've dropped
2537 * an older version that had already been read, whoops! Might want to
2538 * add a level of buffering?
2539 *********************************************************************/
2540 /* static */
2541 OSReturn
2542 OSKext::readMkext2Archive(
2543 OSData * mkextData,
2544 OSDictionary ** mkextPlistOut,
2545 uint32_t * checksumPtr)
2546 {
2547 OSReturn result = kOSReturnError;
2548 uint32_t mkextLength;
2549 mkext2_header * mkextHeader = NULL;// do not free
2550 void * mkextEnd = NULL;// do not free
2551 uint32_t mkextVersion;
2552 uint8_t * crc_address = NULL;
2553 uint32_t checksum;
2554 uint32_t mkextPlistOffset;
2555 uint32_t mkextPlistCompressedSize;
2556 char * mkextPlistEnd = NULL;// do not free
2557 uint32_t mkextPlistFullSize;
2558 OSString * errorString = NULL;// must release
2559 OSData * mkextPlistUncompressedData = NULL;// must release
2560 const char * mkextPlistDataBuffer = NULL;// do not free
2561 OSObject * parsedXML = NULL;// must release
2562 OSDictionary * mkextPlist = NULL;// do not release
2563 OSArray * mkextInfoDictArray = NULL;// do not release
2564 uint32_t count, i;
2565
2566 mkextLength = mkextData->getLength();
2567 mkextHeader = (mkext2_header *)mkextData->getBytesNoCopy();
2568 mkextEnd = (char *)mkextHeader + mkextLength;
2569 mkextVersion = MKEXT_GET_VERSION(mkextHeader);
2570
2571 crc_address = (u_int8_t *)&mkextHeader->version;
2572 checksum = mkext_adler32(crc_address,
2573 (uintptr_t)mkextHeader +
2574 MKEXT_GET_LENGTH(mkextHeader) - (uintptr_t)crc_address);
2575
2576 if (MKEXT_GET_CHECKSUM(mkextHeader) != checksum) {
2577 OSKextLog(/* kext */ NULL,
2578 kOSKextLogErrorLevel |
2579 kOSKextLogArchiveFlag,
2580 "Mkext archive has bad checksum.");
2581 result = kOSKextReturnBadData;
2582 goto finish;
2583 }
2584
2585 if (checksumPtr) {
2586 *checksumPtr = checksum;
2587 }
2588
2589 /* Check that the CPU type & subtype match that of the running kernel. */
2590 if (MKEXT_GET_CPUTYPE(mkextHeader) == (UInt32)CPU_TYPE_ANY) {
2591 OSKextLog(/* kext */ NULL,
2592 kOSKextLogErrorLevel |
2593 kOSKextLogArchiveFlag,
2594 "Mkext archive must have a specific CPU type.");
2595 result = kOSKextReturnBadData;
2596 goto finish;
2597 } else {
2598 if ((UInt32)_mh_execute_header.cputype !=
2599 MKEXT_GET_CPUTYPE(mkextHeader)) {
2600 OSKextLog(/* kext */ NULL,
2601 kOSKextLogErrorLevel |
2602 kOSKextLogArchiveFlag,
2603 "Mkext archive does not match the running kernel's CPU type.");
2604 result = kOSKextReturnArchNotFound;
2605 goto finish;
2606 }
2607 }
2608
2609 mkextPlistOffset = MKEXT2_GET_PLIST(mkextHeader);
2610 mkextPlistCompressedSize = MKEXT2_GET_PLIST_COMPSIZE(mkextHeader);
2611 mkextPlistEnd = (char *)mkextHeader + mkextPlistOffset +
2612 mkextPlistCompressedSize;
2613 if (mkextPlistEnd > mkextEnd) {
2614 OSKextLog(/* kext */ NULL,
2615 kOSKextLogErrorLevel |
2616 kOSKextLogArchiveFlag,
2617 "Mkext archive file overrun.");
2618 result = kOSKextReturnBadData;
2619 }
2620
2621 mkextPlistFullSize = MKEXT2_GET_PLIST_FULLSIZE(mkextHeader);
2622 if (mkextPlistCompressedSize) {
2623 mkextPlistUncompressedData = sKernelKext->extractMkext2FileData(
2624 (UInt8 *)mkextHeader + mkextPlistOffset,
2625 "plist",
2626 mkextPlistCompressedSize, mkextPlistFullSize);
2627 if (!mkextPlistUncompressedData) {
2628 goto finish;
2629 }
2630 mkextPlistDataBuffer = (const char *)
2631 mkextPlistUncompressedData->getBytesNoCopy();
2632 } else {
2633 mkextPlistDataBuffer = (const char *)mkextHeader + mkextPlistOffset;
2634 }
2635
2636 /* IOCFSerialize added a nul byte to the end of the string. Very nice of it.
2637 */
2638 parsedXML = OSUnserializeXML(mkextPlistDataBuffer, &errorString);
2639 if (parsedXML) {
2640 mkextPlist = OSDynamicCast(OSDictionary, parsedXML);
2641 }
2642 if (!mkextPlist) {
2643 const char * errorCString = "(unknown error)";
2644
2645 if (errorString && errorString->getCStringNoCopy()) {
2646 errorCString = errorString->getCStringNoCopy();
2647 } else if (parsedXML) {
2648 errorCString = "not a dictionary";
2649 }
2650 OSKextLog(/* kext */ NULL,
2651 kOSKextLogErrorLevel |
2652 kOSKextLogArchiveFlag,
2653 "Error unserializing mkext plist: %s.", errorCString);
2654 goto finish;
2655 }
2656
2657 /* If the caller needs the plist, hand it back and retain it.
2658 * (This function releases it at the end.)
2659 */
2660 if (mkextPlistOut) {
2661 *mkextPlistOut = mkextPlist;
2662 (*mkextPlistOut)->retain();
2663 }
2664
2665 mkextInfoDictArray = OSDynamicCast(OSArray,
2666 mkextPlist->getObject(kMKEXTInfoDictionariesKey));
2667 if (!mkextInfoDictArray) {
2668 OSKextLog(/* kext */ NULL,
2669 kOSKextLogErrorLevel |
2670 kOSKextLogArchiveFlag,
2671 "Mkext archive contains no kext info dictionaries.");
2672 goto finish;
2673 }
2674
2675 count = mkextInfoDictArray->getCount();
2676 for (i = 0; i < count; i++) {
2677 OSDictionary * infoDict;
2678
2679
2680 infoDict = OSDynamicCast(OSDictionary,
2681 mkextInfoDictArray->getObject(i));
2682
2683 /* Create the kext for the entry, then release it, because the
2684 * kext system keeps them around until explicitly removed.
2685 * Any creation/registration failures are already logged for us.
2686 */
2687 if (infoDict) {
2688 OSKext * newKext = OSKext::withMkext2Info(infoDict, mkextData);
2689 OSSafeReleaseNULL(newKext);
2690 }
2691 }
2692
2693 /* Even if we didn't keep any kexts from the mkext, we may have a load
2694 * request to process, so we are successful (no errors occurred).
2695 */
2696 result = kOSReturnSuccess;
2697
2698 finish:
2699
2700 OSSafeReleaseNULL(parsedXML);
2701 OSSafeReleaseNULL(mkextPlistUncompressedData);
2702 OSSafeReleaseNULL(errorString);
2703
2704 return result;
2705 }
2706
2707 /*********************************************************************
2708 *********************************************************************/
2709 /* static */
2710 OSKext *
2711 OSKext::withMkext2Info(
2712 OSDictionary * anInfoDict,
2713 OSData * mkextData)
2714 {
2715 OSKext * newKext = new OSKext;
2716
2717 if (newKext && !newKext->initWithMkext2Info(anInfoDict, mkextData)) {
2718 newKext->release();
2719 return NULL;
2720 }
2721
2722 return newKext;
2723 }
2724
2725 /*********************************************************************
2726 *********************************************************************/
2727 bool
2728 OSKext::initWithMkext2Info(
2729 OSDictionary * anInfoDict,
2730 OSData * mkextData)
2731 {
2732 bool result = false;
2733 OSString * kextPath = NULL;// do not release
2734 OSNumber * executableOffsetNum = NULL;// do not release
2735 OSCollectionIterator * iterator = NULL;// must release
2736 OSData * executable = NULL;// must release
2737
2738 if (anInfoDict == NULL || !super::init()) {
2739 goto finish;
2740 }
2741
2742 /* Get the path. Don't look for an arch-specific path property.
2743 */
2744 kextPath = OSDynamicCast(OSString,
2745 anInfoDict->getObject(kMKEXTBundlePathKey));
2746
2747 if (!setInfoDictionaryAndPath(anInfoDict, kextPath)) {
2748 goto finish;
2749 }
2750
2751 /* If we have a path to the executable, save it.
2752 */
2753 executableRelPath = OSDynamicCast(OSString,
2754 anInfoDict->getObject(kMKEXTExecutableRelativePathKey));
2755 if (executableRelPath) {
2756 executableRelPath->retain();
2757 }
2758
2759 /* Don't need the paths to be in the info dictionary any more.
2760 */
2761 anInfoDict->removeObject(kMKEXTBundlePathKey);
2762 anInfoDict->removeObject(kMKEXTExecutableRelativePathKey);
2763
2764 executableOffsetNum = OSDynamicCast(OSNumber,
2765 infoDict->getObject(kMKEXTExecutableKey));
2766 if (executableOffsetNum) {
2767 executable = createMkext2FileEntry(mkextData,
2768 executableOffsetNum, "executable");
2769 infoDict->removeObject(kMKEXTExecutableKey);
2770 if (!executable) {
2771 goto finish;
2772 }
2773 if (!setExecutable(executable, mkextData, true)) {
2774 goto finish;
2775 }
2776 }
2777
2778 result = registerIdentifier();
2779
2780 finish:
2781
2782 OSSafeReleaseNULL(executable);
2783 OSSafeReleaseNULL(iterator);
2784 return result;
2785 }
2786
2787 /*********************************************************************
2788 *********************************************************************/
2789 OSData *
2790 OSKext::createMkext2FileEntry(
2791 OSData * mkextData,
2792 OSNumber * offsetNum,
2793 const char * name)
2794 {
2795 OSData * result = NULL;
2796 MkextEntryRef entryRef;
2797 uint8_t * mkextBuffer = (uint8_t *)mkextData->getBytesNoCopy();
2798 uint32_t entryOffset = offsetNum->unsigned32BitValue();
2799
2800 result = OSData::withCapacity(sizeof(entryRef));
2801 if (!result) {
2802 goto finish;
2803 }
2804
2805 entryRef.mkext = (mkext_basic_header *)mkextBuffer;
2806 entryRef.fileinfo = mkextBuffer + entryOffset;
2807 if (!result->appendBytes(&entryRef, sizeof(entryRef))) {
2808 OSSafeReleaseNULL(result);
2809 goto finish;
2810 }
2811
2812 finish:
2813 if (!result) {
2814 OSKextLog(this,
2815 kOSKextLogErrorLevel |
2816 kOSKextLogArchiveFlag,
2817 "Can't create wrapper for mkext file entry '%s' of kext %s.",
2818 name, getIdentifierCString());
2819 }
2820 return result;
2821 }
2822
2823 /*********************************************************************
2824 *********************************************************************/
2825 extern "C" {
2826 static void * z_alloc(void *, u_int items, u_int size);
2827 static void z_free(void *, void *ptr);
2828
2829 typedef struct z_mem {
2830 uint32_t alloc_size;
2831 uint8_t data[0];
2832 } z_mem;
2833
2834 /*
2835 * Space allocation and freeing routines for use by zlib routines.
2836 */
2837 void *
2838 z_alloc(void * notused __unused, u_int num_items, u_int size)
2839 {
2840 void * result = NULL;
2841 z_mem * zmem = NULL;
2842
2843 uint64_t total = ((uint64_t)num_items) * ((uint64_t)size);
2844 //Check for overflow due to multiplication
2845 if (total > UINT32_MAX) {
2846 panic("z_alloc(%p, %x, %x): overflow caused by %x * %x\n",
2847 notused, num_items, size, num_items, size);
2848 }
2849
2850 uint64_t allocSize64 = total + ((uint64_t)sizeof(zmem));
2851 //Check for overflow due to addition
2852 if (allocSize64 > UINT32_MAX) {
2853 panic("z_alloc(%p, %x, %x): overflow caused by %x + %lx\n",
2854 notused, num_items, size, (uint32_t)total, sizeof(zmem));
2855 }
2856 uint32_t allocSize = (uint32_t)allocSize64;
2857
2858 zmem = (z_mem *)kalloc_tag(allocSize, VM_KERN_MEMORY_OSKEXT);
2859 if (!zmem) {
2860 goto finish;
2861 }
2862 zmem->alloc_size = allocSize;
2863 result = (void *)&(zmem->data);
2864 finish:
2865 return result;
2866 }
2867
2868 void
2869 z_free(void * notused __unused, void * ptr)
2870 {
2871 uint32_t * skipper = (uint32_t *)ptr - 1;
2872 z_mem * zmem = (z_mem *)skipper;
2873 kfree(zmem, zmem->alloc_size);
2874 return;
2875 }
2876 };
2877
2878 OSData *
2879 OSKext::extractMkext2FileData(
2880 UInt8 * data,
2881 const char * name,
2882 uint32_t compressedSize,
2883 uint32_t fullSize)
2884 {
2885 OSData * result = NULL;
2886
2887 OSData * uncompressedData = NULL;// release on error
2888
2889 uint8_t * uncompressedDataBuffer = NULL;// do not free
2890 unsigned long uncompressedSize;
2891 z_stream zstream;
2892 bool zstream_inited = false;
2893 int zlib_result;
2894
2895 /* If the file isn't compressed, we want to make a copy
2896 * so that we don't have the tie to the larger mkext file buffer any more.
2897 */
2898 if (!compressedSize) {
2899 uncompressedData = OSData::withBytes(data, fullSize);
2900 // xxx - no check for failure?
2901 result = uncompressedData;
2902 goto finish;
2903 }
2904
2905 if (KERN_SUCCESS != kmem_alloc(kernel_map,
2906 (vm_offset_t*)&uncompressedDataBuffer, fullSize, VM_KERN_MEMORY_OSKEXT)) {
2907 /* How's this for cheesy? The kernel is only asked to extract
2908 * kext plists so we tailor the log messages.
2909 */
2910 if (isKernel()) {
2911 OSKextLog(this,
2912 kOSKextLogErrorLevel |
2913 kOSKextLogArchiveFlag,
2914 "Allocation failure extracting %s from mkext.", name);
2915 } else {
2916 OSKextLog(this,
2917 kOSKextLogErrorLevel |
2918 kOSKextLogArchiveFlag,
2919 "Allocation failure extracting %s from mkext for kext %s.",
2920 name, getIdentifierCString());
2921 }
2922
2923 goto finish;
2924 }
2925 uncompressedData = OSData::withBytesNoCopy(uncompressedDataBuffer, fullSize);
2926 if (!uncompressedData) {
2927 if (isKernel()) {
2928 OSKextLog(this,
2929 kOSKextLogErrorLevel |
2930 kOSKextLogArchiveFlag,
2931 "Allocation failure extracting %s from mkext.", name);
2932 } else {
2933 OSKextLog(this,
2934 kOSKextLogErrorLevel |
2935 kOSKextLogArchiveFlag,
2936 "Allocation failure extracting %s from mkext for kext %s.",
2937 name, getIdentifierCString());
2938 }
2939 goto finish;
2940 }
2941 uncompressedData->setDeallocFunction(&osdata_kmem_free);
2942
2943 if (isKernel()) {
2944 OSKextLog(this,
2945 kOSKextLogDetailLevel |
2946 kOSKextLogArchiveFlag,
2947 "Kernel extracted %s from mkext - compressed size %d, uncompressed size %d.",
2948 name, compressedSize, fullSize);
2949 } else {
2950 OSKextLog(this,
2951 kOSKextLogDetailLevel |
2952 kOSKextLogArchiveFlag,
2953 "Kext %s extracted %s from mkext - compressed size %d, uncompressed size %d.",
2954 getIdentifierCString(), name, compressedSize, fullSize);
2955 }
2956
2957 bzero(&zstream, sizeof(zstream));
2958 zstream.next_in = (UInt8 *)data;
2959 zstream.avail_in = compressedSize;
2960
2961 zstream.next_out = uncompressedDataBuffer;
2962 zstream.avail_out = fullSize;
2963
2964 zstream.zalloc = z_alloc;
2965 zstream.zfree = z_free;
2966
2967 zlib_result = inflateInit(&zstream);
2968 if (Z_OK != zlib_result) {
2969 if (isKernel()) {
2970 OSKextLog(this,
2971 kOSKextLogErrorLevel |
2972 kOSKextLogArchiveFlag,
2973 "Mkext error; zlib inflateInit failed (%d) for %s.",
2974 zlib_result, name);
2975 } else {
2976 OSKextLog(this,
2977 kOSKextLogErrorLevel |
2978 kOSKextLogArchiveFlag,
2979 "Kext %s - mkext error; zlib inflateInit failed (%d) for %s .",
2980 getIdentifierCString(), zlib_result, name);
2981 }
2982 goto finish;
2983 } else {
2984 zstream_inited = true;
2985 }
2986
2987 zlib_result = inflate(&zstream, Z_FINISH);
2988
2989 if (zlib_result == Z_STREAM_END || zlib_result == Z_OK) {
2990 uncompressedSize = zstream.total_out;
2991 } else {
2992 if (isKernel()) {
2993 OSKextLog(this,
2994 kOSKextLogErrorLevel |
2995 kOSKextLogArchiveFlag,
2996 "Mkext error; zlib inflate failed (%d) for %s.",
2997 zlib_result, name);
2998 } else {
2999 OSKextLog(this,
3000 kOSKextLogErrorLevel |
3001 kOSKextLogArchiveFlag,
3002 "Kext %s - mkext error; zlib inflate failed (%d) for %s .",
3003 getIdentifierCString(), zlib_result, name);
3004 }
3005 if (zstream.msg) {
3006 OSKextLog(this,
3007 kOSKextLogErrorLevel |
3008 kOSKextLogArchiveFlag,
3009 "zlib error: %s.", zstream.msg);
3010 }
3011 goto finish;
3012 }
3013
3014 if (uncompressedSize != fullSize) {
3015 if (isKernel()) {
3016 OSKextLog(this,
3017 kOSKextLogErrorLevel |
3018 kOSKextLogArchiveFlag,
3019 "Mkext error; zlib inflate discrepancy for %s, "
3020 "uncompressed size != original size.", name);
3021 } else {
3022 OSKextLog(this,
3023 kOSKextLogErrorLevel |
3024 kOSKextLogArchiveFlag,
3025 "Kext %s - mkext error; zlib inflate discrepancy for %s, "
3026 "uncompressed size != original size.",
3027 getIdentifierCString(), name);
3028 }
3029 goto finish;
3030 }
3031
3032 result = uncompressedData;
3033
3034 finish:
3035 /* Don't bother checking return, nothing we can do on fail.
3036 */
3037 if (zstream_inited) {
3038 inflateEnd(&zstream);
3039 }
3040
3041 if (!result) {
3042 OSSafeReleaseNULL(uncompressedData);
3043 }
3044
3045 return result;
3046 }
3047
3048 /*********************************************************************
3049 *********************************************************************/
3050 /* static */
3051 OSReturn
3052 OSKext::loadFromMkext(
3053 OSKextLogSpec clientLogFilter,
3054 char * mkextBuffer,
3055 uint32_t mkextBufferLength,
3056 char ** logInfoOut,
3057 uint32_t * logInfoLengthOut)
3058 {
3059 OSReturn result = kOSReturnError;
3060 OSReturn tempResult = kOSReturnError;
3061
3062 OSData * mkextData = NULL;// must release
3063 OSDictionary * mkextPlist = NULL;// must release
3064
3065 OSArray * logInfoArray = NULL;// must release
3066 OSSerialize * serializer = NULL;// must release
3067
3068 OSString * predicate = NULL;// do not release
3069 OSDictionary * requestArgs = NULL;// do not release
3070
3071 OSString * kextIdentifier = NULL;// do not release
3072 OSNumber * startKextExcludeNum = NULL;// do not release
3073 OSNumber * startMatchingExcludeNum = NULL;// do not release
3074 OSBoolean * delayAutounloadBool = NULL;// do not release
3075 OSArray * personalityNames = NULL;// do not release
3076
3077 /* Default values for these two options: regular autounload behavior,
3078 * load all kexts, send no personalities.
3079 */
3080 Boolean delayAutounload = false;
3081 OSKextExcludeLevel startKextExcludeLevel = kOSKextExcludeNone;
3082 OSKextExcludeLevel startMatchingExcludeLevel = kOSKextExcludeAll;
3083
3084 IORecursiveLockLock(sKextLock);
3085
3086 if (logInfoOut) {
3087 *logInfoOut = NULL;
3088 *logInfoLengthOut = 0;
3089 }
3090
3091 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
3092
3093 OSKextLog(/* kext */ NULL,
3094 kOSKextLogDebugLevel |
3095 kOSKextLogIPCFlag,
3096 "Received kext load request from user space.");
3097
3098 /* Regardless of processing, the fact that we have gotten here means some
3099 * user-space program is up and talking to us, so we'll switch our kext
3100 * registration to reflect that.
3101 */
3102 if (!sUserLoadsActive) {
3103 OSKextLog(/* kext */ NULL,
3104 kOSKextLogProgressLevel |
3105 kOSKextLogGeneralFlag | kOSKextLogLoadFlag,
3106 "Switching to late startup (user-space) kext loading policy.");
3107
3108 sUserLoadsActive = true;
3109 }
3110
3111 if (!sLoadEnabled) {
3112 OSKextLog(/* kext */ NULL,
3113 kOSKextLogErrorLevel |
3114 kOSKextLogLoadFlag,
3115 "Kext loading is disabled.");
3116 result = kOSKextReturnDisabled;
3117 goto finish;
3118 }
3119
3120 /* Note that we do not set a dealloc function on this OSData
3121 * object! No references to it can remain after the loadFromMkext()
3122 * call since we are in a MIG function, and will vm_deallocate()
3123 * the buffer.
3124 */
3125 mkextData = OSData::withBytesNoCopy(mkextBuffer,
3126 mkextBufferLength);
3127 if (!mkextData) {
3128 OSKextLog(/* kext */ NULL,
3129 kOSKextLogErrorLevel |
3130 kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3131 "Failed to create wrapper for kext load request.");
3132 result = kOSKextReturnNoMemory;
3133 goto finish;
3134 }
3135
3136 result = readMkext2Archive(mkextData, &mkextPlist, NULL);
3137 if (result != kOSReturnSuccess) {
3138 OSKextLog(/* kext */ NULL,
3139 kOSKextLogErrorLevel |
3140 kOSKextLogLoadFlag,
3141 "Failed to read kext load request.");
3142 goto finish;
3143 }
3144
3145 predicate = _OSKextGetRequestPredicate(mkextPlist);
3146 if (!predicate || !predicate->isEqualTo(kKextRequestPredicateLoad)) {
3147 OSKextLog(/* kext */ NULL,
3148 kOSKextLogErrorLevel |
3149 kOSKextLogLoadFlag,
3150 "Received kext load request with no predicate; skipping.");
3151 result = kOSKextReturnInvalidArgument;
3152 goto finish;
3153 }
3154
3155 requestArgs = OSDynamicCast(OSDictionary,
3156 mkextPlist->getObject(kKextRequestArgumentsKey));
3157 if (!requestArgs || !requestArgs->getCount()) {
3158 OSKextLog(/* kext */ NULL,
3159 kOSKextLogErrorLevel |
3160 kOSKextLogLoadFlag,
3161 "Received kext load request with no arguments.");
3162 result = kOSKextReturnInvalidArgument;
3163 goto finish;
3164 }
3165
3166 kextIdentifier = OSDynamicCast(OSString,
3167 requestArgs->getObject(kKextRequestArgumentBundleIdentifierKey));
3168
3169 if (!kextIdentifier) {
3170 OSKextLog(/* kext */ NULL,
3171 kOSKextLogErrorLevel |
3172 kOSKextLogLoadFlag,
3173 "Received kext load request with no kext identifier.");
3174 result = kOSKextReturnInvalidArgument;
3175 goto finish;
3176 }
3177
3178 startKextExcludeNum = OSDynamicCast(OSNumber,
3179 requestArgs->getObject(kKextRequestArgumentStartExcludeKey));
3180 startMatchingExcludeNum = OSDynamicCast(OSNumber,
3181 requestArgs->getObject(kKextRequestArgumentStartMatchingExcludeKey));
3182 delayAutounloadBool = OSDynamicCast(OSBoolean,
3183 requestArgs->getObject(kKextRequestArgumentDelayAutounloadKey));
3184 personalityNames = OSDynamicCast(OSArray,
3185 requestArgs->getObject(kKextRequestArgumentPersonalityNamesKey));
3186
3187 if (delayAutounloadBool) {
3188 delayAutounload = delayAutounloadBool->getValue();
3189 }
3190 if (startKextExcludeNum) {
3191 startKextExcludeLevel = startKextExcludeNum->unsigned8BitValue();
3192 }
3193 if (startMatchingExcludeNum) {
3194 startMatchingExcludeLevel = startMatchingExcludeNum->unsigned8BitValue();
3195 }
3196
3197 OSKextLog(/* kext */ NULL,
3198 kOSKextLogProgressLevel |
3199 kOSKextLogIPCFlag,
3200 "Received request from user space to load kext %s.",
3201 kextIdentifier->getCStringNoCopy());
3202
3203 /* Load the kext, with no deferral, since this is a load from outside
3204 * the kernel.
3205 * xxx - Would like a better way to handle the default values for the
3206 * xxx - start/match opt args.
3207 */
3208 result = OSKext::loadKextWithIdentifier(
3209 kextIdentifier,
3210 /* kextRef */ NULL,
3211 /* allowDefer */ false,
3212 delayAutounload,
3213 startKextExcludeLevel,
3214 startMatchingExcludeLevel,
3215 personalityNames);
3216 if (result != kOSReturnSuccess) {
3217 goto finish;
3218 }
3219 /* If the load came down from kextd, it will shortly inform IOCatalogue
3220 * for matching via a separate IOKit calldown.
3221 */
3222
3223 finish:
3224
3225 /* Gather up the collected log messages for user space. Any
3226 * error messages past this call will not make it up as log messages
3227 * but will be in the system log.
3228 */
3229 logInfoArray = OSKext::clearUserSpaceLogFilter();
3230
3231 if (logInfoArray && logInfoOut && logInfoLengthOut) {
3232 tempResult = OSKext::serializeLogInfo(logInfoArray,
3233 logInfoOut, logInfoLengthOut);
3234 if (tempResult != kOSReturnSuccess) {
3235 result = tempResult;
3236 }
3237 }
3238
3239 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ false);
3240
3241 /* Note: mkextDataObject will have been retained by every kext w/an
3242 * executable in it. That should all have been flushed out at the
3243 * and of the load operation, but you never know....
3244 */
3245 if (mkextData && mkextData->getRetainCount() > 1) {
3246 OSKextLog(/* kext */ NULL,
3247 kOSKextLogErrorLevel |
3248 kOSKextLogLoadFlag | kOSKextLogIPCFlag,
3249 "Kext load request buffer from user space still retained by a kext; "
3250 "probable memory leak.");
3251 }
3252
3253 IORecursiveLockUnlock(sKextLock);
3254
3255 OSSafeReleaseNULL(mkextData);
3256 OSSafeReleaseNULL(mkextPlist);
3257 OSSafeReleaseNULL(serializer);
3258 OSSafeReleaseNULL(logInfoArray);
3259
3260 return result;
3261 }
3262
3263 /*********************************************************************
3264 *********************************************************************/
3265 /* static */
3266 OSReturn
3267 OSKext::serializeLogInfo(
3268 OSArray * logInfoArray,
3269 char ** logInfoOut,
3270 uint32_t * logInfoLengthOut)
3271 {
3272 OSReturn result = kOSReturnError;
3273 char * buffer = NULL;
3274 kern_return_t kmem_result = KERN_FAILURE;
3275 OSSerialize * serializer = NULL;// must release; reused
3276 char * logInfo = NULL;// returned by reference
3277 uint32_t logInfoLength = 0;
3278
3279 if (!logInfoArray || !logInfoOut || !logInfoLengthOut) {
3280 OSKextLog(/* kext */ NULL,
3281 kOSKextLogErrorLevel |
3282 kOSKextLogIPCFlag,
3283 "Internal error; invalid arguments to OSKext::serializeLogInfo().");
3284 /* Bad programmer. */
3285 result = kOSKextReturnInvalidArgument;
3286 goto finish;
3287 }
3288
3289 serializer = OSSerialize::withCapacity(0);
3290 if (!serializer) {
3291 OSKextLog(/* kext */ NULL,
3292 kOSKextLogErrorLevel |
3293 kOSKextLogIPCFlag,
3294 "Failed to create serializer on log info for request from user space.");
3295 /* Incidental error; we're going to (try to) allow the request
3296 * itself to succeed. */
3297 }
3298
3299 if (!logInfoArray->serialize(serializer)) {
3300 OSKextLog(/* kext */ NULL,
3301 kOSKextLogErrorLevel |
3302 kOSKextLogIPCFlag,
3303 "Failed to serialize log info for request from user space.");
3304 /* Incidental error; we're going to (try to) allow the request
3305 * itself to succeed. */
3306 } else {
3307 logInfo = serializer->text();
3308 logInfoLength = serializer->getLength();
3309
3310 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer, round_page(logInfoLength), VM_KERN_MEMORY_OSKEXT);
3311 if (kmem_result != KERN_SUCCESS) {
3312 OSKextLog(/* kext */ NULL,
3313 kOSKextLogErrorLevel |
3314 kOSKextLogIPCFlag,
3315 "Failed to copy log info for request from user space.");
3316 /* Incidental error; we're going to (try to) allow the request
3317 * to succeed. */
3318 } else {
3319 /* 11981737 - clear uninitialized data in last page */
3320 bzero((void *)(buffer + logInfoLength),
3321 (round_page(logInfoLength) - logInfoLength));
3322 memcpy(buffer, logInfo, logInfoLength);
3323 *logInfoOut = buffer;
3324 *logInfoLengthOut = logInfoLength;
3325 }
3326 }
3327
3328 result = kOSReturnSuccess;
3329 finish:
3330 OSSafeReleaseNULL(serializer);
3331 return result;
3332 }
3333
3334 #if PRAGMA_MARK
3335 #pragma mark Instance Management Methods
3336 #endif
3337 /*********************************************************************
3338 *********************************************************************/
3339 OSKext *
3340 OSKext::lookupKextWithIdentifier(const char * kextIdentifier)
3341 {
3342 OSKext * foundKext = NULL;
3343
3344 IORecursiveLockLock(sKextLock);
3345 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
3346 if (foundKext) {
3347 foundKext->retain();
3348 }
3349 IORecursiveLockUnlock(sKextLock);
3350
3351 return foundKext;
3352 }
3353
3354 /*********************************************************************
3355 *********************************************************************/
3356 OSKext *
3357 OSKext::lookupKextWithIdentifier(OSString * kextIdentifier)
3358 {
3359 return OSKext::lookupKextWithIdentifier(kextIdentifier->getCStringNoCopy());
3360 }
3361
3362 /*********************************************************************
3363 *********************************************************************/
3364 OSKext *
3365 OSKext::lookupKextWithLoadTag(uint32_t aTag)
3366 {
3367 OSKext * foundKext = NULL; // returned
3368 uint32_t i, j;
3369 OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
3370 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
3371
3372 IORecursiveLockLock(sKextLock);
3373
3374 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
3375 for (i = 0; i < count[j]; i++) {
3376 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
3377 if (thisKext->getLoadTag() == aTag) {
3378 foundKext = thisKext;
3379 foundKext->retain();
3380 goto finish;
3381 }
3382 }
3383 }
3384
3385 finish:
3386 IORecursiveLockUnlock(sKextLock);
3387
3388 return foundKext;
3389 }
3390
3391 /*********************************************************************
3392 *********************************************************************/
3393 OSKext *
3394 OSKext::lookupKextWithAddress(vm_address_t address)
3395 {
3396 OSKext * foundKext = NULL; // returned
3397 uint32_t count, i;
3398
3399 IORecursiveLockLock(sKextLock);
3400
3401 count = sLoadedKexts->getCount();
3402 for (i = 0; i < count; i++) {
3403 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
3404 if (thisKext->linkedExecutable) {
3405 vm_address_t kext_start =
3406 (vm_address_t)thisKext->linkedExecutable->getBytesNoCopy();
3407 vm_address_t kext_end = kext_start +
3408 thisKext->linkedExecutable->getLength();
3409 if ((kext_start <= address) && (address < kext_end)) {
3410 foundKext = thisKext;
3411 foundKext->retain();
3412 goto finish;
3413 }
3414 }
3415 }
3416
3417 count = sLoadedDriverKitKexts->getCount();
3418 for (i = 0; i < count; i++) {
3419 OSKext * thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
3420 /*
3421 * DriverKitKexts do not have a linkedExecutable,
3422 * so we "fake" their address with the LoadTag
3423 */
3424 if (thisKext->getLoadTag() == address) {
3425 foundKext = thisKext;
3426 foundKext->retain();
3427 }
3428 }
3429
3430 finish:
3431 IORecursiveLockUnlock(sKextLock);
3432
3433 return foundKext;
3434 }
3435
3436 OSData *
3437 OSKext::copyKextUUIDForAddress(OSNumber *address)
3438 {
3439 OSData * uuid = NULL;
3440 OSKextActiveAccount * active;
3441 OSKext * kext = NULL;
3442 uint32_t baseIdx;
3443 uint32_t lim;
3444 uint32_t count, i;
3445
3446 if (!address) {
3447 return NULL;
3448 }
3449
3450 uintptr_t addr = ml_static_slide((uintptr_t)address->unsigned64BitValue());
3451
3452 #if CONFIG_MACF
3453 /* Is the calling process allowed to query kext info? */
3454 if (current_task() != kernel_task) {
3455 int macCheckResult = 0;
3456 kauth_cred_t cred = NULL;
3457
3458 cred = kauth_cred_get_with_ref();
3459 macCheckResult = mac_kext_check_query(cred);
3460 kauth_cred_unref(&cred);
3461
3462 if (macCheckResult != 0) {
3463 OSKextLog(/* kext */ NULL,
3464 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
3465 "Failed to query kext UUID (MAC policy error 0x%x).",
3466 macCheckResult);
3467 return NULL;
3468 }
3469 }
3470 #endif
3471
3472 IOSimpleLockLock(sKextAccountsLock);
3473 // bsearch sKextAccounts list
3474 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
3475 active = &sKextAccounts[baseIdx + (lim >> 1)];
3476 if ((addr >= active->address) && (addr < active->address_end)) {
3477 kext = active->account->kext;
3478 if (kext) {
3479 kext->retain();
3480 }
3481 break;
3482 } else if (addr > active->address) {
3483 // move right
3484 baseIdx += (lim >> 1) + 1;
3485 lim--;
3486 }
3487 // else move left
3488 }
3489 IOSimpleLockUnlock(sKextAccountsLock);
3490
3491 if (!kext) {
3492 /*
3493 * Maybe it is a Dext.
3494 * DriverKit userspace executables do not have a kernel linkedExecutable,
3495 * so we "fake" their address range with the LoadTag.
3496 *
3497 * This is supposed to be used for logging reasons only. When logd
3498 * calls this function it ors the address with FIREHOSE_TRACEPOINT_PC_KERNEL_MASK, so we
3499 * remove it here before checking it against the LoadTag.
3500 * Also we need to remove FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT set when emitting the log line.
3501 */
3502 addr = (uintptr_t)address->unsigned64BitValue() & ~(FIREHOSE_TRACEPOINT_PC_KERNEL_MASK | FIREHOSE_TRACEPOINT_PC_DYNAMIC_BIT);
3503 IORecursiveLockLock(sKextLock);
3504 count = sLoadedDriverKitKexts->getCount();
3505 for (i = 0; i < count; i++) {
3506 OSKext * thisKext = NULL;
3507
3508 thisKext = OSDynamicCast(OSKext, sLoadedDriverKitKexts->getObject(i));
3509 if (!thisKext) {
3510 continue;
3511 }
3512 if (thisKext->getLoadTag() == addr) {
3513 kext = thisKext;
3514 kext->retain();
3515 break;
3516 }
3517 }
3518 IORecursiveLockUnlock(sKextLock);
3519 }
3520
3521 if (kext) {
3522 uuid = kext->copyTextUUID();
3523 kext->release();
3524 } else if (((vm_offset_t)addr >= vm_kernel_stext) && ((vm_offset_t)addr < vm_kernel_etext)) {
3525 uuid = sKernelKext->copyTextUUID();
3526 }
3527
3528 return uuid;
3529 }
3530
3531 /*********************************************************************
3532 *********************************************************************/
3533 OSKext *
3534 OSKext::lookupKextWithUUID(uuid_t wanted)
3535 {
3536 OSKext * foundKext = NULL; // returned
3537 uint32_t j, i;
3538 OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
3539 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
3540
3541
3542 IORecursiveLockLock(sKextLock);
3543
3544 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
3545 for (i = 0; i < count[j]; i++) {
3546 OSKext * thisKext = NULL;
3547
3548 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
3549 if (!thisKext) {
3550 continue;
3551 }
3552
3553 OSData *uuid_data = thisKext->copyUUID();
3554 if (!uuid_data) {
3555 continue;
3556 }
3557
3558 uuid_t uuid;
3559 memcpy(&uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
3560 uuid_data->release();
3561
3562 if (0 == uuid_compare(wanted, uuid)) {
3563 foundKext = thisKext;
3564 foundKext->retain();
3565 goto finish;
3566 }
3567 }
3568 }
3569 finish:
3570 IORecursiveLockUnlock(sKextLock);
3571
3572 return foundKext;
3573 }
3574
3575
3576
3577
3578 /*********************************************************************
3579 *********************************************************************/
3580 /* static */
3581 bool
3582 OSKext::isKextWithIdentifierLoaded(const char * kextIdentifier)
3583 {
3584 bool result = false;
3585 OSKext * foundKext = NULL; // returned
3586
3587 IORecursiveLockLock(sKextLock);
3588
3589 foundKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
3590 if (foundKext && foundKext->isLoaded()) {
3591 result = true;
3592 }
3593
3594 IORecursiveLockUnlock(sKextLock);
3595
3596 return result;
3597 }
3598
3599 /*********************************************************************
3600 * xxx - should spawn a separate thread so a kext can safely have
3601 * xxx - itself unloaded.
3602 *********************************************************************/
3603 /* static */
3604 OSReturn
3605 OSKext::removeKext(
3606 OSKext * aKext,
3607 #if CONFIG_EMBEDDED
3608 __unused
3609 #endif
3610 bool terminateServicesAndRemovePersonalitiesFlag)
3611 {
3612 #if CONFIG_EMBEDDED
3613 OSKextLog(aKext,
3614 kOSKextLogErrorLevel |
3615 kOSKextLogKextBookkeepingFlag,
3616 "removeKext() called for %s, not supported on embedded",
3617 aKext->getIdentifier() ? aKext->getIdentifierCString() : "unknown kext");
3618
3619 return kOSReturnSuccess;
3620 #else /* CONFIG_EMBEDDED */
3621
3622 OSReturn result = kOSKextReturnInUse;
3623 OSKext * checkKext = NULL; // do not release
3624 #if CONFIG_MACF
3625 int macCheckResult = 0;
3626 kauth_cred_t cred = NULL;
3627 #endif
3628
3629 IORecursiveLockLock(sKextLock);
3630
3631 /* If the kext has no identifier, it failed to init
3632 * so isn't in sKextsByID and it isn't loaded.
3633 */
3634 if (!aKext->getIdentifier()) {
3635 result = kOSReturnSuccess;
3636 goto finish;
3637 }
3638
3639 checkKext = OSDynamicCast(OSKext,
3640 sKextsByID->getObject(aKext->getIdentifier()));
3641 if (checkKext != aKext) {
3642 result = kOSKextReturnNotFound;
3643 goto finish;
3644 }
3645
3646 if (aKext->isLoaded()) {
3647 #if CONFIG_MACF
3648 if (current_task() != kernel_task) {
3649 cred = kauth_cred_get_with_ref();
3650 macCheckResult = mac_kext_check_unload(cred, aKext->getIdentifierCString());
3651 kauth_cred_unref(&cred);
3652 }
3653
3654 if (macCheckResult != 0) {
3655 result = kOSReturnError;
3656 OSKextLog(aKext,
3657 kOSKextLogErrorLevel |
3658 kOSKextLogKextBookkeepingFlag,
3659 "Failed to remove kext %s (MAC policy error 0x%x).",
3660 aKext->getIdentifierCString(), macCheckResult);
3661 goto finish;
3662 }
3663 #endif
3664
3665 /* make sure there are no resource requests in flight - 17187548 */
3666 if (aKext->countRequestCallbacks()) {
3667 goto finish;
3668 }
3669
3670 /* If we are terminating, send the request to the IOCatalogue
3671 * (which will actually call us right back but that's ok we have
3672 * a recursive lock don't you know) but do not ask the IOCatalogue
3673 * to call back with an unload, we'll do that right here.
3674 */
3675 if (terminateServicesAndRemovePersonalitiesFlag) {
3676 result = gIOCatalogue->terminateDriversForModule(
3677 aKext->getIdentifierCString(), /* unload */ false);
3678 if (result != kOSReturnSuccess) {
3679 OSKextLog(aKext,
3680 kOSKextLogErrorLevel |
3681 kOSKextLogKextBookkeepingFlag,
3682 "Can't remove kext %s; services failed to terminate - 0x%x.",
3683 aKext->getIdentifierCString(), result);
3684 goto finish;
3685 }
3686 }
3687
3688 result = aKext->unload();
3689 if (result != kOSReturnSuccess) {
3690 goto finish;
3691 }
3692 }
3693
3694 /* Remove personalities as requested. This is a bit redundant for a loaded
3695 * kext as IOCatalogue::terminateDriversForModule() removes driver
3696 * personalities, but it doesn't restart matching, which we always want
3697 * coming from here, and OSKext::removePersonalitiesFromCatalog() ensures
3698 * that happens.
3699 */
3700 if (terminateServicesAndRemovePersonalitiesFlag) {
3701 aKext->removePersonalitiesFromCatalog();
3702 }
3703
3704 OSKextLog(aKext,
3705 kOSKextLogProgressLevel |
3706 kOSKextLogKextBookkeepingFlag,
3707 "Removing kext %s.",
3708 aKext->getIdentifierCString());
3709
3710 sKextsByID->removeObject(aKext->getIdentifier());
3711 result = kOSReturnSuccess;
3712
3713 finish:
3714 IORecursiveLockUnlock(sKextLock);
3715 return result;
3716 #endif /* CONFIG_EMBEDDED */
3717 }
3718
3719 /*********************************************************************
3720 *********************************************************************/
3721 /* static */
3722 OSReturn
3723 OSKext::removeKextWithIdentifier(
3724 const char * kextIdentifier,
3725 bool terminateServicesAndRemovePersonalitiesFlag)
3726 {
3727 OSReturn result = kOSReturnError;
3728
3729 IORecursiveLockLock(sKextLock);
3730
3731 OSKext * aKext = OSDynamicCast(OSKext,
3732 sKextsByID->getObject(kextIdentifier));
3733 if (!aKext) {
3734 result = kOSKextReturnNotFound;
3735 OSKextLog(/* kext */ NULL,
3736 kOSKextLogErrorLevel |
3737 kOSKextLogKextBookkeepingFlag,
3738 "Can't remove kext %s - not found.",
3739 kextIdentifier);
3740 goto finish;
3741 }
3742
3743 result = OSKext::removeKext(aKext,
3744 terminateServicesAndRemovePersonalitiesFlag);
3745
3746 finish:
3747 IORecursiveLockUnlock(sKextLock);
3748
3749 return result;
3750 }
3751
3752 /*********************************************************************
3753 *********************************************************************/
3754 /* static */
3755 OSReturn
3756 OSKext::removeKextWithLoadTag(
3757 OSKextLoadTag loadTag,
3758 bool terminateServicesAndRemovePersonalitiesFlag)
3759 {
3760 OSReturn result = kOSReturnError;
3761 OSKext * foundKext = NULL;
3762 uint32_t i, j;
3763 OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
3764 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
3765
3766
3767 IORecursiveLockLock(sKextLock);
3768
3769 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
3770 for (i = 0; i < count[j]; i++) {
3771 OSKext * thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
3772 if (thisKext->loadTag == loadTag) {
3773 foundKext = thisKext;
3774 break;
3775 }
3776 }
3777 }
3778
3779 if (!foundKext) {
3780 result = kOSKextReturnNotFound;
3781 OSKextLog(/* kext */ NULL,
3782 kOSKextLogErrorLevel |
3783 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
3784 "Can't remove kext with load tag %d - not found.",
3785 loadTag);
3786 goto finish;
3787 }
3788
3789 result = OSKext::removeKext(foundKext,
3790 terminateServicesAndRemovePersonalitiesFlag);
3791
3792 finish:
3793 IORecursiveLockUnlock(sKextLock);
3794
3795 return result;
3796 }
3797
3798 /*********************************************************************
3799 *********************************************************************/
3800 OSDictionary *
3801 OSKext::copyKexts(void)
3802 {
3803 OSDictionary * result;
3804
3805 IORecursiveLockLock(sKextLock);
3806 result = OSDynamicCast(OSDictionary, sKextsByID->copyCollection());
3807 IORecursiveLockUnlock(sKextLock);
3808
3809 return result;
3810 }
3811
3812 /*********************************************************************
3813 *********************************************************************/
3814 #define BOOTER_KEXT_PREFIX "Driver-"
3815
3816 typedef struct _DeviceTreeBuffer {
3817 uint32_t paddr;
3818 uint32_t length;
3819 } _DeviceTreeBuffer;
3820
3821 /*********************************************************************
3822 * Create a dictionary of excluded kexts from the given booter data.
3823 *********************************************************************/
3824 /* static */
3825 void
3826 OSKext::createExcludeListFromBooterData(
3827 OSDictionary * theDictionary,
3828 OSCollectionIterator * theIterator )
3829 {
3830 OSString * deviceTreeName = NULL;// do not release
3831 const _DeviceTreeBuffer * deviceTreeBuffer = NULL;// do not release
3832 char * booterDataPtr = NULL;// do not release
3833 _BooterKextFileInfo * kextFileInfo = NULL;// do not release
3834 char * infoDictAddr = NULL;// do not release
3835 OSObject * parsedXML = NULL;// must release
3836 OSDictionary * theInfoDict = NULL;// do not release
3837
3838 theIterator->reset();
3839
3840 /* look for AppleKextExcludeList.kext */
3841 while ((deviceTreeName =
3842 OSDynamicCast(OSString, theIterator->getNextObject()))) {
3843 const char * devTreeNameCString;
3844 OSData * deviceTreeEntry;
3845 OSString * myBundleID;// do not release
3846
3847 OSSafeReleaseNULL(parsedXML);
3848
3849 deviceTreeEntry =
3850 OSDynamicCast(OSData, theDictionary->getObject(deviceTreeName));
3851 if (!deviceTreeEntry) {
3852 continue;
3853 }
3854
3855 /* Make sure it is a kext */
3856 devTreeNameCString = deviceTreeName->getCStringNoCopy();
3857 if (strncmp(devTreeNameCString, BOOTER_KEXT_PREFIX,
3858 (sizeof(BOOTER_KEXT_PREFIX) - 1)) != 0) {
3859 OSKextLog(NULL,
3860 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
3861 "\"%s\" not a kext",
3862 devTreeNameCString);
3863 continue;
3864 }
3865
3866 deviceTreeBuffer = (const _DeviceTreeBuffer *)
3867 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
3868 if (!deviceTreeBuffer) {
3869 continue;
3870 }
3871
3872 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
3873 if (!booterDataPtr) {
3874 continue;
3875 }
3876
3877 kextFileInfo = (_BooterKextFileInfo *) booterDataPtr;
3878 if (!kextFileInfo->infoDictPhysAddr ||
3879 !kextFileInfo->infoDictLength) {
3880 continue;
3881 }
3882
3883 infoDictAddr = (char *)
3884 ml_static_ptovirt(kextFileInfo->infoDictPhysAddr);
3885 if (!infoDictAddr) {
3886 continue;
3887 }
3888
3889 parsedXML = OSUnserializeXML(infoDictAddr);
3890 if (!parsedXML) {
3891 continue;
3892 }
3893
3894 theInfoDict = OSDynamicCast(OSDictionary, parsedXML);
3895 if (!theInfoDict) {
3896 continue;
3897 }
3898
3899 myBundleID =
3900 OSDynamicCast(OSString,
3901 theInfoDict->getObject(kCFBundleIdentifierKey));
3902 if (myBundleID &&
3903 strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
3904 boolean_t updated = updateExcludeList(theInfoDict);
3905 if (!updated) {
3906 /* 25322874 */
3907 panic("Missing OSKextExcludeList dictionary\n");
3908 }
3909 break;
3910 }
3911 } // while ( (deviceTreeName = ...) )
3912
3913 OSSafeReleaseNULL(parsedXML);
3914 return;
3915 }
3916
3917 /*********************************************************************
3918 * Create a dictionary of excluded kexts from the given prelink
3919 * info (kernelcache).
3920 *********************************************************************/
3921 /* static */
3922 void
3923 OSKext::createExcludeListFromPrelinkInfo( OSArray * theInfoArray )
3924 {
3925 OSDictionary * myInfoDict = NULL;// do not release
3926 OSString * myBundleID; // do not release
3927 u_int i;
3928
3929 /* Find com.apple.driver.KextExcludeList. */
3930 for (i = 0; i < theInfoArray->getCount(); i++) {
3931 myInfoDict = OSDynamicCast(OSDictionary, theInfoArray->getObject(i));
3932 if (!myInfoDict) {
3933 continue;
3934 }
3935 myBundleID =
3936 OSDynamicCast(OSString,
3937 myInfoDict->getObject(kCFBundleIdentifierKey));
3938 if (myBundleID &&
3939 strcmp( myBundleID->getCStringNoCopy(), "com.apple.driver.KextExcludeList" ) == 0) {
3940 boolean_t updated = updateExcludeList(myInfoDict);
3941 if (!updated) {
3942 /* 25322874 */
3943 panic("Missing OSKextExcludeList dictionary\n");
3944 }
3945 break;
3946 }
3947 } // for (i = 0; i < theInfoArray->getCount()...
3948
3949 return;
3950 }
3951
3952 /* static */
3953 boolean_t
3954 OSKext::updateExcludeList(OSDictionary *infoDict)
3955 {
3956 OSDictionary *myTempDict = NULL; // do not free
3957 OSString *myTempString = NULL;// do not free
3958 OSKextVersion newVersion = 0;
3959 boolean_t updated = false;
3960
3961 if (!infoDict) {
3962 return false;
3963 }
3964
3965 myTempDict = OSDynamicCast(OSDictionary, infoDict->getObject("OSKextExcludeList"));
3966 if (!myTempDict) {
3967 return false;
3968 }
3969
3970 myTempString = OSDynamicCast(OSString, infoDict->getObject(kCFBundleVersionKey));
3971 if (!myTempString) {
3972 return false;
3973 }
3974
3975 newVersion = OSKextParseVersionString(myTempString->getCStringNoCopy());
3976 if (newVersion == 0) {
3977 return false;
3978 }
3979
3980 IORecursiveLockLock(sKextLock);
3981
3982 if (newVersion > sExcludeListVersion) {
3983 OSSafeReleaseNULL(sExcludeListByID);
3984 sExcludeListByID = OSDictionary::withDictionary(myTempDict, 0);
3985 sExcludeListVersion = newVersion;
3986 updated = true;
3987 }
3988
3989 IORecursiveLockUnlock(sKextLock);
3990 return updated;
3991 }
3992
3993 #if PRAGMA_MARK
3994 #pragma mark Accessors
3995 #endif
3996 /*********************************************************************
3997 *********************************************************************/
3998 const OSSymbol *
3999 OSKext::getIdentifier(void)
4000 {
4001 return bundleID;
4002 }
4003
4004 /*********************************************************************
4005 * A kext must have a bundle identifier to even survive initialization;
4006 * this is guaranteed to exist past then.
4007 *********************************************************************/
4008 const char *
4009 OSKext::getIdentifierCString(void)
4010 {
4011 return bundleID->getCStringNoCopy();
4012 }
4013
4014 /*********************************************************************
4015 *********************************************************************/
4016 OSKextVersion
4017 OSKext::getVersion(void)
4018 {
4019 return version;
4020 }
4021
4022 /*********************************************************************
4023 *********************************************************************/
4024 OSKextVersion
4025 OSKext::getCompatibleVersion(void)
4026 {
4027 return compatibleVersion;
4028 }
4029
4030 /*********************************************************************
4031 *********************************************************************/
4032 bool
4033 OSKext::isLibrary(void)
4034 {
4035 return getCompatibleVersion() > 0;
4036 }
4037
4038 /*********************************************************************
4039 *********************************************************************/
4040 bool
4041 OSKext::isCompatibleWithVersion(OSKextVersion aVersion)
4042 {
4043 if ((compatibleVersion > -1 && version > -1) &&
4044 (compatibleVersion <= version && aVersion <= version)) {
4045 return true;
4046 }
4047 return false;
4048 }
4049
4050 /*********************************************************************
4051 *********************************************************************/
4052 bool
4053 OSKext::declaresExecutable(void)
4054 {
4055 if (isDriverKit()) {
4056 return false;
4057 }
4058 return getPropertyForHostArch(kCFBundleExecutableKey) != NULL;
4059 }
4060
4061 /*********************************************************************
4062 *********************************************************************/
4063 OSData *
4064 OSKext::getExecutable(void)
4065 {
4066 OSData * result = NULL;
4067 OSData * extractedExecutable = NULL; // must release
4068 OSData * mkextExecutableRef = NULL;// do not release
4069
4070 if (flags.builtin) {
4071 return sKernelKext->linkedExecutable;
4072 }
4073
4074 result = OSDynamicCast(OSData, infoDict->getObject(_kOSKextExecutableKey));
4075 if (result) {
4076 goto finish;
4077 }
4078
4079 mkextExecutableRef = OSDynamicCast(OSData,
4080 getPropertyForHostArch(_kOSKextMkextExecutableReferenceKey));
4081
4082 if (mkextExecutableRef) {
4083 MkextEntryRef * mkextEntryRef = (MkextEntryRef *)
4084 mkextExecutableRef->getBytesNoCopy();
4085 uint32_t mkextVersion = MKEXT_GET_VERSION(mkextEntryRef->mkext);
4086 if (mkextVersion == MKEXT_VERS_2) {
4087 mkext2_file_entry * fileinfo =
4088 (mkext2_file_entry *)mkextEntryRef->fileinfo;
4089 uint32_t compressedSize = MKEXT2_GET_ENTRY_COMPSIZE(fileinfo);
4090 uint32_t fullSize = MKEXT2_GET_ENTRY_FULLSIZE(fileinfo);
4091 extractedExecutable = extractMkext2FileData(
4092 MKEXT2_GET_ENTRY_DATA(fileinfo), "executable",
4093 compressedSize, fullSize);
4094 } else {
4095 OSKextLog(this, kOSKextLogErrorLevel |
4096 kOSKextLogArchiveFlag,
4097 "Kext %s - unknown mkext version 0x%x for executable.",
4098 getIdentifierCString(), mkextVersion);
4099 }
4100
4101 /* Regardless of success, remove the mkext executable,
4102 * and drop one reference on the mkext. (setExecutable() does not
4103 * replace, it removes, or panics if asked to replace.)
4104 */
4105 infoDict->removeObject(_kOSKextMkextExecutableReferenceKey);
4106 infoDict->removeObject(_kOSKextExecutableExternalDataKey);
4107
4108 if (extractedExecutable && extractedExecutable->getLength()) {
4109 if (!setExecutable(extractedExecutable)) {
4110 goto finish;
4111 }
4112 result = extractedExecutable;
4113 } else {
4114 goto finish;
4115 }
4116 }
4117
4118 finish:
4119
4120 OSSafeReleaseNULL(extractedExecutable);
4121
4122 return result;
4123 }
4124
4125 /*********************************************************************
4126 *********************************************************************/
4127 bool
4128 OSKext::isInterface(void)
4129 {
4130 return flags.interface;
4131 }
4132
4133 /*********************************************************************
4134 *********************************************************************/
4135 bool
4136 OSKext::isKernel(void)
4137 {
4138 return this == sKernelKext;
4139 }
4140
4141 /*********************************************************************
4142 *********************************************************************/
4143 bool
4144 OSKext::isKernelComponent(void)
4145 {
4146 return flags.kernelComponent ? true : false;
4147 }
4148
4149 /*********************************************************************
4150 *********************************************************************/
4151 bool
4152 OSKext::isExecutable(void)
4153 {
4154 return !isKernel() && !isInterface() && declaresExecutable();
4155 }
4156
4157 /*********************************************************************
4158 * We might want to check this recursively for all dependencies,
4159 * since a subtree of dependencies could get loaded before we hit
4160 * a dependency that isn't safe-boot-loadable.
4161 *
4162 * xxx - Might want to return false if OSBundleEnableKextLogging or
4163 * OSBundleDebugLevel
4164 * or IOKitDebug is nonzero too (we used to do that, but I don't see
4165 * the point except it's usually development drivers, which might
4166 * cause panics on startup, that have those properties). Heh; could
4167 * use a "kx" boot-arg!
4168 *********************************************************************/
4169 bool
4170 OSKext::isLoadableInSafeBoot(void)
4171 {
4172 bool result = false;
4173 OSString * required = NULL; // do not release
4174
4175 if (isKernel()) {
4176 result = true;
4177 goto finish;
4178 }
4179
4180 required = OSDynamicCast(OSString,
4181 getPropertyForHostArch(kOSBundleRequiredKey));
4182 if (!required) {
4183 goto finish;
4184 }
4185 if (required->isEqualTo(kOSBundleRequiredRoot) ||
4186 required->isEqualTo(kOSBundleRequiredLocalRoot) ||
4187 required->isEqualTo(kOSBundleRequiredNetworkRoot) ||
4188 required->isEqualTo(kOSBundleRequiredSafeBoot) ||
4189 required->isEqualTo(kOSBundleRequiredConsole)) {
4190 result = true;
4191 }
4192
4193 finish:
4194 return result;
4195 }
4196
4197 /*********************************************************************
4198 *********************************************************************/
4199 bool
4200 OSKext::isPrelinked(void)
4201 {
4202 return flags.prelinked ? true : false;
4203 }
4204
4205 /*********************************************************************
4206 *********************************************************************/
4207 bool
4208 OSKext::isLoaded(void)
4209 {
4210 return flags.loaded ? true : false;
4211 }
4212
4213 /*********************************************************************
4214 *********************************************************************/
4215 bool
4216 OSKext::isStarted(void)
4217 {
4218 return flags.started ? true : false;
4219 }
4220
4221 /*********************************************************************
4222 *********************************************************************/
4223 bool
4224 OSKext::isCPPInitialized(void)
4225 {
4226 return flags.CPPInitialized;
4227 }
4228
4229 /*********************************************************************
4230 *********************************************************************/
4231 void
4232 OSKext::setCPPInitialized(bool initialized)
4233 {
4234 flags.CPPInitialized = initialized;
4235 }
4236
4237 /*********************************************************************
4238 *********************************************************************/
4239 uint32_t
4240 OSKext::getLoadTag(void)
4241 {
4242 return loadTag;
4243 }
4244
4245 /*********************************************************************
4246 *********************************************************************/
4247 void
4248 OSKext::getSizeInfo(uint32_t *loadSize, uint32_t *wiredSize)
4249 {
4250 if (linkedExecutable) {
4251 *loadSize = linkedExecutable->getLength();
4252
4253 /* If we have a kmod_info struct, calculated the wired size
4254 * from that. Otherwise it's the full load size.
4255 */
4256 if (kmod_info) {
4257 *wiredSize = *loadSize - kmod_info->hdr_size;
4258 } else {
4259 *wiredSize = *loadSize;
4260 }
4261 } else {
4262 *wiredSize = 0;
4263 *loadSize = 0;
4264 }
4265 }
4266
4267 /*********************************************************************
4268 *********************************************************************/
4269 OSData *
4270 OSKext::copyUUID(void)
4271 {
4272 OSData * result = NULL;
4273 OSData * theExecutable = NULL;// do not release
4274 const kernel_mach_header_t * header;
4275
4276 /* An interface kext doesn't have a linked executable with an LC_UUID,
4277 * we create one when it's linked.
4278 */
4279 if (interfaceUUID) {
4280 result = interfaceUUID;
4281 result->retain();
4282 goto finish;
4283 }
4284
4285 if (flags.builtin || isInterface()) {
4286 return sKernelKext->copyUUID();
4287 }
4288
4289 if (isDriverKit() && infoDict) {
4290 if (driverKitUUID) {
4291 driverKitUUID->retain();
4292 return driverKitUUID;
4293 } else {
4294 return NULL;
4295 }
4296 }
4297
4298 /* For real kexts, try to get the UUID from the linked executable,
4299 * or if is hasn't been linked yet, the unrelocated executable.
4300 */
4301 theExecutable = linkedExecutable;
4302 if (!theExecutable) {
4303 theExecutable = getExecutable();
4304 }
4305
4306 if (!theExecutable) {
4307 goto finish;
4308 }
4309
4310 header = (const kernel_mach_header_t *)theExecutable->getBytesNoCopy();
4311 result = copyMachoUUID(header);
4312
4313 finish:
4314 return result;
4315 }
4316
4317 /*********************************************************************
4318 *********************************************************************/
4319 OSData *
4320 OSKext::copyTextUUID(void)
4321 {
4322 if (flags.builtin) {
4323 return copyMachoUUID((const kernel_mach_header_t *)kmod_info->address);
4324 }
4325 return copyUUID();
4326 }
4327
4328 /*********************************************************************
4329 *********************************************************************/
4330 OSData *
4331 OSKext::copyMachoUUID(const kernel_mach_header_t * header)
4332 {
4333 OSData * result = NULL;
4334 const struct load_command * load_cmd = NULL;
4335 const struct uuid_command * uuid_cmd = NULL;
4336 uint32_t i;
4337
4338 load_cmd = (const struct load_command *)&header[1];
4339
4340 if (header->magic != MH_MAGIC_KERNEL) {
4341 OSKextLog(NULL,
4342 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4343 "%s: bad header %p",
4344 __func__,
4345 header);
4346 goto finish;
4347 }
4348
4349 for (i = 0; i < header->ncmds; i++) {
4350 if (load_cmd->cmd == LC_UUID) {
4351 uuid_cmd = (struct uuid_command *)load_cmd;
4352 result = OSData::withBytes(uuid_cmd->uuid, sizeof(uuid_cmd->uuid));
4353 goto finish;
4354 }
4355 load_cmd = (struct load_command *)((caddr_t)load_cmd + load_cmd->cmdsize);
4356 }
4357
4358 finish:
4359 return result;
4360 }
4361
4362 void
4363 OSKext::setDriverKitUUID(OSData *uuid)
4364 {
4365 if (!OSCompareAndSwapPtr(nullptr, uuid, &driverKitUUID)) {
4366 OSSafeReleaseNULL(uuid);
4367 }
4368 }
4369
4370 /*********************************************************************
4371 *********************************************************************/
4372 #if defined (__arm__)
4373 #include <arm/arch.h>
4374 #endif
4375
4376 #if defined (__x86_64__)
4377 #define ARCHNAME "x86_64"
4378 #elif defined (__arm64__)
4379 #define ARCHNAME "arm64"
4380 #elif defined (__arm__)
4381
4382 #if defined (__ARM_ARCH_7S__)
4383 #define ARCHNAME "armv7s"
4384 #elif defined (__ARM_ARCH_7F__)
4385 #define ARCHNAME "armv7f"
4386 #elif defined (__ARM_ARCH_7K__)
4387 #define ARCHNAME "armv7k"
4388 #elif defined (_ARM_ARCH_7) /* umbrella for all remaining */
4389 #define ARCHNAME "armv7"
4390 #elif defined (_ARM_ARCH_6) /* umbrella for all armv6 */
4391 #define ARCHNAME "armv6"
4392 #endif
4393
4394 #elif defined (__arm64__)
4395 #define ARCHNAME "arm64"
4396 #else
4397 #error architecture not supported
4398 #endif
4399
4400 #define ARCH_SEPARATOR_CHAR '_'
4401
4402 static char *
4403 makeHostArchKey(const char * key, uint32_t * keySizeOut)
4404 {
4405 char * result = NULL;
4406 uint32_t keyLength = strlen(key);
4407 uint32_t keySize;
4408
4409 /* Add 1 for the ARCH_SEPARATOR_CHAR, and 1 for the '\0'.
4410 */
4411 keySize = 1 + 1 + strlen(key) + strlen(ARCHNAME);
4412 result = (char *)kalloc_tag(keySize, VM_KERN_MEMORY_OSKEXT);
4413 if (!result) {
4414 goto finish;
4415 }
4416 strlcpy(result, key, keySize);
4417 result[keyLength++] = ARCH_SEPARATOR_CHAR;
4418 result[keyLength] = '\0';
4419 strlcat(result, ARCHNAME, keySize);
4420 *keySizeOut = keySize;
4421
4422 finish:
4423 return result;
4424 }
4425
4426 /*********************************************************************
4427 *********************************************************************/
4428 OSObject *
4429 OSKext::getPropertyForHostArch(const char * key)
4430 {
4431 OSObject * result = NULL;// do not release
4432 uint32_t hostArchKeySize = 0;
4433 char * hostArchKey = NULL;// must kfree
4434
4435 if (!key || !infoDict) {
4436 goto finish;
4437 }
4438
4439 /* Some properties are not allowed to be arch-variant:
4440 * - Any CFBundle... property.
4441 * - OSBundleIsInterface.
4442 * - OSKernelResource.
4443 */
4444 if (STRING_HAS_PREFIX(key, "OS") ||
4445 STRING_HAS_PREFIX(key, "IO")) {
4446 hostArchKey = makeHostArchKey(key, &hostArchKeySize);
4447 if (!hostArchKey) {
4448 OSKextLog(/* kext (this isn't about a kext) */ NULL,
4449 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
4450 "Allocation failure.");
4451 goto finish;
4452 }
4453 result = infoDict->getObject(hostArchKey);
4454 }
4455
4456 if (!result) {
4457 result = infoDict->getObject(key);
4458 }
4459
4460 finish:
4461 if (hostArchKey) {
4462 kfree(hostArchKey, hostArchKeySize);
4463 }
4464 return result;
4465 }
4466
4467 #if PRAGMA_MARK
4468 #pragma mark Load/Start/Stop/Unload
4469 #endif
4470
4471 #define isWhiteSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == ',' || (c) == '\n')
4472
4473 /*********************************************************************
4474 * sExcludeListByID is a dictionary with keys / values of:
4475 * key = bundleID string of kext we will not allow to load
4476 * value = version string(s) of the kext that is to be denied loading.
4477 * The version strings can be comma delimited. For example if kext
4478 * com.foocompany.fookext has two versions that we want to deny
4479 * loading then the version strings might look like:
4480 * 1.0.0, 1.0.1
4481 * If the current fookext has a version of 1.0.0 OR 1.0.1 we will
4482 * not load the kext.
4483 *
4484 * Value may also be in the form of "LE 2.0.0" (version numbers
4485 * less than or equal to 2.0.0 will not load) or "LT 2.0.0" (version
4486 * number less than 2.0.0 will not load)
4487 *
4488 * NOTE - we cannot use the characters "<=" or "<" because we have code
4489 * that serializes plists and treats '<' as a special character.
4490 *********************************************************************/
4491 bool
4492 OSKext::isInExcludeList(void)
4493 {
4494 OSString * versionString = NULL;// do not release
4495 char * versionCString = NULL;// do not free
4496 size_t i;
4497 boolean_t wantLessThan = false;
4498 boolean_t wantLessThanEqualTo = false;
4499 boolean_t isInExcludeList = true;
4500 char myBuffer[32];
4501
4502 IORecursiveLockLock(sKextLock);
4503
4504 if (!sExcludeListByID) {
4505 isInExcludeList = false;
4506 } else {
4507 /* look up by bundleID in our exclude list and if found get version
4508 * string (or strings) that we will not allow to load
4509 */
4510 versionString = OSDynamicCast(OSString, sExcludeListByID->getObject(bundleID));
4511 if (versionString == NULL || versionString->getLength() > (sizeof(myBuffer) - 1)) {
4512 isInExcludeList = false;
4513 }
4514 }
4515
4516 IORecursiveLockUnlock(sKextLock);
4517
4518 if (!isInExcludeList) {
4519 return false;
4520 }
4521
4522 /* parse version strings */
4523 versionCString = (char *) versionString->getCStringNoCopy();
4524
4525 /* look for "LT" or "LE" form of version string, must be in first two
4526 * positions.
4527 */
4528 if (*versionCString == 'L' && *(versionCString + 1) == 'T') {
4529 wantLessThan = true;
4530 versionCString += 2;
4531 } else if (*versionCString == 'L' && *(versionCString + 1) == 'E') {
4532 wantLessThanEqualTo = true;
4533 versionCString += 2;
4534 }
4535
4536 for (i = 0; *versionCString != 0x00; versionCString++) {
4537 /* skip whitespace */
4538 if (isWhiteSpace(*versionCString)) {
4539 continue;
4540 }
4541
4542 /* peek ahead for version string separator or null terminator */
4543 if (*(versionCString + 1) == ',' || *(versionCString + 1) == 0x00) {
4544 /* OK, we have a version string */
4545 myBuffer[i++] = *versionCString;
4546 myBuffer[i] = 0x00;
4547
4548 OSKextVersion excludeVers;
4549 excludeVers = OSKextParseVersionString(myBuffer);
4550
4551 if (wantLessThanEqualTo) {
4552 if (version <= excludeVers) {
4553 return true;
4554 }
4555 } else if (wantLessThan) {
4556 if (version < excludeVers) {
4557 return true;
4558 }
4559 } else if (version == excludeVers) {
4560 return true;
4561 }
4562
4563 /* reset for the next (if any) version string */
4564 i = 0;
4565 wantLessThan = false;
4566 wantLessThanEqualTo = false;
4567 } else {
4568 /* save valid version character */
4569 myBuffer[i++] = *versionCString;
4570
4571 /* make sure bogus version string doesn't overrun local buffer */
4572 if (i >= sizeof(myBuffer)) {
4573 break;
4574 }
4575 }
4576 }
4577
4578 return false;
4579 }
4580
4581 /*********************************************************************
4582 *********************************************************************/
4583 /* static */
4584 OSReturn
4585 OSKext::loadKextWithIdentifier(
4586 const char * kextIdentifierCString,
4587 Boolean allowDeferFlag,
4588 Boolean delayAutounloadFlag,
4589 OSKextExcludeLevel startOpt,
4590 OSKextExcludeLevel startMatchingOpt,
4591 OSArray * personalityNames)
4592 {
4593 OSReturn result = kOSReturnError;
4594 OSString * kextIdentifier = NULL; // must release
4595
4596 kextIdentifier = OSString::withCString(kextIdentifierCString);
4597 if (!kextIdentifier) {
4598 result = kOSKextReturnNoMemory;
4599 goto finish;
4600 }
4601 result = OSKext::loadKextWithIdentifier(kextIdentifier,
4602 NULL /* kextRef */,
4603 allowDeferFlag, delayAutounloadFlag,
4604 startOpt, startMatchingOpt, personalityNames);
4605
4606 finish:
4607 OSSafeReleaseNULL(kextIdentifier);
4608 return result;
4609 }
4610
4611 /*********************************************************************
4612 *********************************************************************/
4613 OSReturn
4614 OSKext::loadKextWithIdentifier(
4615 OSString * kextIdentifier,
4616 OSObject ** kextRef,
4617 Boolean allowDeferFlag,
4618 Boolean delayAutounloadFlag,
4619 OSKextExcludeLevel startOpt,
4620 OSKextExcludeLevel startMatchingOpt,
4621 OSArray * personalityNames)
4622 {
4623 OSReturn result = kOSReturnError;
4624 OSReturn pingResult = kOSReturnError;
4625 OSKext * theKext = NULL;// do not release
4626 OSDictionary * loadRequest = NULL;// must release
4627 const OSSymbol * kextIdentifierSymbol = NULL;// must release
4628
4629 if (kextRef) {
4630 *kextRef = NULL;
4631 }
4632
4633 IORecursiveLockLock(sKextLock);
4634
4635 if (!kextIdentifier) {
4636 result = kOSKextReturnInvalidArgument;
4637 goto finish;
4638 }
4639
4640 OSKext::recordIdentifierRequest(kextIdentifier);
4641
4642 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
4643 if (!theKext) {
4644 if (!allowDeferFlag) {
4645 OSKextLog(/* kext */ NULL,
4646 kOSKextLogErrorLevel |
4647 kOSKextLogLoadFlag,
4648 "Can't load kext %s - not found.",
4649 kextIdentifier->getCStringNoCopy());
4650 goto finish;
4651 }
4652
4653 if (!sKernelRequestsEnabled) {
4654 OSKextLog(theKext,
4655 kOSKextLogErrorLevel |
4656 kOSKextLogLoadFlag,
4657 "Can't load kext %s - requests to user space are disabled.",
4658 kextIdentifier->getCStringNoCopy());
4659 result = kOSKextReturnDisabled;
4660 goto finish;
4661 }
4662
4663 /* Create a new request unless one is already sitting
4664 * in sKernelRequests for this bundle identifier
4665 */
4666 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
4667 if (!sPostedKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
4668 result = _OSKextCreateRequest(kKextRequestPredicateRequestLoad,
4669 &loadRequest);
4670 if (result != kOSReturnSuccess) {
4671 goto finish;
4672 }
4673 if (!_OSKextSetRequestArgument(loadRequest,
4674 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
4675 result = kOSKextReturnNoMemory;
4676 goto finish;
4677 }
4678 if (!sKernelRequests->setObject(loadRequest)) {
4679 result = kOSKextReturnNoMemory;
4680 goto finish;
4681 }
4682
4683 if (!sPostedKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
4684 result = kOSKextReturnNoMemory;
4685 goto finish;
4686 }
4687
4688 OSKextLog(theKext,
4689 kOSKextLogDebugLevel |
4690 kOSKextLogLoadFlag,
4691 "Kext %s not found; queued load request to user space.",
4692 kextIdentifier->getCStringNoCopy());
4693 }
4694
4695 pingResult = OSKext::pingKextd();
4696 if (pingResult == kOSKextReturnDisabled) {
4697 OSKextLog(/* kext */ NULL,
4698 ((sPrelinkBoot) ? kOSKextLogDebugLevel : kOSKextLogErrorLevel) |
4699 kOSKextLogLoadFlag,
4700 "Kext %s might not load - kextd is currently unavailable.",
4701 kextIdentifier->getCStringNoCopy());
4702 }
4703
4704 result = kOSKextReturnDeferred;
4705 goto finish;
4706 }
4707
4708 result = theKext->load(startOpt, startMatchingOpt, personalityNames);
4709
4710 if (result != kOSReturnSuccess) {
4711 OSKextLog(theKext,
4712 kOSKextLogErrorLevel |
4713 kOSKextLogLoadFlag,
4714 "Failed to load kext %s (error 0x%x).",
4715 kextIdentifier->getCStringNoCopy(), (int)result);
4716
4717 OSKext::removeKext(theKext,
4718 /* terminateService/removePersonalities */ true);
4719 goto finish;
4720 }
4721
4722 if (delayAutounloadFlag) {
4723 OSKextLog(theKext,
4724 kOSKextLogProgressLevel |
4725 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4726 "Setting delayed autounload for %s.",
4727 kextIdentifier->getCStringNoCopy());
4728 theKext->flags.delayAutounload = 1;
4729 }
4730
4731 finish:
4732 OSSafeReleaseNULL(loadRequest);
4733 OSSafeReleaseNULL(kextIdentifierSymbol);
4734
4735 if ((kOSReturnSuccess == result) && kextRef) {
4736 theKext->retain();
4737 theKext->matchingRefCount++;
4738 *kextRef = theKext;
4739 }
4740
4741 IORecursiveLockUnlock(sKextLock);
4742
4743 return result;
4744 }
4745 /*********************************************************************
4746 *********************************************************************/
4747 /* static */
4748 void
4749 OSKext::dropMatchingReferences(
4750 OSSet * kexts)
4751 {
4752 IORecursiveLockLock(sKextLock);
4753 kexts->iterateObjects(^bool (OSObject * obj) {
4754 OSKext * thisKext = OSDynamicCast(OSKext, obj);
4755 if (!thisKext) {
4756 return false;
4757 }
4758 thisKext->matchingRefCount--;
4759 return false;
4760 });
4761 IORecursiveLockUnlock(sKextLock);
4762 }
4763
4764 /*********************************************************************
4765 *********************************************************************/
4766 /* static */
4767 void
4768 OSKext::recordIdentifierRequest(
4769 OSString * kextIdentifier)
4770 {
4771 const OSSymbol * kextIdentifierSymbol = NULL; // must release
4772 bool fail = false;
4773
4774 if (!sAllKextLoadIdentifiers || !kextIdentifier) {
4775 goto finish;
4776 }
4777
4778 kextIdentifierSymbol = OSSymbol::withString(kextIdentifier);
4779 if (!kextIdentifierSymbol) {
4780 // xxx - this is really a basic alloc failure
4781 fail = true;
4782 goto finish;
4783 }
4784
4785 IORecursiveLockLock(sKextLock);
4786 if (!sAllKextLoadIdentifiers->containsObject(kextIdentifierSymbol)) {
4787 if (!sAllKextLoadIdentifiers->setObject(kextIdentifierSymbol)) {
4788 fail = true;
4789 } else {
4790 // xxx - need to find a way to associate this whole func w/the kext
4791 OSKextLog(/* kext */ NULL,
4792 // xxx - check level
4793 kOSKextLogStepLevel |
4794 kOSKextLogArchiveFlag,
4795 "Recorded kext %s as a candidate for inclusion in prelinked kernel.",
4796 kextIdentifier->getCStringNoCopy());
4797 }
4798 }
4799 IORecursiveLockUnlock(sKextLock);
4800
4801 finish:
4802
4803 if (fail) {
4804 OSKextLog(/* kext */ NULL,
4805 kOSKextLogErrorLevel |
4806 kOSKextLogArchiveFlag,
4807 "Failed to record kext %s as a candidate for inclusion in prelinked kernel.",
4808 kextIdentifier->getCStringNoCopy());
4809 }
4810 OSSafeReleaseNULL(kextIdentifierSymbol);
4811 return;
4812 }
4813
4814 /*********************************************************************
4815 *********************************************************************/
4816 OSReturn
4817 OSKext::load(
4818 OSKextExcludeLevel startOpt,
4819 OSKextExcludeLevel startMatchingOpt,
4820 OSArray * personalityNames)
4821 {
4822 OSReturn result = kOSReturnError;
4823 kern_return_t kxldResult;
4824 OSKextExcludeLevel dependenciesStartOpt = startOpt;
4825 OSKextExcludeLevel dependenciesStartMatchingOpt = startMatchingOpt;
4826 unsigned int i, count;
4827 Boolean alreadyLoaded = false;
4828 OSKext * lastLoadedKext = NULL;
4829
4830 if (isInExcludeList()) {
4831 OSKextLog(this,
4832 kOSKextLogErrorLevel | kOSKextLogGeneralFlag |
4833 kOSKextLogLoadFlag,
4834 "Kext %s is in exclude list, not loadable",
4835 getIdentifierCString());
4836
4837 result = kOSKextReturnNotLoadable;
4838 goto finish;
4839 }
4840
4841 if (isLoaded()) {
4842 alreadyLoaded = true;
4843 result = kOSReturnSuccess;
4844
4845 OSKextLog(this,
4846 kOSKextLogDebugLevel |
4847 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
4848 "Kext %s is already loaded.",
4849 getIdentifierCString());
4850 goto loaded;
4851 }
4852
4853 #if CONFIG_MACF
4854 if (current_task() != kernel_task) {
4855 int macCheckResult = 0;
4856 kauth_cred_t cred = NULL;
4857
4858 cred = kauth_cred_get_with_ref();
4859 macCheckResult = mac_kext_check_load(cred, getIdentifierCString());
4860 kauth_cred_unref(&cred);
4861
4862 if (macCheckResult != 0) {
4863 result = kOSReturnError;
4864 OSKextLog(this,
4865 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
4866 "Failed to load kext %s (MAC policy error 0x%x).",
4867 getIdentifierCString(), macCheckResult);
4868 goto finish;
4869 }
4870 }
4871 #endif
4872
4873 if (!sLoadEnabled) {
4874 OSKextLog(this,
4875 kOSKextLogErrorLevel |
4876 kOSKextLogLoadFlag,
4877 "Kext loading is disabled (attempt to load kext %s).",
4878 getIdentifierCString());
4879 result = kOSKextReturnDisabled;
4880 goto finish;
4881 }
4882
4883 /* If we've pushed the next available load tag to the invalid value,
4884 * we can't load any more kexts.
4885 */
4886 if (sNextLoadTag == kOSKextInvalidLoadTag) {
4887 OSKextLog(this,
4888 kOSKextLogErrorLevel |
4889 kOSKextLogLoadFlag,
4890 "Can't load kext %s - no more load tags to assign.",
4891 getIdentifierCString());
4892 result = kOSKextReturnNoResources;
4893 goto finish;
4894 }
4895
4896 /* This is a bit of a hack, because we shouldn't be handling
4897 * personalities within the load function.
4898 */
4899 if (!declaresExecutable()) {
4900 /* There is a special case where a non-executable kext can be loaded: the
4901 * AppleKextExcludeList. Detect that special kext by bundle identifier and
4902 * load its metadata into the global data structures, if appropriate
4903 */
4904 if (strcmp(getIdentifierCString(), "com.apple.driver.KextExcludeList") == 0) {
4905 boolean_t updated = updateExcludeList(infoDict);
4906 if (updated) {
4907 OSKextLog(this,
4908 kOSKextLogDebugLevel | kOSKextLogLoadFlag,
4909 "KextExcludeList was updated to version: %lld", sExcludeListVersion);
4910 }
4911 }
4912
4913 if (isDriverKit()) {
4914 if (loadTag == 0) {
4915 sLoadedDriverKitKexts->setObject(this);
4916 loadTag = sNextLoadTag++;
4917 }
4918 }
4919 result = kOSReturnSuccess;
4920 goto loaded;
4921 }
4922
4923 /* Are we in safe boot?
4924 */
4925 if (sSafeBoot && !isLoadableInSafeBoot()) {
4926 OSKextLog(this,
4927 kOSKextLogErrorLevel |
4928 kOSKextLogLoadFlag,
4929 "Can't load kext %s - not loadable during safe boot.",
4930 getIdentifierCString());
4931 result = kOSKextReturnBootLevel;
4932 goto finish;
4933 }
4934
4935 OSKextLog(this,
4936 kOSKextLogProgressLevel | kOSKextLogLoadFlag,
4937 "Loading kext %s.",
4938 getIdentifierCString());
4939
4940 if (!sKxldContext) {
4941 kxldResult = kxld_create_context(&sKxldContext, &kern_allocate,
4942 &kxld_log_callback, /* Flags */ (KXLDFlags) 0,
4943 /* cputype */ 0, /* cpusubtype */ 0, /* page size */ 0);
4944 if (kxldResult) {
4945 OSKextLog(this,
4946 kOSKextLogErrorLevel |
4947 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
4948 "Can't load kext %s - failed to create link context.",
4949 getIdentifierCString());
4950 result = kOSKextReturnNoMemory;
4951 goto finish;
4952 }
4953 }
4954
4955 /* We only need to resolve dependencies once for the whole graph, but
4956 * resolveDependencies will just return if there's no work to do, so it's
4957 * safe to call it more than once.
4958 */
4959 if (!resolveDependencies()) {
4960 // xxx - check resolveDependencies() for log msg
4961 OSKextLog(this,
4962 kOSKextLogErrorLevel |
4963 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4964 "Can't load kext %s - failed to resolve library dependencies.",
4965 getIdentifierCString());
4966 result = kOSKextReturnDependencies;
4967 goto finish;
4968 }
4969
4970 /* If we are excluding just the kext being loaded now (and not its
4971 * dependencies), drop the exclusion level to none so dependencies
4972 * start and/or add their personalities.
4973 */
4974 if (dependenciesStartOpt == kOSKextExcludeKext) {
4975 dependenciesStartOpt = kOSKextExcludeNone;
4976 }
4977
4978 if (dependenciesStartMatchingOpt == kOSKextExcludeKext) {
4979 dependenciesStartMatchingOpt = kOSKextExcludeNone;
4980 }
4981
4982 /* Load the dependencies, recursively.
4983 */
4984 count = getNumDependencies();
4985 for (i = 0; i < count; i++) {
4986 OSKext * dependency = OSDynamicCast(OSKext,
4987 dependencies->getObject(i));
4988 if (dependency == NULL) {
4989 OSKextLog(this,
4990 kOSKextLogErrorLevel |
4991 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
4992 "Internal error loading kext %s; dependency disappeared.",
4993 getIdentifierCString());
4994 result = kOSKextReturnInternalError;
4995 goto finish;
4996 }
4997
4998 /* Dependencies must be started accorting to the opt,
4999 * but not given the personality names of the main kext.
5000 */
5001 result = dependency->load(dependenciesStartOpt,
5002 dependenciesStartMatchingOpt,
5003 /* personalityNames */ NULL);
5004 if (result != KERN_SUCCESS) {
5005 OSKextLog(this,
5006 kOSKextLogErrorLevel |
5007 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5008 "Dependency %s of kext %s failed to load.",
5009 dependency->getIdentifierCString(),
5010 getIdentifierCString());
5011
5012 OSKext::removeKext(dependency,
5013 /* terminateService/removePersonalities */ true);
5014 result = kOSKextReturnDependencyLoadError;
5015
5016 goto finish;
5017 }
5018 }
5019
5020 result = loadExecutable();
5021 if (result != KERN_SUCCESS) {
5022 goto finish;
5023 }
5024
5025 pendingPgoHead.next = &pendingPgoHead;
5026 pendingPgoHead.prev = &pendingPgoHead;
5027
5028 // The kernel PRNG is not initialized when the first kext is
5029 // loaded, so use early random
5030 uuid_generate_early_random(instance_uuid);
5031 account = IONew(OSKextAccount, 1);
5032 if (!account) {
5033 result = KERN_MEMORY_ERROR;
5034 goto finish;
5035 }
5036 bzero(account, sizeof(*account));
5037 account->loadTag = kmod_info->id;
5038 account->site.refcount = 0;
5039 account->site.flags = VM_TAG_KMOD;
5040 account->kext = this;
5041 if (gIOSurfaceIdentifier == bundleID) {
5042 vm_tag_alloc(&account->site);
5043 gIOSurfaceTag = account->site.tag;
5044 }
5045
5046 flags.loaded = true;
5047
5048 /* Add the kext to the list of loaded kexts and update the kmod_info
5049 * struct to point to that of the last loaded kext (which is the way
5050 * it's always been done, though I'd rather do them in order now).
5051 */
5052 lastLoadedKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
5053 sLoadedKexts->setObject(this);
5054
5055 /* Keep the kernel itself out of the kmod list.
5056 */
5057 if (lastLoadedKext->isKernel()) {
5058 lastLoadedKext = NULL;
5059 }
5060
5061 if (lastLoadedKext) {
5062 kmod_info->next = lastLoadedKext->kmod_info;
5063 }
5064
5065 notifyKextLoadObservers(this, kmod_info);
5066
5067 /* Make the global kmod list point at the just-loaded kext. Note that the
5068 * __kernel__ kext isn't in this list, as it wasn't before SnowLeopard,
5069 * although we do report it in kextstat these days by using the newer
5070 * OSArray of loaded kexts, which does contain it.
5071 *
5072 * (The OSKext object representing the kernel doesn't even have a kmod_info
5073 * struct, though I suppose we could stick a pointer to it from the
5074 * static struct in OSRuntime.cpp.)
5075 */
5076 kmod = kmod_info;
5077
5078 /* Save the list of loaded kexts in case we panic.
5079 */
5080 OSKext::saveLoadedKextPanicList();
5081
5082 if (isExecutable()) {
5083 OSKext::updateLoadedKextSummaries();
5084 savePanicString(/* isLoading */ true);
5085
5086 #if CONFIG_DTRACE
5087 registerWithDTrace();
5088 #else
5089 jettisonLinkeditSegment();
5090 #endif /* CONFIG_DTRACE */
5091
5092 #if !VM_MAPPED_KEXTS
5093 /* If there is a page (or more) worth of padding after the end
5094 * of the last data section but before the end of the data segment
5095 * then free it in the same manner the LinkeditSegment is freed
5096 */
5097 jettisonDATASegmentPadding();
5098 #endif
5099 }
5100
5101 loaded:
5102 if (isExecutable() && !flags.started) {
5103 if (startOpt == kOSKextExcludeNone) {
5104 result = start();
5105 if (result != kOSReturnSuccess) {
5106 OSKextLog(this,
5107 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5108 "Kext %s start failed (result 0x%x).",
5109 getIdentifierCString(), result);
5110 result = kOSKextReturnStartStopError;
5111 }
5112 }
5113 }
5114
5115 /* If not excluding matching, send the personalities to the kernel.
5116 * This never affects the result of the load operation.
5117 * This is a bit of a hack, because we shouldn't be handling
5118 * personalities within the load function.
5119 */
5120 if (result == kOSReturnSuccess && startMatchingOpt == kOSKextExcludeNone) {
5121 result = sendPersonalitiesToCatalog(true, personalityNames);
5122 }
5123
5124 finish:
5125
5126 if (result != kOSReturnSuccess) {
5127 OSKextLog(this,
5128 kOSKextLogErrorLevel |
5129 kOSKextLogLoadFlag,
5130 "Kext %s failed to load (0x%x).",
5131 getIdentifierCString(), (int)result);
5132 } else if (!alreadyLoaded) {
5133 OSKextLog(this,
5134 kOSKextLogProgressLevel |
5135 kOSKextLogLoadFlag,
5136 "Kext %s loaded.",
5137 getIdentifierCString());
5138
5139 queueKextNotification(kKextRequestPredicateLoadNotification,
5140 OSDynamicCast(OSString, bundleID));
5141 }
5142 return result;
5143 }
5144
5145 /*********************************************************************
5146 *
5147 *********************************************************************/
5148 static char *
5149 strdup(const char * string)
5150 {
5151 char * result = NULL;
5152 size_t size;
5153
5154 if (!string) {
5155 goto finish;
5156 }
5157
5158 size = 1 + strlen(string);
5159 result = (char *)kalloc_tag(size, VM_KERN_MEMORY_OSKEXT);
5160 if (!result) {
5161 goto finish;
5162 }
5163
5164 memcpy(result, string, size);
5165
5166 finish:
5167 return result;
5168 }
5169
5170 /*********************************************************************
5171 *
5172 *********************************************************************/
5173
5174 kernel_section_t *
5175 OSKext::lookupSection(const char *segname, const char *secname)
5176 {
5177 kernel_section_t * found_section = NULL;
5178 kernel_mach_header_t * mh = NULL;
5179 kernel_segment_command_t * seg = NULL;
5180 kernel_section_t * sec = NULL;
5181
5182 if (!linkedExecutable) {
5183 return NULL;
5184 }
5185
5186 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
5187
5188 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
5189 if (0 != strncmp(seg->segname, segname, sizeof(seg->segname))) {
5190 continue;
5191 }
5192
5193 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
5194 if (0 == strncmp(sec->sectname, secname, sizeof(sec->sectname))) {
5195 found_section = sec;
5196 goto out;
5197 }
5198 }
5199 }
5200
5201 out:
5202 return found_section;
5203 }
5204
5205 /*********************************************************************
5206 *
5207 *********************************************************************/
5208
5209 OSReturn
5210 OSKext::slidePrelinkedExecutable(bool doCoalesedSlides)
5211 {
5212 OSReturn result = kOSKextReturnBadData;
5213 kernel_mach_header_t * mh = NULL;
5214 kernel_segment_command_t * seg = NULL;
5215 kernel_segment_command_t * linkeditSeg = NULL;
5216 kernel_section_t * sec = NULL;
5217 char * linkeditBase = NULL;
5218 bool haveLinkeditBase = false;
5219 char * relocBase = NULL;
5220 bool haveRelocBase = false;
5221 struct dysymtab_command * dysymtab = NULL;
5222 struct linkedit_data_command * segmentSplitInfo = NULL;
5223 struct symtab_command * symtab = NULL;
5224 kernel_nlist_t * sym = NULL;
5225 struct relocation_info * reloc = NULL;
5226 uint32_t i = 0;
5227 int reloc_size;
5228 vm_offset_t new_kextsize;
5229
5230 if (linkedExecutable == NULL || flags.builtin) {
5231 result = kOSReturnSuccess;
5232 goto finish;
5233 }
5234
5235 mh = (kernel_mach_header_t *)linkedExecutable->getBytesNoCopy();
5236 segmentSplitInfo = (struct linkedit_data_command *) getcommandfromheader(mh, LC_SEGMENT_SPLIT_INFO);
5237
5238 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
5239 if (!seg->vmaddr) {
5240 continue;
5241 }
5242
5243 seg->vmaddr = ml_static_slide(seg->vmaddr);
5244
5245 #if KASLR_KEXT_DEBUG
5246 IOLog("kaslr: segname %s unslid 0x%lx slid 0x%lx \n",
5247 seg->segname,
5248 (unsigned long)ml_static_unslide(seg->vmaddr),
5249 (unsigned long)seg->vmaddr);
5250 #endif
5251
5252 if (!haveRelocBase) {
5253 relocBase = (char *) seg->vmaddr;
5254 haveRelocBase = true;
5255 }
5256 if (!strcmp(seg->segname, "__LINKEDIT")) {
5257 linkeditBase = (char *) seg->vmaddr - seg->fileoff;
5258 haveLinkeditBase = true;
5259 linkeditSeg = seg;
5260 }
5261 for (sec = firstsect(seg); sec != NULL; sec = nextsect(seg, sec)) {
5262 sec->addr = ml_static_slide(sec->addr);
5263
5264 #if KASLR_KEXT_DEBUG
5265 IOLog("kaslr: sectname %s unslid 0x%lx slid 0x%lx \n",
5266 sec->sectname,
5267 (unsigned long)ml_static_unslide(sec->addr),
5268 (unsigned long)sec->addr);
5269 #endif
5270 }
5271 }
5272
5273 dysymtab = (struct dysymtab_command *) getcommandfromheader(mh, LC_DYSYMTAB);
5274
5275 symtab = (struct symtab_command *) getcommandfromheader(mh, LC_SYMTAB);
5276
5277 if (symtab != NULL && doCoalesedSlides == false) {
5278 /* Some pseudo-kexts have symbol tables without segments.
5279 * Ignore them. */
5280 if (symtab->nsyms > 0 && haveLinkeditBase) {
5281 sym = (kernel_nlist_t *) (linkeditBase + symtab->symoff);
5282 for (i = 0; i < symtab->nsyms; i++) {
5283 if (sym[i].n_type & N_STAB) {
5284 continue;
5285 }
5286 sym[i].n_value = ml_static_slide(sym[i].n_value);
5287
5288 #if KASLR_KEXT_DEBUG
5289 #define MAX_SYMS_TO_LOG 5
5290 if (i < MAX_SYMS_TO_LOG) {
5291 IOLog("kaslr: LC_SYMTAB unslid 0x%lx slid 0x%lx \n",
5292 (unsigned long)ml_static_unslide(sym[i].n_value),
5293 (unsigned long)sym[i].n_value);
5294 }
5295 #endif
5296 }
5297 }
5298 }
5299
5300 if (dysymtab != NULL && doCoalesedSlides == false) {
5301 if (dysymtab->nextrel > 0) {
5302 OSKextLog(this,
5303 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5304 kOSKextLogLinkFlag,
5305 "Sliding kext %s: External relocations found.",
5306 getIdentifierCString());
5307 goto finish;
5308 }
5309
5310 if (dysymtab->nlocrel > 0) {
5311 if (!haveLinkeditBase) {
5312 OSKextLog(this,
5313 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5314 kOSKextLogLinkFlag,
5315 "Sliding kext %s: No linkedit segment.",
5316 getIdentifierCString());
5317 goto finish;
5318 }
5319
5320 if (!haveRelocBase) {
5321 OSKextLog(this,
5322 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5323 kOSKextLogLinkFlag,
5324 #if __x86_64__
5325 "Sliding kext %s: No writable segments.",
5326 #else
5327 "Sliding kext %s: No segments.",
5328 #endif
5329 getIdentifierCString());
5330 goto finish;
5331 }
5332
5333 reloc = (struct relocation_info *) (linkeditBase + dysymtab->locreloff);
5334 reloc_size = dysymtab->nlocrel * sizeof(struct relocation_info);
5335
5336 for (i = 0; i < dysymtab->nlocrel; i++) {
5337 if (reloc[i].r_extern != 0
5338 || reloc[i].r_type != 0
5339 || reloc[i].r_length != (sizeof(void *) == 8 ? 3 : 2)
5340 ) {
5341 OSKextLog(this,
5342 kOSKextLogErrorLevel | kOSKextLogLoadFlag |
5343 kOSKextLogLinkFlag,
5344 "Sliding kext %s: Unexpected relocation found.",
5345 getIdentifierCString());
5346 goto finish;
5347 }
5348 if (reloc[i].r_pcrel != 0) {
5349 continue;
5350 }
5351 uintptr_t *relocAddr = (uintptr_t*)(relocBase + reloc[i].r_address);
5352 *relocAddr = ml_static_slide(*relocAddr);
5353
5354 #if KASLR_KEXT_DEBUG
5355 #define MAX_DYSYMS_TO_LOG 5
5356 if (i < MAX_DYSYMS_TO_LOG) {
5357 IOLog("kaslr: LC_DYSYMTAB unslid 0x%lx slid 0x%lx \n",
5358 (unsigned long)ml_static_unslide(*((uintptr_t *)(relocAddr))),
5359 (unsigned long)*((uintptr_t *)(relocBase + reloc[i].r_address)));
5360 }
5361 #endif
5362 }
5363
5364 /* We should free these relocations, not just delete the reference to them.
5365 * <rdar://problem/10535549> Free relocations from PIE kexts.
5366 *
5367 * For now, we do not free LINKEDIT for kexts with split segments.
5368 */
5369 new_kextsize = round_page(kmod_info->size - reloc_size);
5370 if (((kmod_info->size - new_kextsize) > PAGE_SIZE) && (!segmentSplitInfo)) {
5371 vm_offset_t endofkext = kmod_info->address + kmod_info->size;
5372 vm_offset_t new_endofkext = kmod_info->address + new_kextsize;
5373 vm_offset_t endofrelocInfo = (vm_offset_t) (((uint8_t *)reloc) + reloc_size);
5374 int bytes_remaining = endofkext - endofrelocInfo;
5375 OSData * new_osdata = NULL;
5376
5377 /* fix up symbol offsets if they are after the dsymtab local relocs */
5378 if (symtab) {
5379 if (dysymtab->locreloff < symtab->symoff) {
5380 symtab->symoff -= reloc_size;
5381 }
5382 if (dysymtab->locreloff < symtab->stroff) {
5383 symtab->stroff -= reloc_size;
5384 }
5385 }
5386 if (dysymtab->locreloff < dysymtab->extreloff) {
5387 dysymtab->extreloff -= reloc_size;
5388 }
5389
5390 /* move data behind reloc info down to new offset */
5391 if (endofrelocInfo < endofkext) {
5392 memcpy(reloc, (void *)endofrelocInfo, bytes_remaining);
5393 }
5394
5395 /* Create a new OSData for the smaller kext object and reflect
5396 * new linkedit segment size.
5397 */
5398 linkeditSeg->vmsize = round_page(linkeditSeg->vmsize - reloc_size);
5399 linkeditSeg->filesize = linkeditSeg->vmsize;
5400
5401 new_osdata = OSData::withBytesNoCopy((void *)kmod_info->address, new_kextsize);
5402 if (new_osdata) {
5403 /* Fix up kmod info and linkedExecutable.
5404 */
5405 kmod_info->size = new_kextsize;
5406 #if VM_MAPPED_KEXTS
5407 new_osdata->setDeallocFunction(osdata_kext_free);
5408 #else
5409 new_osdata->setDeallocFunction(osdata_phys_free);
5410 #endif
5411 linkedExecutable->setDeallocFunction(NULL);
5412 linkedExecutable->release();
5413 linkedExecutable = new_osdata;
5414
5415 #if VM_MAPPED_KEXTS
5416 kext_free(new_endofkext, (endofkext - new_endofkext));
5417 #else
5418 ml_static_mfree(new_endofkext, (endofkext - new_endofkext));
5419 #endif
5420 }
5421 }
5422 dysymtab->nlocrel = 0;
5423 dysymtab->locreloff = 0;
5424 }
5425 }
5426
5427 result = kOSReturnSuccess;
5428 finish:
5429 return result;
5430 }
5431
5432 /*********************************************************************
5433 * called only by load()
5434 *********************************************************************/
5435 OSReturn
5436 OSKext::loadExecutable()
5437 {
5438 OSReturn result = kOSReturnError;
5439 kern_return_t kxldResult;
5440 KXLDDependency * kxlddeps = NULL;// must kfree
5441 uint32_t num_kxlddeps = 0;
5442 OSArray * linkDependencies = NULL;// must release
5443 uint32_t numDirectDependencies = 0;
5444 uint32_t num_kmod_refs = 0;
5445 struct mach_header ** kxldHeaderPtr = NULL;// do not free
5446 struct mach_header * kxld_header = NULL;// xxx - need to free here?
5447 OSData * theExecutable = NULL;// do not release
5448 OSString * versString = NULL;// do not release
5449 const char * versCString = NULL;// do not free
5450 const char * string = NULL;// do not free
5451 unsigned int i;
5452
5453 /* We need the version string for a variety of bits below.
5454 */
5455 versString = OSDynamicCast(OSString,
5456 getPropertyForHostArch(kCFBundleVersionKey));
5457 if (!versString) {
5458 goto finish;
5459 }
5460 versCString = versString->getCStringNoCopy();
5461
5462 if (isKernelComponent()) {
5463 if (STRING_HAS_PREFIX(versCString, KERNEL_LIB_PREFIX)) {
5464 if (strncmp(versCString, KERNEL6_VERSION, strlen(KERNEL6_VERSION))) {
5465 OSKextLog(this,
5466 kOSKextLogErrorLevel |
5467 kOSKextLogLoadFlag,
5468 "Kernel component %s has incorrect version %s; "
5469 "expected %s.",
5470 getIdentifierCString(),
5471 versCString, KERNEL6_VERSION);
5472 result = kOSKextReturnInternalError;
5473 goto finish;
5474 } else if (strcmp(versCString, osrelease)) {
5475 OSKextLog(this,
5476 kOSKextLogErrorLevel |
5477 kOSKextLogLoadFlag,
5478 "Kernel component %s has incorrect version %s; "
5479 "expected %s.",
5480 getIdentifierCString(),
5481 versCString, osrelease);
5482 result = kOSKextReturnInternalError;
5483 goto finish;
5484 }
5485 }
5486 }
5487
5488 if (isPrelinked()) {
5489 goto register_kmod;
5490 }
5491
5492 /* <rdar://problem/21444003> all callers must be entitled */
5493 if (FALSE == IOTaskHasEntitlement(current_task(), kOSKextManagementEntitlement)) {
5494 OSKextLog(this,
5495 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5496 "Not entitled to link kext '%s'",
5497 getIdentifierCString());
5498 result = kOSKextReturnNotPrivileged;
5499 goto finish;
5500 }
5501
5502 theExecutable = getExecutable();
5503 if (!theExecutable) {
5504 if (declaresExecutable()) {
5505 OSKextLog(this,
5506 kOSKextLogErrorLevel |
5507 kOSKextLogLoadFlag,
5508 "Can't load kext %s - executable is missing.",
5509 getIdentifierCString());
5510 result = kOSKextReturnValidation;
5511 goto finish;
5512 }
5513 goto register_kmod;
5514 }
5515
5516 if (isInterface()) {
5517 OSData *executableCopy = OSData::withData(theExecutable);
5518 setLinkedExecutable(executableCopy);
5519 executableCopy->release();
5520 goto register_kmod;
5521 }
5522
5523 numDirectDependencies = getNumDependencies();
5524
5525 if (flags.hasBleedthrough) {
5526 linkDependencies = dependencies;
5527 linkDependencies->retain();
5528 } else {
5529 linkDependencies = OSArray::withArray(dependencies);
5530 if (!linkDependencies) {
5531 OSKextLog(this,
5532 kOSKextLogErrorLevel |
5533 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5534 "Can't allocate link dependencies to load kext %s.",
5535 getIdentifierCString());
5536 goto finish;
5537 }
5538
5539 for (i = 0; i < numDirectDependencies; ++i) {
5540 OSKext * dependencyKext = OSDynamicCast(OSKext,
5541 dependencies->getObject(i));
5542 dependencyKext->addBleedthroughDependencies(linkDependencies);
5543 }
5544 }
5545
5546 num_kxlddeps = linkDependencies->getCount();
5547 if (!num_kxlddeps) {
5548 OSKextLog(this,
5549 kOSKextLogErrorLevel |
5550 kOSKextLogLoadFlag | kOSKextLogDependenciesFlag,
5551 "Can't load kext %s - it has no library dependencies.",
5552 getIdentifierCString());
5553 goto finish;
5554 }
5555
5556 kxlddeps = (KXLDDependency *)kalloc_tag(num_kxlddeps * sizeof(*kxlddeps), VM_KERN_MEMORY_OSKEXT);
5557 if (!kxlddeps) {
5558 OSKextLog(this,
5559 kOSKextLogErrorLevel |
5560 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5561 "Can't allocate link context to load kext %s.",
5562 getIdentifierCString());
5563 goto finish;
5564 }
5565 bzero(kxlddeps, num_kxlddeps * sizeof(*kxlddeps));
5566
5567 for (i = 0; i < num_kxlddeps; ++i) {
5568 OSKext * dependency = OSDynamicCast(OSKext, linkDependencies->getObject(i));
5569
5570 if (dependency->isInterface()) {
5571 OSKext *interfaceTargetKext = NULL;
5572 OSData * interfaceTarget = NULL;
5573
5574 if (dependency->isKernelComponent()) {
5575 interfaceTargetKext = sKernelKext;
5576 interfaceTarget = sKernelKext->linkedExecutable;
5577 } else {
5578 interfaceTargetKext = OSDynamicCast(OSKext,
5579 dependency->dependencies->getObject(0));
5580
5581 interfaceTarget = interfaceTargetKext->linkedExecutable;
5582 }
5583
5584 if (!interfaceTarget) {
5585 // panic?
5586 goto finish;
5587 }
5588
5589 /* The names set here aren't actually logged yet <rdar://problem/7941514>,
5590 * it will be useful to have them in the debugger.
5591 * strdup() failing isn't critical right here so we don't check that.
5592 */
5593 kxlddeps[i].kext = (u_char *) interfaceTarget->getBytesNoCopy();
5594 kxlddeps[i].kext_size = interfaceTarget->getLength();
5595 kxlddeps[i].kext_name = strdup(interfaceTargetKext->getIdentifierCString());
5596
5597 kxlddeps[i].interface = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
5598 kxlddeps[i].interface_size = dependency->linkedExecutable->getLength();
5599 kxlddeps[i].interface_name = strdup(dependency->getIdentifierCString());
5600 } else {
5601 kxlddeps[i].kext = (u_char *) dependency->linkedExecutable->getBytesNoCopy();
5602 kxlddeps[i].kext_size = dependency->linkedExecutable->getLength();
5603 kxlddeps[i].kext_name = strdup(dependency->getIdentifierCString());
5604 }
5605
5606 kxlddeps[i].is_direct_dependency = (i < numDirectDependencies);
5607 }
5608
5609 kxldHeaderPtr = &kxld_header;
5610
5611 #if DEBUG
5612 OSKextLog(this,
5613 kOSKextLogExplicitLevel |
5614 kOSKextLogLoadFlag | kOSKextLogLinkFlag,
5615 "Kext %s - calling kxld_link_file:\n"
5616 " kxld_context: %p\n"
5617 " executable: %p executable_length: %d\n"
5618 " user_data: %p\n"
5619 " kxld_dependencies: %p num_dependencies: %d\n"
5620 " kxld_header_ptr: %p kmod_info_ptr: %p\n",
5621 getIdentifierCString(), sKxldContext,
5622 theExecutable->getBytesNoCopy(), theExecutable->getLength(),
5623 this, kxlddeps, num_kxlddeps,
5624 kxldHeaderPtr, &kmod_info);
5625 #endif
5626
5627 /* After this call, the linkedExecutable instance variable
5628 * should exist.
5629 */
5630 kxldResult = kxld_link_file(sKxldContext,
5631 (u_char *)theExecutable->getBytesNoCopy(),
5632 theExecutable->getLength(),
5633 getIdentifierCString(), this, kxlddeps, num_kxlddeps,
5634 (u_char **)kxldHeaderPtr, (kxld_addr_t *)&kmod_info);
5635
5636 if (kxldResult != KERN_SUCCESS) {
5637 // xxx - add kxldResult here?
5638 OSKextLog(this,
5639 kOSKextLogErrorLevel |
5640 kOSKextLogLoadFlag,
5641 "Can't load kext %s - link failed.",
5642 getIdentifierCString());
5643 result = kOSKextReturnLinkError;
5644 goto finish;
5645 }
5646
5647 /* We've written data & instructions into kernel memory, so flush the data
5648 * cache and invalidate the instruction cache.
5649 * I/D caches are coherent on x86
5650 */
5651 #if !defined(__i386__) && !defined(__x86_64__)
5652 flush_dcache(kmod_info->address, kmod_info->size, false);
5653 invalidate_icache(kmod_info->address, kmod_info->size, false);
5654 #endif
5655 register_kmod:
5656
5657 if (isInterface()) {
5658 /* Whip up a fake kmod_info entry for the interface kext.
5659 */
5660 kmod_info = (kmod_info_t *)kalloc_tag(sizeof(kmod_info_t), VM_KERN_MEMORY_OSKEXT);
5661 if (!kmod_info) {
5662 result = KERN_MEMORY_ERROR;
5663 goto finish;
5664 }
5665
5666 /* A pseudokext has almost nothing in its kmod_info struct.
5667 */
5668 bzero(kmod_info, sizeof(kmod_info_t));
5669
5670 kmod_info->info_version = KMOD_INFO_VERSION;
5671
5672 /* An interface kext doesn't have a linkedExecutable, so save a
5673 * copy of the UUID out of the original executable via copyUUID()
5674 * while we still have the original executable.
5675 */
5676 interfaceUUID = copyUUID();
5677 }
5678
5679 kmod_info->id = loadTag = sNextLoadTag++;
5680 kmod_info->reference_count = 0; // KMOD_DECL... sets it to -1 (invalid).
5681
5682 /* Stamp the bundle ID and version from the OSKext over anything
5683 * resident inside the kmod_info.
5684 */
5685 string = getIdentifierCString();
5686 strlcpy(kmod_info->name, string, sizeof(kmod_info->name));
5687
5688 string = versCString;
5689 strlcpy(kmod_info->version, string, sizeof(kmod_info->version));
5690
5691 /* Add the dependencies' kmod_info structs as kmod_references.
5692 */
5693 num_kmod_refs = getNumDependencies();
5694 if (num_kmod_refs) {
5695 kmod_info->reference_list = (kmod_reference_t *)kalloc_tag(
5696 num_kmod_refs * sizeof(kmod_reference_t), VM_KERN_MEMORY_OSKEXT);
5697 if (!kmod_info->reference_list) {
5698 result = KERN_MEMORY_ERROR;
5699 goto finish;
5700 }
5701 bzero(kmod_info->reference_list,
5702 num_kmod_refs * sizeof(kmod_reference_t));
5703 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
5704 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
5705 OSKext * refKext = OSDynamicCast(OSKext, dependencies->getObject(refIndex));
5706 ref->info = refKext->kmod_info;
5707 ref->info->reference_count++;
5708
5709 if (refIndex + 1 < num_kmod_refs) {
5710 ref->next = kmod_info->reference_list + refIndex + 1;
5711 }
5712 }
5713 }
5714
5715 if (!isInterface() && linkedExecutable) {
5716 OSKextLog(this,
5717 kOSKextLogProgressLevel |
5718 kOSKextLogLoadFlag,
5719 "Kext %s executable loaded; %u pages at 0x%lx (load tag %u).",
5720 kmod_info->name,
5721 (unsigned)kmod_info->size / PAGE_SIZE,
5722 (unsigned long)ml_static_unslide(kmod_info->address),
5723 (unsigned)kmod_info->id);
5724 }
5725
5726 /* if prelinked, VM protections are already set */
5727 result = setVMAttributes(!isPrelinked(), true);
5728 if (result != KERN_SUCCESS) {
5729 goto finish;
5730 }
5731
5732 #if KASAN
5733 if (linkedExecutable) {
5734 kasan_load_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(),
5735 linkedExecutable->getLength(), getIdentifierCString());
5736 }
5737 #else
5738 if (lookupSection(KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME)) {
5739 OSKextLog(this,
5740 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
5741 "KASAN: cannot load KASAN-ified kext %s on a non-KASAN kernel\n",
5742 getIdentifierCString()
5743 );
5744 result = KERN_FAILURE;
5745 goto finish;
5746 }
5747 #endif
5748
5749 result = kOSReturnSuccess;
5750
5751 finish:
5752 OSSafeReleaseNULL(linkDependencies);
5753
5754 /* Clear up locally allocated dependency info.
5755 */
5756 for (i = 0; i < num_kxlddeps; ++i) {
5757 size_t size;
5758
5759 if (kxlddeps[i].kext_name) {
5760 size = 1 + strlen(kxlddeps[i].kext_name);
5761 kfree(kxlddeps[i].kext_name, size);
5762 }
5763 if (kxlddeps[i].interface_name) {
5764 size = 1 + strlen(kxlddeps[i].interface_name);
5765 kfree(kxlddeps[i].interface_name, size);
5766 }
5767 }
5768 if (kxlddeps) {
5769 kfree(kxlddeps, (num_kxlddeps * sizeof(*kxlddeps)));
5770 }
5771
5772 /* We no longer need the unrelocated executable (which the linker
5773 * has altered anyhow).
5774 */
5775 setExecutable(NULL);
5776
5777 if (result != kOSReturnSuccess) {
5778 OSKextLog(this,
5779 kOSKextLogErrorLevel |
5780 kOSKextLogLoadFlag,
5781 "Failed to load executable for kext %s.",
5782 getIdentifierCString());
5783
5784 if (kmod_info && kmod_info->reference_list) {
5785 kfree(kmod_info->reference_list,
5786 num_kmod_refs * sizeof(kmod_reference_t));
5787 }
5788 if (isInterface()) {
5789 kfree(kmod_info, sizeof(kmod_info_t));
5790 }
5791 kmod_info = NULL;
5792 if (linkedExecutable) {
5793 linkedExecutable->release();
5794 linkedExecutable = NULL;
5795 }
5796 }
5797
5798 return result;
5799 }
5800
5801 /*********************************************************************
5802 * The linkedit segment is used by the kext linker for dependency
5803 * resolution, and by dtrace for probe initialization. We can free it
5804 * for non-library kexts, since no kexts depend on non-library kexts
5805 * by definition, once dtrace has been initialized.
5806 *********************************************************************/
5807 void
5808 OSKext::jettisonLinkeditSegment(void)
5809 {
5810 kernel_mach_header_t * machhdr = (kernel_mach_header_t *)kmod_info->address;
5811 kernel_segment_command_t * linkedit = NULL;
5812 vm_offset_t start;
5813 vm_size_t linkeditsize, kextsize;
5814 OSData * data = NULL;
5815
5816 #if NO_KEXTD
5817 /* We can free symbol tables for all embedded kexts because we don't
5818 * support runtime kext linking.
5819 */
5820 if (sKeepSymbols || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
5821 #else
5822 if (sKeepSymbols || isLibrary() || !isExecutable() || !linkedExecutable || flags.jettisonLinkeditSeg) {
5823 #endif
5824 goto finish;
5825 }
5826
5827 /* Find the linkedit segment. If it's not the last segment, then freeing
5828 * it will fragment the kext into multiple VM regions, which OSKext is not
5829 * designed to handle, so we'll have to skip it.
5830 */
5831 linkedit = getsegbynamefromheader(machhdr, SEG_LINKEDIT);
5832 if (!linkedit) {
5833 goto finish;
5834 }
5835
5836 if (round_page(kmod_info->address + kmod_info->size) !=
5837 round_page(linkedit->vmaddr + linkedit->vmsize)) {
5838 goto finish;
5839 }
5840
5841 /* Create a new OSData for the smaller kext object.
5842 */
5843 linkeditsize = round_page(linkedit->vmsize);
5844 kextsize = kmod_info->size - linkeditsize;
5845 start = linkedit->vmaddr;
5846
5847 data = OSData::withBytesNoCopy((void *)kmod_info->address, kextsize);
5848 if (!data) {
5849 goto finish;
5850 }
5851
5852 /* Fix the kmod info and linkedExecutable.
5853 */
5854 kmod_info->size = kextsize;
5855
5856 #if VM_MAPPED_KEXTS
5857 data->setDeallocFunction(osdata_kext_free);
5858 #else
5859 data->setDeallocFunction(osdata_phys_free);
5860 #endif
5861 linkedExecutable->setDeallocFunction(NULL);
5862 linkedExecutable->release();
5863 linkedExecutable = data;
5864 flags.jettisonLinkeditSeg = 1;
5865
5866 /* Free the linkedit segment.
5867 */
5868 #if VM_MAPPED_KEXTS
5869 kext_free(start, linkeditsize);
5870 #else
5871 ml_static_mfree(start, linkeditsize);
5872 #endif
5873
5874 finish:
5875 return;
5876 }
5877
5878 /*********************************************************************
5879 * If there are whole pages that are unused betweem the last section
5880 * of the DATA segment and the end of the DATA segment then we can free
5881 * them
5882 *********************************************************************/
5883 void
5884 OSKext::jettisonDATASegmentPadding(void)
5885 {
5886 kernel_mach_header_t * mh;
5887 kernel_segment_command_t * dataSeg;
5888 kernel_section_t * sec, * lastSec;
5889 vm_offset_t dataSegEnd, lastSecEnd;
5890 vm_size_t padSize;
5891
5892 if (flags.builtin) {
5893 return;
5894 }
5895 mh = (kernel_mach_header_t *)kmod_info->address;
5896
5897 dataSeg = getsegbynamefromheader(mh, SEG_DATA);
5898 if (dataSeg == NULL) {
5899 return;
5900 }
5901
5902 lastSec = NULL;
5903 sec = firstsect(dataSeg);
5904 while (sec != NULL) {
5905 lastSec = sec;
5906 sec = nextsect(dataSeg, sec);
5907 }
5908
5909 if (lastSec == NULL) {
5910 return;
5911 }
5912
5913 if ((dataSeg->vmaddr != round_page(dataSeg->vmaddr)) ||
5914 (dataSeg->vmsize != round_page(dataSeg->vmsize))) {
5915 return;
5916 }
5917
5918 dataSegEnd = dataSeg->vmaddr + dataSeg->vmsize;
5919 lastSecEnd = round_page(lastSec->addr + lastSec->size);
5920
5921 if (dataSegEnd <= lastSecEnd) {
5922 return;
5923 }
5924
5925 padSize = dataSegEnd - lastSecEnd;
5926
5927 if (padSize >= PAGE_SIZE) {
5928 #if VM_MAPPED_KEXTS
5929 kext_free(lastSecEnd, padSize);
5930 #else
5931 ml_static_mfree(lastSecEnd, padSize);
5932 #endif
5933 }
5934 }
5935
5936 /*********************************************************************
5937 *********************************************************************/
5938 void
5939 OSKext::setLinkedExecutable(OSData * anExecutable)
5940 {
5941 if (linkedExecutable) {
5942 panic("Attempt to set linked executable on kext "
5943 "that already has one (%s).\n",
5944 getIdentifierCString());
5945 }
5946 linkedExecutable = anExecutable;
5947 linkedExecutable->retain();
5948 return;
5949 }
5950
5951 #if CONFIG_DTRACE
5952 /*********************************************************************
5953 * Go through all loaded kexts and tell them to register with dtrace.
5954 * The instance method only registers if necessary.
5955 *********************************************************************/
5956 /* static */
5957 void
5958 OSKext::registerKextsWithDTrace(void)
5959 {
5960 uint32_t count = sLoadedKexts->getCount();
5961 uint32_t i;
5962
5963 IORecursiveLockLock(sKextLock);
5964
5965 for (i = 0; i < count; i++) {
5966 OSKext * thisKext = NULL;// do not release
5967
5968 thisKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
5969 if (!thisKext || !thisKext->isExecutable()) {
5970 continue;
5971 }
5972
5973 thisKext->registerWithDTrace();
5974 }
5975
5976 IORecursiveLockUnlock(sKextLock);
5977
5978 return;
5979 }
5980
5981 extern "C" {
5982 extern int (*dtrace_modload)(struct kmod_info *, uint32_t);
5983 extern int (*dtrace_modunload)(struct kmod_info *);
5984 };
5985
5986 /*********************************************************************
5987 *********************************************************************/
5988 void
5989 OSKext::registerWithDTrace(void)
5990 {
5991 /* Register kext with dtrace. A dtrace_modload failure should not
5992 * prevent a kext from loading, so we ignore the return code.
5993 */
5994 if (!flags.dtraceInitialized && (dtrace_modload != NULL)) {
5995 uint32_t modflag = 0;
5996 OSObject * forceInit = getPropertyForHostArch("OSBundleForceDTraceInit");
5997 if (forceInit == kOSBooleanTrue) {
5998 modflag |= KMOD_DTRACE_FORCE_INIT;
5999 }
6000 if (flags.builtin) {
6001 modflag |= KMOD_DTRACE_STATIC_KEXT;
6002 }
6003
6004 (void)(*dtrace_modload)(kmod_info, modflag);
6005 flags.dtraceInitialized = true;
6006 jettisonLinkeditSegment();
6007 }
6008 return;
6009 }
6010 /*********************************************************************
6011 *********************************************************************/
6012 void
6013 OSKext::unregisterWithDTrace(void)
6014 {
6015 /* Unregister kext with dtrace. A dtrace_modunload failure should not
6016 * prevent a kext from loading, so we ignore the return code.
6017 */
6018 if (flags.dtraceInitialized && (dtrace_modunload != NULL)) {
6019 (void)(*dtrace_modunload)(kmod_info);
6020 flags.dtraceInitialized = false;
6021 }
6022 return;
6023 }
6024 #endif /* CONFIG_DTRACE */
6025
6026
6027 /*********************************************************************
6028 * called only by loadExecutable()
6029 *********************************************************************/
6030 #if !VM_MAPPED_KEXTS
6031 #if defined(__arm__) || defined(__arm64__)
6032 static inline kern_return_t
6033 OSKext_protect(
6034 vm_map_t map,
6035 vm_map_offset_t start,
6036 vm_map_offset_t end,
6037 vm_prot_t new_prot,
6038 boolean_t set_max)
6039 {
6040 #pragma unused(map)
6041 assert(map == kernel_map); // we can handle KEXTs arising from the PRELINK segment and no others
6042 assert(start <= end);
6043 if (start >= end) {
6044 return KERN_SUCCESS; // Punt segments of length zero (e.g., headers) or less (i.e., blunders)
6045 } else if (set_max) {
6046 return KERN_SUCCESS; // Punt set_max, as there's no mechanism to record that state
6047 } else {
6048 return ml_static_protect(start, end - start, new_prot);
6049 }
6050 }
6051
6052 static inline kern_return_t
6053 OSKext_wire(
6054 vm_map_t map,
6055 vm_map_offset_t start,
6056 vm_map_offset_t end,
6057 vm_prot_t access_type,
6058 boolean_t user_wire)
6059 {
6060 #pragma unused(map,start,end,access_type,user_wire)
6061 return KERN_SUCCESS; // No-op as PRELINK kexts are cemented into physical memory at boot
6062 }
6063 #else
6064 #error Unrecognized architecture
6065 #endif
6066 #else
6067 static inline kern_return_t
6068 OSKext_protect(
6069 vm_map_t map,
6070 vm_map_offset_t start,
6071 vm_map_offset_t end,
6072 vm_prot_t new_prot,
6073 boolean_t set_max)
6074 {
6075 if (start == end) { // 10538581
6076 return KERN_SUCCESS;
6077 }
6078 return vm_map_protect(map, start, end, new_prot, set_max);
6079 }
6080
6081 static inline kern_return_t
6082 OSKext_wire(
6083 vm_map_t map,
6084 vm_map_offset_t start,
6085 vm_map_offset_t end,
6086 vm_prot_t access_type,
6087 boolean_t user_wire)
6088 {
6089 return vm_map_wire_kernel(map, start, end, access_type, VM_KERN_MEMORY_KEXT, user_wire);
6090 }
6091 #endif
6092
6093 OSReturn
6094 OSKext::setVMAttributes(bool protect, bool wire)
6095 {
6096 vm_map_t kext_map = NULL;
6097 kernel_segment_command_t * seg = NULL;
6098 vm_map_offset_t start = 0;
6099 vm_map_offset_t end = 0;
6100 OSReturn result = kOSReturnError;
6101
6102 if (isInterface() || !declaresExecutable() || flags.builtin) {
6103 result = kOSReturnSuccess;
6104 goto finish;
6105 }
6106
6107 /* Get the kext's vm map */
6108 kext_map = kext_get_vm_map(kmod_info);
6109 if (!kext_map) {
6110 result = KERN_MEMORY_ERROR;
6111 goto finish;
6112 }
6113
6114 #if !VM_MAPPED_KEXTS
6115 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
6116 /* This is a split kext in a prelinked kernelcache; we'll let the
6117 * platform code take care of protecting it. It is already wired.
6118 */
6119 /* TODO: Should this still allow protections for the first segment
6120 * to go through, in the event that we have a mix of split and
6121 * unsplit kexts?
6122 */
6123 result = KERN_SUCCESS;
6124 goto finish;
6125 }
6126 #endif
6127
6128 /* Protect the headers as read-only; they do not need to be wired */
6129 result = (protect) ? OSKext_protect(kext_map, kmod_info->address,
6130 kmod_info->address + kmod_info->hdr_size, VM_PROT_READ, TRUE)
6131 : KERN_SUCCESS;
6132 if (result != KERN_SUCCESS) {
6133 goto finish;
6134 }
6135
6136 /* Set the VM protections and wire down each of the segments */
6137 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6138 while (seg) {
6139 #if __arm__
6140 /* We build all ARM kexts, so we can ensure they are aligned */
6141 assert((seg->vmaddr & PAGE_MASK) == 0);
6142 assert((seg->vmsize & PAGE_MASK) == 0);
6143 #endif
6144
6145 start = round_page(seg->vmaddr);
6146 end = trunc_page(seg->vmaddr + seg->vmsize);
6147
6148 if (protect) {
6149 result = OSKext_protect(kext_map, start, end, seg->maxprot, TRUE);
6150 if (result != KERN_SUCCESS) {
6151 OSKextLog(this,
6152 kOSKextLogErrorLevel |
6153 kOSKextLogLoadFlag,
6154 "Kext %s failed to set maximum VM protections "
6155 "for segment %s - 0x%x.",
6156 getIdentifierCString(), seg->segname, (int)result);
6157 goto finish;
6158 }
6159
6160 result = OSKext_protect(kext_map, start, end, seg->initprot, FALSE);
6161 if (result != KERN_SUCCESS) {
6162 OSKextLog(this,
6163 kOSKextLogErrorLevel |
6164 kOSKextLogLoadFlag,
6165 "Kext %s failed to set initial VM protections "
6166 "for segment %s - 0x%x.",
6167 getIdentifierCString(), seg->segname, (int)result);
6168 goto finish;
6169 }
6170 }
6171
6172 if (segmentShouldBeWired(seg) && wire) {
6173 result = OSKext_wire(kext_map, start, end, seg->initprot, FALSE);
6174 if (result != KERN_SUCCESS) {
6175 goto finish;
6176 }
6177 }
6178
6179 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
6180 }
6181
6182 finish:
6183 return result;
6184 }
6185
6186 /*********************************************************************
6187 *********************************************************************/
6188 boolean_t
6189 OSKext::segmentShouldBeWired(kernel_segment_command_t *seg)
6190 {
6191 return sKeepSymbols || strncmp(seg->segname, SEG_LINKEDIT, sizeof(seg->segname));
6192 }
6193
6194 /*********************************************************************
6195 *********************************************************************/
6196 OSReturn
6197 OSKext::validateKextMapping(bool startFlag)
6198 {
6199 OSReturn result = kOSReturnError;
6200 const char * whichOp = startFlag ? "start" : "stop";
6201 kern_return_t kern_result = 0;
6202 vm_map_t kext_map = NULL;
6203 kernel_segment_command_t * seg = NULL;
6204 mach_vm_address_t address = 0;
6205 mach_vm_size_t size = 0;
6206 uint32_t depth = 0;
6207 mach_msg_type_number_t count;
6208 vm_region_submap_short_info_data_64_t info;
6209
6210 if (flags.builtin) {
6211 return kOSReturnSuccess;
6212 }
6213
6214 count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
6215 bzero(&info, sizeof(info));
6216
6217 // xxx - do we need a distinct OSReturn value for these or is "bad data"
6218 // xxx - sufficient?
6219
6220 /* Verify that the kmod_info and start/stop pointers are non-NULL.
6221 */
6222 if (!kmod_info) {
6223 OSKextLog(this,
6224 kOSKextLogErrorLevel |
6225 kOSKextLogLoadFlag,
6226 "Kext %s - NULL kmod_info pointer.",
6227 getIdentifierCString());
6228 result = kOSKextReturnBadData;
6229 goto finish;
6230 }
6231
6232 if (startFlag) {
6233 address = (mach_vm_address_t)kmod_info->start;
6234 } else {
6235 address = (mach_vm_address_t)kmod_info->stop;
6236 }
6237
6238 if (!address) {
6239 OSKextLog(this,
6240 kOSKextLogErrorLevel |
6241 kOSKextLogLoadFlag,
6242 "Kext %s - NULL module %s pointer.",
6243 getIdentifierCString(), whichOp);
6244 result = kOSKextReturnBadData;
6245 goto finish;
6246 }
6247
6248 kext_map = kext_get_vm_map(kmod_info);
6249 depth = (kernel_map == kext_map) ? 1 : 2;
6250
6251 /* Verify that the start/stop function lies within the kext's address range.
6252 */
6253 if (getcommandfromheader((kernel_mach_header_t *)kmod_info->address, LC_SEGMENT_SPLIT_INFO)) {
6254 /* This will likely be how we deal with split kexts; walk the segments to
6255 * check that the function lies inside one of the segments of this kext.
6256 */
6257 for (seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6258 seg != NULL;
6259 seg = nextsegfromheader((kernel_mach_header_t *)kmod_info->address, seg)) {
6260 if ((address >= seg->vmaddr) && address < (seg->vmaddr + seg->vmsize)) {
6261 break;
6262 }
6263 }
6264
6265 if (!seg) {
6266 OSKextLog(this,
6267 kOSKextLogErrorLevel |
6268 kOSKextLogLoadFlag,
6269 "Kext %s module %s pointer is outside of kext range "
6270 "(%s %p - kext starts at %p).",
6271 getIdentifierCString(),
6272 whichOp,
6273 whichOp,
6274 (void *)ml_static_unslide(address),
6275 (void *)ml_static_unslide(kmod_info->address));
6276 result = kOSKextReturnBadData;
6277 goto finish;
6278 }
6279
6280 seg = NULL;
6281 } else {
6282 if (address < kmod_info->address + kmod_info->hdr_size ||
6283 kmod_info->address + kmod_info->size <= address) {
6284 OSKextLog(this,
6285 kOSKextLogErrorLevel |
6286 kOSKextLogLoadFlag,
6287 "Kext %s module %s pointer is outside of kext range "
6288 "(%s %p - kext at %p-%p).",
6289 getIdentifierCString(),
6290 whichOp,
6291 whichOp,
6292 (void *)ml_static_unslide(address),
6293 (void *)ml_static_unslide(kmod_info->address),
6294 (void *)(ml_static_unslide(kmod_info->address) + kmod_info->size));
6295 result = kOSKextReturnBadData;
6296 goto finish;
6297 }
6298 }
6299
6300 /* Only do these checks before calling the start function;
6301 * If anything goes wrong with the mapping while the kext is running,
6302 * we'll likely have panicked well before any attempt to stop the kext.
6303 */
6304 if (startFlag) {
6305 /* Verify that the start/stop function is executable.
6306 */
6307 kern_result = mach_vm_region_recurse(kernel_map, &address, &size, &depth,
6308 (vm_region_recurse_info_t)&info, &count);
6309 if (kern_result != KERN_SUCCESS) {
6310 OSKextLog(this,
6311 kOSKextLogErrorLevel |
6312 kOSKextLogLoadFlag,
6313 "Kext %s - bad %s pointer %p.",
6314 getIdentifierCString(),
6315 whichOp, (void *)ml_static_unslide(address));
6316 result = kOSKextReturnBadData;
6317 goto finish;
6318 }
6319
6320 #if VM_MAPPED_KEXTS
6321 if (!(info.protection & VM_PROT_EXECUTE)) {
6322 OSKextLog(this,
6323 kOSKextLogErrorLevel |
6324 kOSKextLogLoadFlag,
6325 "Kext %s - memory region containing module %s function "
6326 "is not executable.",
6327 getIdentifierCString(), whichOp);
6328 result = kOSKextReturnBadData;
6329 goto finish;
6330 }
6331 #endif
6332
6333 /* Verify that the kext's segments are backed by physical memory.
6334 */
6335 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6336 while (seg) {
6337 if (!verifySegmentMapping(seg)) {
6338 result = kOSKextReturnBadData;
6339 goto finish;
6340 }
6341
6342 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
6343 }
6344 }
6345
6346 result = kOSReturnSuccess;
6347 finish:
6348 return result;
6349 }
6350
6351 /*********************************************************************
6352 *********************************************************************/
6353 boolean_t
6354 OSKext::verifySegmentMapping(kernel_segment_command_t *seg)
6355 {
6356 mach_vm_address_t address = 0;
6357
6358 if (!segmentShouldBeWired(seg)) {
6359 return true;
6360 }
6361
6362 for (address = seg->vmaddr;
6363 address < round_page(seg->vmaddr + seg->vmsize);
6364 address += PAGE_SIZE) {
6365 if (!pmap_find_phys(kernel_pmap, (vm_offset_t)address)) {
6366 OSKextLog(this,
6367 kOSKextLogErrorLevel |
6368 kOSKextLogLoadFlag,
6369 "Kext %s - page %p is not backed by physical memory.",
6370 getIdentifierCString(),
6371 (void *)address);
6372 return false;
6373 }
6374 }
6375
6376 return true;
6377 }
6378
6379 /*********************************************************************
6380 *********************************************************************/
6381 static void
6382 OSKextLogKextInfo(OSKext *aKext, uint64_t address, uint64_t size, firehose_tracepoint_code_t code)
6383 {
6384 uint64_t stamp = 0;
6385 firehose_tracepoint_id_u trace_id;
6386 struct firehose_trace_uuid_info_s uuid_info_s;
6387 firehose_trace_uuid_info_t uuid_info = &uuid_info_s;
6388 size_t uuid_info_len = sizeof(struct firehose_trace_uuid_info_s);
6389 OSData *uuid_data;
6390
6391 stamp = firehose_tracepoint_time(firehose_activity_flags_default);
6392 trace_id.ftid_value = FIREHOSE_TRACE_ID_MAKE(firehose_tracepoint_namespace_metadata, _firehose_tracepoint_type_metadata_kext, (firehose_tracepoint_flags_t)0, code);
6393
6394 uuid_data = aKext->copyTextUUID();
6395 if (uuid_data) {
6396 memcpy(uuid_info->ftui_uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_info->ftui_uuid));
6397 OSSafeReleaseNULL(uuid_data);
6398 }
6399
6400 uuid_info->ftui_size = size;
6401 if (aKext->isDriverKit()) {
6402 uuid_info->ftui_address = address;
6403 } else {
6404 uuid_info->ftui_address = ml_static_unslide(address);
6405 }
6406 firehose_trace_metadata(firehose_stream_metadata, trace_id, stamp, uuid_info, uuid_info_len);
6407 return;
6408 }
6409
6410 void
6411 OSKext::OSKextLogDriverKitInfoLoad(OSKext *kext)
6412 {
6413 OSKextLogKextInfo(kext, kext->getLoadTag(), 1, firehose_tracepoint_code_load);
6414 }
6415
6416 /*********************************************************************
6417 *********************************************************************/
6418 OSReturn
6419 OSKext::start(bool startDependenciesFlag)
6420 {
6421 OSReturn result = kOSReturnError;
6422 kern_return_t (* startfunc)(kmod_info_t *, void *);
6423 unsigned int i, count;
6424 void * kmodStartData = NULL;
6425
6426 if (isStarted() || isInterface() || isKernelComponent()) {
6427 result = kOSReturnSuccess;
6428 goto finish;
6429 }
6430
6431 if (!isLoaded()) {
6432 OSKextLog(this,
6433 kOSKextLogErrorLevel |
6434 kOSKextLogLoadFlag,
6435 "Attempt to start nonloaded kext %s.",
6436 getIdentifierCString());
6437 result = kOSKextReturnInvalidArgument;
6438 goto finish;
6439 }
6440
6441 if (!sLoadEnabled) {
6442 OSKextLog(this,
6443 kOSKextLogErrorLevel |
6444 kOSKextLogLoadFlag,
6445 "Kext loading is disabled (attempt to start kext %s).",
6446 getIdentifierCString());
6447 result = kOSKextReturnDisabled;
6448 goto finish;
6449 }
6450
6451 result = validateKextMapping(/* start? */ true);
6452 if (result != kOSReturnSuccess) {
6453 goto finish;
6454 }
6455
6456 startfunc = kmod_info->start;
6457
6458 count = getNumDependencies();
6459 for (i = 0; i < count; i++) {
6460 OSKext * dependency = OSDynamicCast(OSKext, dependencies->getObject(i));
6461 if (dependency == NULL) {
6462 OSKextLog(this,
6463 kOSKextLogErrorLevel |
6464 kOSKextLogLoadFlag,
6465 "Kext %s start - internal error, dependency disappeared.",
6466 getIdentifierCString());
6467 goto finish;
6468 }
6469 if (!dependency->isStarted()) {
6470 if (startDependenciesFlag) {
6471 OSReturn dependencyResult =
6472 dependency->start(startDependenciesFlag);
6473 if (dependencyResult != KERN_SUCCESS) {
6474 OSKextLog(this,
6475 kOSKextLogErrorLevel |
6476 kOSKextLogLoadFlag,
6477 "Kext %s start - dependency %s failed to start (error 0x%x).",
6478 getIdentifierCString(),
6479 dependency->getIdentifierCString(),
6480 dependencyResult);
6481 goto finish;
6482 }
6483 } else {
6484 OSKextLog(this,
6485 kOSKextLogErrorLevel |
6486 kOSKextLogLoadFlag,
6487 "Not starting %s - dependency %s not started yet.",
6488 getIdentifierCString(),
6489 dependency->getIdentifierCString());
6490 result = kOSKextReturnStartStopError; // xxx - make new return?
6491 goto finish;
6492 }
6493 }
6494 }
6495
6496 OSKextLog(this,
6497 kOSKextLogDetailLevel |
6498 kOSKextLogLoadFlag,
6499 "Kext %s calling module start function.",
6500 getIdentifierCString());
6501
6502 flags.starting = 1;
6503
6504 // Drop a log message so logd can grab the needed information to decode this kext
6505 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_load);
6506 result = OSRuntimeInitializeCPP(this);
6507 if (result == KERN_SUCCESS) {
6508 result = startfunc(kmod_info, kmodStartData);
6509 }
6510
6511 flags.starting = 0;
6512
6513 /* On success overlap the setting of started/starting. On failure just
6514 * clear starting.
6515 */
6516 if (result == KERN_SUCCESS) {
6517 flags.started = 1;
6518
6519 // xxx - log start error from kernel?
6520 OSKextLog(this,
6521 kOSKextLogProgressLevel |
6522 kOSKextLogLoadFlag,
6523 "Kext %s is now started.",
6524 getIdentifierCString());
6525 } else {
6526 invokeOrCancelRequestCallbacks(
6527 /* result not actually used */ kOSKextReturnStartStopError,
6528 /* invokeFlag */ false);
6529 OSKextLog(this,
6530 kOSKextLogProgressLevel |
6531 kOSKextLogLoadFlag,
6532 "Kext %s did not start (return code 0x%x).",
6533 getIdentifierCString(), result);
6534 }
6535
6536 finish:
6537 return result;
6538 }
6539
6540 /*********************************************************************
6541 *********************************************************************/
6542 /* static */
6543 bool
6544 OSKext::canUnloadKextWithIdentifier(
6545 OSString * kextIdentifier,
6546 bool checkClassesFlag)
6547 {
6548 bool result = false;
6549 OSKext * aKext = NULL;// do not release
6550
6551 IORecursiveLockLock(sKextLock);
6552
6553 aKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
6554
6555 if (!aKext) {
6556 goto finish; // can't unload what's not loaded
6557 }
6558
6559 if (aKext->isLoaded()) {
6560 if (aKext->getRetainCount() > kOSKextMinLoadedRetainCount) {
6561 goto finish;
6562 }
6563 if (checkClassesFlag && aKext->hasOSMetaClassInstances()) {
6564 goto finish;
6565 }
6566 }
6567
6568 result = true;
6569
6570 finish:
6571 IORecursiveLockUnlock(sKextLock);
6572 return result;
6573 }
6574
6575 /*********************************************************************
6576 *********************************************************************/
6577 OSReturn
6578 OSKext::stop(void)
6579 {
6580 OSReturn result = kOSReturnError;
6581 kern_return_t (*stopfunc)(kmod_info_t *, void *);
6582
6583 if (!isStarted() || isInterface()) {
6584 result = kOSReturnSuccess;
6585 goto finish;
6586 }
6587
6588 if (!isLoaded()) {
6589 OSKextLog(this,
6590 kOSKextLogErrorLevel |
6591 kOSKextLogLoadFlag,
6592 "Attempt to stop nonloaded kext %s.",
6593 getIdentifierCString());
6594 result = kOSKextReturnInvalidArgument;
6595 goto finish;
6596 }
6597
6598 /* Refuse to stop if we have clients or instances. It is up to
6599 * the caller to make sure those aren't true.
6600 */
6601 if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6602 OSKextLog(this,
6603 kOSKextLogErrorLevel |
6604 kOSKextLogLoadFlag,
6605 "Kext %s - C++ instances; can't stop.",
6606 getIdentifierCString());
6607 result = kOSKextReturnInUse;
6608 goto finish;
6609 }
6610
6611 if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6612 OSKextLog(this,
6613 kOSKextLogErrorLevel |
6614 kOSKextLogLoadFlag,
6615 "Kext %s - has references (linkage or tracking object); "
6616 "can't stop.",
6617 getIdentifierCString());
6618 result = kOSKextReturnInUse;
6619 goto finish;
6620 }
6621
6622 /* Note: If validateKextMapping fails on the stop & unload path,
6623 * we are in serious trouble and a kernel panic is likely whether
6624 * we stop & unload the kext or not.
6625 */
6626 result = validateKextMapping(/* start? */ false);
6627 if (result != kOSReturnSuccess) {
6628 goto finish;
6629 }
6630
6631 stopfunc = kmod_info->stop;
6632 if (stopfunc) {
6633 OSKextLog(this,
6634 kOSKextLogDetailLevel |
6635 kOSKextLogLoadFlag,
6636 "Kext %s calling module stop function.",
6637 getIdentifierCString());
6638
6639 flags.stopping = 1;
6640
6641 result = stopfunc(kmod_info, /* userData */ NULL);
6642 if (result == KERN_SUCCESS) {
6643 result = OSRuntimeFinalizeCPP(this);
6644 }
6645
6646 flags.stopping = 0;
6647
6648 if (result == KERN_SUCCESS) {
6649 flags.started = 0;
6650
6651 OSKextLog(this,
6652 kOSKextLogDetailLevel |
6653 kOSKextLogLoadFlag,
6654 "Kext %s is now stopped and ready to unload.",
6655 getIdentifierCString());
6656 } else {
6657 OSKextLog(this,
6658 kOSKextLogErrorLevel |
6659 kOSKextLogLoadFlag,
6660 "Kext %s did not stop (return code 0x%x).",
6661 getIdentifierCString(), result);
6662 result = kOSKextReturnStartStopError;
6663 }
6664 }
6665
6666 finish:
6667 // Drop a log message so logd can update this kext's metadata
6668 OSKextLogKextInfo(this, kmod_info->address, kmod_info->size, firehose_tracepoint_code_unload);
6669 return result;
6670 }
6671
6672 /*********************************************************************
6673 *********************************************************************/
6674 OSReturn
6675 OSKext::unload(void)
6676 {
6677 OSReturn result = kOSReturnError;
6678 unsigned int index;
6679 uint32_t num_kmod_refs = 0;
6680 OSKextAccount * freeAccount;
6681
6682 if (!sUnloadEnabled) {
6683 OSKextLog(this,
6684 kOSKextLogErrorLevel |
6685 kOSKextLogLoadFlag,
6686 "Kext unloading is disabled (%s).",
6687 this->getIdentifierCString());
6688
6689 result = kOSKextReturnDisabled;
6690 goto finish;
6691 }
6692
6693 /* Refuse to unload if we have clients or instances. It is up to
6694 * the caller to make sure those aren't true.
6695 */
6696 if (getRetainCount() > kOSKextMinLoadedRetainCount) {
6697 // xxx - Don't log under errors? this is more of an info thing
6698 OSKextLog(this,
6699 kOSKextLogErrorLevel |
6700 kOSKextLogKextBookkeepingFlag,
6701 "Can't unload kext %s; outstanding references (linkage or tracking object).",
6702 getIdentifierCString());
6703 result = kOSKextReturnInUse;
6704 goto finish;
6705 }
6706
6707 if (isDriverKit()) {
6708 index = sLoadedKexts->getNextIndexOfObject(this, 0);
6709 if (index != (unsigned int)-1) {
6710 sLoadedDriverKitKexts->removeObject(index);
6711 OSKextLogKextInfo(this, loadTag, 1, firehose_tracepoint_code_unload);
6712 loadTag = 0;
6713 }
6714 }
6715
6716 if (!isLoaded()) {
6717 result = kOSReturnSuccess;
6718 goto finish;
6719 }
6720
6721 if (isKernelComponent()) {
6722 result = kOSKextReturnInvalidArgument;
6723 goto finish;
6724 }
6725
6726 if (metaClasses && !OSMetaClass::removeClasses(metaClasses)) {
6727 OSKextLog(this,
6728 kOSKextLogErrorLevel |
6729 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
6730 "Can't unload kext %s; classes have instances:",
6731 getIdentifierCString());
6732 reportOSMetaClassInstances(kOSKextLogErrorLevel |
6733 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag);
6734 result = kOSKextReturnInUse;
6735 goto finish;
6736 }
6737
6738 /* Note that the kext is unloading before running any code that
6739 * might be in the kext (request callbacks, module stop function).
6740 * We will deny certain requests made against a kext in the process
6741 * of unloading.
6742 */
6743 flags.unloading = 1;
6744
6745 /* Update the string describing the last kext to unload in case we panic.
6746 */
6747 savePanicString(/* isLoading */ false);
6748
6749 if (isStarted()) {
6750 result = stop();
6751 if (result != KERN_SUCCESS) {
6752 OSKextLog(this,
6753 kOSKextLogErrorLevel |
6754 kOSKextLogLoadFlag,
6755 "Kext %s can't unload - module stop returned 0x%x.",
6756 getIdentifierCString(), (unsigned)result);
6757 result = kOSKextReturnStartStopError;
6758 goto finish;
6759 }
6760 }
6761
6762 OSKextLog(this,
6763 kOSKextLogProgressLevel |
6764 kOSKextLogLoadFlag,
6765 "Kext %s unloading.",
6766 getIdentifierCString());
6767
6768 {
6769 struct list_head *p;
6770 struct list_head *prev;
6771 struct list_head *next;
6772 for (p = pendingPgoHead.next; p != &pendingPgoHead; p = next) {
6773 OSKextGrabPgoStruct *s = container_of(p, OSKextGrabPgoStruct, list_head);
6774 s->err = OSKextGrabPgoDataLocked(this, s->metadata, instance_uuid, s->pSize, s->pBuffer, s->bufferSize);
6775 prev = p->prev;
6776 next = p->next;
6777 prev->next = next;
6778 next->prev = prev;
6779 p->prev = p;
6780 p->next = p;
6781 IORecursiveLockWakeup(sKextLock, s, false);
6782 }
6783 }
6784
6785
6786 /* Even if we don't call the stop function, we want to be sure we
6787 * have no OSMetaClass references before unloading the kext executable
6788 * from memory. OSMetaClasses may have pointers into the kext executable
6789 * and that would cause a panic on OSKext::free() when metaClasses is freed.
6790 */
6791 if (metaClasses) {
6792 metaClasses->flushCollection();
6793 }
6794 (void) OSRuntimeFinalizeCPP(this);
6795
6796 /* Remove the kext from the list of loaded kexts, patch the gap
6797 * in the kmod_info_t linked list, and reset "kmod" to point to the
6798 * last loaded kext that isn't the fake kernel kext (sKernelKext).
6799 */
6800 index = sLoadedKexts->getNextIndexOfObject(this, 0);
6801 if (index != (unsigned int)-1) {
6802 sLoadedKexts->removeObject(index);
6803
6804 OSKext * nextKext = OSDynamicCast(OSKext,
6805 sLoadedKexts->getObject(index));
6806
6807 if (nextKext) {
6808 if (index > 0) {
6809 OSKext * gapKext = OSDynamicCast(OSKext,
6810 sLoadedKexts->getObject(index - 1));
6811
6812 nextKext->kmod_info->next = gapKext->kmod_info;
6813 } else { /* index == 0 */
6814 nextKext->kmod_info->next = NULL;
6815 }
6816 }
6817
6818 OSKext * lastKext = OSDynamicCast(OSKext, sLoadedKexts->getLastObject());
6819 if (lastKext && !lastKext->isKernel()) {
6820 kmod = lastKext->kmod_info;
6821 } else {
6822 kmod = NULL; // clear the global kmod variable
6823 }
6824 }
6825
6826 /* Clear out the kmod references that we're keeping for compatibility
6827 * with current panic backtrace code & kgmacros.
6828 * xxx - will want to update those bits sometime and remove this.
6829 */
6830 num_kmod_refs = getNumDependencies();
6831 if (num_kmod_refs && kmod_info && kmod_info->reference_list) {
6832 for (uint32_t refIndex = 0; refIndex < num_kmod_refs; refIndex++) {
6833 kmod_reference_t * ref = &(kmod_info->reference_list[refIndex]);
6834 ref->info->reference_count--;
6835 }
6836 kfree(kmod_info->reference_list,
6837 num_kmod_refs * sizeof(kmod_reference_t));
6838 }
6839
6840 #if CONFIG_DTRACE
6841 unregisterWithDTrace();
6842 #endif /* CONFIG_DTRACE */
6843
6844 notifyKextUnloadObservers(this);
6845
6846 freeAccount = NULL;
6847 IOSimpleLockLock(sKextAccountsLock);
6848 account->kext = NULL;
6849 if (account->site.tag) {
6850 account->site.flags |= VM_TAG_UNLOAD;
6851 } else {
6852 freeAccount = account;
6853 }
6854 IOSimpleLockUnlock(sKextAccountsLock);
6855 if (freeAccount) {
6856 IODelete(freeAccount, OSKextAccount, 1);
6857 }
6858
6859 /* Unwire and free the linked executable.
6860 */
6861 if (linkedExecutable) {
6862 #if KASAN
6863 kasan_unload_kext((vm_offset_t)linkedExecutable->getBytesNoCopy(), linkedExecutable->getLength());
6864 #endif
6865
6866 #if VM_MAPPED_KEXTS
6867 if (!isInterface()) {
6868 kernel_segment_command_t *seg = NULL;
6869 vm_map_t kext_map = kext_get_vm_map(kmod_info);
6870
6871 if (!kext_map) {
6872 OSKextLog(this,
6873 kOSKextLogErrorLevel |
6874 kOSKextLogLoadFlag,
6875 "Failed to free kext %s; couldn't find the kext map.",
6876 getIdentifierCString());
6877 result = kOSKextReturnInternalError;
6878 goto finish;
6879 }
6880
6881 OSKextLog(this,
6882 kOSKextLogProgressLevel |
6883 kOSKextLogLoadFlag,
6884 "Kext %s unwiring and unmapping linked executable.",
6885 getIdentifierCString());
6886
6887 seg = firstsegfromheader((kernel_mach_header_t *)kmod_info->address);
6888 while (seg) {
6889 if (segmentShouldBeWired(seg)) {
6890 result = vm_map_unwire(kext_map, seg->vmaddr,
6891 seg->vmaddr + seg->vmsize, FALSE);
6892 if (result != KERN_SUCCESS) {
6893 OSKextLog(this,
6894 kOSKextLogErrorLevel |
6895 kOSKextLogLoadFlag,
6896 "Failed to unwire kext %s.",
6897 getIdentifierCString());
6898 result = kOSKextReturnInternalError;
6899 goto finish;
6900 }
6901 }
6902
6903 seg = nextsegfromheader((kernel_mach_header_t *) kmod_info->address, seg);
6904 }
6905 }
6906 #endif
6907 OSSafeReleaseNULL(linkedExecutable);
6908 }
6909
6910 /* An interface kext has a fake kmod_info that was allocated,
6911 * so we have to free it.
6912 */
6913 if (isInterface()) {
6914 kfree(kmod_info, sizeof(kmod_info_t));
6915 }
6916
6917 kmod_info = NULL;
6918
6919 flags.loaded = false;
6920 flushDependencies();
6921
6922 /* save a copy of the bundle ID for us to check when deciding to
6923 * rebuild the kernel cache file. If a kext was already in the kernel
6924 * cache and unloaded then later loaded we do not need to rebuild the
6925 * kernel cache. 9055303
6926 */
6927 if (isPrelinked()) {
6928 if (!_OSKextInUnloadedPrelinkedKexts(bundleID)) {
6929 IORecursiveLockLock(sKextLock);
6930 if (sUnloadedPrelinkedKexts) {
6931 sUnloadedPrelinkedKexts->setObject(bundleID);
6932 }
6933 IORecursiveLockUnlock(sKextLock);
6934 }
6935 }
6936
6937 OSKextLog(this,
6938 kOSKextLogProgressLevel | kOSKextLogLoadFlag,
6939 "Kext %s unloaded.", getIdentifierCString());
6940
6941 queueKextNotification(kKextRequestPredicateUnloadNotification,
6942 OSDynamicCast(OSString, bundleID));
6943
6944 finish:
6945 OSKext::saveLoadedKextPanicList();
6946 OSKext::updateLoadedKextSummaries();
6947
6948 flags.unloading = 0;
6949 return result;
6950 }
6951
6952 /*********************************************************************
6953 * Assumes sKextLock is held.
6954 *********************************************************************/
6955 /* static */
6956 OSReturn
6957 OSKext::queueKextNotification(
6958 const char * notificationName,
6959 OSString * kextIdentifier)
6960 {
6961 OSReturn result = kOSReturnError;
6962 OSDictionary * loadRequest = NULL;// must release
6963
6964 if (!kextIdentifier) {
6965 result = kOSKextReturnInvalidArgument;
6966 goto finish;
6967 }
6968
6969 /* Create a new request unless one is already sitting
6970 * in sKernelRequests for this bundle identifier
6971 */
6972 result = _OSKextCreateRequest(notificationName, &loadRequest);
6973 if (result != kOSReturnSuccess) {
6974 goto finish;
6975 }
6976 if (!_OSKextSetRequestArgument(loadRequest,
6977 kKextRequestArgumentBundleIdentifierKey, kextIdentifier)) {
6978 result = kOSKextReturnNoMemory;
6979 goto finish;
6980 }
6981 if (!sKernelRequests->setObject(loadRequest)) {
6982 result = kOSKextReturnNoMemory;
6983 goto finish;
6984 }
6985
6986 /* We might want to only queue the notification if kextd is active,
6987 * but that wouldn't work for embedded. Note that we don't care if
6988 * the ping immediately succeeds here so don't do anything with the
6989 * result of this call.
6990 */
6991 OSKext::pingKextd();
6992
6993 result = kOSReturnSuccess;
6994
6995 finish:
6996 OSSafeReleaseNULL(loadRequest);
6997
6998 return result;
6999 }
7000
7001 /*********************************************************************
7002 *********************************************************************/
7003 static void
7004 _OSKextConsiderDestroyingLinkContext(
7005 __unused thread_call_param_t p0,
7006 __unused thread_call_param_t p1)
7007 {
7008 /* Take multiple locks in the correct order.
7009 */
7010 IORecursiveLockLock(sKextLock);
7011 IORecursiveLockLock(sKextInnerLock);
7012
7013 /* The first time we destroy the kxldContext is in the first
7014 * OSKext::considerUnloads() call, which sets sConsiderUnloadsCalled
7015 * before calling this function. Thereafter any call to this function
7016 * will actually destroy the context.
7017 */
7018 if (sConsiderUnloadsCalled && sKxldContext) {
7019 kxld_destroy_context(sKxldContext);
7020 sKxldContext = NULL;
7021 }
7022
7023 /* Free the thread_call that was allocated to execute this function.
7024 */
7025 if (sDestroyLinkContextThread) {
7026 if (!thread_call_free(sDestroyLinkContextThread)) {
7027 OSKextLog(/* kext */ NULL,
7028 kOSKextLogErrorLevel |
7029 kOSKextLogGeneralFlag,
7030 "thread_call_free() failed for kext link context.");
7031 }
7032 sDestroyLinkContextThread = NULL;
7033 }
7034
7035 IORecursiveLockUnlock(sKextInnerLock);
7036 IORecursiveLockUnlock(sKextLock);
7037
7038 return;
7039 }
7040
7041 /*********************************************************************
7042 * Destroying the kxldContext requires checking variables under both
7043 * sKextInnerLock and sKextLock, so we do it on a separate thread
7044 * to avoid deadlocks with IOService, with which OSKext has a reciprocal
7045 * call relationship.
7046 *
7047 * This function must be invoked with sKextInnerLock held.
7048 * Do not call any function that takes sKextLock here!
7049 *********************************************************************/
7050 /* static */
7051 void
7052 OSKext::considerDestroyingLinkContext(void)
7053 {
7054 IORecursiveLockLock(sKextInnerLock);
7055
7056 /* If we have already queued a thread to destroy the link context,
7057 * don't bother resetting; that thread will take care of it.
7058 */
7059 if (sDestroyLinkContextThread) {
7060 goto finish;
7061 }
7062
7063 /* The function to be invoked in the thread will deallocate
7064 * this thread_call, so don't share it around.
7065 */
7066 sDestroyLinkContextThread = thread_call_allocate(
7067 &_OSKextConsiderDestroyingLinkContext, NULL);
7068 if (!sDestroyLinkContextThread) {
7069 OSKextLog(/* kext */ NULL,
7070 kOSKextLogErrorLevel | kOSKextLogGeneralFlag | kOSKextLogLinkFlag,
7071 "Can't create thread to destroy kext link context.");
7072 goto finish;
7073 }
7074
7075 thread_call_enter(sDestroyLinkContextThread);
7076
7077 finish:
7078 IORecursiveLockUnlock(sKextInnerLock);
7079 return;
7080 }
7081
7082 #if PRAGMA_MARK
7083 #pragma mark Autounload
7084 #endif
7085 /*********************************************************************
7086 * This is a static method because the kext will be deallocated if it
7087 * does unload!
7088 *********************************************************************/
7089 /* static */
7090 OSReturn
7091 OSKext::autounloadKext(OSKext * aKext)
7092 {
7093 OSReturn result = kOSKextReturnInUse;
7094
7095 /* Check for external references to this kext (usu. dependents),
7096 * instances of defined classes (or classes derived from them),
7097 * outstanding requests.
7098 */
7099 if ((aKext->getRetainCount() > kOSKextMinLoadedRetainCount) ||
7100 !aKext->flags.autounloadEnabled ||
7101 aKext->isKernelComponent()) {
7102 goto finish;
7103 }
7104
7105 /* Skip a delay-autounload kext, once.
7106 */
7107 if (aKext->flags.delayAutounload) {
7108 OSKextLog(aKext,
7109 kOSKextLogProgressLevel |
7110 kOSKextLogLoadFlag | kOSKextLogKextBookkeepingFlag,
7111 "Kext %s has delayed autounload set; skipping and clearing flag.",
7112 aKext->getIdentifierCString());
7113 aKext->flags.delayAutounload = 0;
7114 goto finish;
7115 }
7116
7117 if (aKext->hasOSMetaClassInstances() ||
7118 aKext->countRequestCallbacks()) {
7119 goto finish;
7120 }
7121
7122 result = OSKext::removeKext(aKext);
7123
7124 finish:
7125 return result;
7126 }
7127
7128 /*********************************************************************
7129 *********************************************************************/
7130 void
7131 _OSKextConsiderUnloads(
7132 __unused thread_call_param_t p0,
7133 __unused thread_call_param_t p1)
7134 {
7135 bool didUnload = false;
7136 unsigned int count, i;
7137
7138 /* Take multiple locks in the correct order
7139 * (note also sKextSummaries lock further down).
7140 */
7141 IORecursiveLockLock(sKextLock);
7142 IORecursiveLockLock(sKextInnerLock);
7143
7144 OSKext::flushNonloadedKexts(/* flushPrelinkedKexts */ true);
7145
7146 /* If the system is powering down, don't try to unload anything.
7147 */
7148 if (sSystemSleep) {
7149 goto finish;
7150 }
7151
7152 OSKextLog(/* kext */ NULL,
7153 kOSKextLogProgressLevel | kOSKextLogLoadFlag,
7154 "Checking for unused kexts to autounload.");
7155
7156 /*****
7157 * Remove any request callbacks marked as stale,
7158 * and mark as stale any currently in flight.
7159 */
7160 count = sRequestCallbackRecords->getCount();
7161 if (count) {
7162 i = count - 1;
7163 do {
7164 OSDictionary * callbackRecord = OSDynamicCast(OSDictionary,
7165 sRequestCallbackRecords->getObject(i));
7166 OSBoolean * stale = OSDynamicCast(OSBoolean,
7167 callbackRecord->getObject(kKextRequestStaleKey));
7168
7169 if (stale == kOSBooleanTrue) {
7170 OSKext::invokeRequestCallback(callbackRecord,
7171 kOSKextReturnTimeout);
7172 } else {
7173 callbackRecord->setObject(kKextRequestStaleKey,
7174 kOSBooleanTrue);
7175 }
7176 } while (i--);
7177 }
7178
7179 /*****
7180 * Make multiple passes through the array of loaded kexts until
7181 * we don't unload any. This handles unwinding of dependency
7182 * chains. We have to go *backwards* through the array because
7183 * kexts are removed from it when unloaded, and we cannot make
7184 * a copy or we'll mess up the retain counts we rely on to
7185 * check whether a kext will unload. If only we could have
7186 * nonretaining collections like CF has....
7187 */
7188 do {
7189 didUnload = false;
7190
7191 count = sLoadedKexts->getCount();
7192 if (count) {
7193 i = count - 1;
7194 do {
7195 OSKext * thisKext = OSDynamicCast(OSKext,
7196 sLoadedKexts->getObject(i));
7197 didUnload |= (kOSReturnSuccess == OSKext::autounloadKext(thisKext));
7198 } while (i--);
7199 }
7200 } while (didUnload);
7201
7202 finish:
7203 sConsiderUnloadsPending = false;
7204 sConsiderUnloadsExecuted = true;
7205
7206 (void) OSKext::considerRebuildOfPrelinkedKernel();
7207
7208 IORecursiveLockUnlock(sKextInnerLock);
7209 IORecursiveLockUnlock(sKextLock);
7210
7211 return;
7212 }
7213
7214 /*********************************************************************
7215 * Do not call any function that takes sKextLock here!
7216 *********************************************************************/
7217 void
7218 OSKext::considerUnloads(Boolean rescheduleOnlyFlag)
7219 {
7220 AbsoluteTime when;
7221
7222 IORecursiveLockLock(sKextInnerLock);
7223
7224 if (!sUnloadCallout) {
7225 sUnloadCallout = thread_call_allocate(&_OSKextConsiderUnloads, NULL);
7226 }
7227
7228 /* we only reset delay value for unloading if we already have something
7229 * pending. rescheduleOnlyFlag should not start the count down.
7230 */
7231 if (rescheduleOnlyFlag && !sConsiderUnloadsPending) {
7232 goto finish;
7233 }
7234
7235 thread_call_cancel(sUnloadCallout);
7236 if (OSKext::getAutounloadEnabled() && !sSystemSleep) {
7237 clock_interval_to_deadline(sConsiderUnloadDelay,
7238 1000 * 1000 * 1000, &when);
7239
7240 OSKextLog(/* kext */ NULL,
7241 kOSKextLogProgressLevel |
7242 kOSKextLogLoadFlag,
7243 "%scheduling %sscan for unused kexts in %lu seconds.",
7244 sConsiderUnloadsPending ? "Res" : "S",
7245 sConsiderUnloadsCalled ? "" : "initial ",
7246 (unsigned long)sConsiderUnloadDelay);
7247
7248 sConsiderUnloadsPending = true;
7249 thread_call_enter_delayed(sUnloadCallout, when);
7250 }
7251
7252 finish:
7253 /* The kxld context should be reused throughout boot. We mark the end of
7254 * period as the first time considerUnloads() is called, and we destroy
7255 * the first kxld context in that function. Afterwards, it will be
7256 * destroyed in flushNonloadedKexts.
7257 */
7258 if (!sConsiderUnloadsCalled) {
7259 sConsiderUnloadsCalled = true;
7260 OSKext::considerDestroyingLinkContext();
7261 }
7262
7263 IORecursiveLockUnlock(sKextInnerLock);
7264 return;
7265 }
7266
7267 /*********************************************************************
7268 * Do not call any function that takes sKextLock here!
7269 *********************************************************************/
7270 extern "C" {
7271 IOReturn OSKextSystemSleepOrWake(UInt32 messageType);
7272 IOReturn
7273 OSKextSystemSleepOrWake(UInt32 messageType)
7274 {
7275 IORecursiveLockLock(sKextInnerLock);
7276
7277 /* If the system is going to sleep, cancel the reaper thread timer,
7278 * and note that we're in a sleep state in case it just fired but hasn't
7279 * taken the lock yet. If we are coming back from sleep, just
7280 * clear the sleep flag; IOService's normal operation will cause
7281 * unloads to be considered soon enough.
7282 */
7283 if (messageType == kIOMessageSystemWillSleep) {
7284 if (sUnloadCallout) {
7285 thread_call_cancel(sUnloadCallout);
7286 }
7287 sSystemSleep = true;
7288 AbsoluteTime_to_scalar(&sLastWakeTime) = 0;
7289 } else if (messageType == kIOMessageSystemHasPoweredOn) {
7290 sSystemSleep = false;
7291 clock_get_uptime(&sLastWakeTime);
7292 }
7293 IORecursiveLockUnlock(sKextInnerLock);
7294
7295 return kIOReturnSuccess;
7296 }
7297 };
7298
7299
7300 #if PRAGMA_MARK
7301 #pragma mark Prelinked Kernel
7302 #endif
7303 /*********************************************************************
7304 * Do not access sConsiderUnloads... variables other than
7305 * sConsiderUnloadsExecuted in this function. They are guarded by a
7306 * different lock.
7307 *********************************************************************/
7308 /* static */
7309 void
7310 OSKext::considerRebuildOfPrelinkedKernel(void)
7311 {
7312 static bool requestedPrelink = false;
7313 OSReturn checkResult = kOSReturnError;
7314 OSDictionary * prelinkRequest = NULL;// must release
7315 OSCollectionIterator * kextIterator = NULL;// must release
7316 const OSSymbol * thisID = NULL;// do not release
7317 bool doRebuild = false;
7318 AbsoluteTime my_abstime;
7319 UInt64 my_ns;
7320 SInt32 delta_secs;
7321
7322 /* Only one auto rebuild per boot and only on boot from prelinked kernel */
7323 if (requestedPrelink || !sPrelinkBoot) {
7324 return;
7325 }
7326
7327 /* no direct return from this point */
7328 IORecursiveLockLock(sKextLock);
7329
7330 /* We need to wait for kextd to get up and running with unloads already done
7331 * and any new startup kexts loaded.
7332 */
7333 if (!sConsiderUnloadsExecuted ||
7334 !sDeferredLoadSucceeded) {
7335 goto finish;
7336 }
7337
7338 /* we really only care about boot / system start up related kexts so bail
7339 * if we're here after REBUILD_MAX_TIME.
7340 */
7341 if (!_OSKextInPrelinkRebuildWindow()) {
7342 OSKextLog(/* kext */ NULL,
7343 kOSKextLogArchiveFlag,
7344 "%s prebuild rebuild has expired",
7345 __FUNCTION__);
7346 requestedPrelink = true;
7347 goto finish;
7348 }
7349
7350 /* we do not want to trigger a rebuild if we get here too close to waking
7351 * up. (see radar 10233768)
7352 */
7353 IORecursiveLockLock(sKextInnerLock);
7354
7355 clock_get_uptime(&my_abstime);
7356 delta_secs = MINIMUM_WAKEUP_SECONDS + 1;
7357 if (AbsoluteTime_to_scalar(&sLastWakeTime) != 0) {
7358 SUB_ABSOLUTETIME(&my_abstime, &sLastWakeTime);
7359 absolutetime_to_nanoseconds(my_abstime, &my_ns);
7360 delta_secs = (SInt32)(my_ns / NSEC_PER_SEC);
7361 }
7362 IORecursiveLockUnlock(sKextInnerLock);
7363
7364 if (delta_secs < MINIMUM_WAKEUP_SECONDS) {
7365 /* too close to time of last wake from sleep */
7366 goto finish;
7367 }
7368 requestedPrelink = true;
7369
7370 /* Now it's time to see if we have a reason to rebuild. We may have done
7371 * some loads and unloads but the kernel cache didn't actually change.
7372 * We will rebuild if any kext is not marked prelinked AND is not in our
7373 * list of prelinked kexts that got unloaded. (see radar 9055303)
7374 */
7375 kextIterator = OSCollectionIterator::withCollection(sKextsByID);
7376 if (!kextIterator) {
7377 goto finish;
7378 }
7379
7380 while ((thisID = OSDynamicCast(OSSymbol, kextIterator->getNextObject()))) {
7381 OSKext * thisKext;// do not release
7382
7383 thisKext = OSDynamicCast(OSKext, sKextsByID->getObject(thisID));
7384 if (!thisKext || thisKext->isPrelinked() || thisKext->isKernel()) {
7385 continue;
7386 }
7387
7388 if (_OSKextInUnloadedPrelinkedKexts(thisKext->bundleID)) {
7389 continue;
7390 }
7391 /* kext is loaded and was not in current kernel cache so let's rebuild
7392 */
7393 doRebuild = true;
7394 OSKextLog(/* kext */ NULL,
7395 kOSKextLogArchiveFlag,
7396 "considerRebuildOfPrelinkedKernel %s triggered rebuild",
7397 thisKext->bundleID->getCStringNoCopy());
7398 break;
7399 }
7400 sUnloadedPrelinkedKexts->flushCollection();
7401
7402 if (!doRebuild) {
7403 goto finish;
7404 }
7405
7406 checkResult = _OSKextCreateRequest(kKextRequestPredicateRequestPrelink,
7407 &prelinkRequest);
7408 if (checkResult != kOSReturnSuccess) {
7409 goto finish;
7410 }
7411
7412 if (!sKernelRequests->setObject(prelinkRequest)) {
7413 goto finish;
7414 }
7415
7416 OSKext::pingKextd();
7417
7418 finish:
7419 IORecursiveLockUnlock(sKextLock);
7420 OSSafeReleaseNULL(prelinkRequest);
7421 OSSafeReleaseNULL(kextIterator);
7422
7423 return;
7424 }
7425
7426 #if PRAGMA_MARK
7427 #pragma mark Dependencies
7428 #endif
7429 /*********************************************************************
7430 *********************************************************************/
7431 bool
7432 OSKext::resolveDependencies(
7433 OSArray * loopStack)
7434 {
7435 bool result = false;
7436 OSArray * localLoopStack = NULL;// must release
7437 bool addedToLoopStack = false;
7438 OSDictionary * libraries = NULL;// do not release
7439 OSCollectionIterator * libraryIterator = NULL;// must release
7440 OSString * libraryID = NULL;// do not release
7441 OSString * infoString = NULL;// do not release
7442 OSString * readableString = NULL;// do not release
7443 OSKext * libraryKext = NULL;// do not release
7444 bool hasRawKernelDependency = false;
7445 bool hasKernelDependency = false;
7446 bool hasKPIDependency = false;
7447 bool hasPrivateKPIDependency = false;
7448 unsigned int count;
7449
7450 /* A kernel component will automatically have this flag set,
7451 * and a loaded kext should also have it set (as should all its
7452 * loaded dependencies).
7453 */
7454 if (flags.hasAllDependencies) {
7455 result = true;
7456 goto finish;
7457 }
7458
7459 /* Check for loops in the dependency graph.
7460 */
7461 if (loopStack) {
7462 if (loopStack->getNextIndexOfObject(this, 0) != (unsigned int)-1) {
7463 OSKextLog(this,
7464 kOSKextLogErrorLevel |
7465 kOSKextLogDependenciesFlag,
7466 "Kext %s has a dependency loop; can't resolve dependencies.",
7467 getIdentifierCString());
7468 goto finish;
7469 }
7470 } else {
7471 OSKextLog(this,
7472 kOSKextLogStepLevel |
7473 kOSKextLogDependenciesFlag,
7474 "Kext %s resolving dependencies.",
7475 getIdentifierCString());
7476
7477 loopStack = OSArray::withCapacity(6); // any small capacity will do
7478 if (!loopStack) {
7479 OSKextLog(this,
7480 kOSKextLogErrorLevel |
7481 kOSKextLogDependenciesFlag,
7482 "Kext %s can't create bookkeeping stack to resolve dependencies.",
7483 getIdentifierCString());
7484 goto finish;
7485 }
7486 localLoopStack = loopStack;
7487 }
7488 if (!loopStack->setObject(this)) {
7489 OSKextLog(this,
7490 kOSKextLogErrorLevel |
7491 kOSKextLogDependenciesFlag,
7492 "Kext %s - internal error resolving dependencies.",
7493 getIdentifierCString());
7494 goto finish;
7495 }
7496 addedToLoopStack = true;
7497
7498 /* Purge any existing kexts in the dependency list and start over.
7499 */
7500 flushDependencies();
7501 if (dependencies) {
7502 OSKextLog(this,
7503 kOSKextLogErrorLevel |
7504 kOSKextLogDependenciesFlag,
7505 "Kext %s - internal error resolving dependencies.",
7506 getIdentifierCString());
7507 }
7508
7509 libraries = OSDynamicCast(OSDictionary,
7510 getPropertyForHostArch(kOSBundleLibrariesKey));
7511 if (libraries == NULL || libraries->getCount() == 0) {
7512 OSKextLog(this,
7513 kOSKextLogErrorLevel |
7514 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7515 "Kext %s - can't resolve dependencies; %s missing/invalid type.",
7516 getIdentifierCString(), kOSBundleLibrariesKey);
7517 goto finish;
7518 }
7519
7520 /* Make a new array to hold the dependencies (flush freed the old one).
7521 */
7522 dependencies = OSArray::withCapacity(libraries->getCount());
7523 if (!dependencies) {
7524 OSKextLog(this,
7525 kOSKextLogErrorLevel |
7526 kOSKextLogDependenciesFlag,
7527 "Kext %s - can't allocate dependencies array.",
7528 getIdentifierCString());
7529 goto finish;
7530 }
7531
7532 // xxx - compat: We used to add an implicit dependency on kernel 6.0
7533 // xxx - compat: if none were declared.
7534
7535 libraryIterator = OSCollectionIterator::withCollection(libraries);
7536 if (!libraryIterator) {
7537 OSKextLog(this,
7538 kOSKextLogErrorLevel |
7539 kOSKextLogDependenciesFlag,
7540 "Kext %s - can't allocate dependencies iterator.",
7541 getIdentifierCString());
7542 goto finish;
7543 }
7544
7545 while ((libraryID = OSDynamicCast(OSString,
7546 libraryIterator->getNextObject()))) {
7547 const char * library_id = libraryID->getCStringNoCopy();
7548
7549 OSString * libraryVersion = OSDynamicCast(OSString,
7550 libraries->getObject(libraryID));
7551 if (libraryVersion == NULL) {
7552 OSKextLog(this,
7553 kOSKextLogErrorLevel |
7554 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7555 "Kext %s - illegal type in OSBundleLibraries.",
7556 getIdentifierCString());
7557 goto finish;
7558 }
7559
7560 OSKextVersion libraryVers =
7561 OSKextParseVersionString(libraryVersion->getCStringNoCopy());
7562 if (libraryVers == -1) {
7563 OSKextLog(this,
7564 kOSKextLogErrorLevel |
7565 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7566 "Kext %s - invalid library version %s.",
7567 getIdentifierCString(),
7568 libraryVersion->getCStringNoCopy());
7569 goto finish;
7570 }
7571
7572 libraryKext = OSDynamicCast(OSKext, sKextsByID->getObject(libraryID));
7573 if (libraryKext == NULL) {
7574 OSKextLog(this,
7575 kOSKextLogErrorLevel |
7576 kOSKextLogDependenciesFlag,
7577 "Kext %s - library kext %s not found.",
7578 getIdentifierCString(), library_id);
7579 goto finish;
7580 }
7581
7582 if (!libraryKext->isCompatibleWithVersion(libraryVers)) {
7583 OSKextLog(this,
7584 kOSKextLogErrorLevel |
7585 kOSKextLogDependenciesFlag,
7586 "Kext %s - library kext %s not compatible "
7587 "with requested version %s.",
7588 getIdentifierCString(), library_id,
7589 libraryVersion->getCStringNoCopy());
7590 goto finish;
7591 }
7592
7593 /* If a nonprelinked library somehow got into the mix for a
7594 * prelinked kext, at any point in the chain, we must fail
7595 * because the prelinked relocs for the library will be all wrong.
7596 */
7597 if (this->isPrelinked() &&
7598 libraryKext->declaresExecutable() &&
7599 !libraryKext->isPrelinked()) {
7600 OSKextLog(this,
7601 kOSKextLogErrorLevel |
7602 kOSKextLogDependenciesFlag,
7603 "Kext %s (prelinked) - library kext %s (v%s) not prelinked.",
7604 getIdentifierCString(), library_id,
7605 libraryVersion->getCStringNoCopy());
7606 goto finish;
7607 }
7608
7609 if (!libraryKext->resolveDependencies(loopStack)) {
7610 goto finish;
7611 }
7612
7613 /* Add the library directly only if it has an executable to link.
7614 * Otherwise it's just used to collect other dependencies, so put
7615 * *its* dependencies on the list for this kext.
7616 */
7617 // xxx - We are losing info here; would like to make fake entries or
7618 // xxx - keep these in the dependency graph for loaded kexts.
7619 // xxx - I really want to make kernel components not a special case!
7620 if (libraryKext->declaresExecutable() ||
7621 libraryKext->isInterface()) {
7622 if (dependencies->getNextIndexOfObject(libraryKext, 0) == (unsigned)-1) {
7623 dependencies->setObject(libraryKext);
7624
7625 OSKextLog(this,
7626 kOSKextLogDetailLevel |
7627 kOSKextLogDependenciesFlag,
7628 "Kext %s added dependency %s.",
7629 getIdentifierCString(),
7630 libraryKext->getIdentifierCString());
7631 }
7632 } else {
7633 int numLibDependencies = libraryKext->getNumDependencies();
7634 OSArray * libraryDependencies = libraryKext->getDependencies();
7635 int index;
7636
7637 if (numLibDependencies) {
7638 // xxx - this msg level should be 1 lower than the per-kext one
7639 OSKextLog(this,
7640 kOSKextLogDetailLevel |
7641 kOSKextLogDependenciesFlag,
7642 "Kext %s pulling %d dependencies from codeless library %s.",
7643 getIdentifierCString(),
7644 numLibDependencies,
7645 libraryKext->getIdentifierCString());
7646 }
7647 for (index = 0; index < numLibDependencies; index++) {
7648 OSKext * thisLibDependency = OSDynamicCast(OSKext,
7649 libraryDependencies->getObject(index));
7650 if (dependencies->getNextIndexOfObject(thisLibDependency, 0) == (unsigned)-1) {
7651 dependencies->setObject(thisLibDependency);
7652 OSKextLog(this,
7653 kOSKextLogDetailLevel |
7654 kOSKextLogDependenciesFlag,
7655 "Kext %s added dependency %s from codeless library %s.",
7656 getIdentifierCString(),
7657 thisLibDependency->getIdentifierCString(),
7658 libraryKext->getIdentifierCString());
7659 }
7660 }
7661 }
7662
7663 if ((strlen(library_id) == strlen(KERNEL_LIB)) &&
7664 0 == strncmp(library_id, KERNEL_LIB, sizeof(KERNEL_LIB) - 1)) {
7665 hasRawKernelDependency = true;
7666 } else if (STRING_HAS_PREFIX(library_id, KERNEL_LIB_PREFIX)) {
7667 hasKernelDependency = true;
7668 } else if (STRING_HAS_PREFIX(library_id, KPI_LIB_PREFIX)) {
7669 hasKPIDependency = true;
7670 if (!strncmp(library_id, PRIVATE_KPI, sizeof(PRIVATE_KPI) - 1)) {
7671 hasPrivateKPIDependency = true;
7672 }
7673 }
7674 }
7675
7676 if (hasRawKernelDependency) {
7677 OSKextLog(this,
7678 kOSKextLogErrorLevel |
7679 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7680 "Error - kext %s declares a dependency on %s, which is not permitted.",
7681 getIdentifierCString(), KERNEL_LIB);
7682 goto finish;
7683 }
7684 #if __LP64__
7685 if (hasKernelDependency) {
7686 OSKextLog(this,
7687 kOSKextLogErrorLevel |
7688 kOSKextLogValidationFlag | kOSKextLogDependenciesFlag,
7689 "Error - kext %s declares %s dependencies. "
7690 "Only %s* dependencies are supported for 64-bit kexts.",
7691 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
7692 goto finish;
7693 }
7694 if (!hasKPIDependency) {
7695 OSKextLog(this,
7696 kOSKextLogWarningLevel |
7697 kOSKextLogDependenciesFlag,
7698 "Warning - kext %s declares no %s* dependencies. "
7699 "If it uses any KPIs, the link may fail with undefined symbols.",
7700 getIdentifierCString(), KPI_LIB_PREFIX);
7701 }
7702 #else /* __LP64__ */
7703 // xxx - will change to flatly disallow "kernel" dependencies at some point
7704 // xxx - is it invalid to do both "com.apple.kernel" and any
7705 // xxx - "com.apple.kernel.*"?
7706
7707 if (hasKernelDependency && hasKPIDependency) {
7708 OSKextLog(this,
7709 kOSKextLogWarningLevel |
7710 kOSKextLogDependenciesFlag,
7711 "Warning - kext %s has immediate dependencies on both "
7712 "%s* and %s* components; use only one style.",
7713 getIdentifierCString(), KERNEL_LIB, KPI_LIB_PREFIX);
7714 }
7715
7716 if (!hasKernelDependency && !hasKPIDependency) {
7717 // xxx - do we want to use validation flag for these too?
7718 OSKextLog(this,
7719 kOSKextLogWarningLevel |
7720 kOSKextLogDependenciesFlag,
7721 "Warning - %s declares no kernel dependencies; using %s.",
7722 getIdentifierCString(), KERNEL6_LIB);
7723 OSKext * kernelKext = OSDynamicCast(OSKext,
7724 sKextsByID->getObject(KERNEL6_LIB));
7725 if (kernelKext) {
7726 dependencies->setObject(kernelKext);
7727 } else {
7728 OSKextLog(this,
7729 kOSKextLogErrorLevel |
7730 kOSKextLogDependenciesFlag,
7731 "Error - Library %s not found for %s.",
7732 KERNEL6_LIB, getIdentifierCString());
7733 }
7734 }
7735
7736 /* If the kext doesn't have a raw kernel or KPI dependency, then add all of
7737 * its indirect dependencies to simulate old-style linking. XXX - Should
7738 * check for duplicates.
7739 */
7740 if (!hasKPIDependency) {
7741 unsigned int i;
7742
7743 flags.hasBleedthrough = true;
7744
7745 count = getNumDependencies();
7746
7747 /* We add to the dependencies array in this loop, but do not iterate
7748 * past its original count.
7749 */
7750 for (i = 0; i < count; i++) {
7751 OSKext * dependencyKext = OSDynamicCast(OSKext,
7752 dependencies->getObject(i));
7753 dependencyKext->addBleedthroughDependencies(dependencies);
7754 }
7755 }
7756 #endif /* __LP64__ */
7757
7758 if (hasPrivateKPIDependency) {
7759 bool hasApplePrefix = false;
7760 bool infoCopyrightIsValid = false;
7761 bool readableCopyrightIsValid = false;
7762
7763 hasApplePrefix = STRING_HAS_PREFIX(getIdentifierCString(),
7764 APPLE_KEXT_PREFIX);
7765
7766 infoString = OSDynamicCast(OSString,
7767 getPropertyForHostArch("CFBundleGetInfoString"));
7768 if (infoString) {
7769 infoCopyrightIsValid =
7770 kxld_validate_copyright_string(infoString->getCStringNoCopy());
7771 }
7772
7773 readableString = OSDynamicCast(OSString,
7774 getPropertyForHostArch("NSHumanReadableCopyright"));
7775 if (readableString) {
7776 readableCopyrightIsValid =
7777 kxld_validate_copyright_string(readableString->getCStringNoCopy());
7778 }
7779
7780 if (!hasApplePrefix || (!infoCopyrightIsValid && !readableCopyrightIsValid)) {
7781 OSKextLog(this,
7782 kOSKextLogErrorLevel |
7783 kOSKextLogDependenciesFlag,
7784 "Error - kext %s declares a dependency on %s. "
7785 "Only Apple kexts may declare a dependency on %s.",
7786 getIdentifierCString(), PRIVATE_KPI, PRIVATE_KPI);
7787 goto finish;
7788 }
7789 }
7790
7791 result = true;
7792 flags.hasAllDependencies = 1;
7793
7794 finish:
7795
7796 if (addedToLoopStack) {
7797 count = loopStack->getCount();
7798 if (count > 0 && (this == loopStack->getObject(count - 1))) {
7799 loopStack->removeObject(count - 1);
7800 } else {
7801 OSKextLog(this,
7802 kOSKextLogErrorLevel |
7803 kOSKextLogDependenciesFlag,
7804 "Kext %s - internal error resolving dependencies.",
7805 getIdentifierCString());
7806 }
7807 }
7808
7809 if (result && localLoopStack) {
7810 OSKextLog(this,
7811 kOSKextLogStepLevel |
7812 kOSKextLogDependenciesFlag,
7813 "Kext %s successfully resolved dependencies.",
7814 getIdentifierCString());
7815 }
7816
7817 OSSafeReleaseNULL(localLoopStack);
7818 OSSafeReleaseNULL(libraryIterator);
7819
7820 return result;
7821 }
7822
7823 /*********************************************************************
7824 *********************************************************************/
7825 bool
7826 OSKext::addBleedthroughDependencies(OSArray * anArray)
7827 {
7828 bool result = false;
7829 unsigned int dependencyIndex, dependencyCount;
7830
7831 dependencyCount = getNumDependencies();
7832
7833 for (dependencyIndex = 0;
7834 dependencyIndex < dependencyCount;
7835 dependencyIndex++) {
7836 OSKext * dependency = OSDynamicCast(OSKext,
7837 dependencies->getObject(dependencyIndex));
7838 if (!dependency) {
7839 OSKextLog(this,
7840 kOSKextLogErrorLevel |
7841 kOSKextLogDependenciesFlag,
7842 "Kext %s - internal error propagating compatibility dependencies.",
7843 getIdentifierCString());
7844 goto finish;
7845 }
7846 if (anArray->getNextIndexOfObject(dependency, 0) == (unsigned int)-1) {
7847 anArray->setObject(dependency);
7848 }
7849 dependency->addBleedthroughDependencies(anArray);
7850 }
7851
7852 result = true;
7853
7854 finish:
7855 return result;
7856 }
7857
7858 /*********************************************************************
7859 *********************************************************************/
7860 bool
7861 OSKext::flushDependencies(bool forceFlag)
7862 {
7863 bool result = false;
7864
7865 /* Only clear the dependencies if the kext isn't loaded;
7866 * we need the info for loaded kexts to track references.
7867 */
7868 if (!isLoaded() || forceFlag) {
7869 if (dependencies) {
7870 // xxx - check level
7871 OSKextLog(this,
7872 kOSKextLogProgressLevel |
7873 kOSKextLogDependenciesFlag,
7874 "Kext %s flushing dependencies.",
7875 getIdentifierCString());
7876 OSSafeReleaseNULL(dependencies);
7877 }
7878 if (!isKernelComponent()) {
7879 flags.hasAllDependencies = 0;
7880 }
7881 result = true;
7882 }
7883
7884 return result;
7885 }
7886
7887 /*********************************************************************
7888 *********************************************************************/
7889 uint32_t
7890 OSKext::getNumDependencies(void)
7891 {
7892 if (!dependencies) {
7893 return 0;
7894 }
7895 return dependencies->getCount();
7896 }
7897
7898 /*********************************************************************
7899 *********************************************************************/
7900 OSArray *
7901 OSKext::getDependencies(void)
7902 {
7903 return dependencies;
7904 }
7905
7906 #if PRAGMA_MARK
7907 #pragma mark OSMetaClass Support
7908 #endif
7909 /*********************************************************************
7910 *********************************************************************/
7911 OSReturn
7912 OSKext::addClass(
7913 OSMetaClass * aClass,
7914 uint32_t numClasses)
7915 {
7916 OSReturn result = kOSMetaClassNoInsKModSet;
7917
7918 if (!metaClasses) {
7919 metaClasses = OSSet::withCapacity(numClasses);
7920 if (!metaClasses) {
7921 goto finish;
7922 }
7923 }
7924
7925 if (metaClasses->containsObject(aClass)) {
7926 OSKextLog(this,
7927 kOSKextLogWarningLevel |
7928 kOSKextLogLoadFlag,
7929 "Notice - kext %s has already registered class %s.",
7930 getIdentifierCString(),
7931 aClass->getClassName());
7932 result = kOSReturnSuccess;
7933 goto finish;
7934 }
7935
7936 if (!metaClasses->setObject(aClass)) {
7937 goto finish;
7938 } else {
7939 OSKextLog(this,
7940 kOSKextLogDetailLevel |
7941 kOSKextLogLoadFlag,
7942 "Kext %s registered class %s.",
7943 getIdentifierCString(),
7944 aClass->getClassName());
7945 }
7946
7947 if (!flags.autounloadEnabled) {
7948 const OSMetaClass * metaScan = NULL;// do not release
7949
7950 for (metaScan = aClass; metaScan; metaScan = metaScan->getSuperClass()) {
7951 if (metaScan == OSTypeID(IOService)) {
7952 OSKextLog(this,
7953 kOSKextLogProgressLevel |
7954 kOSKextLogLoadFlag,
7955 "Kext %s has IOService subclass %s; enabling autounload.",
7956 getIdentifierCString(),
7957 aClass->getClassName());
7958
7959 flags.autounloadEnabled = 1;
7960 break;
7961 }
7962 }
7963 }
7964
7965 notifyAddClassObservers(this, aClass, flags);
7966
7967 result = kOSReturnSuccess;
7968
7969 finish:
7970 if (result != kOSReturnSuccess) {
7971 OSKextLog(this,
7972 kOSKextLogErrorLevel |
7973 kOSKextLogLoadFlag,
7974 "Kext %s failed to register class %s.",
7975 getIdentifierCString(),
7976 aClass->getClassName());
7977 }
7978
7979 return result;
7980 }
7981
7982 /*********************************************************************
7983 *********************************************************************/
7984 OSReturn
7985 OSKext::removeClass(
7986 OSMetaClass * aClass)
7987 {
7988 OSReturn result = kOSMetaClassNoKModSet;
7989
7990 if (!metaClasses) {
7991 goto finish;
7992 }
7993
7994 if (!metaClasses->containsObject(aClass)) {
7995 OSKextLog(this,
7996 kOSKextLogWarningLevel |
7997 kOSKextLogLoadFlag,
7998 "Notice - kext %s asked to unregister unknown class %s.",
7999 getIdentifierCString(),
8000 aClass->getClassName());
8001 result = kOSReturnSuccess;
8002 goto finish;
8003 }
8004
8005 OSKextLog(this,
8006 kOSKextLogDetailLevel |
8007 kOSKextLogLoadFlag,
8008 "Kext %s unregistering class %s.",
8009 getIdentifierCString(),
8010 aClass->getClassName());
8011
8012 metaClasses->removeObject(aClass);
8013
8014 notifyRemoveClassObservers(this, aClass, flags);
8015
8016 result = kOSReturnSuccess;
8017
8018 finish:
8019 if (result != kOSReturnSuccess) {
8020 OSKextLog(this,
8021 kOSKextLogErrorLevel |
8022 kOSKextLogLoadFlag,
8023 "Failed to unregister kext %s class %s.",
8024 getIdentifierCString(),
8025 aClass->getClassName());
8026 }
8027 return result;
8028 }
8029
8030 /*********************************************************************
8031 *********************************************************************/
8032 OSSet *
8033 OSKext::getMetaClasses(void)
8034 {
8035 return metaClasses;
8036 }
8037
8038 /*********************************************************************
8039 *********************************************************************/
8040 bool
8041 OSKext::hasOSMetaClassInstances(void)
8042 {
8043 bool result = false;
8044 OSCollectionIterator * classIterator = NULL; // must release
8045 OSMetaClass * checkClass = NULL;// do not release
8046
8047 if (!metaClasses) {
8048 goto finish;
8049 }
8050
8051 classIterator = OSCollectionIterator::withCollection(metaClasses);
8052 if (!classIterator) {
8053 // xxx - log alloc failure?
8054 goto finish;
8055 }
8056 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
8057 if (checkClass->getInstanceCount()) {
8058 result = true;
8059 goto finish;
8060 }
8061 }
8062
8063 finish:
8064
8065 OSSafeReleaseNULL(classIterator);
8066 return result;
8067 }
8068
8069 /*********************************************************************
8070 *********************************************************************/
8071 /* static */
8072 void
8073 OSKext::reportOSMetaClassInstances(
8074 const char * kextIdentifier,
8075 OSKextLogSpec msgLogSpec)
8076 {
8077 OSKext * theKext = NULL; // must release
8078
8079 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier);
8080 if (!theKext) {
8081 goto finish;
8082 }
8083
8084 theKext->reportOSMetaClassInstances(msgLogSpec);
8085 finish:
8086 OSSafeReleaseNULL(theKext);
8087 return;
8088 }
8089
8090 /*********************************************************************
8091 *********************************************************************/
8092 void
8093 OSKext::reportOSMetaClassInstances(OSKextLogSpec msgLogSpec)
8094 {
8095 OSCollectionIterator * classIterator = NULL; // must release
8096 OSMetaClass * checkClass = NULL;// do not release
8097
8098 if (!metaClasses) {
8099 goto finish;
8100 }
8101
8102 classIterator = OSCollectionIterator::withCollection(metaClasses);
8103 if (!classIterator) {
8104 goto finish;
8105 }
8106 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) {
8107 if (checkClass->getInstanceCount()) {
8108 OSKextLog(this,
8109 msgLogSpec,
8110 " Kext %s class %s has %d instance%s.",
8111 getIdentifierCString(),
8112 checkClass->getClassName(),
8113 checkClass->getInstanceCount(),
8114 checkClass->getInstanceCount() == 1 ? "" : "s");
8115 }
8116 }
8117
8118 finish:
8119 OSSafeReleaseNULL(classIterator);
8120 return;
8121 }
8122
8123 #if PRAGMA_MARK
8124 #pragma mark User-Space Requests
8125 #endif
8126 /*********************************************************************
8127 * XXX - this function is a big ugly mess
8128 *********************************************************************/
8129 /* static */
8130 OSReturn
8131 OSKext::handleRequest(
8132 host_priv_t hostPriv,
8133 OSKextLogSpec clientLogFilter,
8134 char * requestBuffer,
8135 uint32_t requestLength,
8136 char ** responseOut,
8137 uint32_t * responseLengthOut,
8138 char ** logInfoOut,
8139 uint32_t * logInfoLengthOut)
8140 {
8141 OSReturn result = kOSReturnError;
8142 kern_return_t kmem_result = KERN_FAILURE;
8143
8144 char * response = NULL;// returned by reference
8145 uint32_t responseLength = 0;
8146
8147 OSObject * parsedXML = NULL;// must release
8148 OSDictionary * requestDict = NULL;// do not release
8149 OSString * errorString = NULL;// must release
8150
8151 OSObject * responseObject = NULL;// must release
8152
8153 OSSerialize * serializer = NULL;// must release
8154
8155 OSArray * logInfoArray = NULL;// must release
8156
8157 OSString * predicate = NULL;// do not release
8158 OSString * kextIdentifier = NULL;// do not release
8159 OSArray * kextIdentifiers = NULL;// do not release
8160 OSKext * theKext = NULL;// do not release
8161 OSBoolean * boolArg = NULL;// do not release
8162
8163 IORecursiveLockLock(sKextLock);
8164
8165 if (responseOut) {
8166 *responseOut = NULL;
8167 *responseLengthOut = 0;
8168 }
8169 if (logInfoOut) {
8170 *logInfoOut = NULL;
8171 *logInfoLengthOut = 0;
8172 }
8173
8174 OSKext::setUserSpaceLogFilter(clientLogFilter, logInfoOut ? true : false);
8175
8176 /* XML must be nul-terminated.
8177 */
8178 if (requestBuffer[requestLength - 1] != '\0') {
8179 OSKextLog(/* kext */ NULL,
8180 kOSKextLogErrorLevel |
8181 kOSKextLogIPCFlag,
8182 "Invalid request from user space (not nul-terminated).");
8183 result = kOSKextReturnBadData;
8184 goto finish;
8185 }
8186 parsedXML = OSUnserializeXML((const char *)requestBuffer, &errorString);
8187 if (parsedXML) {
8188 requestDict = OSDynamicCast(OSDictionary, parsedXML);
8189 }
8190 if (!requestDict) {
8191 const char * errorCString = "(unknown error)";
8192
8193 if (errorString && errorString->getCStringNoCopy()) {
8194 errorCString = errorString->getCStringNoCopy();
8195 } else if (parsedXML) {
8196 errorCString = "not a dictionary";
8197 }
8198 OSKextLog(/* kext */ NULL,
8199 kOSKextLogErrorLevel |
8200 kOSKextLogIPCFlag,
8201 "Error unserializing request from user space: %s.",
8202 errorCString);
8203 result = kOSKextReturnSerialization;
8204 goto finish;
8205 }
8206
8207 predicate = _OSKextGetRequestPredicate(requestDict);
8208 if (!predicate) {
8209 OSKextLog(/* kext */ NULL,
8210 kOSKextLogErrorLevel |
8211 kOSKextLogIPCFlag,
8212 "Recieved kext request from user space with no predicate.");
8213 result = kOSKextReturnInvalidArgument;
8214 goto finish;
8215 }
8216
8217 OSKextLog(/* kext */ NULL,
8218 kOSKextLogDebugLevel |
8219 kOSKextLogIPCFlag,
8220 "Received '%s' request from user space.",
8221 predicate->getCStringNoCopy());
8222
8223 result = kOSKextReturnNotPrivileged;
8224 if (hostPriv == HOST_PRIV_NULL) {
8225 /* must be root to use these kext requests */
8226 if (predicate->isEqualTo(kKextRequestPredicateUnload) ||
8227 predicate->isEqualTo(kKextRequestPredicateStart) ||
8228 predicate->isEqualTo(kKextRequestPredicateStop) ||
8229 predicate->isEqualTo(kKextRequestPredicateGetKernelRequests) ||
8230 predicate->isEqualTo(kKextRequestPredicateSendResource)) {
8231 OSKextLog(/* kext */ NULL,
8232 kOSKextLogErrorLevel |
8233 kOSKextLogIPCFlag,
8234 "Access Failure - must be root user.");
8235 goto finish;
8236 }
8237 }
8238
8239 /* Get common args in anticipation of use.
8240 */
8241 kextIdentifier = OSDynamicCast(OSString, _OSKextGetRequestArgument(
8242 requestDict, kKextRequestArgumentBundleIdentifierKey));
8243 kextIdentifiers = OSDynamicCast(OSArray, _OSKextGetRequestArgument(
8244 requestDict, kKextRequestArgumentBundleIdentifierKey));
8245 if (kextIdentifier) {
8246 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextIdentifier));
8247 }
8248 boolArg = OSDynamicCast(OSBoolean, _OSKextGetRequestArgument(
8249 requestDict, kKextRequestArgumentValueKey));
8250
8251 result = kOSKextReturnInvalidArgument;
8252
8253 if (predicate->isEqualTo(kKextRequestPredicateStart)) {
8254 if (!kextIdentifier) {
8255 OSKextLog(/* kext */ NULL,
8256 kOSKextLogErrorLevel |
8257 kOSKextLogIPCFlag,
8258 "Invalid arguments to kext start request.");
8259 } else if (!theKext) {
8260 OSKextLog(/* kext */ NULL,
8261 kOSKextLogErrorLevel |
8262 kOSKextLogIPCFlag,
8263 "Kext %s not found for start request.",
8264 kextIdentifier->getCStringNoCopy());
8265 result = kOSKextReturnNotFound;
8266 } else {
8267 result = theKext->start();
8268 }
8269 } else if (predicate->isEqualTo(kKextRequestPredicateStop)) {
8270 if (!kextIdentifier) {
8271 OSKextLog(/* kext */ NULL,
8272 kOSKextLogErrorLevel |
8273 kOSKextLogIPCFlag,
8274 "Invalid arguments to kext stop request.");
8275 } else if (!theKext) {
8276 OSKextLog(/* kext */ NULL,
8277 kOSKextLogErrorLevel |
8278 kOSKextLogIPCFlag,
8279 "Kext %s not found for stop request.",
8280 kextIdentifier->getCStringNoCopy());
8281 result = kOSKextReturnNotFound;
8282 } else {
8283 result = theKext->stop();
8284 }
8285 } else if (predicate->isEqualTo(kKextRequestPredicateUnload)) {
8286 if (!kextIdentifier) {
8287 OSKextLog(/* kext */ NULL,
8288 kOSKextLogErrorLevel |
8289 kOSKextLogIPCFlag,
8290 "Invalid arguments to kext unload request.");
8291 } else if (!theKext) {
8292 OSKextLog(/* kext */ NULL,
8293 kOSKextLogErrorLevel |
8294 kOSKextLogIPCFlag,
8295 "Kext %s not found for unload request.",
8296 kextIdentifier->getCStringNoCopy());
8297 result = kOSKextReturnNotFound;
8298 } else {
8299 OSBoolean * terminateFlag = OSDynamicCast(OSBoolean,
8300 _OSKextGetRequestArgument(requestDict,
8301 kKextRequestArgumentTerminateIOServicesKey));
8302 result = OSKext::removeKext(theKext, terminateFlag == kOSBooleanTrue);
8303 }
8304 } else if (predicate->isEqualTo(kKextRequestPredicateSendResource)) {
8305 result = OSKext::dispatchResource(requestDict);
8306 } else if (predicate->isEqualTo(kKextRequestPredicateGetUUIDByAddress)) {
8307 OSNumber *lookupNum = NULL;
8308 lookupNum = OSDynamicCast(OSNumber,
8309 _OSKextGetRequestArgument(requestDict,
8310 kKextRequestArgumentLookupAddressKey));
8311
8312 responseObject = OSKext::copyKextUUIDForAddress(lookupNum);
8313 if (responseObject) {
8314 result = kOSReturnSuccess;
8315 } else {
8316 goto finish;
8317 }
8318 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoaded) ||
8319 predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
8320 OSBoolean * delayAutounloadBool = NULL;
8321 OSObject * infoKeysRaw = NULL;
8322 OSArray * infoKeys = NULL;
8323 uint32_t infoKeysCount = 0;
8324
8325 delayAutounloadBool = OSDynamicCast(OSBoolean,
8326 _OSKextGetRequestArgument(requestDict,
8327 kKextRequestArgumentDelayAutounloadKey));
8328
8329 /* If asked to delay autounload, reset the timer if it's currently set.
8330 * (That is, don't schedule an unload if one isn't already pending.
8331 */
8332 if (delayAutounloadBool == kOSBooleanTrue) {
8333 OSKext::considerUnloads(/* rescheduleOnly? */ true);
8334 }
8335
8336 infoKeysRaw = _OSKextGetRequestArgument(requestDict,
8337 kKextRequestArgumentInfoKeysKey);
8338 infoKeys = OSDynamicCast(OSArray, infoKeysRaw);
8339 if (infoKeysRaw && !infoKeys) {
8340 OSKextLog(/* kext */ NULL,
8341 kOSKextLogErrorLevel |
8342 kOSKextLogIPCFlag,
8343 "Invalid arguments to kext info request.");
8344 goto finish;
8345 }
8346
8347 if (infoKeys) {
8348 infoKeysCount = infoKeys->getCount();
8349 for (uint32_t i = 0; i < infoKeysCount; i++) {
8350 if (!OSDynamicCast(OSString, infoKeys->getObject(i))) {
8351 OSKextLog(/* kext */ NULL,
8352 kOSKextLogErrorLevel |
8353 kOSKextLogIPCFlag,
8354 "Invalid arguments to kext info request.");
8355 goto finish;
8356 }
8357 }
8358 }
8359
8360 if (predicate->isEqualTo(kKextRequestPredicateGetLoaded)) {
8361 responseObject = OSKext::copyLoadedKextInfo(kextIdentifiers, infoKeys);
8362 } else if (predicate->isEqualTo(kKextRequestPredicateGetLoadedByUUID)) {
8363 responseObject = OSKext::copyLoadedKextInfoByUUID(kextIdentifiers, infoKeys);
8364 }
8365 if (!responseObject) {
8366 result = kOSKextReturnInternalError;
8367 } else {
8368 OSKextLog(/* kext */ NULL,
8369 kOSKextLogDebugLevel |
8370 kOSKextLogIPCFlag,
8371 "Returning loaded kext info.");
8372 result = kOSReturnSuccess;
8373 }
8374 } else if (predicate->isEqualTo(kKextRequestPredicateGetKernelRequests)) {
8375 /* Hand the current sKernelRequests array to the caller
8376 * (who must release it), and make a new one.
8377 */
8378 responseObject = sKernelRequests;
8379 sKernelRequests = OSArray::withCapacity(0);
8380 sPostedKextLoadIdentifiers->flushCollection();
8381 OSKextLog(/* kext */ NULL,
8382 kOSKextLogDebugLevel |
8383 kOSKextLogIPCFlag,
8384 "Returning kernel requests.");
8385 result = kOSReturnSuccess;
8386 } else if (predicate->isEqualTo(kKextRequestPredicateGetAllLoadRequests)) {
8387 /* Return the set of all requested bundle identifiers */
8388 responseObject = sAllKextLoadIdentifiers;
8389 responseObject->retain();
8390 OSKextLog(/* kext */ NULL,
8391 kOSKextLogDebugLevel |
8392 kOSKextLogIPCFlag,
8393 "Returning load requests.");
8394 result = kOSReturnSuccess;
8395 } else {
8396 OSKextLog(/* kext */ NULL,
8397 kOSKextLogDebugLevel |
8398 kOSKextLogIPCFlag,
8399 "Received '%s' invalid request from user space.",
8400 predicate->getCStringNoCopy());
8401 goto finish;
8402 }
8403
8404 /**********
8405 * Now we have handle the request, or not. Gather up the response & logging
8406 * info to ship to user space.
8407 *********/
8408
8409 /* Note: Nothing in OSKext is supposed to retain requestDict,
8410 * but you never know....
8411 */
8412 if (requestDict->getRetainCount() > 1) {
8413 OSKextLog(/* kext */ NULL,
8414 kOSKextLogWarningLevel |
8415 kOSKextLogIPCFlag,
8416 "Request from user space still retained by a kext; "
8417 "probable memory leak.");
8418 }
8419
8420 if (responseOut && responseObject) {
8421 serializer = OSSerialize::withCapacity(0);
8422 if (!serializer) {
8423 result = kOSKextReturnNoMemory;
8424 goto finish;
8425 }
8426
8427 if (!responseObject->serialize(serializer)) {
8428 OSKextLog(/* kext */ NULL,
8429 kOSKextLogGeneralFlag | kOSKextLogErrorLevel,
8430 "Failed to serialize response to request from user space.");
8431 result = kOSKextReturnSerialization;
8432 goto finish;
8433 }
8434
8435 response = (char *)serializer->text();
8436 responseLength = serializer->getLength();
8437 }
8438
8439 if (responseOut && response) {
8440 char * buffer;
8441
8442 /* This kmem_alloc sets the return value of the function.
8443 */
8444 kmem_result = kmem_alloc(kernel_map, (vm_offset_t *)&buffer,
8445 round_page(responseLength), VM_KERN_MEMORY_OSKEXT);
8446 if (kmem_result != KERN_SUCCESS) {
8447 OSKextLog(/* kext */ NULL,
8448 kOSKextLogErrorLevel |
8449 kOSKextLogIPCFlag,
8450 "Failed to copy response to request from user space.");
8451 result = kmem_result;
8452 goto finish;
8453 } else {
8454 /* 11981737 - clear uninitialized data in last page */
8455 bzero((void *)(buffer + responseLength),
8456 (round_page(responseLength) - responseLength));
8457 memcpy(buffer, response, responseLength);
8458 *responseOut = buffer;
8459 *responseLengthOut = responseLength;
8460 }
8461 }
8462
8463 finish:
8464
8465 /* Gather up the collected log messages for user space. Any messages
8466 * messages past this call will not make it up as log messages but
8467 * will be in the system log. Note that we ignore the return of the
8468 * serialize; it has no bearing on the operation at hand even if we
8469 * fail to get the log messages.
8470 */
8471 logInfoArray = OSKext::clearUserSpaceLogFilter();
8472
8473 if (logInfoArray && logInfoOut && logInfoLengthOut) {
8474 (void)OSKext::serializeLogInfo(logInfoArray,
8475 logInfoOut, logInfoLengthOut);
8476 }
8477
8478 IORecursiveLockUnlock(sKextLock);
8479
8480 OSSafeReleaseNULL(parsedXML);
8481 OSSafeReleaseNULL(errorString);
8482 OSSafeReleaseNULL(responseObject);
8483 OSSafeReleaseNULL(serializer);
8484 OSSafeReleaseNULL(logInfoArray);
8485
8486 return result;
8487 }
8488
8489
8490 // #include <InstrProfiling.h>
8491 extern "C" {
8492 uint64_t __llvm_profile_get_size_for_buffer_internal(const char *DataBegin,
8493 const char *DataEnd,
8494 const char *CountersBegin,
8495 const char *CountersEnd,
8496 const char *NamesBegin,
8497 const char *NamesEnd);
8498 int __llvm_profile_write_buffer_internal(char *Buffer,
8499 const char *DataBegin,
8500 const char *DataEnd,
8501 const char *CountersBegin,
8502 const char *CountersEnd,
8503 const char *NamesBegin,
8504 const char *NamesEnd);
8505 }
8506
8507
8508 static
8509 void
8510 OSKextPgoMetadataPut(char *pBuffer,
8511 size_t *position,
8512 size_t bufferSize,
8513 uint32_t *num_pairs,
8514 const char *key,
8515 const char *value)
8516 {
8517 size_t strlen_key = strlen(key);
8518 size_t strlen_value = strlen(value);
8519 size_t len = strlen(key) + 1 + strlen(value) + 1;
8520 char *pos = pBuffer + *position;
8521 *position += len;
8522 if (pBuffer && bufferSize && *position <= bufferSize) {
8523 memcpy(pos, key, strlen_key); pos += strlen_key;
8524 *(pos++) = '=';
8525 memcpy(pos, value, strlen_value); pos += strlen_value;
8526 *(pos++) = 0;
8527 if (num_pairs) {
8528 (*num_pairs)++;
8529 }
8530 }
8531 }
8532
8533
8534 static
8535 void
8536 OSKextPgoMetadataPutMax(size_t *position, const char *key, size_t value_max)
8537 {
8538 *position += strlen(key) + 1 + value_max + 1;
8539 }
8540
8541
8542 static
8543 void
8544 OSKextPgoMetadataPutAll(OSKext *kext,
8545 uuid_t instance_uuid,
8546 char *pBuffer,
8547 size_t *position,
8548 size_t bufferSize,
8549 uint32_t *num_pairs)
8550 {
8551 _static_assert_1_arg(sizeof(clock_sec_t) % 2 == 0);
8552 //log_10 2^16 ≈ 4.82
8553 const size_t max_secs_string_size = 5 * sizeof(clock_sec_t) / 2;
8554 const size_t max_timestamp_string_size = max_secs_string_size + 1 + 6;
8555
8556 if (!pBuffer) {
8557 OSKextPgoMetadataPutMax(position, "INSTANCE", 36);
8558 OSKextPgoMetadataPutMax(position, "UUID", 36);
8559 OSKextPgoMetadataPutMax(position, "TIMESTAMP", max_timestamp_string_size);
8560 } else {
8561 uuid_string_t instance_uuid_string;
8562 uuid_unparse(instance_uuid, instance_uuid_string);
8563 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8564 "INSTANCE", instance_uuid_string);
8565
8566 OSData *uuid_data;
8567 uuid_t uuid;
8568 uuid_string_t uuid_string;
8569 uuid_data = kext->copyUUID();
8570 if (uuid_data) {
8571 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid));
8572 OSSafeReleaseNULL(uuid_data);
8573 uuid_unparse(uuid, uuid_string);
8574 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8575 "UUID", uuid_string);
8576 }
8577
8578 clock_sec_t secs;
8579 clock_usec_t usecs;
8580 clock_get_calendar_microtime(&secs, &usecs);
8581 assert(usecs < 1000000);
8582 char timestamp[max_timestamp_string_size + 1];
8583 _static_assert_1_arg(sizeof(long) >= sizeof(clock_sec_t));
8584 snprintf(timestamp, sizeof(timestamp), "%lu.%06d", (unsigned long)secs, (int)usecs);
8585 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8586 "TIMESTAMP", timestamp);
8587 }
8588
8589 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8590 "NAME", kext->getIdentifierCString());
8591
8592 char versionCString[kOSKextVersionMaxLength];
8593 OSKextVersionGetString(kext->getVersion(), versionCString, kOSKextVersionMaxLength);
8594 OSKextPgoMetadataPut(pBuffer, position, bufferSize, num_pairs,
8595 "VERSION", versionCString);
8596 }
8597
8598 static
8599 size_t
8600 OSKextPgoMetadataSize(OSKext *kext)
8601 {
8602 size_t position = 0;
8603 uuid_t fakeuuid = {};
8604 OSKextPgoMetadataPutAll(kext, fakeuuid, NULL, &position, 0, NULL);
8605 return position;
8606 }
8607
8608 int
8609 OSKextGrabPgoDataLocked(OSKext *kext,
8610 bool metadata,
8611 uuid_t instance_uuid,
8612 uint64_t *pSize,
8613 char *pBuffer,
8614 uint64_t bufferSize)
8615 {
8616 int err = 0;
8617
8618 kernel_section_t *sect_prf_data = NULL;
8619 kernel_section_t *sect_prf_name = NULL;
8620 kernel_section_t *sect_prf_cnts = NULL;
8621 uint64_t size;
8622 size_t metadata_size = 0;
8623
8624 sect_prf_data = kext->lookupSection("__DATA", "__llvm_prf_data");
8625 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_names");
8626 if (!sect_prf_name) {
8627 // kextcache sometimes truncates the section name to 15 chars
8628 // <rdar://problem/52080551> 16 character section name is truncated to 15 characters by kextcache
8629 sect_prf_name = kext->lookupSection("__DATA", "__llvm_prf_name");
8630 }
8631 sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
8632
8633 if (!sect_prf_data || !sect_prf_name || !sect_prf_cnts) {
8634 err = ENOTSUP;
8635 goto out;
8636 }
8637
8638 size = __llvm_profile_get_size_for_buffer_internal(
8639 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
8640 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
8641 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
8642
8643 if (metadata) {
8644 metadata_size = OSKextPgoMetadataSize(kext);
8645 size += metadata_size;
8646 size += sizeof(pgo_metadata_footer);
8647 }
8648
8649
8650 if (pSize) {
8651 *pSize = size;
8652 }
8653
8654 if (pBuffer && bufferSize) {
8655 if (bufferSize < size) {
8656 err = ERANGE;
8657 goto out;
8658 }
8659
8660 err = __llvm_profile_write_buffer_internal(
8661 pBuffer,
8662 (const char*) sect_prf_data->addr, (const char*) sect_prf_data->addr + sect_prf_data->size,
8663 (const char*) sect_prf_cnts->addr, (const char*) sect_prf_cnts->addr + sect_prf_cnts->size,
8664 (const char*) sect_prf_name->addr, (const char*) sect_prf_name->addr + sect_prf_name->size);
8665
8666 if (err) {
8667 err = EIO;
8668 goto out;
8669 }
8670
8671 if (metadata) {
8672 char *end_of_buffer = pBuffer + size;
8673 struct pgo_metadata_footer *footerp = (struct pgo_metadata_footer *) (end_of_buffer - sizeof(struct pgo_metadata_footer));
8674 char *metadata_buffer = end_of_buffer - (sizeof(struct pgo_metadata_footer) + metadata_size);
8675
8676 size_t metadata_position = 0;
8677 uint32_t num_pairs = 0;
8678 OSKextPgoMetadataPutAll(kext, instance_uuid, metadata_buffer, &metadata_position, metadata_size, &num_pairs);
8679 while (metadata_position < metadata_size) {
8680 metadata_buffer[metadata_position++] = 0;
8681 }
8682
8683 struct pgo_metadata_footer footer;
8684 footer.magic = htonl(0x6d657461);
8685 footer.number_of_pairs = htonl( num_pairs );
8686 footer.offset_to_pairs = htonl( sizeof(struct pgo_metadata_footer) + metadata_size );
8687 memcpy(footerp, &footer, sizeof(footer));
8688 }
8689 }
8690
8691 out:
8692 return err;
8693 }
8694
8695
8696 int
8697 OSKextGrabPgoData(uuid_t uuid,
8698 uint64_t *pSize,
8699 char *pBuffer,
8700 uint64_t bufferSize,
8701 int wait_for_unload,
8702 int metadata)
8703 {
8704 int err = 0;
8705 OSKext *kext = NULL;
8706
8707
8708 IORecursiveLockLock(sKextLock);
8709
8710 kext = OSKext::lookupKextWithUUID(uuid);
8711 if (!kext) {
8712 err = ENOENT;
8713 goto out;
8714 }
8715
8716 if (wait_for_unload) {
8717 OSKextGrabPgoStruct s;
8718
8719 s.metadata = metadata;
8720 s.pSize = pSize;
8721 s.pBuffer = pBuffer;
8722 s.bufferSize = bufferSize;
8723 s.err = EINTR;
8724
8725 struct list_head *prev = &kext->pendingPgoHead;
8726 struct list_head *next = kext->pendingPgoHead.next;
8727
8728 s.list_head.prev = prev;
8729 s.list_head.next = next;
8730
8731 prev->next = &s.list_head;
8732 next->prev = &s.list_head;
8733
8734 kext->release();
8735 kext = NULL;
8736
8737 IORecursiveLockSleep(sKextLock, &s, THREAD_ABORTSAFE);
8738
8739 prev = s.list_head.prev;
8740 next = s.list_head.next;
8741
8742 prev->next = next;
8743 next->prev = prev;
8744
8745 err = s.err;
8746 } else {
8747 err = OSKextGrabPgoDataLocked(kext, metadata, kext->instance_uuid, pSize, pBuffer, bufferSize);
8748 }
8749
8750 out:
8751 if (kext) {
8752 kext->release();
8753 }
8754
8755 IORecursiveLockUnlock(sKextLock);
8756
8757 return err;
8758 }
8759
8760 void
8761 OSKextResetPgoCountersLock()
8762 {
8763 IORecursiveLockLock(sKextLock);
8764 }
8765
8766 void
8767 OSKextResetPgoCountersUnlock()
8768 {
8769 IORecursiveLockUnlock(sKextLock);
8770 }
8771
8772
8773 extern unsigned int not_in_kdp;
8774
8775 void
8776 OSKextResetPgoCounters()
8777 {
8778 assert(!not_in_kdp);
8779 uint32_t count = sLoadedKexts->getCount();
8780 for (uint32_t i = 0; i < count; i++) {
8781 OSKext *kext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
8782 kernel_section_t *sect_prf_cnts = kext->lookupSection("__DATA", "__llvm_prf_cnts");
8783 if (!sect_prf_cnts) {
8784 continue;
8785 }
8786 memset((void*)sect_prf_cnts->addr, 0, sect_prf_cnts->size);
8787 }
8788 }
8789
8790 OSDictionary *
8791 OSKext::copyLoadedKextInfoByUUID(
8792 OSArray * kextIdentifiers,
8793 OSArray * infoKeys)
8794 {
8795 OSDictionary * result = NULL;
8796 OSDictionary * kextInfo = NULL; // must release
8797 uint32_t max_count, i, j;
8798 uint32_t idCount = 0;
8799 uint32_t idIndex = 0;
8800 IORecursiveLockLock(sKextLock);
8801 OSArray *list[2] = {sLoadedKexts, sLoadedDriverKitKexts};
8802 uint32_t count[2] = {sLoadedKexts->getCount(), sLoadedDriverKitKexts->getCount()};
8803
8804 #if CONFIG_MACF
8805 /* Is the calling process allowed to query kext info? */
8806 if (current_task() != kernel_task) {
8807 int macCheckResult = 0;
8808 kauth_cred_t cred = NULL;
8809
8810 cred = kauth_cred_get_with_ref();
8811 macCheckResult = mac_kext_check_query(cred);
8812 kauth_cred_unref(&cred);
8813
8814 if (macCheckResult != 0) {
8815 OSKextLog(/* kext */ NULL,
8816 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
8817 "Failed to query kext info (MAC policy error 0x%x).",
8818 macCheckResult);
8819 goto finish;
8820 }
8821 }
8822 #endif
8823
8824 /* Empty list of UUIDs is equivalent to no list (get all).
8825 */
8826 if (kextIdentifiers && !kextIdentifiers->getCount()) {
8827 kextIdentifiers = NULL;
8828 } else if (kextIdentifiers) {
8829 idCount = kextIdentifiers->getCount();
8830 }
8831
8832 /* Same for keys.
8833 */
8834 if (infoKeys && !infoKeys->getCount()) {
8835 infoKeys = NULL;
8836 }
8837
8838 max_count = count[0] + count[1];
8839 result = OSDictionary::withCapacity(max_count);
8840 if (!result) {
8841 goto finish;
8842 }
8843
8844 for (j = 0; j < (sizeof(list) / sizeof(list[0])); j++) {
8845 for (i = 0; i < count[j]; i++) {
8846 OSKext *thisKext = NULL;// do not release
8847 Boolean includeThis = true;
8848 uuid_t thisKextUUID;
8849 uuid_t thisKextTextUUID;
8850 OSData *uuid_data;
8851 uuid_string_t uuid_key;
8852
8853 thisKext = OSDynamicCast(OSKext, list[j]->getObject(i));
8854 if (!thisKext) {
8855 continue;
8856 }
8857
8858 uuid_data = thisKext->copyUUID();
8859 if (!uuid_data) {
8860 continue;
8861 }
8862
8863 memcpy(&thisKextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextUUID));
8864 OSSafeReleaseNULL(uuid_data);
8865
8866 uuid_unparse(thisKextUUID, uuid_key);
8867
8868 uuid_data = thisKext->copyTextUUID();
8869 if (!uuid_data) {
8870 continue;
8871 }
8872 memcpy(&thisKextTextUUID, uuid_data->getBytesNoCopy(), sizeof(thisKextTextUUID));
8873 OSSafeReleaseNULL(uuid_data);
8874
8875 /* Skip current kext if we have a list of UUIDs and
8876 * it isn't in the list.
8877 */
8878 if (kextIdentifiers) {
8879 includeThis = false;
8880
8881 for (idIndex = 0; idIndex < idCount; idIndex++) {
8882 const OSString* wantedUUID = OSDynamicCast(OSString,
8883 kextIdentifiers->getObject(idIndex));
8884
8885 uuid_t uuid;
8886 uuid_parse(wantedUUID->getCStringNoCopy(), uuid);
8887
8888 if ((0 == uuid_compare(uuid, thisKextUUID))
8889 || (0 == uuid_compare(uuid, thisKextTextUUID))) {
8890 includeThis = true;
8891 /* Only need to find the first kext if multiple match,
8892 * ie. asking for the kernel uuid does not need to find
8893 * interface kexts or builtin static kexts.
8894 */
8895 kextIdentifiers->removeObject(idIndex);
8896 uuid_unparse(uuid, uuid_key);
8897 break;
8898 }
8899 }
8900 }
8901
8902 if (!includeThis) {
8903 continue;
8904 }
8905
8906 kextInfo = thisKext->copyInfo(infoKeys);
8907 if (kextInfo) {
8908 result->setObject(uuid_key, kextInfo);
8909 kextInfo->release();
8910 }
8911
8912 if (kextIdentifiers && !kextIdentifiers->getCount()) {
8913 goto finish;
8914 }
8915 }
8916 }
8917
8918 finish:
8919 IORecursiveLockUnlock(sKextLock);
8920
8921 return result;
8922 }
8923
8924 /*********************************************************************
8925 *********************************************************************/
8926 /* static */
8927 OSDictionary *
8928 OSKext::copyLoadedKextInfo(
8929 OSArray * kextIdentifiers,
8930 OSArray * infoKeys)
8931 {
8932 OSDictionary * result = NULL;
8933 uint32_t idCount = 0;
8934 bool onlyLoaded;
8935
8936 IORecursiveLockLock(sKextLock);
8937
8938 #if CONFIG_MACF
8939 /* Is the calling process allowed to query kext info? */
8940 if (current_task() != kernel_task) {
8941 int macCheckResult = 0;
8942 kauth_cred_t cred = NULL;
8943
8944 cred = kauth_cred_get_with_ref();
8945 macCheckResult = mac_kext_check_query(cred);
8946 kauth_cred_unref(&cred);
8947
8948 if (macCheckResult != 0) {
8949 OSKextLog(/* kext */ NULL,
8950 kOSKextLogErrorLevel | kOSKextLogLoadFlag,
8951 "Failed to query kext info (MAC policy error 0x%x).",
8952 macCheckResult);
8953 goto finish;
8954 }
8955 }
8956 #endif
8957
8958 /* Empty list of bundle ids is equivalent to no list (get all).
8959 */
8960 if (kextIdentifiers && !kextIdentifiers->getCount()) {
8961 kextIdentifiers = NULL;
8962 } else if (kextIdentifiers) {
8963 idCount = kextIdentifiers->getCount();
8964 }
8965
8966 /* Same for keys.
8967 */
8968 if (infoKeys && !infoKeys->getCount()) {
8969 infoKeys = NULL;
8970 }
8971
8972 onlyLoaded = (!infoKeys || !_OSArrayContainsCString(infoKeys, kOSBundleAllPrelinkedKey));
8973
8974 result = OSDictionary::withCapacity(128);
8975 if (!result) {
8976 goto finish;
8977 }
8978
8979 #if 0
8980 OSKextLog(/* kext */ NULL,
8981 kOSKextLogErrorLevel |
8982 kOSKextLogGeneralFlag,
8983 "kaslr: vm_kernel_slide 0x%lx \n",
8984 vm_kernel_slide);
8985 OSKextLog(/* kext */ NULL,
8986 kOSKextLogErrorLevel |
8987 kOSKextLogGeneralFlag,
8988 "kaslr: vm_kernel_stext 0x%lx vm_kernel_etext 0x%lx \n",
8989 vm_kernel_stext, vm_kernel_etext);
8990 OSKextLog(/* kext */ NULL,
8991 kOSKextLogErrorLevel |
8992 kOSKextLogGeneralFlag,
8993 "kaslr: vm_kernel_base 0x%lx vm_kernel_top 0x%lx \n",
8994 vm_kernel_base, vm_kernel_top);
8995 OSKextLog(/* kext */ NULL,
8996 kOSKextLogErrorLevel |
8997 kOSKextLogGeneralFlag,
8998 "kaslr: vm_kext_base 0x%lx vm_kext_top 0x%lx \n",
8999 vm_kext_base, vm_kext_top);
9000 OSKextLog(/* kext */ NULL,
9001 kOSKextLogErrorLevel |
9002 kOSKextLogGeneralFlag,
9003 "kaslr: vm_prelink_stext 0x%lx vm_prelink_etext 0x%lx \n",
9004 vm_prelink_stext, vm_prelink_etext);
9005 OSKextLog(/* kext */ NULL,
9006 kOSKextLogErrorLevel |
9007 kOSKextLogGeneralFlag,
9008 "kaslr: vm_prelink_sinfo 0x%lx vm_prelink_einfo 0x%lx \n",
9009 vm_prelink_sinfo, vm_prelink_einfo);
9010 OSKextLog(/* kext */ NULL,
9011 kOSKextLogErrorLevel |
9012 kOSKextLogGeneralFlag,
9013 "kaslr: vm_slinkedit 0x%lx vm_elinkedit 0x%lx \n",
9014 vm_slinkedit, vm_elinkedit);
9015 #endif
9016
9017 sKextsByID->iterateObjects(^bool (const OSSymbol * thisKextID, OSObject * obj)
9018 {
9019 OSKext * thisKext = NULL;// do not release
9020 Boolean includeThis = true;
9021 OSDictionary * kextInfo = NULL;// must release
9022
9023 thisKext = OSDynamicCast(OSKext, obj);
9024 if (!thisKext) {
9025 return false;;
9026 }
9027
9028 /* Skip current kext if not yet started and caller didn't request all.
9029 */
9030 if (onlyLoaded && (-1U == sLoadedKexts->getNextIndexOfObject(thisKext, 0))) {
9031 return false;;
9032 }
9033
9034 /* Skip current kext if we have a list of bundle IDs and
9035 * it isn't in the list.
9036 */
9037 if (kextIdentifiers) {
9038 includeThis = false;
9039
9040 for (uint32_t idIndex = 0; idIndex < idCount; idIndex++) {
9041 const OSString * thisRequestID = OSDynamicCast(OSString,
9042 kextIdentifiers->getObject(idIndex));
9043 if (thisKextID->isEqualTo(thisRequestID)) {
9044 includeThis = true;
9045 break;
9046 }
9047 }
9048 }
9049
9050 if (!includeThis) {
9051 return false;
9052 }
9053
9054 kextInfo = thisKext->copyInfo(infoKeys);
9055 if (kextInfo) {
9056 result->setObject(thisKext->getIdentifier(), kextInfo);
9057 kextInfo->release();
9058 }
9059 return false;
9060 });
9061
9062 finish:
9063 IORecursiveLockUnlock(sKextLock);
9064
9065 return result;
9066 }
9067
9068 /*********************************************************************
9069 * Any info that needs to do allocations must goto finish on alloc
9070 * failure. Info that is just a lookup should just not set the object
9071 * if the info does not exist.
9072 *********************************************************************/
9073 #define _OSKextLoadInfoDictCapacity (12)
9074
9075 OSDictionary *
9076 OSKext::copyInfo(OSArray * infoKeys)
9077 {
9078 OSDictionary * result = NULL;
9079 bool success = false;
9080 OSData * headerData = NULL;// must release
9081 OSData * logData = NULL;// must release
9082 OSNumber * cpuTypeNumber = NULL;// must release
9083 OSNumber * cpuSubtypeNumber = NULL;// must release
9084 OSString * versionString = NULL;// do not release
9085 uint32_t executablePathCStringSize = 0;
9086 char * executablePathCString = NULL;// must release
9087 OSString * executablePathString = NULL;// must release
9088 OSData * uuid = NULL;// must release
9089 OSNumber * scratchNumber = NULL;// must release
9090 OSArray * dependencyLoadTags = NULL;// must release
9091 OSCollectionIterator * metaClassIterator = NULL;// must release
9092 OSArray * metaClassInfo = NULL;// must release
9093 OSDictionary * metaClassDict = NULL;// must release
9094 OSMetaClass * thisMetaClass = NULL;// do not release
9095 OSString * metaClassName = NULL;// must release
9096 OSString * superclassName = NULL;// must release
9097 uint32_t count, i;
9098
9099 result = OSDictionary::withCapacity(_OSKextLoadInfoDictCapacity);
9100 if (!result) {
9101 goto finish;
9102 }
9103
9104
9105 /* Empty keys means no keys, but NULL is quicker to check.
9106 */
9107 if (infoKeys && !infoKeys->getCount()) {
9108 infoKeys = NULL;
9109 }
9110
9111 /* Headers, CPU type, and CPU subtype.
9112 */
9113 if (!infoKeys ||
9114 _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey) ||
9115 _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey) ||
9116 _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey) ||
9117 _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
9118 if (linkedExecutable && !isInterface()) {
9119 kernel_mach_header_t *kext_mach_hdr = (kernel_mach_header_t *)
9120 linkedExecutable->getBytesNoCopy();
9121
9122 #if !SECURE_KERNEL
9123 // do not return macho header info on shipping iOS - 19095897
9124 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleMachOHeadersKey)) {
9125 kernel_mach_header_t * temp_kext_mach_hdr;
9126 struct load_command * lcp;
9127
9128 headerData = OSData::withBytes(kext_mach_hdr,
9129 (u_int) (sizeof(*kext_mach_hdr) + kext_mach_hdr->sizeofcmds));
9130 if (!headerData) {
9131 goto finish;
9132 }
9133
9134 // unslide any vmaddrs we return to userspace - 10726716
9135 temp_kext_mach_hdr = (kernel_mach_header_t *)
9136 headerData->getBytesNoCopy();
9137 if (temp_kext_mach_hdr == NULL) {
9138 goto finish;
9139 }
9140
9141 lcp = (struct load_command *) (temp_kext_mach_hdr + 1);
9142 for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) {
9143 if (lcp->cmd == LC_SEGMENT_KERNEL) {
9144 kernel_segment_command_t * segp;
9145 kernel_section_t * secp;
9146
9147 segp = (kernel_segment_command_t *) lcp;
9148 // 10543468 - if we jettisoned __LINKEDIT clear size info
9149 if (flags.jettisonLinkeditSeg) {
9150 if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) {
9151 segp->vmsize = 0;
9152 segp->fileoff = 0;
9153 segp->filesize = 0;
9154 }
9155 }
9156
9157 #if 0
9158 OSKextLog(/* kext */ NULL,
9159 kOSKextLogErrorLevel |
9160 kOSKextLogGeneralFlag,
9161 "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u",
9162 __FUNCTION__, segp->segname, segp->vmaddr,
9163 VM_KERNEL_UNSLIDE(segp->vmaddr),
9164 segp->vmsize, segp->nsects);
9165 if ((VM_KERNEL_IS_SLID(segp->vmaddr) == false) &&
9166 (VM_KERNEL_IS_KEXT(segp->vmaddr) == false) &&
9167 (VM_KERNEL_IS_PRELINKTEXT(segp->vmaddr) == false) &&
9168 (VM_KERNEL_IS_PRELINKINFO(segp->vmaddr) == false) &&
9169 (VM_KERNEL_IS_KEXT_LINKEDIT(segp->vmaddr) == false)) {
9170 OSKextLog(/* kext */ NULL,
9171 kOSKextLogErrorLevel |
9172 kOSKextLogGeneralFlag,
9173 "%s: not in kext range - vmaddr 0x%llX vm_kext_base 0x%lX vm_kext_top 0x%lX",
9174 __FUNCTION__, segp->vmaddr, vm_kext_base, vm_kext_top);
9175 }
9176 #endif
9177 segp->vmaddr = ml_static_unslide(segp->vmaddr);
9178
9179 for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) {
9180 secp->addr = ml_static_unslide(secp->addr);
9181 }
9182 }
9183 lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize);
9184 }
9185 result->setObject(kOSBundleMachOHeadersKey, headerData);
9186 }
9187 #endif // SECURE_KERNEL
9188
9189 if (_OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
9190 osLogDataHeaderRef *header;
9191 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
9192
9193 void *os_log_data = NULL;
9194 void *cstring_data = NULL;
9195 unsigned long os_log_size = 0;
9196 unsigned long cstring_size = 0;
9197 uint32_t os_log_offset = 0;
9198 uint32_t cstring_offset = 0;
9199 bool res;
9200
9201 os_log_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__os_log", &os_log_size);
9202 os_log_offset = getsectoffsetfromheader(kext_mach_hdr, "__TEXT", "__os_log");
9203 cstring_data = getsectdatafromheader(kext_mach_hdr, "__TEXT", "__cstring", &cstring_size);
9204 cstring_offset = getsectoffsetfromheader(kext_mach_hdr, "__TEXT", "__cstring");
9205
9206 header = (osLogDataHeaderRef *) headerBytes;
9207 header->version = OS_LOG_HDR_VERSION;
9208 header->sect_count = NUM_OS_LOG_SECTIONS;
9209 header->sections[OS_LOG_SECT_IDX].sect_offset = os_log_offset;
9210 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) os_log_size;
9211 header->sections[CSTRING_SECT_IDX].sect_offset = cstring_offset;
9212 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) cstring_size;
9213
9214
9215 logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef)));
9216 if (!logData) {
9217 goto finish;
9218 }
9219 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
9220 if (!res) {
9221 goto finish;
9222 }
9223 if (os_log_data) {
9224 res = logData->appendBytes(os_log_data, (u_int)header->sections[OS_LOG_SECT_IDX].sect_size);
9225 if (!res) {
9226 goto finish;
9227 }
9228 }
9229 if (cstring_data) {
9230 res = logData->appendBytes(cstring_data, (u_int)header->sections[CSTRING_SECT_IDX].sect_size);
9231 if (!res) {
9232 goto finish;
9233 }
9234 }
9235 result->setObject(kOSBundleLogStringsKey, logData);
9236 }
9237
9238 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUTypeKey)) {
9239 cpuTypeNumber = OSNumber::withNumber(
9240 (uint64_t) kext_mach_hdr->cputype,
9241 8 * sizeof(kext_mach_hdr->cputype));
9242 if (!cpuTypeNumber) {
9243 goto finish;
9244 }
9245 result->setObject(kOSBundleCPUTypeKey, cpuTypeNumber);
9246 }
9247
9248 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCPUSubtypeKey)) {
9249 cpuSubtypeNumber = OSNumber::withNumber(
9250 (uint64_t) kext_mach_hdr->cpusubtype,
9251 8 * sizeof(kext_mach_hdr->cpusubtype));
9252 if (!cpuSubtypeNumber) {
9253 goto finish;
9254 }
9255 result->setObject(kOSBundleCPUSubtypeKey, cpuSubtypeNumber);
9256 }
9257 } else {
9258 if (isDriverKit() && _OSArrayContainsCString(infoKeys, kOSBundleLogStringsKey)) {
9259 osLogDataHeaderRef *header;
9260 char headerBytes[offsetof(osLogDataHeaderRef, sections) + NUM_OS_LOG_SECTIONS * sizeof(header->sections[0])];
9261 bool res;
9262
9263 header = (osLogDataHeaderRef *) headerBytes;
9264 header->version = OS_LOG_HDR_VERSION;
9265 header->sect_count = NUM_OS_LOG_SECTIONS;
9266 header->sections[OS_LOG_SECT_IDX].sect_offset = 0;
9267 header->sections[OS_LOG_SECT_IDX].sect_size = (uint32_t) 0;
9268 header->sections[CSTRING_SECT_IDX].sect_offset = 0;
9269 header->sections[CSTRING_SECT_IDX].sect_size = (uint32_t) 0;
9270
9271 logData = OSData::withBytes(header, (u_int) (sizeof(osLogDataHeaderRef)));
9272 if (!logData) {
9273 goto finish;
9274 }
9275 res = logData->appendBytes(&(header->sections[0]), (u_int)(header->sect_count * sizeof(header->sections[0])));
9276 if (!res) {
9277 goto finish;
9278 }
9279 result->setObject(kOSBundleLogStringsKey, logData);
9280 }
9281 }
9282 }
9283
9284 /* CFBundleIdentifier. We set this regardless because it's just stupid not to.
9285 */
9286 result->setObject(kCFBundleIdentifierKey, bundleID);
9287
9288 /* CFBundleVersion.
9289 */
9290 if (!infoKeys || _OSArrayContainsCString(infoKeys, kCFBundleVersionKey)) {
9291 versionString = OSDynamicCast(OSString,
9292 getPropertyForHostArch(kCFBundleVersionKey));
9293 if (versionString) {
9294 result->setObject(kCFBundleVersionKey, versionString);
9295 }
9296 }
9297
9298 /* OSBundleCompatibleVersion.
9299 */
9300 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCompatibleVersionKey)) {
9301 versionString = OSDynamicCast(OSString,
9302 getPropertyForHostArch(kOSBundleCompatibleVersionKey));
9303 if (versionString) {
9304 result->setObject(kOSBundleCompatibleVersionKey, versionString);
9305 }
9306 }
9307
9308 /* Path.
9309 */
9310 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePathKey)) {
9311 if (path) {
9312 result->setObject(kOSBundlePathKey, path);
9313 }
9314 }
9315
9316
9317 /* OSBundleExecutablePath.
9318 */
9319 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecutablePathKey)) {
9320 if (path && executableRelPath) {
9321 uint32_t pathLength = path->getLength(); // gets incremented below
9322
9323 // +1 for slash, +1 for \0
9324 executablePathCStringSize = pathLength + executableRelPath->getLength() + 2;
9325
9326 executablePathCString = (char *)kalloc_tag((executablePathCStringSize) *
9327 sizeof(char), VM_KERN_MEMORY_OSKEXT); // +1 for \0
9328 if (!executablePathCString) {
9329 goto finish;
9330 }
9331 strlcpy(executablePathCString, path->getCStringNoCopy(),
9332 executablePathCStringSize);
9333 executablePathCString[pathLength++] = '/';
9334 executablePathCString[pathLength++] = '\0';
9335 strlcat(executablePathCString, executableRelPath->getCStringNoCopy(),
9336 executablePathCStringSize);
9337
9338 executablePathString = OSString::withCString(executablePathCString);
9339
9340 if (!executablePathString) {
9341 goto finish;
9342 }
9343
9344 result->setObject(kOSBundleExecutablePathKey, executablePathString);
9345 } else if (flags.builtin) {
9346 result->setObject(kOSBundleExecutablePathKey, bundleID);
9347 } else if (isDriverKit()) {
9348 if (path) {
9349 // +1 for slash, +1 for \0
9350 uint32_t pathLength = path->getLength();
9351 executablePathCStringSize = pathLength + 2;
9352
9353 executablePathCString = (char *)kalloc_tag((executablePathCStringSize) *
9354 sizeof(char), VM_KERN_MEMORY_OSKEXT);
9355 if (!executablePathCString) {
9356 goto finish;
9357 }
9358 strlcpy(executablePathCString, path->getCStringNoCopy(), executablePathCStringSize);
9359 executablePathCString[pathLength++] = '/';
9360 executablePathCString[pathLength++] = '\0';
9361
9362 executablePathString = OSString::withCString(executablePathCString);
9363
9364 if (!executablePathString) {
9365 goto finish;
9366 }
9367
9368 result->setObject(kOSBundleExecutablePathKey, executablePathString);
9369 }
9370 }
9371 }
9372
9373 /* UUID, if the kext has one.
9374 */
9375 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleUUIDKey)) {
9376 uuid = copyUUID();
9377 if (uuid) {
9378 result->setObject(kOSBundleUUIDKey, uuid);
9379 uuid->release();
9380 }
9381 }
9382 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleTextUUIDKey)) {
9383 uuid = copyTextUUID();
9384 if (uuid) {
9385 result->setObject(kOSBundleTextUUIDKey, uuid); uuid->release();
9386 }
9387 }
9388
9389 /*****
9390 * OSKernelResource, OSBundleIsInterface, OSBundlePrelinked, OSBundleStarted.
9391 */
9392 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSKernelResourceKey)) {
9393 result->setObject(kOSKernelResourceKey,
9394 isKernelComponent() ? kOSBooleanTrue : kOSBooleanFalse);
9395 }
9396
9397 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleIsInterfaceKey)) {
9398 result->setObject(kOSBundleIsInterfaceKey,
9399 isInterface() ? kOSBooleanTrue : kOSBooleanFalse);
9400 }
9401
9402 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundlePrelinkedKey)) {
9403 result->setObject(kOSBundlePrelinkedKey,
9404 isPrelinked() ? kOSBooleanTrue : kOSBooleanFalse);
9405 }
9406
9407 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleStartedKey)) {
9408 result->setObject(kOSBundleStartedKey,
9409 isStarted() ? kOSBooleanTrue : kOSBooleanFalse);
9410 }
9411
9412 /* LoadTag (Index).
9413 */
9414 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadTagKey)) {
9415 scratchNumber = OSNumber::withNumber((unsigned long long)loadTag,
9416 /* numBits */ 8 * sizeof(loadTag));
9417 if (!scratchNumber) {
9418 goto finish;
9419 }
9420 result->setObject(kOSBundleLoadTagKey, scratchNumber);
9421 OSSafeReleaseNULL(scratchNumber);
9422 }
9423
9424 /* LoadAddress, LoadSize.
9425 */
9426 if (!infoKeys ||
9427 _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey) ||
9428 _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey) ||
9429 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey) ||
9430 _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey) ||
9431 _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
9432 bool is_dext = isDriverKit();
9433 if (isInterface() || flags.builtin || linkedExecutable || is_dext) {
9434 /* These go to userspace via serialization, so we don't want any doubts
9435 * about their size.
9436 */
9437 uint64_t loadAddress = 0;
9438 uint32_t loadSize = 0;
9439 uint32_t wiredSize = 0;
9440 uint64_t execLoadAddress = 0;
9441 uint32_t execLoadSize = 0;
9442
9443 /* Interfaces always report 0 load address & size.
9444 * Just the way they roll.
9445 *
9446 * xxx - leaving in # when we have a linkedExecutable...a kernelcomp
9447 * xxx - shouldn't have one!
9448 */
9449
9450 if (flags.builtin || linkedExecutable) {
9451 kernel_mach_header_t *mh = NULL;
9452 kernel_segment_command_t *seg = NULL;
9453
9454 if (flags.builtin) {
9455 loadAddress = kmod_info->address;
9456 loadSize = kmod_info->size;
9457 } else {
9458 loadAddress = (uint64_t)linkedExecutable->getBytesNoCopy();
9459 loadSize = linkedExecutable->getLength();
9460 }
9461 mh = (kernel_mach_header_t *)loadAddress;
9462 loadAddress = ml_static_unslide(loadAddress);
9463
9464 /* Walk through the kext, looking for the first executable
9465 * segment in case we were asked for its size/address.
9466 */
9467 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
9468 if (seg->initprot & VM_PROT_EXECUTE) {
9469 execLoadAddress = ml_static_unslide(seg->vmaddr);
9470 execLoadSize = seg->vmsize;
9471 break;
9472 }
9473 }
9474
9475 /* If we have a kmod_info struct, calculated the wired size
9476 * from that. Otherwise it's the full load size.
9477 */
9478 if (kmod_info) {
9479 wiredSize = loadSize - kmod_info->hdr_size;
9480 } else {
9481 wiredSize = loadSize;
9482 }
9483 } else if (is_dext) {
9484 /*
9485 * DriverKit userspace executables do not have a kernel linkedExecutable,
9486 * so we "fake" their address range with the LoadTag.
9487 */
9488 if (loadTag) {
9489 loadAddress = execLoadAddress = loadTag;
9490 loadSize = execLoadSize = 1;
9491 }
9492 }
9493
9494 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadAddressKey)) {
9495 scratchNumber = OSNumber::withNumber(
9496 (unsigned long long)(loadAddress),
9497 /* numBits */ 8 * sizeof(loadAddress));
9498 if (!scratchNumber) {
9499 goto finish;
9500 }
9501 result->setObject(kOSBundleLoadAddressKey, scratchNumber);
9502 OSSafeReleaseNULL(scratchNumber);
9503 }
9504 #if CONFIG_EMBEDDED
9505 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleCacheLoadAddressKey))
9506 && loadAddress && loadSize) {
9507 scratchNumber = OSNumber::withNumber(
9508 (unsigned long long)ml_static_unslide((uintptr_t)segLOWESTTEXT),
9509 /* numBits */ 8 * sizeof(loadAddress));
9510 if (!scratchNumber) {
9511 goto finish;
9512 }
9513 result->setObject(kOSBundleCacheLoadAddressKey, scratchNumber);
9514 OSSafeReleaseNULL(scratchNumber);
9515 }
9516 if ((!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleKextsInKernelTextKey))
9517 && (this == sKernelKext) && gBuiltinKmodsCount) {
9518 result->setObject(kOSBundleKextsInKernelTextKey, kOSBooleanTrue);
9519 }
9520 #endif /* CONFIG_EMBEDDED */
9521 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadAddressKey)) {
9522 scratchNumber = OSNumber::withNumber(
9523 (unsigned long long)(execLoadAddress),
9524 /* numBits */ 8 * sizeof(execLoadAddress));
9525 if (!scratchNumber) {
9526 goto finish;
9527 }
9528 result->setObject(kOSBundleExecLoadAddressKey, scratchNumber);
9529 OSSafeReleaseNULL(scratchNumber);
9530 }
9531 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleLoadSizeKey)) {
9532 scratchNumber = OSNumber::withNumber(
9533 (unsigned long long)(loadSize),
9534 /* numBits */ 8 * sizeof(loadSize));
9535 if (!scratchNumber) {
9536 goto finish;
9537 }
9538 result->setObject(kOSBundleLoadSizeKey, scratchNumber);
9539 OSSafeReleaseNULL(scratchNumber);
9540 }
9541 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleExecLoadSizeKey)) {
9542 scratchNumber = OSNumber::withNumber(
9543 (unsigned long long)(execLoadSize),
9544 /* numBits */ 8 * sizeof(execLoadSize));
9545 if (!scratchNumber) {
9546 goto finish;
9547 }
9548 result->setObject(kOSBundleExecLoadSizeKey, scratchNumber);
9549 OSSafeReleaseNULL(scratchNumber);
9550 }
9551 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleWiredSizeKey)) {
9552 scratchNumber = OSNumber::withNumber(
9553 (unsigned long long)(wiredSize),
9554 /* numBits */ 8 * sizeof(wiredSize));
9555 if (!scratchNumber) {
9556 goto finish;
9557 }
9558 result->setObject(kOSBundleWiredSizeKey, scratchNumber);
9559 OSSafeReleaseNULL(scratchNumber);
9560 }
9561 }
9562 }
9563
9564 /* OSBundleDependencies. In descending order for
9565 * easy compatibility with kextstat(8).
9566 */
9567 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleDependenciesKey)) {
9568 if ((count = getNumDependencies())) {
9569 dependencyLoadTags = OSArray::withCapacity(count);
9570 result->setObject(kOSBundleDependenciesKey, dependencyLoadTags);
9571
9572 i = count - 1;
9573 do {
9574 OSKext * dependency = OSDynamicCast(OSKext,
9575 dependencies->getObject(i));
9576
9577 OSSafeReleaseNULL(scratchNumber);
9578
9579 if (!dependency) {
9580 continue;
9581 }
9582 scratchNumber = OSNumber::withNumber(
9583 (unsigned long long)dependency->getLoadTag(),
9584 /* numBits*/ 8 * sizeof(loadTag));
9585 if (!scratchNumber) {
9586 goto finish;
9587 }
9588 dependencyLoadTags->setObject(scratchNumber);
9589 } while (i--);
9590 }
9591 }
9592
9593 OSSafeReleaseNULL(scratchNumber);
9594
9595 /* OSBundleMetaClasses.
9596 */
9597 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleClassesKey)) {
9598 if (metaClasses && metaClasses->getCount()) {
9599 metaClassIterator = OSCollectionIterator::withCollection(metaClasses);
9600 metaClassInfo = OSArray::withCapacity(metaClasses->getCount());
9601 if (!metaClassIterator || !metaClassInfo) {
9602 goto finish;
9603 }
9604 result->setObject(kOSBundleClassesKey, metaClassInfo);
9605
9606 while ((thisMetaClass = OSDynamicCast(OSMetaClass,
9607 metaClassIterator->getNextObject()))) {
9608 OSSafeReleaseNULL(metaClassDict);
9609 OSSafeReleaseNULL(scratchNumber);
9610 OSSafeReleaseNULL(metaClassName);
9611 OSSafeReleaseNULL(superclassName);
9612
9613 metaClassDict = OSDictionary::withCapacity(3);
9614 if (!metaClassDict) {
9615 goto finish;
9616 }
9617
9618 metaClassName = OSString::withCString(thisMetaClass->getClassName());
9619 if (thisMetaClass->getSuperClass()) {
9620 superclassName = OSString::withCString(
9621 thisMetaClass->getSuperClass()->getClassName());
9622 }
9623 scratchNumber = OSNumber::withNumber(thisMetaClass->getInstanceCount(),
9624 8 * sizeof(unsigned int));
9625
9626 /* Bail if any of the essentials is missing. The root class lacks a superclass,
9627 * of course.
9628 */
9629 if (!metaClassDict || !metaClassName || !scratchNumber) {
9630 goto finish;
9631 }
9632
9633 metaClassInfo->setObject(metaClassDict);
9634 metaClassDict->setObject(kOSMetaClassNameKey, metaClassName);
9635 if (superclassName) {
9636 metaClassDict->setObject(kOSMetaClassSuperclassNameKey, superclassName);
9637 }
9638 metaClassDict->setObject(kOSMetaClassTrackingCountKey, scratchNumber);
9639 }
9640 }
9641 }
9642
9643 /* OSBundleRetainCount.
9644 */
9645 if (!infoKeys || _OSArrayContainsCString(infoKeys, kOSBundleRetainCountKey)) {
9646 OSSafeReleaseNULL(scratchNumber);
9647 {
9648 int kextRetainCount = getRetainCount() - 1;
9649 if (isLoaded()) {
9650 kextRetainCount--;
9651 }
9652 scratchNumber = OSNumber::withNumber(
9653 (int)kextRetainCount,
9654 /* numBits*/ 8 * sizeof(int));
9655 if (scratchNumber) {
9656 result->setObject(kOSBundleRetainCountKey, scratchNumber);
9657 }
9658 }
9659 }
9660
9661 success = true;
9662
9663 finish:
9664 OSSafeReleaseNULL(headerData);
9665 OSSafeReleaseNULL(logData);
9666 OSSafeReleaseNULL(cpuTypeNumber);
9667 OSSafeReleaseNULL(cpuSubtypeNumber);
9668 OSSafeReleaseNULL(executablePathString);
9669 if (executablePathCString) {
9670 kfree(executablePathCString, executablePathCStringSize);
9671 }
9672 OSSafeReleaseNULL(scratchNumber);
9673 OSSafeReleaseNULL(dependencyLoadTags);
9674 OSSafeReleaseNULL(metaClassIterator);
9675 OSSafeReleaseNULL(metaClassInfo);
9676 OSSafeReleaseNULL(metaClassDict);
9677 OSSafeReleaseNULL(metaClassName);
9678 OSSafeReleaseNULL(superclassName);
9679 if (!success) {
9680 OSSafeReleaseNULL(result);
9681 }
9682 return result;
9683 }
9684
9685 /*********************************************************************
9686 *********************************************************************/
9687 /* static */
9688 bool
9689 OSKext::copyUserExecutablePath(const OSSymbol * bundleID, char * pathResult, size_t pathSize)
9690 {
9691 bool ok;
9692 OSKext * kext;
9693
9694 IORecursiveLockLock(sKextLock);
9695 kext = OSDynamicCast(OSKext, sKextsByID->getObject(bundleID));
9696 if (kext) {
9697 kext->retain();
9698 }
9699 IORecursiveLockUnlock(sKextLock);
9700
9701 if (!kext || !kext->path || !kext->userExecutableRelPath) {
9702 OSSafeReleaseNULL(kext);
9703 return false;
9704 }
9705 snprintf(pathResult, pathSize, "%s/Contents/MacOS/%s",
9706 kext->path->getCStringNoCopy(),
9707 kext->userExecutableRelPath->getCStringNoCopy());
9708 ok = true;
9709 kext->release();
9710
9711 return ok;
9712 }
9713
9714 /*********************************************************************
9715 *********************************************************************/
9716 /* static */
9717 OSReturn
9718 OSKext::requestResource(
9719 const char * kextIdentifierCString,
9720 const char * resourceNameCString,
9721 OSKextRequestResourceCallback callback,
9722 void * context,
9723 OSKextRequestTag * requestTagOut)
9724 {
9725 OSReturn result = kOSReturnError;
9726 OSKext * callbackKext = NULL;// must release (looked up)
9727
9728 OSKextRequestTag requestTag = -1;
9729 OSNumber * requestTagNum = NULL;// must release
9730
9731 OSDictionary * requestDict = NULL;// must release
9732 OSString * kextIdentifier = NULL;// must release
9733 OSString * resourceName = NULL;// must release
9734
9735 OSDictionary * callbackRecord = NULL;// must release
9736 OSData * callbackWrapper = NULL;// must release
9737
9738 OSData * contextWrapper = NULL;// must release
9739
9740 IORecursiveLockLock(sKextLock);
9741
9742 if (requestTagOut) {
9743 *requestTagOut = kOSKextRequestTagInvalid;
9744 }
9745
9746 /* If requests to user space are disabled, don't go any further */
9747 if (!sKernelRequestsEnabled) {
9748 OSKextLog(/* kext */ NULL,
9749 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9750 "Can't request resource %s for %s - requests to user space are disabled.",
9751 resourceNameCString,
9752 kextIdentifierCString);
9753 result = kOSKextReturnDisabled;
9754 goto finish;
9755 }
9756
9757 if (!kextIdentifierCString || !resourceNameCString || !callback) {
9758 result = kOSKextReturnInvalidArgument;
9759 goto finish;
9760 }
9761
9762 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
9763 if (!callbackKext) {
9764 OSKextLog(/* kext */ NULL,
9765 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9766 "Resource request has bad callback address.");
9767 result = kOSKextReturnInvalidArgument;
9768 goto finish;
9769 }
9770 if (!callbackKext->flags.starting && !callbackKext->flags.started) {
9771 OSKextLog(/* kext */ NULL,
9772 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9773 "Resource request callback is in a kext that is not started.");
9774 result = kOSKextReturnInvalidArgument;
9775 goto finish;
9776 }
9777
9778 /* Do not allow any new requests to be made on a kext that is unloading.
9779 */
9780 if (callbackKext->flags.stopping) {
9781 result = kOSKextReturnStopping;
9782 goto finish;
9783 }
9784
9785 /* If we're wrapped the next available request tag around to the negative
9786 * numbers, we can't service any more requests.
9787 */
9788 if (sNextRequestTag == kOSKextRequestTagInvalid) {
9789 OSKextLog(/* kext */ NULL,
9790 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
9791 "No more request tags available; restart required.");
9792 result = kOSKextReturnNoResources;
9793 goto finish;
9794 }
9795 requestTag = sNextRequestTag++;
9796
9797 result = _OSKextCreateRequest(kKextRequestPredicateRequestResource,
9798 &requestDict);
9799 if (result != kOSReturnSuccess) {
9800 goto finish;
9801 }
9802
9803 kextIdentifier = OSString::withCString(kextIdentifierCString);
9804 resourceName = OSString::withCString(resourceNameCString);
9805 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag,
9806 8 * sizeof(requestTag));
9807 if (!kextIdentifier ||
9808 !resourceName ||
9809 !requestTagNum ||
9810 !_OSKextSetRequestArgument(requestDict,
9811 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
9812 !_OSKextSetRequestArgument(requestDict,
9813 kKextRequestArgumentNameKey, resourceName) ||
9814 !_OSKextSetRequestArgument(requestDict,
9815 kKextRequestArgumentRequestTagKey, requestTagNum)) {
9816 result = kOSKextReturnNoMemory;
9817 goto finish;
9818 }
9819
9820 callbackRecord = OSDynamicCast(OSDictionary, requestDict->copyCollection());
9821 if (!callbackRecord) {
9822 result = kOSKextReturnNoMemory;
9823 goto finish;
9824 }
9825 // we validate callback address at call time
9826 callbackWrapper = OSData::withBytes((void *)&callback, sizeof(void *));
9827 if (context) {
9828 contextWrapper = OSData::withBytes((void *)&context, sizeof(void *));
9829 }
9830 if (!callbackWrapper || !_OSKextSetRequestArgument(callbackRecord,
9831 kKextRequestArgumentCallbackKey, callbackWrapper)) {
9832 result = kOSKextReturnNoMemory;
9833 goto finish;
9834 }
9835
9836 if (context) {
9837 if (!contextWrapper || !_OSKextSetRequestArgument(callbackRecord,
9838 kKextRequestArgumentContextKey, contextWrapper)) {
9839 result = kOSKextReturnNoMemory;
9840 goto finish;
9841 }
9842 }
9843
9844 /* Only post the requests after all the other potential failure points
9845 * have been passed.
9846 */
9847 if (!sKernelRequests->setObject(requestDict) ||
9848 !sRequestCallbackRecords->setObject(callbackRecord)) {
9849 result = kOSKextReturnNoMemory;
9850 goto finish;
9851 }
9852
9853 OSKext::pingKextd();
9854
9855 result = kOSReturnSuccess;
9856 if (requestTagOut) {
9857 *requestTagOut = requestTag;
9858 }
9859
9860 finish:
9861
9862 /* If we didn't succeed, yank the request & callback
9863 * from their holding arrays.
9864 */
9865 if (result != kOSReturnSuccess) {
9866 unsigned int index;
9867
9868 index = sKernelRequests->getNextIndexOfObject(requestDict, 0);
9869 if (index != (unsigned int)-1) {
9870 sKernelRequests->removeObject(index);
9871 }
9872 index = sRequestCallbackRecords->getNextIndexOfObject(callbackRecord, 0);
9873 if (index != (unsigned int)-1) {
9874 sRequestCallbackRecords->removeObject(index);
9875 }
9876 }
9877
9878 OSKext::considerUnloads(/* rescheduleOnly? */ true);
9879
9880 IORecursiveLockUnlock(sKextLock);
9881
9882 if (callbackKext) {
9883 callbackKext->release();
9884 }
9885 if (requestTagNum) {
9886 requestTagNum->release();
9887 }
9888
9889 if (requestDict) {
9890 requestDict->release();
9891 }
9892 if (kextIdentifier) {
9893 kextIdentifier->release();
9894 }
9895 if (resourceName) {
9896 resourceName->release();
9897 }
9898
9899 if (callbackRecord) {
9900 callbackRecord->release();
9901 }
9902 if (callbackWrapper) {
9903 callbackWrapper->release();
9904 }
9905 if (contextWrapper) {
9906 contextWrapper->release();
9907 }
9908
9909 return result;
9910 }
9911
9912 OSReturn
9913 OSKext::requestDaemonLaunch(
9914 OSString *kextIdentifier,
9915 OSString *serverName,
9916 OSNumber *serverTag)
9917 {
9918 OSReturn result = kOSReturnError;
9919 OSDictionary * requestDict = NULL; // must release
9920
9921 if (!kextIdentifier || !serverName || !serverTag) {
9922 result = kOSKextReturnInvalidArgument;
9923 goto finish;
9924 }
9925
9926 IORecursiveLockLock(sKextLock);
9927
9928 OSKextLog(/* kext */ NULL,
9929 kOSKextLogDebugLevel |
9930 kOSKextLogGeneralFlag,
9931 "Requesting daemon launch for %s with serverName %s and tag %llu",
9932 kextIdentifier->getCStringNoCopy(),
9933 serverName->getCStringNoCopy(),
9934 serverTag->unsigned64BitValue()
9935 );
9936
9937 result = _OSKextCreateRequest(kKextRequestPredicateRequestDaemonLaunch, &requestDict);
9938 if (result != kOSReturnSuccess) {
9939 goto finish;
9940 }
9941
9942 if (!_OSKextSetRequestArgument(requestDict,
9943 kKextRequestArgumentBundleIdentifierKey, kextIdentifier) ||
9944 !_OSKextSetRequestArgument(requestDict,
9945 kKextRequestArgumentDriverExtensionServerName, serverName) ||
9946 !_OSKextSetRequestArgument(requestDict,
9947 kKextRequestArgumentDriverExtensionServerTag, serverTag)) {
9948 result = kOSKextReturnNoMemory;
9949 goto finish;
9950 }
9951
9952 /* Only post the requests after all the other potential failure points
9953 * have been passed.
9954 */
9955 if (!sKernelRequests->setObject(requestDict)) {
9956 result = kOSKextReturnNoMemory;
9957 goto finish;
9958 }
9959 OSKext::pingKextd();
9960
9961 result = kOSReturnSuccess;
9962 finish:
9963 IORecursiveLockUnlock(sKextLock);
9964 if (requestDict) {
9965 requestDict->release();
9966 }
9967 return result;
9968 }
9969
9970 /*********************************************************************
9971 * Assumes sKextLock is held.
9972 *********************************************************************/
9973 /* static */
9974 OSReturn
9975 OSKext::dequeueCallbackForRequestTag(
9976 OSKextRequestTag requestTag,
9977 OSDictionary ** callbackRecordOut)
9978 {
9979 OSReturn result = kOSReturnError;
9980 OSNumber * requestTagNum = NULL;// must release
9981
9982 requestTagNum = OSNumber::withNumber((long long unsigned int)requestTag,
9983 8 * sizeof(requestTag));
9984 if (!requestTagNum) {
9985 goto finish;
9986 }
9987
9988 result = OSKext::dequeueCallbackForRequestTag(requestTagNum,
9989 callbackRecordOut);
9990
9991 finish:
9992 OSSafeReleaseNULL(requestTagNum);
9993
9994 return result;
9995 }
9996
9997 /*********************************************************************
9998 * Assumes sKextLock is held.
9999 *********************************************************************/
10000 /* static */
10001 OSReturn
10002 OSKext::dequeueCallbackForRequestTag(
10003 OSNumber * requestTagNum,
10004 OSDictionary ** callbackRecordOut)
10005 {
10006 OSReturn result = kOSKextReturnInvalidArgument;
10007 OSDictionary * callbackRecord = NULL;// retain if matched!
10008 OSNumber * callbackTagNum = NULL;// do not release
10009 unsigned int count, i;
10010
10011 result = kOSReturnError;
10012 count = sRequestCallbackRecords->getCount();
10013 for (i = 0; i < count; i++) {
10014 callbackRecord = OSDynamicCast(OSDictionary,
10015 sRequestCallbackRecords->getObject(i));
10016 if (!callbackRecord) {
10017 goto finish;
10018 }
10019
10020 /* If we don't find a tag, we basically have a leak here. Maybe
10021 * we should just remove it.
10022 */
10023 callbackTagNum = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(
10024 callbackRecord, kKextRequestArgumentRequestTagKey));
10025 if (!callbackTagNum) {
10026 goto finish;
10027 }
10028
10029 /* We could be even more paranoid and check that all the incoming
10030 * args match what's in the callback record.
10031 */
10032 if (callbackTagNum->isEqualTo(requestTagNum)) {
10033 if (callbackRecordOut) {
10034 *callbackRecordOut = callbackRecord;
10035 callbackRecord->retain();
10036 }
10037 sRequestCallbackRecords->removeObject(i);
10038 result = kOSReturnSuccess;
10039 goto finish;
10040 }
10041 }
10042 result = kOSKextReturnNotFound;
10043
10044 finish:
10045 return result;
10046 }
10047
10048
10049 /*********************************************************************
10050 * Busy timeout triage
10051 *********************************************************************/
10052 /* static */
10053 bool
10054 OSKext::isWaitingKextd(void)
10055 {
10056 return sRequestCallbackRecords && sRequestCallbackRecords->getCount();
10057 }
10058
10059 /*********************************************************************
10060 * Assumes sKextLock is held.
10061 *********************************************************************/
10062 /* static */
10063 OSReturn
10064 OSKext::dispatchResource(OSDictionary * requestDict)
10065 {
10066 OSReturn result = kOSReturnError;
10067 OSDictionary * callbackRecord = NULL;// must release
10068 OSNumber * requestTag = NULL;// do not release
10069 OSNumber * requestResult = NULL;// do not release
10070 OSData * dataObj = NULL;// do not release
10071 uint32_t dataLength = 0;
10072 const void * dataPtr = NULL;// do not free
10073 OSData * callbackWrapper = NULL;// do not release
10074 OSKextRequestResourceCallback callback = NULL;
10075 OSData * contextWrapper = NULL;// do not release
10076 void * context = NULL;// do not free
10077 OSKext * callbackKext = NULL;// must release (looked up)
10078
10079 /* Get the args from the request. Right now we need the tag
10080 * to look up the callback record, and the result for invoking the callback.
10081 */
10082 requestTag = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
10083 kKextRequestArgumentRequestTagKey));
10084 requestResult = OSDynamicCast(OSNumber, _OSKextGetRequestArgument(requestDict,
10085 kKextRequestArgumentResultKey));
10086 if (!requestTag || !requestResult) {
10087 result = kOSKextReturnInvalidArgument;
10088 goto finish;
10089 }
10090
10091 /* Look for a callback record matching this request's tag.
10092 */
10093 result = dequeueCallbackForRequestTag(requestTag, &callbackRecord);
10094 if (result != kOSReturnSuccess) {
10095 goto finish;
10096 }
10097
10098 /*****
10099 * Get the context pointer of the callback record (if there is one).
10100 */
10101 contextWrapper = OSDynamicCast(OSData, _OSKextGetRequestArgument(callbackRecord,
10102 kKextRequestArgumentContextKey));
10103 context = _OSKextExtractPointer(contextWrapper);
10104 if (contextWrapper && !context) {
10105 goto finish;
10106 }
10107
10108 callbackWrapper = OSDynamicCast(OSData,
10109 _OSKextGetRequestArgument(callbackRecord,
10110 kKextRequestArgumentCallbackKey));
10111 callback = (OSKextRequestResourceCallback)
10112 _OSKextExtractPointer(callbackWrapper);
10113 if (!callback) {
10114 goto finish;
10115 }
10116
10117 /* Check for a data obj. We might not have one and that's ok, that means
10118 * we didn't find the requested resource, and we still have to tell the
10119 * caller that via the callback.
10120 */
10121 dataObj = OSDynamicCast(OSData, _OSKextGetRequestArgument(requestDict,
10122 kKextRequestArgumentValueKey));
10123 if (dataObj) {
10124 dataPtr = dataObj->getBytesNoCopy();
10125 dataLength = dataObj->getLength();
10126 }
10127
10128 callbackKext = OSKext::lookupKextWithAddress((vm_address_t)callback);
10129 if (!callbackKext) {
10130 OSKextLog(/* kext */ NULL,
10131 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
10132 "Can't invoke callback for resource request; ");
10133 goto finish;
10134 }
10135 if (!callbackKext->flags.starting && !callbackKext->flags.started) {
10136 OSKextLog(/* kext */ NULL,
10137 kOSKextLogErrorLevel | kOSKextLogIPCFlag,
10138 "Can't invoke kext resource callback; ");
10139 goto finish;
10140 }
10141
10142 (void)callback(requestTag->unsigned32BitValue(),
10143 (OSReturn)requestResult->unsigned32BitValue(),
10144 dataPtr, dataLength, context);
10145
10146 result = kOSReturnSuccess;
10147
10148 finish:
10149 if (callbackKext) {
10150 callbackKext->release();
10151 }
10152 if (callbackRecord) {
10153 callbackRecord->release();
10154 }
10155
10156 return result;
10157 }
10158
10159 /*********************************************************************
10160 *********************************************************************/
10161 /* static */
10162 void
10163 OSKext::invokeRequestCallback(
10164 OSDictionary * callbackRecord,
10165 OSReturn callbackResult)
10166 {
10167 OSString * predicate = _OSKextGetRequestPredicate(callbackRecord);
10168 OSNumber * resultNum = NULL;// must release
10169
10170 if (!predicate) {
10171 goto finish;
10172 }
10173
10174 resultNum = OSNumber::withNumber((long long unsigned int)callbackResult,
10175 8 * sizeof(callbackResult));
10176 if (!resultNum) {
10177 goto finish;
10178 }
10179
10180 /* Insert the result into the callback record and dispatch it as if it
10181 * were the reply coming down from user space.
10182 */
10183 _OSKextSetRequestArgument(callbackRecord, kKextRequestArgumentResultKey,
10184 resultNum);
10185
10186 if (predicate->isEqualTo(kKextRequestPredicateRequestResource)) {
10187 /* This removes the pending callback record.
10188 */
10189 OSKext::dispatchResource(callbackRecord);
10190 }
10191
10192 finish:
10193 if (resultNum) {
10194 resultNum->release();
10195 }
10196 return;
10197 }
10198
10199 /*********************************************************************
10200 * Assumes sKextLock is held.
10201 *********************************************************************/
10202 /* static */
10203 OSReturn
10204 OSKext::cancelRequest(
10205 OSKextRequestTag requestTag,
10206 void ** contextOut)
10207 {
10208 OSReturn result = kOSKextReturnNoMemory;
10209 OSDictionary * callbackRecord = NULL; // must release
10210 OSData * contextWrapper = NULL;// do not release
10211
10212 IORecursiveLockLock(sKextLock);
10213 result = OSKext::dequeueCallbackForRequestTag(requestTag,
10214 &callbackRecord);
10215 IORecursiveLockUnlock(sKextLock);
10216
10217 if (result == kOSReturnSuccess && contextOut) {
10218 contextWrapper = OSDynamicCast(OSData,
10219 _OSKextGetRequestArgument(callbackRecord,
10220 kKextRequestArgumentContextKey));
10221 *contextOut = _OSKextExtractPointer(contextWrapper);
10222 }
10223
10224 if (callbackRecord) {
10225 callbackRecord->release();
10226 }
10227
10228 return result;
10229 }
10230
10231 /*********************************************************************
10232 * Assumes sKextLock is held.
10233 *********************************************************************/
10234 void
10235 OSKext::invokeOrCancelRequestCallbacks(
10236 OSReturn callbackResult,
10237 bool invokeFlag)
10238 {
10239 unsigned int count, i;
10240
10241 count = sRequestCallbackRecords->getCount();
10242 if (!count) {
10243 goto finish;
10244 }
10245
10246 i = count - 1;
10247 do {
10248 OSDictionary * request = OSDynamicCast(OSDictionary,
10249 sRequestCallbackRecords->getObject(i));
10250
10251 if (!request) {
10252 continue;
10253 }
10254 OSData * callbackWrapper = OSDynamicCast(OSData,
10255 _OSKextGetRequestArgument(request,
10256 kKextRequestArgumentCallbackKey));
10257
10258 if (!callbackWrapper) {
10259 sRequestCallbackRecords->removeObject(i);
10260 continue;
10261 }
10262
10263 vm_address_t callbackAddress = (vm_address_t)
10264 _OSKextExtractPointer(callbackWrapper);
10265
10266 if ((kmod_info->address <= callbackAddress) &&
10267 (callbackAddress < (kmod_info->address + kmod_info->size))) {
10268 if (invokeFlag) {
10269 /* This removes the callback record.
10270 */
10271 invokeRequestCallback(request, callbackResult);
10272 } else {
10273 sRequestCallbackRecords->removeObject(i);
10274 }
10275 }
10276 } while (i--);
10277
10278 finish:
10279 return;
10280 }
10281
10282 /*********************************************************************
10283 * Assumes sKextLock is held.
10284 *********************************************************************/
10285 uint32_t
10286 OSKext::countRequestCallbacks(void)
10287 {
10288 uint32_t result = 0;
10289 unsigned int count, i;
10290
10291 count = sRequestCallbackRecords->getCount();
10292 if (!count) {
10293 goto finish;
10294 }
10295
10296 i = count - 1;
10297 do {
10298 OSDictionary * request = OSDynamicCast(OSDictionary,
10299 sRequestCallbackRecords->getObject(i));
10300
10301 if (!request) {
10302 continue;
10303 }
10304 OSData * callbackWrapper = OSDynamicCast(OSData,
10305 _OSKextGetRequestArgument(request,
10306 kKextRequestArgumentCallbackKey));
10307
10308 if (!callbackWrapper) {
10309 continue;
10310 }
10311
10312 vm_address_t callbackAddress = (vm_address_t)
10313 _OSKextExtractPointer(callbackWrapper);
10314
10315 if ((kmod_info->address <= callbackAddress) &&
10316 (callbackAddress < (kmod_info->address + kmod_info->size))) {
10317 result++;
10318 }
10319 } while (i--);
10320
10321 finish:
10322 return result;
10323 }
10324
10325 /*********************************************************************
10326 *********************************************************************/
10327 static OSReturn
10328 _OSKextCreateRequest(
10329 const char * predicate,
10330 OSDictionary ** requestP)
10331 {
10332 OSReturn result = kOSKextReturnNoMemory;
10333 OSDictionary * request = NULL; // must release on error
10334
10335 request = OSDictionary::withCapacity(2);
10336 if (!request) {
10337 goto finish;
10338 }
10339 result = _OSDictionarySetCStringValue(request,
10340 kKextRequestPredicateKey, predicate);
10341 if (result != kOSReturnSuccess) {
10342 goto finish;
10343 }
10344 result = kOSReturnSuccess;
10345
10346 finish:
10347 if (result != kOSReturnSuccess) {
10348 if (request) {
10349 request->release();
10350 }
10351 } else {
10352 *requestP = request;
10353 }
10354
10355 return result;
10356 }
10357
10358 /*********************************************************************
10359 *********************************************************************/
10360 static OSString *
10361 _OSKextGetRequestPredicate(OSDictionary * requestDict)
10362 {
10363 return OSDynamicCast(OSString,
10364 requestDict->getObject(kKextRequestPredicateKey));
10365 }
10366
10367 /*********************************************************************
10368 *********************************************************************/
10369 static OSObject *
10370 _OSKextGetRequestArgument(
10371 OSDictionary * requestDict,
10372 const char * argName)
10373 {
10374 OSDictionary * args = OSDynamicCast(OSDictionary,
10375 requestDict->getObject(kKextRequestArgumentsKey));
10376 if (args) {
10377 return args->getObject(argName);
10378 }
10379 return NULL;
10380 }
10381
10382 /*********************************************************************
10383 *********************************************************************/
10384 static bool
10385 _OSKextSetRequestArgument(
10386 OSDictionary * requestDict,
10387 const char * argName,
10388 OSObject * value)
10389 {
10390 OSDictionary * args = OSDynamicCast(OSDictionary,
10391 requestDict->getObject(kKextRequestArgumentsKey));
10392 if (!args) {
10393 args = OSDictionary::withCapacity(2);
10394 if (!args) {
10395 goto finish;
10396 }
10397 requestDict->setObject(kKextRequestArgumentsKey, args);
10398 args->release();
10399 }
10400 if (args) {
10401 return args->setObject(argName, value);
10402 }
10403 finish:
10404 return false;
10405 }
10406
10407 /*********************************************************************
10408 *********************************************************************/
10409 static void *
10410 _OSKextExtractPointer(OSData * wrapper)
10411 {
10412 void * result = NULL;
10413 const void * resultPtr = NULL;
10414
10415 if (!wrapper) {
10416 goto finish;
10417 }
10418 resultPtr = wrapper->getBytesNoCopy();
10419 result = *(void **)resultPtr;
10420 finish:
10421 return result;
10422 }
10423
10424 /*********************************************************************
10425 *********************************************************************/
10426 static OSReturn
10427 _OSDictionarySetCStringValue(
10428 OSDictionary * dict,
10429 const char * cKey,
10430 const char * cValue)
10431 {
10432 OSReturn result = kOSKextReturnNoMemory;
10433 const OSSymbol * key = NULL; // must release
10434 OSString * value = NULL; // must release
10435
10436 key = OSSymbol::withCString(cKey);
10437 value = OSString::withCString(cValue);
10438 if (!key || !value) {
10439 goto finish;
10440 }
10441 if (dict->setObject(key, value)) {
10442 result = kOSReturnSuccess;
10443 }
10444
10445 finish:
10446 if (key) {
10447 key->release();
10448 }
10449 if (value) {
10450 value->release();
10451 }
10452
10453 return result;
10454 }
10455
10456 /*********************************************************************
10457 *********************************************************************/
10458 static bool
10459 _OSArrayContainsCString(
10460 OSArray * array,
10461 const char * cString)
10462 {
10463 bool result = false;
10464 const OSSymbol * symbol = NULL;
10465 uint32_t count, i;
10466
10467 if (!array || !cString) {
10468 goto finish;
10469 }
10470
10471 symbol = OSSymbol::withCStringNoCopy(cString);
10472 if (!symbol) {
10473 goto finish;
10474 }
10475
10476 count = array->getCount();
10477 for (i = 0; i < count; i++) {
10478 OSObject * thisObject = array->getObject(i);
10479 if (symbol->isEqualTo(thisObject)) {
10480 result = true;
10481 goto finish;
10482 }
10483 }
10484
10485 finish:
10486 if (symbol) {
10487 symbol->release();
10488 }
10489 return result;
10490 }
10491
10492 /*********************************************************************
10493 * We really only care about boot / system start up related kexts.
10494 * We return true if we're less than REBUILD_MAX_TIME since start up,
10495 * otherwise return false.
10496 *********************************************************************/
10497 bool
10498 _OSKextInPrelinkRebuildWindow(void)
10499 {
10500 static bool outside_the_window = false;
10501 AbsoluteTime my_abstime;
10502 UInt64 my_ns;
10503 SInt32 my_secs;
10504
10505 if (outside_the_window) {
10506 return false;
10507 }
10508 clock_get_uptime(&my_abstime);
10509 absolutetime_to_nanoseconds(my_abstime, &my_ns);
10510 my_secs = (SInt32)(my_ns / NSEC_PER_SEC);
10511 if (my_secs > REBUILD_MAX_TIME) {
10512 outside_the_window = true;
10513 return false;
10514 }
10515 return true;
10516 }
10517
10518 /*********************************************************************
10519 *********************************************************************/
10520 bool
10521 _OSKextInUnloadedPrelinkedKexts( const OSSymbol * theBundleID )
10522 {
10523 int unLoadedCount, i;
10524 bool result = false;
10525
10526 IORecursiveLockLock(sKextLock);
10527
10528 if (sUnloadedPrelinkedKexts == NULL) {
10529 goto finish;
10530 }
10531 unLoadedCount = sUnloadedPrelinkedKexts->getCount();
10532 if (unLoadedCount == 0) {
10533 goto finish;
10534 }
10535
10536 for (i = 0; i < unLoadedCount; i++) {
10537 const OSSymbol * myBundleID;// do not release
10538
10539 myBundleID = OSDynamicCast(OSSymbol, sUnloadedPrelinkedKexts->getObject(i));
10540 if (!myBundleID) {
10541 continue;
10542 }
10543 if (theBundleID->isEqualTo(myBundleID->getCStringNoCopy())) {
10544 result = true;
10545 break;
10546 }
10547 }
10548 finish:
10549 IORecursiveLockUnlock(sKextLock);
10550 return result;
10551 }
10552
10553 #if PRAGMA_MARK
10554 #pragma mark Personalities (IOKit Drivers)
10555 #endif
10556 /*********************************************************************
10557 *********************************************************************/
10558 /* static */
10559 OSArray *
10560 OSKext::copyAllKextPersonalities(bool filterSafeBootFlag)
10561 {
10562 OSArray * result = NULL;// returned
10563 OSCollectionIterator * kextIterator = NULL;// must release
10564 OSArray * personalities = NULL;// must release
10565 OSCollectionIterator * personalitiesIterator = NULL; // must release
10566
10567 OSString * kextID = NULL;// do not release
10568 OSKext * theKext = NULL;// do not release
10569
10570 IORecursiveLockLock(sKextLock);
10571
10572 /* Let's conservatively guess that any given kext has around 3
10573 * personalities for now.
10574 */
10575 result = OSArray::withCapacity(sKextsByID->getCount() * 3);
10576 if (!result) {
10577 goto finish;
10578 }
10579
10580 kextIterator = OSCollectionIterator::withCollection(sKextsByID);
10581 if (!kextIterator) {
10582 goto finish;
10583 }
10584
10585 while ((kextID = OSDynamicCast(OSString, kextIterator->getNextObject()))) {
10586 if (personalitiesIterator) {
10587 personalitiesIterator->release();
10588 personalitiesIterator = NULL;
10589 }
10590 if (personalities) {
10591 personalities->release();
10592 personalities = NULL;
10593 }
10594
10595 theKext = OSDynamicCast(OSKext, sKextsByID->getObject(kextID));
10596 if (!sSafeBoot || !filterSafeBootFlag || theKext->isLoadableInSafeBoot()) {
10597 personalities = theKext->copyPersonalitiesArray();
10598 if (!personalities) {
10599 continue;
10600 }
10601 result->merge(personalities);
10602 } else {
10603 // xxx - check for better place to put this log msg
10604 OSKextLog(theKext,
10605 kOSKextLogWarningLevel |
10606 kOSKextLogLoadFlag,
10607 "Kext %s is not loadable during safe boot; "
10608 "omitting its personalities.",
10609 theKext->getIdentifierCString());
10610 }
10611 }
10612
10613 finish:
10614 IORecursiveLockUnlock(sKextLock);
10615
10616 if (kextIterator) {
10617 kextIterator->release();
10618 }
10619 if (personalitiesIterator) {
10620 personalitiesIterator->release();
10621 }
10622 if (personalities) {
10623 personalities->release();
10624 }
10625
10626 return result;
10627 }
10628
10629 /*********************************************************************
10630 *********************************************************************/
10631 /* static */
10632 void
10633 OSKext::sendAllKextPersonalitiesToCatalog(bool startMatching)
10634 {
10635 int numPersonalities = 0;
10636
10637 OSKextLog(/* kext */ NULL,
10638 kOSKextLogStepLevel |
10639 kOSKextLogLoadFlag,
10640 "Sending all eligible registered kexts' personalities "
10641 "to the IOCatalogue %s.",
10642 startMatching ? "and starting matching" : "but not starting matching");
10643
10644 OSArray * personalities = OSKext::copyAllKextPersonalities(
10645 /* filterSafeBootFlag */ true);
10646
10647 if (personalities) {
10648 gIOCatalogue->addDrivers(personalities, startMatching);
10649 numPersonalities = personalities->getCount();
10650 personalities->release();
10651 }
10652
10653 OSKextLog(/* kext */ NULL,
10654 kOSKextLogStepLevel |
10655 kOSKextLogLoadFlag,
10656 "%d kext personalit%s sent to the IOCatalogue; %s.",
10657 numPersonalities, numPersonalities > 0 ? "ies" : "y",
10658 startMatching ? "matching started" : "matching not started");
10659 return;
10660 }
10661
10662 /*********************************************************************
10663 * Do not make a deep copy, just convert the IOKitPersonalities dict
10664 * to an array for sending to the IOCatalogue.
10665 *********************************************************************/
10666 OSArray *
10667 OSKext::copyPersonalitiesArray(void)
10668 {
10669 OSArray * result = NULL;
10670 OSDictionary * personalities = NULL;// do not release
10671 OSCollectionIterator * personalitiesIterator = NULL;// must release
10672
10673 OSString * personalityName = NULL;// do not release
10674 OSString * personalityBundleIdentifier = NULL;// do not release
10675
10676 personalities = OSDynamicCast(OSDictionary,
10677 getPropertyForHostArch(kIOKitPersonalitiesKey));
10678 if (!personalities) {
10679 goto finish;
10680 }
10681
10682 result = OSArray::withCapacity(personalities->getCount());
10683 if (!result) {
10684 goto finish;
10685 }
10686
10687 personalitiesIterator =
10688 OSCollectionIterator::withCollection(personalities);
10689 if (!personalitiesIterator) {
10690 goto finish;
10691 }
10692 while ((personalityName = OSDynamicCast(OSString,
10693 personalitiesIterator->getNextObject()))) {
10694 OSDictionary * personality = OSDynamicCast(OSDictionary,
10695 personalities->getObject(personalityName));
10696
10697 /******
10698 * If the personality doesn't have a CFBundleIdentifier, or if it
10699 * differs from the kext's, insert the kext's ID so we can find it.
10700 * The publisher ID is used to remove personalities from bundles
10701 * correctly.
10702 */
10703 personalityBundleIdentifier = OSDynamicCast(OSString,
10704 personality->getObject(kCFBundleIdentifierKey));
10705
10706 if (!personalityBundleIdentifier) {
10707 personality->setObject(kCFBundleIdentifierKey, bundleID);
10708 } else if (!personalityBundleIdentifier->isEqualTo(bundleID)) {
10709 personality->setObject(kIOPersonalityPublisherKey, bundleID);
10710 }
10711
10712 result->setObject(personality);
10713 }
10714
10715 finish:
10716 if (personalitiesIterator) {
10717 personalitiesIterator->release();
10718 }
10719
10720 return result;
10721 }
10722
10723 /*********************************************************************
10724 * Might want to change this to a bool return?
10725 *********************************************************************/
10726 OSReturn
10727 OSKext::sendPersonalitiesToCatalog(
10728 bool startMatching,
10729 OSArray * personalityNames)
10730 {
10731 OSReturn result = kOSReturnSuccess;
10732 OSArray * personalitiesToSend = NULL;// must release
10733 OSDictionary * kextPersonalities = NULL;// do not release
10734 int count, i;
10735
10736 if (!sLoadEnabled) {
10737 OSKextLog(this,
10738 kOSKextLogErrorLevel |
10739 kOSKextLogLoadFlag,
10740 "Kext loading is disabled (attempt to start matching for kext %s).",
10741 getIdentifierCString());
10742 result = kOSKextReturnDisabled;
10743 goto finish;
10744 }
10745
10746 if (sSafeBoot && !isLoadableInSafeBoot()) {
10747 OSKextLog(this,
10748 kOSKextLogErrorLevel |
10749 kOSKextLogLoadFlag,
10750 "Kext %s is not loadable during safe boot; "
10751 "not sending personalities to the IOCatalogue.",
10752 getIdentifierCString());
10753 result = kOSKextReturnNotLoadable;
10754 goto finish;
10755 }
10756
10757 if (!personalityNames || !personalityNames->getCount()) {
10758 personalitiesToSend = copyPersonalitiesArray();
10759 } else {
10760 kextPersonalities = OSDynamicCast(OSDictionary,
10761 getPropertyForHostArch(kIOKitPersonalitiesKey));
10762 if (!kextPersonalities || !kextPersonalities->getCount()) {
10763 // not an error
10764 goto finish;
10765 }
10766 personalitiesToSend = OSArray::withCapacity(0);
10767 if (!personalitiesToSend) {
10768 result = kOSKextReturnNoMemory;
10769 goto finish;
10770 }
10771 count = personalityNames->getCount();
10772 for (i = 0; i < count; i++) {
10773 OSString * name = OSDynamicCast(OSString,
10774 personalityNames->getObject(i));
10775 if (!name) {
10776 continue;
10777 }
10778 OSDictionary * personality = OSDynamicCast(OSDictionary,
10779 kextPersonalities->getObject(name));
10780 if (personality) {
10781 personalitiesToSend->setObject(personality);
10782 }
10783 }
10784 }
10785 if (personalitiesToSend) {
10786 unsigned numPersonalities = personalitiesToSend->getCount();
10787 OSKextLog(this,
10788 kOSKextLogStepLevel |
10789 kOSKextLogLoadFlag,
10790 "Kext %s sending %d personalit%s to the IOCatalogue%s.",
10791 getIdentifierCString(),
10792 numPersonalities,
10793 numPersonalities > 1 ? "ies" : "y",
10794 startMatching ? " and starting matching" : " but not starting matching");
10795 gIOCatalogue->addDrivers(personalitiesToSend, startMatching);
10796 }
10797 finish:
10798 if (personalitiesToSend) {
10799 personalitiesToSend->release();
10800 }
10801 return result;
10802 }
10803
10804 /*********************************************************************
10805 * xxx - We should allow removing the kext's declared personalities,
10806 * xxx - even with other bundle identifiers.
10807 *********************************************************************/
10808 void
10809 OSKext::removePersonalitiesFromCatalog(void)
10810 {
10811 OSDictionary * personality = NULL; // do not release
10812
10813 personality = OSDictionary::withCapacity(1);
10814 if (!personality) {
10815 goto finish;
10816 }
10817 personality->setObject(kCFBundleIdentifierKey, getIdentifier());
10818
10819 OSKextLog(this,
10820 kOSKextLogStepLevel |
10821 kOSKextLogLoadFlag,
10822 "Kext %s removing all personalities naming it from the IOCatalogue.",
10823 getIdentifierCString());
10824
10825 /* Have the IOCatalog remove all personalities matching this kext's
10826 * bundle ID and trigger matching anew.
10827 */
10828 gIOCatalogue->removeDrivers(personality, /* startMatching */ true);
10829
10830 finish:
10831 if (personality) {
10832 personality->release();
10833 }
10834
10835 return;
10836 }
10837
10838
10839 #if PRAGMA_MARK
10840 #pragma mark Logging
10841 #endif
10842 /*********************************************************************
10843 * Do not call any function that takes sKextLock here!
10844 *********************************************************************/
10845 /* static */
10846 OSKextLogSpec
10847 OSKext::setUserSpaceLogFilter(
10848 OSKextLogSpec newUserLogFilter,
10849 bool captureFlag)
10850 {
10851 OSKextLogSpec result;
10852 bool allocError = false;
10853
10854 /* Do not call any function that takes sKextLoggingLock during
10855 * this critical block. That means do logging after.
10856 */
10857 IOLockLock(sKextLoggingLock);
10858
10859 result = sUserSpaceKextLogFilter;
10860 sUserSpaceKextLogFilter = newUserLogFilter;
10861
10862 if (newUserLogFilter && captureFlag &&
10863 !sUserSpaceLogSpecArray && !sUserSpaceLogMessageArray) {
10864 // xxx - do some measurements for a good initial capacity?
10865 sUserSpaceLogSpecArray = OSArray::withCapacity(0);
10866 sUserSpaceLogMessageArray = OSArray::withCapacity(0);
10867
10868 if (!sUserSpaceLogSpecArray || !sUserSpaceLogMessageArray) {
10869 OSSafeReleaseNULL(sUserSpaceLogSpecArray);
10870 OSSafeReleaseNULL(sUserSpaceLogMessageArray);
10871 allocError = true;
10872 }
10873 }
10874
10875 IOLockUnlock(sKextLoggingLock);
10876
10877 /* If the config flag itself is changing, log the state change
10878 * going both ways, before setting up the user-space log arrays,
10879 * so that this is only logged in the kernel.
10880 */
10881 if (result != newUserLogFilter) {
10882 OSKextLog(/* kext */ NULL,
10883 kOSKextLogDebugLevel |
10884 kOSKextLogGeneralFlag,
10885 "User-space log flags changed from 0x%x to 0x%x.",
10886 result, newUserLogFilter);
10887 }
10888 if (allocError) {
10889 OSKextLog(/* kext */ NULL,
10890 kOSKextLogErrorLevel |
10891 kOSKextLogGeneralFlag,
10892 "Failed to allocate user-space log message arrays.");
10893 }
10894
10895 return result;
10896 }
10897
10898 /*********************************************************************
10899 * Do not call any function that takes sKextLock here!
10900 *********************************************************************/
10901 /* static */
10902 OSArray *
10903 OSKext::clearUserSpaceLogFilter(void)
10904 {
10905 OSArray * result = NULL;
10906 OSKextLogSpec oldLogFilter;
10907 OSKextLogSpec newLogFilter = kOSKextLogSilentFilter;
10908
10909 /* Do not call any function that takes sKextLoggingLock during
10910 * this critical block. That means do logging after.
10911 */
10912 IOLockLock(sKextLoggingLock);
10913
10914 result = OSArray::withCapacity(2);
10915 if (result) {
10916 result->setObject(sUserSpaceLogSpecArray);
10917 result->setObject(sUserSpaceLogMessageArray);
10918 }
10919 OSSafeReleaseNULL(sUserSpaceLogSpecArray);
10920 OSSafeReleaseNULL(sUserSpaceLogMessageArray);
10921
10922 oldLogFilter = sUserSpaceKextLogFilter;
10923 sUserSpaceKextLogFilter = newLogFilter;
10924
10925 IOLockUnlock(sKextLoggingLock);
10926
10927 /* If the config flag itself is changing, log the state change
10928 * going both ways, after tearing down the user-space log
10929 * arrays, so this is only logged within the kernel.
10930 */
10931 if (oldLogFilter != newLogFilter) {
10932 OSKextLog(/* kext */ NULL,
10933 kOSKextLogDebugLevel |
10934 kOSKextLogGeneralFlag,
10935 "User-space log flags changed from 0x%x to 0x%x.",
10936 oldLogFilter, newLogFilter);
10937 }
10938
10939 return result;
10940 }
10941
10942
10943 /*********************************************************************
10944 * Do not call any function that takes sKextLock here!
10945 *********************************************************************/
10946 /* static */
10947 OSKextLogSpec
10948 OSKext::getUserSpaceLogFilter(void)
10949 {
10950 OSKextLogSpec result;
10951
10952 IOLockLock(sKextLoggingLock);
10953 result = sUserSpaceKextLogFilter;
10954 IOLockUnlock(sKextLoggingLock);
10955
10956 return result;
10957 }
10958
10959 /*********************************************************************
10960 * This function is called by OSMetaClass during kernel C++ setup.
10961 * Be careful what you access here; assume only OSKext::initialize()
10962 * has been called.
10963 *
10964 * Do not call any function that takes sKextLock here!
10965 *********************************************************************/
10966 #define VTRESET "\033[0m"
10967
10968 #define VTBOLD "\033[1m"
10969 #define VTUNDER "\033[4m"
10970
10971 #define VTRED "\033[31m"
10972 #define VTGREEN "\033[32m"
10973 #define VTYELLOW "\033[33m"
10974 #define VTBLUE "\033[34m"
10975 #define VTMAGENTA "\033[35m"
10976 #define VTCYAN "\033[36m"
10977
10978 inline const char *
10979 colorForFlags(OSKextLogSpec flags)
10980 {
10981 OSKextLogSpec logLevel = flags & kOSKextLogLevelMask;
10982
10983 switch (logLevel) {
10984 case kOSKextLogErrorLevel:
10985 return VTRED VTBOLD;
10986 case kOSKextLogWarningLevel:
10987 return VTRED;
10988 case kOSKextLogBasicLevel:
10989 return VTYELLOW VTUNDER;
10990 case kOSKextLogProgressLevel:
10991 return VTYELLOW;
10992 case kOSKextLogStepLevel:
10993 return VTGREEN;
10994 case kOSKextLogDetailLevel:
10995 return VTCYAN;
10996 case kOSKextLogDebugLevel:
10997 return VTMAGENTA;
10998 default:
10999 return ""; // white
11000 }
11001 }
11002
11003 inline bool
11004 logSpecMatch(
11005 OSKextLogSpec msgLogSpec,
11006 OSKextLogSpec logFilter)
11007 {
11008 OSKextLogSpec filterKextGlobal = logFilter & kOSKextLogKextOrGlobalMask;
11009 OSKextLogSpec filterLevel = logFilter & kOSKextLogLevelMask;
11010 OSKextLogSpec filterFlags = logFilter & kOSKextLogFlagsMask;
11011
11012 OSKextLogSpec msgKextGlobal = msgLogSpec & kOSKextLogKextOrGlobalMask;
11013 OSKextLogSpec msgLevel = msgLogSpec & kOSKextLogLevelMask;
11014 OSKextLogSpec msgFlags = msgLogSpec & kOSKextLogFlagsMask;
11015
11016 /* Explicit messages always get logged.
11017 */
11018 if (msgLevel == kOSKextLogExplicitLevel) {
11019 return true;
11020 }
11021
11022 /* Warnings and errors are logged regardless of the flags.
11023 */
11024 if (msgLevel <= kOSKextLogBasicLevel && (msgLevel <= filterLevel)) {
11025 return true;
11026 }
11027
11028 /* A verbose message that isn't for a logging-enabled kext and isn't global
11029 * does *not* get logged.
11030 */
11031 if (!msgKextGlobal && !filterKextGlobal) {
11032 return false;
11033 }
11034
11035 /* Warnings and errors are logged regardless of the flags.
11036 * All other messages must fit the flags and
11037 * have a level at or below the filter.
11038 *
11039 */
11040 if ((msgFlags & filterFlags) && (msgLevel <= filterLevel)) {
11041 return true;
11042 }
11043 return false;
11044 }
11045
11046 extern "C" {
11047 void
11048 OSKextLog(
11049 OSKext * aKext,
11050 OSKextLogSpec msgLogSpec,
11051 const char * format, ...)
11052 {
11053 va_list argList;
11054
11055 va_start(argList, format);
11056 OSKextVLog(aKext, msgLogSpec, format, argList);
11057 va_end(argList);
11058 }
11059
11060 void
11061 OSKextVLog(
11062 OSKext * aKext,
11063 OSKextLogSpec msgLogSpec,
11064 const char * format,
11065 va_list srcArgList)
11066 {
11067 extern int disableConsoleOutput;
11068
11069 bool logForKernel = false;
11070 bool logForUser = false;
11071 va_list argList;
11072 char stackBuffer[120];
11073 uint32_t length = 0;
11074 char * allocBuffer = NULL; // must kfree
11075 OSNumber * logSpecNum = NULL; // must release
11076 OSString * logString = NULL; // must release
11077 char * buffer = stackBuffer;// do not free
11078
11079 IOLockLock(sKextLoggingLock);
11080
11081 /* Set the kext/global bit in the message spec if we have no
11082 * kext or if the kext requests logging.
11083 */
11084 if (!aKext || aKext->flags.loggingEnabled) {
11085 msgLogSpec = msgLogSpec | kOSKextLogKextOrGlobalMask;
11086 }
11087
11088 logForKernel = logSpecMatch(msgLogSpec, sKernelLogFilter);
11089 if (sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
11090 logForUser = logSpecMatch(msgLogSpec, sUserSpaceKextLogFilter);
11091 }
11092
11093 if (!(logForKernel || logForUser)) {
11094 goto finish;
11095 }
11096
11097 /* No goto from here until past va_end()!
11098 */
11099 va_copy(argList, srcArgList);
11100 length = vsnprintf(stackBuffer, sizeof(stackBuffer), format, argList);
11101 va_end(argList);
11102
11103 if (length + 1 >= sizeof(stackBuffer)) {
11104 allocBuffer = (char *)kalloc_tag((length + 1) * sizeof(char), VM_KERN_MEMORY_OSKEXT);
11105 if (!allocBuffer) {
11106 goto finish;
11107 }
11108
11109 /* No goto from here until past va_end()!
11110 */
11111 va_copy(argList, srcArgList);
11112 vsnprintf(allocBuffer, length + 1, format, argList);
11113 va_end(argList);
11114
11115 buffer = allocBuffer;
11116 }
11117
11118 /* If user space wants the log message, queue it up.
11119 */
11120 if (logForUser && sUserSpaceLogSpecArray && sUserSpaceLogMessageArray) {
11121 logSpecNum = OSNumber::withNumber(msgLogSpec, 8 * sizeof(msgLogSpec));
11122 logString = OSString::withCString(buffer);
11123 if (logSpecNum && logString) {
11124 sUserSpaceLogSpecArray->setObject(logSpecNum);
11125 sUserSpaceLogMessageArray->setObject(logString);
11126 }
11127 }
11128
11129 /* Always log messages from the kernel according to the kernel's
11130 * log flags.
11131 */
11132 if (logForKernel) {
11133 /* If we are in console mode and have a custom log filter,
11134 * colorize the log message.
11135 */
11136 if (!disableConsoleOutput && sBootArgLogFilterFound) {
11137 const char * color = ""; // do not free
11138 color = colorForFlags(msgLogSpec);
11139 printf("%s%s%s\n", colorForFlags(msgLogSpec),
11140 buffer, color[0] ? VTRESET : "");
11141 } else {
11142 printf("%s\n", buffer);
11143 }
11144 }
11145
11146 finish:
11147 IOLockUnlock(sKextLoggingLock);
11148
11149 if (allocBuffer) {
11150 kfree(allocBuffer, (length + 1) * sizeof(char));
11151 }
11152 OSSafeReleaseNULL(logString);
11153 OSSafeReleaseNULL(logSpecNum);
11154 return;
11155 }
11156
11157 #if KASLR_IOREG_DEBUG
11158
11159 #define IOLOG_INDENT( the_indention ) \
11160 { \
11161 int i; \
11162 for ( i = 0; i < (the_indention); i++ ) { \
11163 IOLog(" "); \
11164 } \
11165 }
11166
11167 extern vm_offset_t vm_kernel_stext;
11168 extern vm_offset_t vm_kernel_etext;
11169 extern mach_vm_offset_t kext_alloc_base;
11170 extern mach_vm_offset_t kext_alloc_max;
11171
11172 bool ScanForAddrInObject(OSObject * theObject,
11173 int indent );
11174
11175 bool
11176 ScanForAddrInObject(OSObject * theObject,
11177 int indent)
11178 {
11179 const OSMetaClass * myTypeID;
11180 OSCollectionIterator * myIter;
11181 OSSymbol * myKey;
11182 OSObject * myValue;
11183 bool myResult = false;
11184
11185 if (theObject == NULL) {
11186 IOLog("%s: theObject is NULL \n",
11187 __FUNCTION__);
11188 return myResult;
11189 }
11190
11191 myTypeID = OSTypeIDInst(theObject);
11192
11193 if (myTypeID == OSTypeID(OSDictionary)) {
11194 OSDictionary * myDictionary;
11195
11196 myDictionary = OSDynamicCast(OSDictionary, theObject);
11197 myIter = OSCollectionIterator::withCollection( myDictionary );
11198 if (myIter == NULL) {
11199 return myResult;
11200 }
11201 myIter->reset();
11202
11203 while ((myKey = OSDynamicCast(OSSymbol, myIter->getNextObject()))) {
11204 bool myTempResult;
11205
11206 myValue = myDictionary->getObject(myKey);
11207 myTempResult = ScanForAddrInObject(myValue, (indent + 4));
11208 if (myTempResult) {
11209 // if we ever get a true result return true
11210 myResult = true;
11211 IOLOG_INDENT(indent);
11212 IOLog("OSDictionary key \"%s\" \n", myKey->getCStringNoCopy());
11213 }
11214 }
11215 myIter->release();
11216 } else if (myTypeID == OSTypeID(OSArray)) {
11217 OSArray * myArray;
11218
11219 myArray = OSDynamicCast(OSArray, theObject);
11220 myIter = OSCollectionIterator::withCollection(myArray);
11221 if (myIter == NULL) {
11222 return myResult;
11223 }
11224 myIter->reset();
11225
11226 while ((myValue = myIter->getNextObject())) {
11227 bool myTempResult;
11228 myTempResult = ScanForAddrInObject(myValue, (indent + 4));
11229 if (myTempResult) {
11230 // if we ever get a true result return true
11231 myResult = true;
11232 IOLOG_INDENT(indent);
11233 IOLog("OSArray: \n");
11234 }
11235 }
11236 myIter->release();
11237 } else if (myTypeID == OSTypeID(OSString) || myTypeID == OSTypeID(OSSymbol)) {
11238 // should we look for addresses in strings?
11239 } else if (myTypeID == OSTypeID(OSData)) {
11240 void * * myPtrPtr;
11241 unsigned int myLen;
11242 OSData * myDataObj;
11243
11244 myDataObj = OSDynamicCast(OSData, theObject);
11245 myPtrPtr = (void * *) myDataObj->getBytesNoCopy();
11246 myLen = myDataObj->getLength();
11247
11248 if (myPtrPtr && myLen && myLen > 7) {
11249 int i;
11250 int myPtrCount = (myLen / sizeof(void *));
11251
11252 for (i = 0; i < myPtrCount; i++) {
11253 UInt64 numberValue = (UInt64) * (myPtrPtr);
11254
11255 if (kext_alloc_max != 0 &&
11256 numberValue >= kext_alloc_base &&
11257 numberValue < kext_alloc_max) {
11258 OSKext * myKext = NULL;// must release (looked up)
11259 // IOLog("found OSData %p in kext map %p to %p \n",
11260 // *(myPtrPtr),
11261 // (void *) kext_alloc_base,
11262 // (void *) kext_alloc_max);
11263
11264 myKext = OSKext::lookupKextWithAddress((vm_address_t) *(myPtrPtr));
11265 if (myKext) {
11266 IOLog("found addr %p from an OSData obj within kext \"%s\" \n",
11267 *(myPtrPtr),
11268 myKext->getIdentifierCString());
11269 myKext->release();
11270 }
11271 myResult = true;
11272 }
11273 if (vm_kernel_etext != 0 &&
11274 numberValue >= vm_kernel_stext &&
11275 numberValue < vm_kernel_etext) {
11276 IOLog("found addr %p from an OSData obj within kernel text segment %p to %p \n",
11277 *(myPtrPtr),
11278 (void *) vm_kernel_stext,
11279 (void *) vm_kernel_etext);
11280 myResult = true;
11281 }
11282 myPtrPtr++;
11283 }
11284 }
11285 } else if (myTypeID == OSTypeID(OSBoolean)) {
11286 // do nothing here...
11287 } else if (myTypeID == OSTypeID(OSNumber)) {
11288 OSNumber * number = OSDynamicCast(OSNumber, theObject);
11289
11290 UInt64 numberValue = number->unsigned64BitValue();
11291
11292 if (kext_alloc_max != 0 &&
11293 numberValue >= kext_alloc_base &&
11294 numberValue < kext_alloc_max) {
11295 OSKext * myKext = NULL;// must release (looked up)
11296 IOLog("found OSNumber in kext map %p to %p \n",
11297 (void *) kext_alloc_base,
11298 (void *) kext_alloc_max);
11299 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
11300
11301 myKext = OSKext::lookupKextWithAddress((vm_address_t) numberValue );
11302 if (myKext) {
11303 IOLog("found in kext \"%s\" \n",
11304 myKext->getIdentifierCString());
11305 myKext->release();
11306 }
11307
11308 myResult = true;
11309 }
11310 if (vm_kernel_etext != 0 &&
11311 numberValue >= vm_kernel_stext &&
11312 numberValue < vm_kernel_etext) {
11313 IOLog("found OSNumber in kernel text segment %p to %p \n",
11314 (void *) vm_kernel_stext,
11315 (void *) vm_kernel_etext);
11316 IOLog("OSNumber 0x%08llx (%llu) \n", numberValue, numberValue);
11317 myResult = true;
11318 }
11319 }
11320 #if 0
11321 else {
11322 const OSMetaClass* myMetaClass = NULL;
11323
11324 myMetaClass = theObject->getMetaClass();
11325 if (myMetaClass) {
11326 IOLog("class %s \n", myMetaClass->getClassName());
11327 } else {
11328 IOLog("Unknown object \n" );
11329 }
11330 }
11331 #endif
11332
11333 return myResult;
11334 }
11335 #endif // KASLR_KEXT_DEBUG
11336 }; /* extern "C" */
11337
11338 #if PRAGMA_MARK
11339 #pragma mark Backtrace Dump & kmod_get_info() support
11340 #endif
11341 /*********************************************************************
11342 * This function must be safe to call in panic context.
11343 *********************************************************************/
11344 /* static */
11345 void
11346 OSKext::printKextsInBacktrace(
11347 vm_offset_t * addr __unused,
11348 unsigned int cnt __unused,
11349 int (* printf_func)(const char *fmt, ...) __unused,
11350 uint32_t flags __unused)
11351 {
11352 addr64_t summary_page = 0;
11353 addr64_t last_summary_page = 0;
11354 bool found_kmod = false;
11355 u_int i = 0;
11356
11357 if (kPrintKextsLock & flags) {
11358 if (!sKextSummariesLock) {
11359 return;
11360 }
11361 IOLockLock(sKextSummariesLock);
11362 }
11363
11364 if (!gLoadedKextSummaries) {
11365 (*printf_func)(" can't perform kext scan: no kext summary");
11366 goto finish;
11367 }
11368
11369 summary_page = trunc_page((addr64_t)(uintptr_t)gLoadedKextSummaries);
11370 last_summary_page = round_page(summary_page + sLoadedKextSummariesAllocSize);
11371 for (; summary_page < last_summary_page; summary_page += PAGE_SIZE) {
11372 if (pmap_find_phys(kernel_pmap, summary_page) == 0) {
11373 (*printf_func)(" can't perform kext scan: "
11374 "missing kext summary page %p", summary_page);
11375 goto finish;
11376 }
11377 }
11378
11379 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
11380 OSKextLoadedKextSummary * summary;
11381
11382 summary = gLoadedKextSummaries->summaries + i;
11383 if (!summary->address) {
11384 continue;
11385 }
11386
11387 if (!summaryIsInBacktrace(summary, addr, cnt)) {
11388 continue;
11389 }
11390
11391 if (!found_kmod) {
11392 if (!(kPrintKextsTerse & flags)) {
11393 (*printf_func)(" Kernel Extensions in backtrace:\n");
11394 }
11395 found_kmod = true;
11396 }
11397
11398 printSummary(summary, printf_func, flags);
11399 }
11400
11401 finish:
11402 if (kPrintKextsLock & flags) {
11403 IOLockUnlock(sKextSummariesLock);
11404 }
11405
11406 return;
11407 }
11408
11409 /*********************************************************************
11410 * This function must be safe to call in panic context.
11411 *********************************************************************/
11412 /* static */
11413 boolean_t
11414 OSKext::summaryIsInBacktrace(
11415 OSKextLoadedKextSummary * summary,
11416 vm_offset_t * addr,
11417 unsigned int cnt)
11418 {
11419 u_int i = 0;
11420
11421 for (i = 0; i < cnt; i++) {
11422 vm_offset_t kscan_addr = addr[i];
11423 if ((kscan_addr >= summary->address) &&
11424 (kscan_addr < (summary->address + summary->size))) {
11425 return TRUE;
11426 }
11427 }
11428
11429 return FALSE;
11430 }
11431
11432 /*
11433 * Get the kext summary object for the kext where 'addr' lies. Must be called with
11434 * sKextSummariesLock held.
11435 */
11436 OSKextLoadedKextSummary *
11437 OSKext::summaryForAddress(const uintptr_t addr)
11438 {
11439 for (unsigned i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
11440 OSKextLoadedKextSummary *summary = &gLoadedKextSummaries->summaries[i];
11441 if (!summary->address) {
11442 continue;
11443 }
11444
11445 #if VM_MAPPED_KEXTS
11446 /* On our platforms that use VM_MAPPED_KEXTS, we currently do not
11447 * support split kexts, but we also may unmap the kexts, which can
11448 * race with the above codepath (see OSKext::unload). As such,
11449 * use a simple range lookup if we are using VM_MAPPED_KEXTS.
11450 */
11451 if ((addr >= summary->address) && (addr < (summary->address + summary->size))) {
11452 return summary;
11453 }
11454 #else
11455 kernel_mach_header_t *mh = (kernel_mach_header_t *)summary->address;
11456 kernel_segment_command_t *seg;
11457
11458 for (seg = firstsegfromheader(mh); seg != NULL; seg = nextsegfromheader(mh, seg)) {
11459 if ((addr >= seg->vmaddr) && (addr < (seg->vmaddr + seg->vmsize))) {
11460 return summary;
11461 }
11462 }
11463 #endif
11464 }
11465
11466 /* addr did not map to any kext */
11467 return NULL;
11468 }
11469
11470 /* static */
11471 void *
11472 OSKext::kextForAddress(const void *address)
11473 {
11474 void * image = NULL;
11475 OSKextActiveAccount * active;
11476 OSKext * kext = NULL;
11477 uint32_t baseIdx;
11478 uint32_t lim;
11479 uintptr_t addr = (uintptr_t) address;
11480
11481 if (!addr) {
11482 return NULL;
11483 }
11484
11485 if (sKextAccountsCount) {
11486 IOSimpleLockLock(sKextAccountsLock);
11487 // bsearch sKextAccounts list
11488 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
11489 active = &sKextAccounts[baseIdx + (lim >> 1)];
11490 if ((addr >= active->address) && (addr < active->address_end)) {
11491 kext = active->account->kext;
11492 if (kext && kext->kmod_info) {
11493 image = (void *) kext->kmod_info->address;
11494 }
11495 break;
11496 } else if (addr > active->address) {
11497 // move right
11498 baseIdx += (lim >> 1) + 1;
11499 lim--;
11500 }
11501 // else move left
11502 }
11503 IOSimpleLockUnlock(sKextAccountsLock);
11504 }
11505 if (!image && (addr >= vm_kernel_stext) && (addr < vm_kernel_etext)) {
11506 image = (void *) &_mh_execute_header;
11507 }
11508
11509 return image;
11510 }
11511
11512 /*********************************************************************
11513 * scan list of loaded kext summaries looking for a load address match and if
11514 * found return the UUID C string. If not found then set empty string.
11515 *********************************************************************/
11516 static void findSummaryUUID(
11517 uint32_t tag_ID,
11518 uuid_string_t uuid);
11519
11520 static void
11521 findSummaryUUID(
11522 uint32_t tag_ID,
11523 uuid_string_t uuid)
11524 {
11525 u_int i;
11526
11527 uuid[0] = 0x00; // default to no UUID
11528
11529 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
11530 OSKextLoadedKextSummary * summary;
11531
11532 summary = gLoadedKextSummaries->summaries + i;
11533
11534 if (summary->loadTag == tag_ID) {
11535 (void) uuid_unparse(summary->uuid, uuid);
11536 break;
11537 }
11538 }
11539 return;
11540 }
11541
11542 /*********************************************************************
11543 * This function must be safe to call in panic context.
11544 *********************************************************************/
11545 void
11546 OSKext::printSummary(
11547 OSKextLoadedKextSummary * summary,
11548 int (* printf_func)(const char *fmt, ...),
11549 uint32_t flags)
11550 {
11551 kmod_reference_t * kmod_ref = NULL;
11552 uuid_string_t uuid;
11553 char version[kOSKextVersionMaxLength];
11554 uint64_t tmpAddr;
11555
11556 if (!OSKextVersionGetString(summary->version, version, sizeof(version))) {
11557 strlcpy(version, "unknown version", sizeof(version));
11558 }
11559 (void) uuid_unparse(summary->uuid, uuid);
11560
11561 if (kPrintKextsUnslide & flags) {
11562 tmpAddr = ml_static_unslide(summary->address);
11563 } else {
11564 tmpAddr = summary->address;
11565 }
11566 (*printf_func)("%s%s(%s)[%s]@0x%llx->0x%llx\n",
11567 (kPrintKextsTerse & flags) ? "" : " ",
11568 summary->name, version, uuid,
11569 tmpAddr, tmpAddr + summary->size - 1);
11570
11571 if (kPrintKextsTerse & flags) {
11572 return;
11573 }
11574
11575 /* print dependency info */
11576 for (kmod_ref = (kmod_reference_t *) summary->reference_list;
11577 kmod_ref;
11578 kmod_ref = kmod_ref->next) {
11579 kmod_info_t * rinfo;
11580
11581 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_ref)) == 0) {
11582 (*printf_func)(" kmod dependency scan stopped "
11583 "due to missing dependency page: %p\n",
11584 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)kmod_ref) : kmod_ref);
11585 break;
11586 }
11587 rinfo = kmod_ref->info;
11588
11589 if (pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)rinfo)) == 0) {
11590 (*printf_func)(" kmod dependency scan stopped "
11591 "due to missing kmod page: %p\n",
11592 (kPrintKextsUnslide & flags) ? (void *)ml_static_unslide((vm_offset_t)rinfo) : rinfo);
11593 break;
11594 }
11595
11596 if (!rinfo->address) {
11597 continue; // skip fake entries for built-ins
11598 }
11599
11600 /* locate UUID in gLoadedKextSummaries */
11601 findSummaryUUID(rinfo->id, uuid);
11602
11603 if (kPrintKextsUnslide & flags) {
11604 tmpAddr = ml_static_unslide(rinfo->address);
11605 } else {
11606 tmpAddr = rinfo->address;
11607 }
11608 (*printf_func)(" dependency: %s(%s)[%s]@%p\n",
11609 rinfo->name, rinfo->version, uuid, tmpAddr);
11610 }
11611 return;
11612 }
11613
11614
11615 /*******************************************************************************
11616 * substitute() looks at an input string (a pointer within a larger buffer)
11617 * for a match to a substring, and on match it writes the marker & substitution
11618 * character to an output string, updating the scan (from) and
11619 * output (to) indexes as appropriate.
11620 *******************************************************************************/
11621 static int substitute(
11622 const char * scan_string,
11623 char * string_out,
11624 uint32_t * to_index,
11625 uint32_t * from_index,
11626 const char * substring,
11627 char marker,
11628 char substitution);
11629
11630 /* string_out must be at least KMOD_MAX_NAME bytes.
11631 */
11632 static int
11633 substitute(
11634 const char * scan_string,
11635 char * string_out,
11636 uint32_t * to_index,
11637 uint32_t * from_index,
11638 const char * substring,
11639 char marker,
11640 char substitution)
11641 {
11642 uint32_t substring_length = strnlen(substring, KMOD_MAX_NAME - 1);
11643
11644 /* On a substring match, append the marker (if there is one) and then
11645 * the substitution character, updating the output (to) index accordingly.
11646 * Then update the input (from) length by the length of the substring
11647 * that got replaced.
11648 */
11649 if (!strncmp(scan_string, substring, substring_length)) {
11650 if (marker) {
11651 string_out[(*to_index)++] = marker;
11652 }
11653 string_out[(*to_index)++] = substitution;
11654 (*from_index) += substring_length;
11655 return 1;
11656 }
11657 return 0;
11658 }
11659
11660 /*******************************************************************************
11661 * compactIdentifier() takes a CFBundleIdentifier in a buffer of at least
11662 * KMOD_MAX_NAME characters and performs various substitutions of common
11663 * prefixes & substrings as defined by tables in kext_panic_report.h.
11664 *******************************************************************************/
11665 static void compactIdentifier(
11666 const char * identifier,
11667 char * identifier_out,
11668 char ** identifier_out_end);
11669
11670 static void
11671 compactIdentifier(
11672 const char * identifier,
11673 char * identifier_out,
11674 char ** identifier_out_end)
11675 {
11676 uint32_t from_index, to_index;
11677 uint32_t scan_from_index = 0;
11678 uint32_t scan_to_index = 0;
11679 subs_entry_t * subs_entry = NULL;
11680 int did_sub = 0;
11681
11682 from_index = to_index = 0;
11683 identifier_out[0] = '\0';
11684
11685 /* Replace certain identifier prefixes with shorter @+character sequences.
11686 * Check the return value of substitute() so we only replace the prefix.
11687 */
11688 for (subs_entry = &kext_identifier_prefix_subs[0];
11689 subs_entry->substring && !did_sub;
11690 subs_entry++) {
11691 did_sub = substitute(identifier, identifier_out,
11692 &scan_to_index, &scan_from_index,
11693 subs_entry->substring, /* marker */ '\0', subs_entry->substitute);
11694 }
11695 did_sub = 0;
11696
11697 /* Now scan through the identifier looking for the common substrings
11698 * and replacing them with shorter !+character sequences via substitute().
11699 */
11700 for (/* see above */;
11701 scan_from_index < KMOD_MAX_NAME - 1 && identifier[scan_from_index];
11702 /* see loop */) {
11703 const char * scan_string = &identifier[scan_from_index];
11704
11705 did_sub = 0;
11706
11707 if (scan_from_index) {
11708 for (subs_entry = &kext_identifier_substring_subs[0];
11709 subs_entry->substring && !did_sub;
11710 subs_entry++) {
11711 did_sub = substitute(scan_string, identifier_out,
11712 &scan_to_index, &scan_from_index,
11713 subs_entry->substring, '!', subs_entry->substitute);
11714 }
11715 }
11716
11717 /* If we didn't substitute, copy the input character to the output.
11718 */
11719 if (!did_sub) {
11720 identifier_out[scan_to_index++] = identifier[scan_from_index++];
11721 }
11722 }
11723
11724 identifier_out[scan_to_index] = '\0';
11725 if (identifier_out_end) {
11726 *identifier_out_end = &identifier_out[scan_to_index];
11727 }
11728
11729 return;
11730 }
11731
11732 /*******************************************************************************
11733 * assemble_identifier_and_version() adds to a string buffer a compacted
11734 * bundle identifier followed by a version string.
11735 *******************************************************************************/
11736
11737 /* identPlusVers must be at least 2*KMOD_MAX_NAME in length.
11738 */
11739 static int assemble_identifier_and_version(
11740 kmod_info_t * kmod_info,
11741 char * identPlusVers,
11742 int bufSize);
11743
11744 static int
11745 assemble_identifier_and_version(
11746 kmod_info_t * kmod_info,
11747 char * identPlusVers,
11748 int bufSize)
11749 {
11750 int result = 0;
11751
11752 compactIdentifier(kmod_info->name, identPlusVers, NULL);
11753 result = strnlen(identPlusVers, KMOD_MAX_NAME - 1);
11754 identPlusVers[result++] = '\t'; // increment for real char
11755 identPlusVers[result] = '\0'; // don't increment for nul char
11756 result = strlcat(identPlusVers, kmod_info->version, bufSize);
11757 if (result >= bufSize) {
11758 identPlusVers[bufSize - 1] = '\0';
11759 result = bufSize - 1;
11760 }
11761
11762 return result;
11763 }
11764
11765 /*******************************************************************************
11766 * Assumes sKextLock is held.
11767 *******************************************************************************/
11768 /* static */
11769 int
11770 OSKext::saveLoadedKextPanicListTyped(
11771 const char * prefix,
11772 int invertFlag,
11773 int libsFlag,
11774 char * paniclist,
11775 uint32_t list_size)
11776 {
11777 int result = -1;
11778 unsigned int count, i;
11779
11780 count = sLoadedKexts->getCount();
11781 if (!count) {
11782 goto finish;
11783 }
11784
11785 i = count - 1;
11786 do {
11787 OSObject * rawKext = sLoadedKexts->getObject(i);
11788 OSKext * theKext = OSDynamicCast(OSKext, rawKext);
11789 int match;
11790 uint32_t identPlusVersLength;
11791 uint32_t tempLen;
11792 char identPlusVers[2 * KMOD_MAX_NAME];
11793
11794 if (!rawKext) {
11795 printf("OSKext::saveLoadedKextPanicListTyped - "
11796 "NULL kext in loaded kext list; continuing\n");
11797 continue;
11798 }
11799
11800 if (!theKext) {
11801 printf("OSKext::saveLoadedKextPanicListTyped - "
11802 "Kext type cast failed in loaded kext list; continuing\n");
11803 continue;
11804 }
11805
11806 /* Skip all built-in kexts.
11807 */
11808 if (theKext->isKernelComponent()) {
11809 continue;
11810 }
11811
11812 kmod_info_t * kmod_info = theKext->kmod_info;
11813
11814 /* Filter for kmod name (bundle identifier).
11815 */
11816 match = !strncmp(kmod_info->name, prefix, strnlen(prefix, KMOD_MAX_NAME));
11817 if ((match && invertFlag) || (!match && !invertFlag)) {
11818 continue;
11819 }
11820
11821 /* Filter for libraries (kexts that have a compatible version).
11822 */
11823 if ((libsFlag == 0 && theKext->getCompatibleVersion() > 1) ||
11824 (libsFlag == 1 && theKext->getCompatibleVersion() < 1)) {
11825 continue;
11826 }
11827
11828 if (!kmod_info ||
11829 !pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)kmod_info))) {
11830 printf("kext scan stopped due to missing kmod_info page: %p\n",
11831 kmod_info);
11832 goto finish;
11833 }
11834
11835 identPlusVersLength = assemble_identifier_and_version(kmod_info,
11836 identPlusVers,
11837 sizeof(identPlusVers));
11838 if (!identPlusVersLength) {
11839 printf("error saving loaded kext info\n");
11840 goto finish;
11841 }
11842
11843 /* make sure everything fits and we null terminate.
11844 */
11845 tempLen = strlcat(paniclist, identPlusVers, list_size);
11846 if (tempLen >= list_size) {
11847 // panic list is full, keep it and null terminate
11848 paniclist[list_size - 1] = 0x00;
11849 result = 0;
11850 goto finish;
11851 }
11852 tempLen = strlcat(paniclist, "\n", list_size);
11853 if (tempLen >= list_size) {
11854 // panic list is full, keep it and null terminate
11855 paniclist[list_size - 1] = 0x00;
11856 result = 0;
11857 goto finish;
11858 }
11859 } while (i--);
11860
11861 result = 0;
11862 finish:
11863
11864 return result;
11865 }
11866
11867 /*********************************************************************
11868 *********************************************************************/
11869 /* static */
11870 void
11871 OSKext::saveLoadedKextPanicList(void)
11872 {
11873 char * newlist = NULL;
11874 uint32_t newlist_size = 0;
11875
11876 newlist_size = KEXT_PANICLIST_SIZE;
11877 newlist = (char *)kalloc_tag(newlist_size, VM_KERN_MEMORY_OSKEXT);
11878
11879 if (!newlist) {
11880 OSKextLog(/* kext */ NULL,
11881 kOSKextLogErrorLevel | kOSKextLogGeneralFlag,
11882 "Couldn't allocate kext panic log buffer.");
11883 goto finish;
11884 }
11885
11886 newlist[0] = '\0';
11887
11888 // non-"com.apple." kexts
11889 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 1,
11890 /* libs? */ -1, newlist, newlist_size) != 0) {
11891 goto finish;
11892 }
11893 // "com.apple." nonlibrary kexts
11894 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11895 /* libs? */ 0, newlist, newlist_size) != 0) {
11896 goto finish;
11897 }
11898 // "com.apple." library kexts
11899 if (OSKext::saveLoadedKextPanicListTyped("com.apple.", /* invert? */ 0,
11900 /* libs? */ 1, newlist, newlist_size) != 0) {
11901 goto finish;
11902 }
11903
11904 if (loaded_kext_paniclist) {
11905 kfree(loaded_kext_paniclist, loaded_kext_paniclist_size);
11906 }
11907 loaded_kext_paniclist = newlist;
11908 newlist = NULL;
11909 loaded_kext_paniclist_size = newlist_size;
11910
11911 finish:
11912 if (newlist) {
11913 kfree(newlist, newlist_size);
11914 }
11915 return;
11916 }
11917
11918 /*********************************************************************
11919 * Assumes sKextLock is held.
11920 *********************************************************************/
11921 void
11922 OSKext::savePanicString(bool isLoading)
11923 {
11924 u_long len;
11925
11926 if (!kmod_info) {
11927 return; // do not goto finish here b/c of lock
11928 }
11929
11930 len = assemble_identifier_and_version( kmod_info,
11931 (isLoading) ? last_loaded_str_buf : last_unloaded_str_buf,
11932 (isLoading) ? sizeof(last_loaded_str_buf) : sizeof(last_unloaded_str_buf));
11933 if (!len) {
11934 printf("error saving unloaded kext info\n");
11935 goto finish;
11936 }
11937
11938 if (isLoading) {
11939 last_loaded_strlen = len;
11940 last_loaded_address = (void *)kmod_info->address;
11941 last_loaded_size = kmod_info->size;
11942 clock_get_uptime(&last_loaded_timestamp);
11943 } else {
11944 last_unloaded_strlen = len;
11945 last_unloaded_address = (void *)kmod_info->address;
11946 last_unloaded_size = kmod_info->size;
11947 clock_get_uptime(&last_unloaded_timestamp);
11948 }
11949
11950 finish:
11951 return;
11952 }
11953
11954 /*********************************************************************
11955 *********************************************************************/
11956 /* static */
11957 void
11958 OSKext::printKextPanicLists(int (*printf_func)(const char *fmt, ...))
11959 {
11960 if (last_loaded_strlen) {
11961 printf_func("last loaded kext at %llu: %.*s (addr %p, size %lu)\n",
11962 AbsoluteTime_to_scalar(&last_loaded_timestamp),
11963 last_loaded_strlen, last_loaded_str_buf,
11964 last_loaded_address, last_loaded_size);
11965 }
11966
11967 if (last_unloaded_strlen) {
11968 printf_func("last unloaded kext at %llu: %.*s (addr %p, size %lu)\n",
11969 AbsoluteTime_to_scalar(&last_unloaded_timestamp),
11970 last_unloaded_strlen, last_unloaded_str_buf,
11971 last_unloaded_address, last_unloaded_size);
11972 }
11973
11974 printf_func("loaded kexts:\n");
11975 if (loaded_kext_paniclist &&
11976 pmap_find_phys(kernel_pmap, (addr64_t) (uintptr_t) loaded_kext_paniclist) &&
11977 loaded_kext_paniclist[0]) {
11978 printf_func("%.*s",
11979 strnlen(loaded_kext_paniclist, loaded_kext_paniclist_size),
11980 loaded_kext_paniclist);
11981 } else {
11982 printf_func("(none)\n");
11983 }
11984 return;
11985 }
11986
11987 /*********************************************************************
11988 * Assumes sKextLock is held.
11989 *********************************************************************/
11990 /* static */
11991 void
11992 OSKext::updateLoadedKextSummaries(void)
11993 {
11994 kern_return_t result = KERN_FAILURE;
11995 OSKextLoadedKextSummaryHeader *summaryHeader = NULL;
11996 OSKextLoadedKextSummaryHeader *summaryHeaderAlloc = NULL;
11997 OSKext *aKext;
11998 vm_map_offset_t start, end;
11999 size_t summarySize = 0;
12000 size_t size;
12001 u_int count;
12002 u_int maxKexts;
12003 u_int i, j;
12004 OSKextActiveAccount * accountingList;
12005 OSKextActiveAccount * prevAccountingList;
12006 uint32_t idx, accountingListAlloc, accountingListCount, prevAccountingListCount;
12007
12008 prevAccountingList = NULL;
12009 prevAccountingListCount = 0;
12010
12011 #if DEVELOPMENT || DEBUG
12012 if (IORecursiveLockHaveLock(sKextLock) == false) {
12013 panic("sKextLock must be held");
12014 }
12015 #endif
12016
12017 IOLockLock(sKextSummariesLock);
12018
12019 count = sLoadedKexts->getCount();
12020 for (i = 0, maxKexts = 0; i < count; ++i) {
12021 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
12022 maxKexts += (aKext && aKext->isExecutable());
12023 }
12024
12025 if (!maxKexts) {
12026 goto finish;
12027 }
12028 if (maxKexts < kOSKextTypicalLoadCount) {
12029 maxKexts = kOSKextTypicalLoadCount;
12030 }
12031
12032 /* Calculate the size needed for the new summary headers.
12033 */
12034
12035 size = sizeof(*gLoadedKextSummaries);
12036 size += maxKexts * sizeof(*gLoadedKextSummaries->summaries);
12037 size = round_page(size);
12038
12039 if (gLoadedKextSummaries == NULL || sLoadedKextSummariesAllocSize < size) {
12040 if (gLoadedKextSummaries) {
12041 kmem_free(kernel_map, (vm_offset_t)gLoadedKextSummaries, sLoadedKextSummariesAllocSize);
12042 gLoadedKextSummaries = NULL;
12043 gLoadedKextSummariesTimestamp = mach_absolute_time();
12044 sLoadedKextSummariesAllocSize = 0;
12045 }
12046 result = kmem_alloc(kernel_map, (vm_offset_t *)&summaryHeaderAlloc, size, VM_KERN_MEMORY_OSKEXT);
12047 if (result != KERN_SUCCESS) {
12048 goto finish;
12049 }
12050 summaryHeader = summaryHeaderAlloc;
12051 summarySize = size;
12052 } else {
12053 summaryHeader = gLoadedKextSummaries;
12054 summarySize = sLoadedKextSummariesAllocSize;
12055
12056 start = (vm_map_offset_t) summaryHeader;
12057 end = start + summarySize;
12058 result = vm_map_protect(kernel_map,
12059 start,
12060 end,
12061 VM_PROT_DEFAULT,
12062 FALSE);
12063 if (result != KERN_SUCCESS) {
12064 goto finish;
12065 }
12066 }
12067
12068 /* Populate the summary header.
12069 */
12070
12071 bzero(summaryHeader, summarySize);
12072 summaryHeader->version = kOSKextLoadedKextSummaryVersion;
12073 summaryHeader->entry_size = sizeof(OSKextLoadedKextSummary);
12074
12075 /* Populate each kext summary.
12076 */
12077
12078 count = sLoadedKexts->getCount();
12079 accountingListAlloc = 0;
12080 for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
12081 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
12082 if (!aKext || !aKext->isExecutable()) {
12083 continue;
12084 }
12085
12086 aKext->updateLoadedKextSummary(&summaryHeader->summaries[j++]);
12087 summaryHeader->numSummaries++;
12088 accountingListAlloc++;
12089 }
12090
12091 accountingList = IONew(typeof(accountingList[0]), accountingListAlloc);
12092 accountingListCount = 0;
12093 for (i = 0, j = 0; i < count && j < maxKexts; ++i) {
12094 aKext = OSDynamicCast(OSKext, sLoadedKexts->getObject(i));
12095 if (!aKext || !aKext->isExecutable()) {
12096 continue;
12097 }
12098
12099 OSKextActiveAccount activeAccount;
12100 aKext->updateActiveAccount(&activeAccount);
12101 // order by address
12102 for (idx = 0; idx < accountingListCount; idx++) {
12103 if (activeAccount.address < accountingList[idx].address) {
12104 break;
12105 }
12106 }
12107 bcopy(&accountingList[idx], &accountingList[idx + 1], (accountingListCount - idx) * sizeof(accountingList[0]));
12108 accountingList[idx] = activeAccount;
12109 accountingListCount++;
12110 }
12111 assert(accountingListCount == accountingListAlloc);
12112 /* Write protect the buffer and move it into place.
12113 */
12114
12115 start = (vm_map_offset_t) summaryHeader;
12116 end = start + summarySize;
12117
12118 result = vm_map_protect(kernel_map, start, end, VM_PROT_READ, FALSE);
12119 if (result != KERN_SUCCESS) {
12120 goto finish;
12121 }
12122
12123 gLoadedKextSummaries = summaryHeader;
12124 gLoadedKextSummariesTimestamp = mach_absolute_time();
12125 sLoadedKextSummariesAllocSize = summarySize;
12126 summaryHeaderAlloc = NULL;
12127
12128 /* Call the magic breakpoint function through a static function pointer so
12129 * the compiler can't optimize the function away.
12130 */
12131 if (sLoadedKextSummariesUpdated) {
12132 (*sLoadedKextSummariesUpdated)();
12133 }
12134
12135 IOSimpleLockLock(sKextAccountsLock);
12136 prevAccountingList = sKextAccounts;
12137 prevAccountingListCount = sKextAccountsCount;
12138 sKextAccounts = accountingList;
12139 sKextAccountsCount = accountingListCount;
12140 IOSimpleLockUnlock(sKextAccountsLock);
12141
12142 finish:
12143 IOLockUnlock(sKextSummariesLock);
12144
12145 /* If we had to allocate a new buffer but failed to generate the summaries,
12146 * free that now.
12147 */
12148 if (summaryHeaderAlloc) {
12149 kmem_free(kernel_map, (vm_offset_t)summaryHeaderAlloc, summarySize);
12150 }
12151 if (prevAccountingList) {
12152 IODelete(prevAccountingList, typeof(accountingList[0]), prevAccountingListCount);
12153 }
12154
12155 return;
12156 }
12157
12158 /*********************************************************************
12159 *********************************************************************/
12160 void
12161 OSKext::updateLoadedKextSummary(OSKextLoadedKextSummary *summary)
12162 {
12163 OSData *uuid;
12164
12165 strlcpy(summary->name, getIdentifierCString(),
12166 sizeof(summary->name));
12167
12168 uuid = copyUUID();
12169 if (uuid) {
12170 memcpy(summary->uuid, uuid->getBytesNoCopy(), sizeof(summary->uuid));
12171 OSSafeReleaseNULL(uuid);
12172 }
12173
12174 if (flags.builtin) {
12175 // this value will stop lldb from parsing the mach-o header
12176 // summary->address = UINT64_MAX;
12177 // summary->size = 0;
12178 summary->address = kmod_info->address;
12179 summary->size = kmod_info->size;
12180 } else {
12181 summary->address = kmod_info->address;
12182 summary->size = kmod_info->size;
12183 }
12184 summary->version = getVersion();
12185 summary->loadTag = kmod_info->id;
12186 summary->flags = 0;
12187 summary->reference_list = (uint64_t) kmod_info->reference_list;
12188
12189 return;
12190 }
12191
12192 /*********************************************************************
12193 *********************************************************************/
12194
12195 void
12196 OSKext::updateActiveAccount(OSKextActiveAccount *accountp)
12197 {
12198 kernel_mach_header_t *hdr = NULL;
12199 kernel_segment_command_t *seg = NULL;
12200
12201 bzero(accountp, sizeof(*accountp));
12202
12203 hdr = (kernel_mach_header_t *)kmod_info->address;
12204 if (getcommandfromheader(hdr, LC_SEGMENT_SPLIT_INFO)) {
12205 /* If this kext supports split segments, use the first
12206 * executable segment as the range for instructions
12207 * (and thus for backtracing.
12208 */
12209 for (seg = firstsegfromheader(hdr); seg != NULL; seg = nextsegfromheader(hdr, seg)) {
12210 if (seg->initprot & VM_PROT_EXECUTE) {
12211 break;
12212 }
12213 }
12214 }
12215 if (seg) {
12216 accountp->address = seg->vmaddr;
12217 if (accountp->address) {
12218 accountp->address_end = seg->vmaddr + seg->vmsize;
12219 }
12220 } else {
12221 /* For non-split kexts and for kexts without executable
12222 * segments, just use the kmod_info range (as the kext
12223 * is either all in one range or should not show up in
12224 * instruction backtraces).
12225 */
12226 accountp->address = kmod_info->address;
12227 if (accountp->address) {
12228 accountp->address_end = kmod_info->address + kmod_info->size;
12229 }
12230 }
12231
12232 accountp->account = this->account;
12233 }
12234
12235 bool
12236 OSKext::isDriverKit(void)
12237 {
12238 OSString *bundleType;
12239
12240 if (infoDict) {
12241 bundleType = OSDynamicCast(OSString, infoDict->getObject(kCFBundlePackageTypeKey));
12242 if (bundleType && bundleType->isEqualTo(kOSKextBundlePackageTypeDriverKit)) {
12243 return TRUE;
12244 }
12245 }
12246 return FALSE;
12247 }
12248
12249 extern "C" const vm_allocation_site_t *
12250 OSKextGetAllocationSiteForCaller(uintptr_t address)
12251 {
12252 OSKextActiveAccount * active;
12253 vm_allocation_site_t * site;
12254 vm_allocation_site_t * releasesite;
12255
12256 uint32_t baseIdx;
12257 uint32_t lim;
12258
12259 IOSimpleLockLock(sKextAccountsLock);
12260 site = releasesite = NULL;
12261
12262 // bsearch sKextAccounts list
12263 for (baseIdx = 0, lim = sKextAccountsCount; lim; lim >>= 1) {
12264 active = &sKextAccounts[baseIdx + (lim >> 1)];
12265 if ((address >= active->address) && (address < active->address_end)) {
12266 site = &active->account->site;
12267 if (!site->tag) {
12268 vm_tag_alloc_locked(site, &releasesite);
12269 }
12270 break;
12271 } else if (address > active->address) {
12272 // move right
12273 baseIdx += (lim >> 1) + 1;
12274 lim--;
12275 }
12276 // else move left
12277 }
12278 IOSimpleLockUnlock(sKextAccountsLock);
12279 if (releasesite) {
12280 kern_allocation_name_release(releasesite);
12281 }
12282
12283 return site;
12284 }
12285
12286 extern "C" uint32_t
12287 OSKextGetKmodIDForSite(const vm_allocation_site_t * site, char * name, vm_size_t namelen)
12288 {
12289 OSKextAccount * account = (typeof(account))site;
12290 const char * kname;
12291
12292 if (name) {
12293 if (account->kext) {
12294 kname = account->kext->getIdentifierCString();
12295 } else {
12296 kname = "<>";
12297 }
12298 strlcpy(name, kname, namelen);
12299 }
12300
12301 return account->loadTag;
12302 }
12303
12304 extern "C" void
12305 OSKextFreeSite(vm_allocation_site_t * site)
12306 {
12307 OSKextAccount * freeAccount = (typeof(freeAccount))site;
12308 IODelete(freeAccount, OSKextAccount, 1);
12309 }
12310
12311 /*********************************************************************
12312 *********************************************************************/
12313
12314 #if CONFIG_IMAGEBOOT
12315 int
12316 OSKextGetUUIDForName(const char *name, uuid_t uuid)
12317 {
12318 OSKext *kext = OSKext::lookupKextWithIdentifier(name);
12319 if (!kext) {
12320 return 1;
12321 }
12322
12323 OSData *uuid_data = kext->copyUUID();
12324 if (uuid_data) {
12325 memcpy(uuid, uuid_data->getBytesNoCopy(), sizeof(uuid_t));
12326 OSSafeReleaseNULL(uuid_data);
12327 return 0;
12328 }
12329
12330 return 1;
12331 }
12332 #endif